How To use Dynamic Libraries in Xcode 3.1 (using FMOD)

Filed under Apple on Thursday, 21 August, 2008 1:12 am

I am writing this article to help people running Xcode on Mac OS X get around the dreaded FMOD dynamic libary not found error from happening at runtime:

dyld: Library not loaded: @loader_path/../Frameworks/libfmodex.dylib
Referenced from: /Users/brock/Game/Debug/mine.app/Contents/MacOS/mine
Reason: image not found

So here we go, the first step is to install FMOD Ex Programmers API. You can download it here:
http://www.fmod.org/index.php/download

Once you have downloaded it, run the FMOD Installer.
Once installed, all FMOD resources should be located:

/Developer/FMOD Programmers API/

The dynamic libraries that you will need to include with your application will be located in:

/Developer/FMOD Programmers API/api/lib/

You should drag the library you wish to use into your Xcode project"s Framework folder so that it looks like:

Picture 2.png

Once you have completed your FMOD coded application in Xcode, you will need to create a shell script that Xcode will automatically run upon completion of building your .app bundle.

If you are compiling a shell tool, which doesn"t encapsulate all the project"s code, this will still work, but you will need to modify the code below by removing the .app path stuff where appropriate.

In order to get rid of the dreaded dylib not found error, then you will need to run the otool command as well as creating a script for Xcode to run after everything is built. The otool command will tell you where your application is expecting to find the libraries and frameworks that it looks for at runtime.
So, type this:

otool -L /path/to/AppName.app/Contents/MacOS/AppName

which should produce something like:

./libfmodex.dylib (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/GLUT.framework/Versions/A/GLUT (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/OpenGL.framework/Versions/A/OpenGL (compatibility version 1.0.0, current version 1.0.0)
@executable_path/../Frameworks/SDL.framework/Versions/A/SDL (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/OpenAL.framework/Versions/A/OpenAL (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.0.0)

Notice the top line, this means that the application expects to find:
"./libfmodex.dylib". Which is our FMOD dylib file.
However this will not exist at runtime, so we have to get Xcode to copy this file into the app bundle as well as modify the binary to look in its new location:

So, in Xcode, right-click on your target and choose:

Add > New Build Phase > New Run Script Build Phase

Picture 3.png

You should see a new item under the target called "Run Script":

Picture 4.png

Now, Double-click the "Run Script" folder and paste in the following command:
WARNING! If you are copy pasting this be sure to change the the curly quotes " " into normal quotes by simply re-typing them.

mkdir "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/Frameworks"
cp -f /Developer/FMOD Programmers API/api/lib/libfmodex.dylib "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/Frameworks/libfmodex.dylib"

install_name_tool -change ./libfmodex.dylib @loader_path/../Frameworks/libfmodex.dylib "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/MacOS/$PRODUCT_NAME"

Picture 6.png

You will need to modify this script according to your own setup.
Xcode will also inform you of any errors with your script in the Build Warning and Errors window when you build your project.

You should do a clean then do a build. After the build is complete Xcode will run the script.
Step by step what this script does it:

1) Creates a new directory called "Frameworks" inside the application"s bundle
2) Copies the "libfmodex.dylib" file from the FMOD developer folder to the /Frameworks directory that was just created.
3) And lastly the install_name_tool command will modify the application binary to look for the library in the new location.

Thanks for reading my little tutorial on this. This process was really not as straight forward as it ought to be so I wanted others to benefit from this (as well as myself should I ever forget how to do this!). Any questions or if you would like me to change anything please login and leave a comment.

If you liked this article and would like to download a copy for reference you can download it:

Download a zipped iWork Pages document 834AB2CD-A0EB-40EB-B650-DD5F73B2FEAE.jpg
Download Pages Download PDF

Cheers
Brock

16 Comments »

Comment by shams

December 8, 2008 @ 11:27pm

hi!
I ve got some trouble using fmod + Qt on xCode. I was able to launch my project from xCode but it doesn't work from the finder. I tried your tips and now, it doesn't work anymore on xCode and still not in the Finder...!
Can you help me?

Comment by Brock Woolf

December 9, 2008 @ 1:08am

Shams,

It can be a challenge to get this all working. Perhaps you can email me at brock.woolf@gmail(.com) without the brackets, and I might be able to help you. If you like, you could probably zip and email me your Xcode project and I might be able to get it working, then I could email it back to you.

Brock

Comment by Coral

January 20, 2009 @ 6:29pm

Hey!
Thanks for the Great guide.

I just wanted to inform that the FMOD API folder is by default called "FMOD Programmers API Mac" and not "FMOD Programmers API" in the newest release. They added the "Mac" suffix.

I solved it but a newbie may not, so please add a note in this post to ensure minumum confusion.

And again, BIG THANKS!

Comment by Steve

February 8, 2009 @ 12:44am

Hey,
I want to use the FMOD API in my iPhone app. I have download the API for iPhone, install it, copied the libfmodex.dylib
in my app Frameworks folder, set the search Path for lib and headers and make the run script. But it doesn't works.
It could be the run script for iPhone must be another than for MacOSX.
Can you help me?
Thanks!

Comment by Brock

February 8, 2009 @ 7:00pm

@Coral:

I just wanted to inform that the FMOD API folder is by default called “FMOD Programmers API Mac” and not “FMOD Programmers API” in the newest release. They added the “Mac” suffix.

Sorry for taking so long to reply, I've been rather busy.
Thanks for your comments Coral, I was not aware of the change in the name, I will indeed change it when I get the chance.

Brock

Comment by Brock

February 8, 2009 @ 7:08pm

@Steve:


Hey,
I want to use the FMOD API in my iPhone app. I have download the API for iPhone, install it, copied the libfmodex.dylib
in my app Frameworks folder, set the search Path for lib and headers and make the run script. But it doesn’t works.
It could be the run script for iPhone must be another than for MacOSX.
Can you help me?
Thanks!

Hi Steve,
I have not done any iPhone development (yet!) but I have read around the place that the iPhone does not support dynamic libraries. The iPhone has a few funny quirks that will not work the same as developing a normal Cocoa app in Xcode. You may want to have a look around for something iPhone specific. However this could be wrong, so don't take my word as sage.

I am leaving tomorrow to do a 3 day Cocoa workshop at the University of New South Wales so I will be putting up some new Apple articles in the near future no doubt as well as some iPhone ones that may solve your problem.

Brock

Comment by satyanarayana

February 26, 2009 @ 6:57pm

Hi,

Thanks a lot for this article. It is really good. Could you please add the following description.
If it is user defined dynamic library then user has to set "install name" property to ./dynamic library name (like ./libxyz.dylib).

Comment by Sean

March 12, 2009 @ 4:07am

Hi! Great info. I was trying to use this advice with Boost and I found out that there are some limitations to this technique (at least for command line tools). For one thing, if the app is run as a script, the working directory will not (necessarily) be that of the executable, and the library will not be found.

Another option is to put dynamic libraries where they can be found e.g. /usr/local/lib. Then you can skip the copy step and just drag the libs. Of course, you would have to take this into account when deploying, but it works great for development!

If interested, I describe the steps in detail

- Sean

Comment by Brock

May 16, 2009 @ 2:30am

@Sean

Hey Sean, sorry for my late reply I have been immensely busy. Yes there are limitations to this technique, I have been told me someone one the interwebs that there is a better way to do this linking (although I have not actually been shown what it is). The advantage that this technique brings is that although it is a pain, it is a one click build solution which is what we should aim for in our development.

I am familiar with putting the libraries in the user's local library directory. I do however think this is an inferior approach because it means you have to touch a part of the system that requires admin privileges. What if another developer did the same thing with a different version of the framework? It's possible you could break another application if the frameworks are named identically. Also your uninstaller tool needs to remember to remove this directory when the user uninstalls your application. Otherwise it will take up space forever. The user will never even know it was installed there.

Those are the main reasons why I believe the framework should be bundled with the application. It binds with the Apple guidelines of a simplified "Drag and drop" install. And anyways, frameworks are usually pretty small these days.

Cheers,
Brock

Comment by Ash

May 18, 2009 @ 4:29pm

Thank you very much for the article.. its superb..

Comment by Ojaswa

July 28, 2009 @ 6:50pm

Thanks Brock!

Very helpful article indeed. you saved my time :)

Comment by Brock

July 28, 2009 @ 7:28pm

No worries guys! Just glad to help out other Mac users :D

Comment by FengShuiAvenger

August 29, 2009 @ 6:44pm

After desperately searching Apple's Mac OS X reference library, and trying numerous google searches, this article came up. Thanks for posting this, I can finally stop screaming at my monitor.

Comment by Jeremy

September 3, 2009 @ 11:23pm

@Steve

The FMOD package comes with example iPhone XCode projects which show how to set them up without the need of directly importing the dylib or making a run script. Check out the header search path and the xcconfig files.

Pingback by – Compile and Use Boost Libraries in Xcode & Visual Studio BrockWoolf.com

September 20, 2009 @ 12:52pm

[...] The actual process of scripting the dylib copy and modifying the darwin executable are already covered in another article I wrote here: How To use Dynamic Libraries in Xcode 3.1 [...]

Comment by Martin Robinson

February 28, 2010 @ 12:04am

Just trying to do this where more than one FMOD lib is used... you also need to change the library paths for the additional library linking to libfmodex.dylib. I'm using libfmodevent.dylib for example and the script then needs to be something more like below (BTW I've defined FMOD_SDK as a source tree in Xcode which is what that refers to):


mkdir "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/Frameworks"
cp -f $FMOD_SDK/fmod/api/lib/libfmodex.dylib "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/Frameworks/libfmodex.dylib"
cp -f $FMOD_SDK/fmod/fmoddesignerapi/api/lib/libfmodevent.dylib "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/Frameworks/libfmodevent.dylib"
install_name_tool -change ./libfmodex.dylib @loader_path/../Frameworks/libfmodex.dylib "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/MacOS/$PRODUCT_NAME"
install_name_tool -change ./libfmodex.dylib @loader_path/../Frameworks/libfmodex.dylib "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/Frameworks/libfmodevent.dylib"
install_name_tool -change ./libfmodevent.dylib @loader_path/../Frameworks/libfmodevent.dylib "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/MacOS/$PRODUCT_NAME"

RSS feed for comments on this post. TrackBack URI

Leave a comment

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

8) :wink: :P :D :) :o :? :( :x