{{{ #!forumlinks }}} = Building binaries on Mac OS/X = Compiling sources into binaries on Mac OS/X, and getting everything right when creating an application bundle (= a {{{.app}}} directory which represents an application), there are many details that might frustrate the casual coder or are not that easy to find information about. I've described some of them here, in any order. Use the search function of your browser, etc. == Which Python version == Several python versions are bugged or behave annoyingly when compiling binaries. For instance, by default, any Universal Binary version of Python will insist on creating fat binaries even if we want to create modules for only the current platform. The build process will fail by lack of dependencies for the other platform. To fix this, set {{{MACOSX_DEVELOPMENT_TARGET=10.3}}} to force compiling for OS/X 10.3. However, some Python versions are bugged in the handling of this variable (in {{{distutils/util.py}}} around line 110). Since this keeps on changing between versions, I often use Python 2.3 (non-fat, shipped with Mac OS/X) to build the binaries. The only downside is a warning when loading the libraries with Python 2.4/2.5. == Dependencies == 1. Be careful not to ship one of the following prefixes for your dependencies, or any other custom installed library that the end user does not have: a. {{{/usr/local/}}}, containing manually installed applications a. {{{/opt/local/}}}, containing applications installed through {{{MacPorts}}} a. {{{/sw/}}}, containing applications installed through {{{Fink}}} a. {{{/Users/}}}, containing applications installed with some {{{./configure --prefix=/Users/}}} script. 1. Dependencies can have the form of {{{@executable_path/....}}}, which only makes sense inside an application bundle. {{{@executable_path}}} points to {{{APPNAME.app/Contents/MacOS}}}. Note that libraries are often installed in {{{APPNAME.app/Contents/Frameworks}}}, making the prefix {{{@executable_path/../Frameworks/}}} common. 1. Use the {{{DYLD_LIBRARY_PATH}}} environment variable for a colon-seperated list of directories to look for libraries. Ugly when shipping binaries, but handy when debugging or running a checked-out source from the command line. "man dyld" for more information about. 1. To support older versions of OS/X, set the {{{MACOSX_DEPLOYMENT_TARGET}}} environment variable to, for instance, {{{10.3}}} when building with gcc or Python. 1. Use the {{{lipo}}} tool with {{{grep}}} to see what files are open by the running applications. Useful for checking whether an application really doesn't use the wrong binaries. == Library analysis tools == Dynamic libraries come with the {{{.dylib}}} extension, or with an {{{.so}}} extension if they were badly ported from Linux. Most of the following tools work on executables as well. 1. {{{otool -L libname.dylib}}} to view which libraries are required for libname to load. Note that Mac OS/X, unlike Linux, often uses absolute paths. See the dependencies section for more information. 1. {{{install_name_tool -change old new libname.dylib}}} changes a dependency from "old" to "new" in libname.dylib. Succeeds whether the dependency is found or not. 1. {{{strip -x libname.dylib}}} removes debugging symbols and the like, to save space without changing the functionality. Can save quite a lot. Furthermore, there are tools to work with fat binaries (Universal Binaries). These binaries contain object code for both PPC and i386. 1. {{{lipo -info libname.dylib}}} prints which platforms are represented in the binary. Note that some compilation processes insert stubs for one of the platforms. Use {{{-detailed_info}}} with lipo to see the respective sizes for ppc and i386. 1. {{{lipo -thin i386 libname.dylib -output libname-i386.dylib}}} to extract the i386 object code out of a fat library. Use a similar syntax for ppc. Fails on a non-fat library. Use the [source:abc/branches/mainbranch/Tribler/Player/Build/Mac/smart_lipo_thin smart_lipo_thin] script to be able to thin a file, keeping the same name, and can be run on anything. 1. {{{lipo -create libname-i386.dylib libname-ppc.dylib -output libname.dylib}}} to merge two single-platform libraries into an universal library. Use the [source:abc/branches/mainbranch/Tribler/Player/Build/Mac/smart_lipo_thin smart_lipo_merge] script to be able to merge two libraries regardless of whether they happen to have stubs for another architecture. == Disk image tools == Disk images ({{{.dmg}}} files) are similar to {{{.iso}}} files in that they contain a mountable directory structure within a single container. First, some handy tools: 1. {{{hdiutil create -srcfolder /dir/containing/contents -format UDRW -scrub -volname "Volume Name" diskimage.dmg}}} to create a r/w disk image with a certain volume name and contents. UDRW=r/w, UDZO=r/o, UDCO=r/o compressed. 1. {{{hdiutil attach -readwrite -noverify -noautoopen diskimage.dmg /my/mountpoint}}} to mount a disk image. 1. {{{hdiutil detach /my/mountpoint}}} to unmount a disk image. Can fail if the image is busy. 1. {{{hdiutil convert diskimage.dmg -format UDZO -imagekey zlib-level=9 -o diskimage-readonly.dmg}}} to convert an unmounted disk image to a proper read-only one, and to compress it. 1. To add an EULA, see the EULA section. Note that you might get the error: {{{ hdiutil: create failed - Device not configured }}} According to {{{man hdiutil}}}, this can be caused by running inside a reattached {{{screen}}} session and other detached shells. On a mounted image, you can do the following: 1. {{{bless --folder /my/mountpoint --openfolder /my/mountpoint}}} to let the root folder open when the disk image is opened. {{{bless}}} controls what happens when the disk image is opened. Some source recommended a {{{sleep 1}}} command after {{{bless}}} to make sure it completed. 1. {{{/Developer/Tools/SetFile -a C /my/mountpoint}}} to enable the use of the volume icon (the icon of the disk image itself). Call the icon {{{.VolumeIcon.icns}}} and put it in the root directory. You can edit the icon file with {{{/Developer/Applications/Utilities/Icon Composer.app}}}. Make sure to include at least the highest resolution icon since it's really used. == EULA == Mac OS/X can present the user with an EULA when the disk image is opened. This EULA is stored in the resource fork of the disk image. Special care is needed, as the EULA has special file format and subversion cannot be used to store resource forks. An example EULA file can be found in the [ftp://ftp.apple.com/developer/Development_Kits/SLAs_for_UDIFs_1.0.dmg SLA SDK] of Apple, and is called {{{SLAResources}}}. We'll first extract the EULA from the example file's resource fork: {{{ cp SLAResources/rsrc SLAResources.rsrc }}} The file {{{SLAResources.rsrc}}} can be stored in Subversion. To edit it, use for example [http://resknife.sourceforge.net/ RezKnife]. Finally, to attach the EULA to a disk image, the image needs to be unflattened (i.e. data/resource forks restored), but it needs to be flattened again in the end: {{{ hdiutil unflatten Tribler.dmg /Developer/Tools/DeRez -useDF SLAResources.rsrc > sla.r /Developer/Tools/Rez -a sla.r -o Tribler.dmg hdiutil flatten Tribler.dmg }}} I used this on read-only disk image.