0
0

Howdy there! I’m the guy from Gaijin Games who is taking care of most of the FMOD related stuff for our project on multiple platforms, and on OS X we ran into a doozy that took some research to overcome. Our solution is below, but as a pre-amble, we’d like to ask:

How did you not run into this problem? Is there an easier way to set up the project?

I was reminded because I have another couple of bugs to post, and I’m trying to repro them using your api example source files, and I can’t build your examples in XCode without having to use this trick to [b:19wky2t8]alter the install names of the binaries you distribute[/b:19wky2t8]. Which seems like a strange requirement to get things to work.


When trying to dynamically to link FMOD libs into our game on startup we were hit by this error:

[quote:19wky2t8]
dyld: Library not loaded: ./libfmodex.dylib
Referenced from: ~/Library/Developer/Xcode/DerivedData/FMODLoadExample-hjigzjbrivipgbadmtzttieqzhqv/Build/Products/Debug/FMODLoadExample
Reason: image not found
[/quote:19wky2t8]

At first this was baffling, as the fmod binaries were placed in the usual place where linked binaries go in an app bundle. With some playing around, we found that placing the binaries in the working directory instead would cause everything to run fine, but our working directory is reserved for the data we need to make our game run (which gets deleted and refreshed constantly), and the idea of putting redistributable dylibs in the data folder instead of the app bundle struck us as unsavory.

And after some researching (the crucial documents are [url=http://stackoverflow.com/questions/5522126/dyld-not-able-to-load-dylibs:19wky2t8]here[/url:19wky2t8] and [url=http://lapcatsoftware.com/blog/2007/08/11/embedding-frameworks-in-loadable-bundles/:19wky2t8]here[/url:19wky2t8]) we realized that we had to use otool and install_name_tool to alter the install names of the FMOD libs.

otool will tell you the current install names and paths embedded in the library, which, coming from other spaces, is a bizarre concept. In this case, running otool on the libfmodex.dylib will give you this:

[quote:19wky2t8]
[b:19wky2t8]otool -L libfmodex.dylib[/b:19wky2t8]
libfmodex.dylib:
[i:19wky2t8]./libfmodex.dylib (compatibility version 1.0.0, current version 1.0.0)[/i:19wky2t8]
/System/Library/Frameworks/Carbon.framework/Versions/A/Carbon (compatibility version 2.0.0, current version 136.0.0)
/System/Library/Frameworks/AudioUnit.framework/Versions/A/AudioUnit (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/CoreAudio.framework/Versions/A/CoreAudio (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 7.4.0)
/usr/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 111.1.4)
/System/Library/Frameworks/CoreServices.framework/Versions/A/CoreServices (compatibility version 1.0.0, current version 32.0.0)
/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 476.19.0)
[/quote:19wky2t8]

That initial [i:19wky2t8]./libfmodex.dylib[/i:19wky2t8] is the problem that we need to solve. See the linked documents above for the full explanation, but the short of it is that due to some weird unixy legacy with different applications relying on different versions of the same system libs (which often live in a system folder, a la Window’s former DLL-Hell), there arose a convention that the linker would tell the application the path of the dylib that you were linking against, using [b:19wky2t8]absolute path information from the dylib itself[/b:19wky2t8].

This mostly works when dynamically linking against some OS X library, but for third party libs like FMOD, this doesn’t work so well, because who knows where an application using FMOD will be installed, and where users would install common FMOD dylibs if they so wanted to do so? That this is an issue is frankly bizarre to me, but, hey, I’m in Rome, doin’ the Roman thing. There are a few dynamic linking keywords that were then created to aid such developers, and there are two that suit our needs – either [b:19wky2t8]@executable_path[/b:19wky2t8], which will dynamically substitute the full path to the application wanting to dynamically link (using from deep with in the bowels of the app bundle); or [b:19wky2t8]@loader_path[/b:19wky2t8], which is the dynamic path to the root of the app bundle. Since we are dealing with binary code here, it makes sense for us to put the FMOD dylibs right next to the executable object (i.e. at @executable_path/); but the other option (of something like @loader_path/Contents/Resources/) might make sense if you want to treat dylibs as resources.

Using install_name_tool is how you deal with this:

[quote:19wky2t8]
install_name_tool -id "@executable_path/libfmodex.dylib" libfmodex.dylib
[/quote:19wky2t8]

The FMOD Event dylibs require a further step, because if you otool them, you get the following out of them:

[quote:19wky2t8]
[b:19wky2t8]otool -L libfmodevent.dylib[/b:19wky2t8]
libfmodevent.dylib:
[i:19wky2t8]./libfmodevent.dylib (compatibility version 1.0.0, current version 1.0.0)[/i:19wky2t8]
/System/Library/Frameworks/Carbon.framework/Versions/A/Carbon (compatibility version 2.0.0, current version 136.0.0)
[i:19wky2t8]./libfmodex.dylib (compatibility version 1.0.0, current version 1.0.0)[/i:19wky2t8]
/System/Library/Frameworks/CoreAudio.framework/Versions/A/CoreAudio (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 7.4.0)
/usr/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 111.1.4)
/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 476.19.0)
[/quote:19wky2t8]

which tells us that not only the install name is bad, but the install dependency path is also relying on a bad install name from the fmodex.dylib that we fixed above.

[quote:19wky2t8]
install_name_tool -id "@executable_path/libfmodevent.dylib" libfmodevent.dylib
install_name_tool -change "./libfmodex.dylib" "@executable_path/libfmodex.dylib" libfmodevent.dylib
[/quote:19wky2t8]

  • You must to post comments
0
0

Thanks for all the details, I’m sure others new to Mac dylibs will appreciate the information here.

Unfortunately install_name_tool is a necessary aspect of using dynamic library use on Mac. We don’t use any of the special names like @executable_path because they can cause their own issues. It’s expected that most developers will include a couple of lines for doing install_name_tool to direct your app executable to any dependant libraries. We certainly have to do this kind of thing for our Mac version of FMOD Designer when using other 3rd party libs.

  • You must to post comments
0
0

Ah. Darn. Thanks!

  • You must to post comments
Showing 2 results
Your Answer

Please first to submit.