Running self-compiled Panda3D without installer on OSX

I am building an OSX version for our audio engineer, this is the first time I’ve used a Mac for more than 5 minutes. I have managed to generate a build (thanks makepanda) and now I am on the next part.

What are the minimal steps needed to run my build? For example to be able to run “ppython whatever.py” where whatever.py is using Panda3D imports. Generating an installer would be the obvious way, but I would much prefer to distribute the build (to the other developers) via our svn repository along with all the scripts and assets.

On Windows this was as easy as setting the PYTHONHOME variable to Panda’s copy of Python and everything magically worked. Not sure how to do this on OSX though since it uses the python built into the OS.

Alternatively if someone could point me at the install script (or equivalent) that Panda uses is I could figure it out from that.

Pretty sure you just have to run the right version of python from wherever you put it, assuming that all of the Panda libraries and support files are also in the right place relative to it.

You might also need to set PYTHONHOME, PATH, and DYLD_LIBRARY_PATH to add the appropriate directories, though. You’ll have to experiment a bit with this.

David

I seem to have got it mostly working.
By digging around in makepanda I found out that ppython is just a symbolic link, and there is a Panda3D.pth in the site-packages folder to point python to the right place.
I can now import from panda3d.core, but trying to use anything results in an error:

ImportError: dlopen(/work/game/Panda3D-darwin/lib/libpandaexpress.dylib, 2): Library not loaded: libp3dtool.1.8.dylib
Referenced from: /work/game/Panda3D-darwin/lib/libpandaexpress.dylib
Reason: image not found

There are a bunch of calls of “install_name_tool” on the dylib files in makepanda so I think by dissecting that I will find my solution.

I suspect this is a missing third-party library that needs to be added to your DYLD_LIBRARY_PATH, or perhaps simply that /work/game/Panda3D-darwin/lib needs to be added to your DYLD_LIBRARY_PATH. Note that you have to manipulate this variable from a parent process, before the Python process starts; I’m pretty sure you cannot add directories to this path in the current process.

David

Monkeying with the code from makepanda, I ended up with this modified bit of code which when run from the root of the build will convert all the dylib files to use a relative path. This results in a more portable installation suitable for distribution in source control. I think it might not work for Panda C++ programs outside the bin directory but it works great for Python. Here it is for anyone who stumbles upon this thread:

import os

for base in os.listdir("lib"):
    if (not base.endswith(".a")):
        libname = "lib/" + base
        if (libname.endswith(".dylib") and not os.path.islink(libname)):
            os.system("install_name_tool -id @loader_path/../lib/%s %s" % (base, libname))
            os.system("otool -L %s | grep .dylib > otool-libs.txt" % libname)
            for line in open("otool-libs.txt", "r"):
                if len(line.strip()) > 0 and not line.strip().endswith(":"):
                    libdep = line.strip().split(" ", 1)[0]
                    if not libdep.startswith("/"):
                        os.system("install_name_tool -change %s @loader_path/../lib/%s %s" % (libdep, os.path.basename(libdep), libname))

for base in os.listdir("bin"):
    binname = "bin/" + base
    if (not os.path.islink(binname)):
        os.system("otool -L %s | grep .dylib > otool-libs.txt" % binname)
        for line in open("otool-libs.txt", "r"):
            if len(line.strip()) > 0 and not line.strip().endswith(":"):
                libdep = line.strip().split(" ", 1)[0]
                if not libdep.startswith("/"):
                    os.system("install_name_tool -change %s @loader_path/../lib/%s %s" % (libdep, os.path.basename(libdep), binname))

os.system('rm otool-libs.txt')