How to deploy Qt application on MacOS – part I

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.

External links

Leave a Reply

Your email address will not be published. Required fields are marked *