[CMake] fixup-bundle usability

Francis Giraldeau francis.giraldeau at gmail.com
Mon Feb 18 09:56:44 EST 2019


You are right, the fixup bundle is difficult to use. Here are some
undocumented tips:

Put the install(CODE) with the fixup_bundle() call in a CMakeLists.txt in
its own directory. In your main CMakeLists.txt file, add this directory
with add_subdirectory() last. This install(CODE) will run after all the
other install directive, otherwise the fixup_bundle() might run before
other targets are installed.

The main thing is to build the library path variable. Yes, this information
can be recovered from the target itself, but fixup_bundle() won't gather
that info for you. Here is an example with Qt:

get_target_property(QT_CORE_LIB Qt5::Core LOCATION)

get_filename_component(QT_RUNTIME_DIR "${QT_CORE_LIB}" DIRECTORY)

list(APPEND LIBS_PATH "${QT_RUNTIME_DIR}")


If you are using VTK, there is already a variable:

list(APPEND LIBS_PATH "${VTK_RUNTIME_LIBRARY_DIRS}")


You might as well run windeployqt (and similar tool for other platforms)
inside install(CODE) script if you have a Qt app, such that the styles and
the plugins and other stuff gets copied.

execute_process(COMMAND windeployqt.exe --release \"\${MAIN_APP}\")


Workaround wrong tool detection using MinGW on Windows:

if(WIN32 AND NOT MSVC)

  set(GP_TOOL "objdump")

endif()


install(CODE "\

...

  include(BundleUtilities)

  set(gp_tool \"${GP_TOOL}\")

  fixup_bundle(\"\${MAIN_APP}\" \"\" \"${LIBS_PATH}\")

...


And there is the escaping... You have to escape quotes inside
the script. Escape the '$' sign if you want to refer to the
variable at install time. Remember that you don't have access

to configure-time variables at install time. Unescaped '$' prefix

will be replaced by its value at configure time, somewhat like

a macro or a template.


To see the generated script, look into ${CMAKE_BINARY_DIR} with

the directory name corresponding to the CMakeLists.txt containing

the install(CODE). Example:


${CMAKE_SOURCE_DIR}/cmake/bundle/CMakeLists.txt

-> ${CMAKE_BINARY_DIR}/cmake/bundle/cmake_install.cmake


You can check the generated script, its very

handy when things go wrong.


Also, it is easier to put all libraries and binaries in their

own directory. I have this near the begining of my project's

CMakeLists.


set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)

set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)


If you have some library that you don't want in your bundle,

you might want to disable install for it, for instance,

google test:


add_subdirectory(3rdparty/googletest/ EXCLUDE_FROM_ALL)


I'm using "ntldd.exe -R" on Windows to check the dependencies manually

(its very much like ldd on Linux). It is much more handy than

dependency walker.


Fixup_bundle is not magical either. The library dependencies must be

known beforehand. It means that if you do some dlopen() tricks at

runtime, fixup_bundle() cannot know that and you will have to install

these libraries manually yourself. One notable example of this is

Intel MKL using the Single Dynamic Library (mkl_rt). Using this

library entry point simplifies the linking and will load the

best library at runtime depending on the hardware. Fixup_bundle() will

copy only mkl_rt and you have to copy the other mkl libraries to

avoid runtime error.


Fixup bundle is tricky to put in place, but having a fixed list

of libraries to copy is even more cumbersome and flaky. When

supplied with the proper directories, the bundle is right every time.


Francis


Le sam. 16 févr. 2019 à 04:04, Andreas Naumann <Andreas-Naumann at gmx.net> a
écrit :

> Dear CMakers,
>
> recently I tried to bundle an application in Windows. From the
> documentation [1] I see that I should provide the directories to the
> non-system libraries.
>
> But these information should be already in the properties of the
> targets, arent they? Is there any extension in cmake, that provides
> these paths?
>
> How do other users handle dependencies to external dlls?
>
>
> [1] https://cmake.org/cmake/help/v3.0/module/BundleUtilities.html
>
> Regards,
> Andreas
>
> --
>
> Powered by www.kitware.com
>
> Please keep messages on-topic and check the CMake FAQ at:
> http://www.cmake.org/Wiki/CMake_FAQ
>
> Kitware offers various services to support the CMake community. For more
> information on each offering, please visit:
>
> CMake Support: http://cmake.org/cmake/help/support.html
> CMake Consulting: http://cmake.org/cmake/help/consulting.html
> CMake Training Courses: http://cmake.org/cmake/help/training.html
>
> Visit other Kitware open-source projects at
> http://www.kitware.com/opensource/opensource.html
>
> Follow this link to subscribe/unsubscribe:
> https://cmake.org/mailman/listinfo/cmake
>
-- 
Francis Giraldeau
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://cmake.org/pipermail/cmake/attachments/20190218/ad5e0611/attachment-0001.html>


More information about the CMake mailing list