0

I'm bundling a pygame app using py2app. The bundling works and the resulting bundle runs on my mac just fine. It also used to run on another person's mac just fine. However, recently I've started getting this error (from the console) when trying to run the bundle on his computer:

Traceback (most recent call last):
  File "/Users/.../tmp/withconsole.app/Contents/Resources/__boot__.py", line 316, in <module>
    _run()
  File "/Users/.../tmp/withconsole.app/Contents/Resources/__boot__.py", line 311, in _run
    exec(compile(source, path, 'exec'), globals(), globals())
  File "/Users/.../tmp/withconsole.app/Contents/Resources/withconsole.py", line 18, in <module>
pdb.set_trace()
  File "bdb.pyc", line 53, in trace_dispatch
  File "bdb.pyc", line 88, in dispatch_return
  File "pdb.pyc", line 190, in user_return
  File "pdb.pyc", line 210, in interaction
  File "cmd.pyc", line 142, in cmdloop
  File "pdb.pyc", line 279, in onecmd
  File "cmd.pyc", line 218, in onecmd
  File "pygame/macosx.pyc", line 10, in <module>
  File "pygame/sdlmain_osx.pyc", line 14, in <module>
  File "pygame/sdlmain_osx.pyc", line 10, in __load
ImportError: dlopen(/Users/.../tmp/withconsole.app/Contents/Resources/lib/python2.7/lib-dynload/pygame/sdlmain_osx.so, 2): Symbol not found: _OBJC_CLASS_$_NSObject
  Referenced from: /Users/.../tmp/withconsole.app/Contents/Resources/lib/python2.7/lib-dynload/pygame/sdlmain_osx.so
  Expected in: /usr/lib/libobjc.A.dylib
 in /Users/.../tmp/withconsole.app/Contents/Resources/lib/python2.7/lib-dynload/pygame/sdlmain_osx.so
2013-11-09 06:19:50.794 withconsole[2797:1c03] ogclient Error

I even tried running an older bundle that used to work, yet now it no longer works! I'm 95% certain of that, anyway.

In any case, what's the issue and how can I fix it?

Claudiu
  • 224,032
  • 165
  • 485
  • 680
  • Is this a semi-standalone, fully-standalone, or non-standalone build? If it's fully-standalone, how did you build or install the Python it's built against? What OS X version do each of you have? Have either of you upgraded recently? – abarnert Nov 08 '13 at 22:27
  • Thanks for getting involved! It's fully standalone. at least, that is my intention. I built my python using homebrew and in the process destroyed my system's install of python somehow. he has 10.7.4 and I have 10.8.3. I haven't upgraded recently and, to my knowledge, I don't think the other guy has either, but I'm not entirely sure. – Claudiu Nov 08 '13 at 22:35
  • You can't have destroyed your system's installation of Python. It is possible to destroy site packages and scripts/programs installed for the system Python, but it's very hard to accidentally destroy Python itself. Especially since it's all only writable by root, and Homebrew never uses sudo unless you go out of your way to force it. More likely you just shadowed it in your PATH, and `/usr/bin/python` still runs Apple's Python just fine. Which is all beside the point, but if it implies that you don't understand how PATH works and the like, it might hint that you've mixed them up in py2app-ing. – abarnert Nov 08 '13 at 23:36
  • Anyway, I think I know what the problem is. Let me write up an answer. – abarnert Nov 08 '13 at 23:36
  • @abarnert: oh it wasn't accidental. I purposefully deleted it. I forget why but I thought it was necessary at the time... checking out your answer now – Claudiu Nov 09 '13 at 00:17
  • Deleting your system Python is a very bad idea. There are parts of the OS that rely on it. There are third-party tools that expect it to be there, and won't build and/or won't run properly unless it's there. I believe if you just upgrade to OS X 10.8.5, it will re-install Python for you; if not, you may have to dig through the installer .mpkg bundle and/or a hidden Packages directory on the DMG to find the Python 2.7 installer and re-run it manually. At any rate, don't do that again. – abarnert Nov 09 '13 at 01:24
  • @abarnert: Thanks, I have learned my lesson since then. I think I did it because of [this page](http://web.mit.edu/6.090/www/pygame.html) which is the first hit for "pygame 64 bit mac". I've been unable to use one app already because of it =(. I tried reinstalling it but I couldn't find an easy way to do it. I might just reinstall the OS and be a lot more careful with where I put everything and what I do to it. – Claudiu Nov 09 '13 at 01:31
  • OK, deleting `/Applications/Python 2.7` isn't a problem; in fact, you won't even have that on a clean 10.8 install; you'll only have it from a third-party install, or possibly from Apple if you started with 10.5 and upgraded continuously to 10.6, 10.7, and 10.8. Either way, it's safe to scrap. Just so long as you don't touch Apple's Python stuff in /System or /usr. – abarnert Nov 09 '13 at 01:55

1 Answers1

2

A standalone app from py2app creates its baked-in Python interpreter from whichever version of Python you use for py2app.

If you use, say, a Python built to run on any OS X 10.6 or later, the application (so long as it doesn't use any post-10.6 features) will also run on any OS X 10.6 or later. If you use a Python built to run on one particular 10.8 machine, the application will very likely not work on anything earlier than 10.8, and may not even work on other 10.8+ machines.

On top of that, if you're using any C extension modules that you built against C libraries that you built yourself, if those C libraries were built for your particular machine, they'll probably cause the same problem.

You built your Python interpreter with Homebrew. And maybe your SDL as well, which pygame depends on. And possibly other things. By default, Homebrew builds everything to run on your particular machine, not to be redistributable. Hence the problem.

To build an app that can run on 10.7 machines, you need to either build Python, SDL, etc. against the 10.7 SDK, or build it against a later API and specify -mmacosx-version-min=10.7. (There are a few other issues that can come up, but I'm pretty sure none of them affect CPython, so let's keep it simple.)

That will automatically set things up so any C extension modules you build use the same SDK and version settings, so you shouldn't have to worry about those. But you do have to worry about any C libraries you built that those extension modules depend on. For example, pygame links against libSDL, and if you built SDL for your local machine only, pygame isn't going to work on someone else's machine.

It's possible to get Homebrew to create SDK builds, but not always that easy. It's easier to just build Python manually and pass the right --configure flags. But it's even easier to take a binary that someone else has already built for portability and use that.

The official Python installers at python.org are built for 10.6+. The official SDL development libraries are built for 10.5+. Hopefully the same is true for other things you're depending on. If so, just brew uninstall (or, if you're wary and want to be able to undo this later, brew unlink) everything, run the binary installers, reinstall all the Python modules you need for the new Python, and py2app with it.


I wrote this all in general terms. From the output, it looks like the specific problem you're hitting on this particular run on your friend's particular 10.7 machine is that the SDL wrappers are depending on features of the ObjC runtime that didn't exist in 10.7. So, it's possible that just using a 10.7-friendly SDL, and your existing Python, would be sufficient. But I think you're better off using 10.7-friendly everything if at all possible.


If you're wondering what exactly the SDK does, the SDK Compatibility Guide in Apple's official docs explain the technical side of it pretty well, and there are a zillion blog posts like this one that explain the practical parts, but I'll try to summarize.

Each SDK is just a directory that has its own /usr/include, /usr/lib, /System/Library/Frameworks, and a few other things inside. When you build against an SDK, you end up compiling against its header files instead of your system's, and linking against its dylibs instead of your system's. This prevents you from using any new features added since 10.6 (with a nice compiler error, instead of a successful build that then won't start on half your users' machines). And it makes sure that, if you don't use any such new features, your program doesn't have load-time dependencies on anything that didn't exist in 10.6.

abarnert
  • 354,177
  • 51
  • 601
  • 671
  • Ah thanks for that explanation, that all makes sense. I wondered if I just got lucky that the app I made ran on any other mac at all and it looks like the answer is "yes". So it goes for not understanding stuff fully... in any case, how would I go about building things for, say, any 10.8 OSX as opposed to just my very own 10.8 OSX? As in, what are the ways compiling something myself would limit it to only working on my machine? – Claudiu Nov 09 '13 at 00:22
  • As to the SDL wrappers, yep I did built SDL using brew, and the python as well, and pygame also... I'll try using the pre-built pygame libraries which says 10.3+ and see if that fixes the issue. – Claudiu Nov 09 '13 at 00:24
  • @Claudiu: To build for any 10.8+, just use the 10.8 SDK (or use the 10.9 SDK with min version set to 10.8, once you upgrade to Xcode 5). [This blog post](http://www.cocoawithlove.com/2009/09/building-for-earlier-os-versions-in.html), despite being pretty out of date, explains most of the issues. There are also a bunch of SO questions about this. And of course Apple's official [SDK Compatibility Guide](https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/cross_development/Introduction/Introduction.html). I'll try to edit a bit more into the answer as well. – abarnert Nov 09 '13 at 00:32
  • @Claudiu: I'm not sure the pre-build pygame libraries are a good idea. Last I checked, they were way out of date, and didn't even handle 64-bit Python installs (which are, of course, the default from python.org nowadays, and what you almost certainly want). – abarnert Nov 09 '13 at 00:35