Using the Boost libraries with QtCreator on OSX
Now that we know where the libraries have to go and how the executable and each library must be prepared, so that everything works together. The problem is here that I certainly don't want to do those necessary steps by hand. On the other hand I ask myself if there is really a need to change the information in the libraries itself? How to put all that together in the application bundle in a way that works smooth with QtCreator?
First thing I will try is linking the application in way that the path information AKA @executable_path/../Frameworks
is already in the binary, so that I don't need to fiddle around with install_name_tool
after each new compile/link process. Last time I saw
QMAKE_LFLAGS_SONAME = -Wl,-install_name,@executable_path/../Frameworks/
I didn't know what that was all about. All compiled code pieces are glued together from the linker, hence this could be a linker option. I read the qmake Variable Reference
again
This variable specifies the link flags to set the name of shared objects, such as .so or .dll. The value of this variable is typically handled by qmake or qmake.conf and rarely needs to be modified.
This time I didn't miss it. Link is the hint. Let's look in the man page of ld
(the linker).
-install_name name
Sets an internal "install path" (LC_ID_DYLIB) in a dynamic library. Any clients linked
against the library will record that path as the way dyld should locate this library. If
this option is not specified, then the -o path will be used. This option is also called
-dylib_install_name for compatibility.
No talking about -Wl
in the man page. Maybe that goes for other linkers and/or other operating systems. (Update: in the meanwhile I've learned that this is a compiler flag for linker options)
I've decided to add
QMAKE_LFLAGS_SONAME = -install_name,@executable_path/../Frameworks/
and ran qmake
and look into the produced Makefile
.
First thing I notice is
LFLAGS = -headerpad_max_install_names -arch x86_64 -Xarch_x86_64 -mmacosx-version-min=10.5
-headerpad_max_install_names
is used, that way everything is compiled with enough space in the files to change the path information with install_name_tool
afterwards.
Here is the call of the linker:
$(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJCOMP) $(LIBS)
Apparently there is no way to get the QMAKE_LFLAGS_SONAME
variable working. Maybe I am doing it wrong or it is just a bug. That's something I'm going to ask the Qt-Project soon.
For every library with a valid install_name you can use macdeployqt
. It does all the needed steps.
QMAKE_POST_LINK += ;/Developer/Tools/Qt/macdeployqt $${OUT_PWD}/$${TARGET}.app -no-strip
On the positive side is the (intentional) handling of all dependent libraries, that means every library our new executable depends on is copied to the Frameworks
directory and the install_name
is corrected in the library and in the executable. That includes the Qt libraries, this way the application bundle can be transferred to another Mac without having Qt installed. Perfect!
But it also stumbles on an invalid install_name, so we have to prepend some stuff to copy the prepared boost libraries and do the adjustments with the install_name.
QMAKE_POST_LINK += ;cp -n $${PWD}/osx/libboost_filesystem.dylib $${OUT_PWD}/$${TARGET}.app/Contents/Frameworks/
QMAKE_POST_LINK += ;cp -n $${PWD}/osx/libboost_system.dylib $${OUT_PWD}/$${TARGET}.app/Contents/Frameworks/
QMAKE_POST_LINK += ;/usr/bin/install_name_tool -change \"libboost_filesystem.dylib\" \"@executable_path/../Frameworks/libboost_filesystem.dylib\" $${OUT_PWD}/$${TARGET}.app/Contents/MacOS/$${TARGET}
QMAKE_POST_LINK += ;/usr/bin/install_name_tool -change \"libboost_system.dylib\" \"@executable_path/../Frameworks/libboost_system.dylib\" $${OUT_PWD}/$${TARGET}.app/Contents/MacOS/$${TARGET}
In retrospective it seems easier to put change the install_name of the Boost libraries and also use the macdeployqt
tool. Perfect would be a way to compile the Boost libraries in a way that doesn't need any work afterwards. Future will tell...