# Managing shared libraries ¶

Reminder: we want to the hello executable to find the world library when it is run.

We have two cases to deal with:

• When we have just compiled the hello executable
• When we have made a package containing hello and world.

## Linux and .so ¶

This is by far the easiest case!

CMake already does The Right Thing when hello has just been compiled.

It just strips the RPATH during installation.

This is fixed by calling:



set_target_properties("${name}" PROPERTIES INSTALL_RPATH "\$ORIGIN/../lib"
)



## Windows and .dll ¶

Windows is just a bit harder. The hello.exe will be happy as soon as the world.dll is just next to it.

Since CMake knows about the dependencies of the hello project, it is easy to parse the list of hello dependencies, look for which of them are dynamic libraries, and copy them next to the executable in a “post build” command.

This is achieved by running a cmake script called. post-copy-dlls.cmake. It is was generated in the build dir of the hello and then called with correct arguments.

More specifically, the “post-copy-dlls.cmake+ we create is always the same

Here is what it looks like



set(_to_copy)

foreach(_dep ${PROJECT_DEPENDS}) list(APPEND _to_copy${_dep}_LIBRARIES)
endforeach()

file(COPY ${_in_dlls} DESTINATION${QI_SDK_DIR}/${QI_SDK_LIB}/${BUILD_TYPE})



We then add a post-build rule :



add_custom_command(TARGET ${name} POST_BUILD COMMAND${CMAKE_COMMAND}
-DBUILD_TYPE=${CMAKE_CFG_INTDIR} -DPROJECT=${_U_name}
-P ${CMAKE_BINARY_DIR}/post-copy-dlls.cmake${CMAKE_BINARY_DIR}



 CMAKE_CFG_INTDIR  is something like  \$(OutDir)  , a variable that is expanded by the native tool. In the case of visual studio, it’s the name of the current build configuration.

Remember, CMake configures one  .sln  that must be used in several build configurations.

So for instance, we will call:



c:\cmake\cmake.exe -DBUILD_TYPE=Debug -DPROJECT=HELLO -P hello\build\post-copy-dlls.cmake hello\build



When you run  cmake -P  with two arguments, the last one is the path to the cache.

This is how we can find every variable we need, like  HELLO_DEPENDS  and  WORLD_LIBRARIES  .

The last two variables we need (  PROJECT  and  BUILD_TYPE  ), are directly set on the command line.

Nice, isn’t it?

## MacOSx and .dylib ¶

MacOSx is tricky. In fact we still do not have a working implementation for the moment.

You may still need to tweak DYLD_LIBRARY_PATH from time to time.

If libworld.dylib has NOT been installed, everything works. CMake gently set the install_name_too so that hello is able to find /path/to/src/world/build/sdk/lib.

But, when libworld.dylib is installed, hello cannot find libworld.dylib, even though the linker knows the full path of libworld.dylib.

(this is different from the way ld works on linux)

This is how it works today:

• We tell cmake to always set install_name to @executable_path/../lib

• In the post-build rule of hello, we look for hello dependencies, and copy the .dlylib, so that we can have:



path/to/src/hello/build/sdk/bin/hello
path/to/src/hello/build/sdk/lib/libworld.dylib



(this is exactly the same trick as for the post-copy-dlls.cmake file.)

The only problem left is with third-party libraries: we did not know what install name tool they have chosen, nor if they used the correct linker flags....

We could try to run install_name_tool -change ... on the third party libraries, but we have to know the original install name in order to change it :/