[SOLVED] OSX Deployment Fatal Error with DyLib -- Library Not Loaded / Image Not Found
-
On Mac OSX with QT 5.5, I've got a Qt app that calls a custom dylib that I coded.
I can get my app and dylib to run just fine if I do it from QT Creator, and can get it to run from command line if I open a terminal and "cd" into the deployment's Content/MacOS directory, and then run it with "./LibraryTester". It finds that dylib just fine because it's in the same directory as the executable "LibraryTester".
However, when trying to use this in production, it jams with a fatal error. How do I get past this "library not loaded / image not found" deployment error when doubleclicking the following LibraryTester.app?
/Users/mike/Projects/build-LibraryTester-Desktop_Qt_5_5_0_clang_64bit-Debug/LibraryTester.app
Dyld Error Message:
Library not loaded: mylib.1.dylib
Referenced from: /Users/USER/*/LibraryTester.app/Contents/MacOS/LibraryTester
Reason: image not foundIt's like it can't find the file path for mylib.1.dylib.
-
Note that I just discovered that if I run the following command, I can make the .app file run:
install_name_tool LibraryTester -change mylib.1.dylib @loader_path/mylib.1.dylib
However, I want this to be automated so that I don't have to keep typing this when rebuilding the LibraryTester application.
-
Hi,
You are probably looking for macdeployqt
-
Yes, macdeployqt can work for final deployment. However, if you want it on the fly for testing purposes, so that it works without having to run command line tools each time you compile your main application, I found the solution from hints left here:
http://stackoverflow.com/a/15106738/105539
The fix is that when I compile my dylib file, I need to use install_name_tool on it so that it knows to load from either the @rpath or the @loader_path. The @loader_path would be inside the .app under Contents/MacOS. The @rpath would be inside the .app under Contents/Frameworks.
At that point, when the main executable project is compiled with this adjusted dylib file, it will always know the proper path and I won't need to keep doing install_name_tool on the main executable project.
Restating this so that I'm more clear:
Let's say you create a custom dylib named mylib.1.dylib. Let's say your main application that will use this dylib is called LibraryTester. Let's say you want to put mylib.1.dylib in the same directory as the LibraryTester executable, which would be Contents/MacOS.
Step 1
Compile your dylib file like you normally would. This would be a normal Qt/C++ external, dynamic shared library project.
Step 2
Before you include this in your main application project, go to command line in the directory where your compiled dylib is located, and use
install_name_tool
like so:install_name_tool -id @loader_path/mylib.1.dylib mylib.1.dylib
(Sidebar: If you used
@rpath
instead of@loader_path
, then later on in these instructions where I specify Contents/MacOS, you'd want to swap that with Contents/Frameworks.)Step 3
Copy mylib.1.dylib now to your main application project folder.
Step 4
Add (or adjust) the following in your .pro file of that main application project (LibraryTester, in this example):
macx: LIBS += -L$$PWD/ -lmylib.1 INCLUDEPATH += $$PWD/ DEPENDPATH += $$PWD/ mac { Resources.files += mylib.1.dylib # repeat with Resources.files += blah for anything else you want in this folder Resources.path = Contents/MacOS QMAKE_BUNDLE_DATA += Resources }
Step 5
Copy the header of your dylib file project into this main application project. So, in this case, I would be copying mylib.h into the LibraryTester project folder.
Step 6
In the header file of your main application, add a line to reference this new dylib:
#include mylib.h
Step 7
Run qmake on your main application project, from the Build menu in Qt Creator.
Step 8
Edit the code of your main application so that you now use this new dynamic library.
Step 9
From the Build menu, choose Run. This compiles and runs your application. You can then close the main application window because that was only to get this build folder ready.
Step 10
Now look for where it compiled this project -- where it placed the LibraryTester.app file, using Mac Finder. Rightclick and choose Show Package Contents. Go into Contents/MacOS, and you should see your dylib already copied there. If you opened a command prompt there and did:
otool -L LibraryTester
It would show you @loader_path/mylib.1.dylib instead of just mylib.1.dylib. If it doesn't, then you missed a step.
Step 11
You can now go back and doubleclick LibraryTester.app and instead of the application crashing because it can't find your custom dylib, it will find it properly.
Now, you still need to do macdeployqt when you finally want to deploy your application in production. However, this will let you see what your app might run like before it goes into production, ensuring that things will hook up properly.
-
You can also set DYLD_FRAMEWORK_PATH before launching your application