I want to release an application as a self-contained project so that anyone can download it, double click it and run it in their Macs (I’m working on Snow Leopard with XCode). The thing is this code makes use of external libraries such as FontForge and ImageMagick. The libraries are open-source so no worries on that but I don’t know how to compile/package the project so that it includes them.
I suppose that these are shared libraries right ?? You can either check if there is an option to compile them as static libraries (if size is not a problem) and link them to your app so that you dont have to package anything and just upload your application binary for download ( which will then contain all the necessary parts ) or if there is no option for static compilation you could create a Disk Image Installer with all the necessary components ( libs , binaries etc ) which then could be downloaded and installed in the system.
It shouldn’t be too hard ( my experience is only with linux ) but I think here you can find some useful infos :
Like petroskataras said, if there are static versions of the libraries available, use them and youre done.
Otherwise, check what dynamic (.dylib or .framework) versions of the libraries are available. On Mac OS X, dynamic libraries are built to be placed in a specific location on the end-users hard disk (that is, the absolute path to the location where the library will be installed is burned into the library when it is built). There is a special magic variable that one can use at the beginning of this path to make a path that is relative to the executable that uses the library, called @executable_path. Using this variable, it is possible to build dynamic libraries that are supposed to live inside the application bundle of apps that use them, instead of being placed in some global location on the hard drive. For private frameworks, the path should then be @executable_path/…/Frameworks/[frameworkname]. For private dylibs, that path is instead @executable_path/[dylibname].
Check what dynamic (.dylib or .framework) versions are available of the libraries you are interested in. If you are lucky, there are private versions available, if so just link against those versions, and then copy the .framework/.dylib to the appropriate location inside your bundle using a Run Script build phase.
If there are no private builds of the libraries available, there is still a way to make them private: there is a command-line tool called install_name_tool that can patch a framework/dylib and change the install path; this way you can convert a public library into a private one. All OF apps actually do this on Mac, check the build phases of your app target, there should be a Run Script phase that copies the fmodex dylib into the MacOS folder of the application bundle, and then uses the install_name_tool to change the dylib path to @executable_path/libfmodex.dylib. Just add your own Run Script build phase to do the same with tour other dylibs/frameworks (or add new lines in this one with your stuff).
I basically need a way to include ‘/opt/local/bin/fontforge’ and ‘/opt/local/bin/convert’ inside of the oF app. It sounds as if @executable_path is the solution, putting those executables somewhere inside the project as resources?
Sorry, I misunderstood you, I thought you had the external code in shared libraries, not in separate executables.
In that case, @executable_path is of no help to you. Instead, I would copy the needed executables to the MacOS folder inside you application bundle (using a Run Script build phase), and then run them from there at runtime. You can use CFBundleCopyAuxiliaryExecutableURL() to get the absolute paths to the executables. Something like this:
Though it seems to me that using separate executables and system() calls like this is probably a pretty slow way to do this, my guess is that it would be a lot faster (and less prone to security issues due to bringing in an entire shell every time you want to convert an image) to call a function in a shred library, if there is one available that provides the same functionality.
Hey thanks for the reply. An image is converted (ImageMagick) only when the user presses a specific key, and this is only needed every ten seconds or so. The other executable is only needed once the user wants to “save” a file so that won’t happen very often either. It is more of an experimental app that would be cool other people could sort of easily use (that is, if they have a Mac OS 10.6.8 or later and a Kinect lying around). I will look into the code you sent.
I havent used FontForge or ImageMagick, but I think it depends exactly on how theyre built. You can check that using the otool command in the terminal:
otool -D [path to the dylib/framework you want to check]
This will print out the path where this library expects to be installed. This path will be copied into your application when it is linked by Xcode.
If this path is something other than @executable_path/[dylibname] (or @executable_path/…/Frameworks/[frameworkname] for frameworks), you will want to change it.
If the path is simply ./[dylib/framework name] (just a path that points to it int he current directory), I think you can get away with just patching the dylib using install_name_tool at the end of the build process, after linking, just as all Openframeworks apps do on Mac using the Run Script build phase to patch the libfmodex.dylib (which I guess you have found and used as a template for your script above).
However, if the path contains a real path, for example to /opt/local/lib/, I think you will have to patch both the dylib and your application. See the Shared Libraries section of this page, for example: http://doc.qt.nokia.com/qq/qq09-mac-deployment.html#sharedlibraries
As an alternative to patching both the dylib and your application each time you build your app, you could make a copy of the dylib and patch that, and then link against your patched copy of the dylib when you build your app. That way, you only have to patch the dylib once (for each new version you download at least), and the app will be built with the correct dylib path from the get-go. The downside is that you will have to remember to patch the dylib manually each time you download a new copy.
Oh, and one more thing I forgot to mention: check out the man page for install_name_tool. The first parameter after the -change option should be the current install name of the library, that is the output from otool -D.
The issue I ran into was that I had ~10 dylibs many of them mutually dependant. This means I need to write the install_name_tool process many, many times. I think I will just require the user to install fontforge, potrace and imagemagick (although most OS X versions have it by default) on their own, before using my app for now.