As I wrote yesterday, I found the way how to proceed deployment on the Linux system. Today I have to manage it the same on the MacOS systems.
Note: the simplest way is introduced in the second part of this article.
The first usefull command for tracking dependencies between your application and other shared libraries is otool:
#path to executable, not .App directory! otool -L Application.app/Contents/MacOS/AppExecutable
Now we can see paths to our libraries. The bad news is that MacOS doesn’t have any -RPATH and $ORIGIN. The good news is utility install_name_tool and variable @executable_path which works similar like $ORIGIN.
Note: For newer versions of MacOS there are more variables like @executable_path. On version 10.4 was introduced @loader_path and on version 10.5 apple introduce @rpath variable.
The step-by-step solution
As first step it’s necessary to upload all dependent libraries directly to the Application.app/Contents/MacOS/. For list all required files use otool:
cd Application.app/Contents/MacOS otool -L AppExecutable
When we have copied all libraries, we need to change paths for and in all libraries.
Here is example how to set libxml2 library. As first step we will check how is library referred.
$user otool -L AtomixDevelopment AtomixDevelopment: libboost_iostreams.dylib (compatibility version 0.0.0, current version 0.0.0) libboost_filesystem.dylib (compatibility version 0.0.0, current version 0.0.0) /Users/User/dev/SharedLibraries/libxml/lib/libxml2.2.dylib (compatibility version 10.0.0, current version 10.8.0) /Users/User/dev/SharedLibraries/libxslt/lib/libxslt.1.dylib (compatibility version 3.0.0, current version 3.26.0) /Users/User/dev/SharedLibraries/libxslt/lib/libexslt.0.dylib (compatibility version 9.0.0, current version 9.15.0)
And Library:
User$ otool -L libxml2.2.dylib libxml2.2.dylib: /Users/User/dev/SharedLibraries/libxml/lib/libxml2.2.dylib (compatibility version 10.0.0, current version 10.8.0) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0) /usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.5) /usr/lib/libiconv.2.dylib (compatibility version 7.0.0, current version 7.0.0)
When we checked libxml2.2.dylib library with otool, we can see that library has hardocoded our development path. This isn’t good ;-). So we now change this value to path relative to the executable and again verify this inner path.
install_name_tool -id "@loader_path/libxml2.2.dylib" libxml2.2.dylib otool -L libxml2.2.dylib libxml2.2.dylib: @loader_path/libxml2.2.dylib (compatibility version 10.0.0, current version 10.8.0) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0) /usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.5) /usr/lib/libiconv.2.dylib (compatibility version 7.0.0, current version 7.0.0)
As you can see, now is path (first line) set up to reffer @loader_path/libxml2.2.dylib. It’s correct now. As second step we have to update path in our executable, because also there is path hardcoded to our library repository.
install_name_tool -change "/Users/User/dev/ExternalLibraries/../SharedLibraries/libxml/lib/libxml2.2.dylib" "@loader_path/libxml2.2.dylib" AtomixDevelopment otool -L AtomixDevelopment AtomixDevelopment: libboost_iostreams.dylib (compatibility version 0.0.0, current version 0.0.0) libboost_filesystem.dylib (compatibility version 0.0.0, current version 0.0.0) @loader_path/libxml2.2.dylib (compatibility version 10.0.0, current version 10.8.0) ...
So, now we have changed also path in our executable. And now we need to do all these steps for all libraries….. ;-).
Notes
To follow the MacOS application convention it’s better to place libraries to folder Application.app/Contents/Frameworks. Here is a directory schema for Qt example application plugAndPaint.
Leave a Reply