<div dir="ltr">You are right, the fixup bundle is difficult to use. Here are some undocumented tips:<div><br></div><div>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.</div><div><br></div><div>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: </div><div><br></div><div><div><pre style="margin-top:0px;margin-bottom:0px"><span style="font-style:italic;color:rgb(69,198,214)">get_target_property</span>(QT_CORE_LIB<span style="color:rgb(190,192,194)"> </span>Qt5::Core<span style="color:rgb(190,192,194)"> </span>LOCATION)</pre><pre style="margin-top:0px;margin-bottom:0px"><span style="font-style:italic;color:rgb(69,198,214)">get_filename_component</span>(QT_RUNTIME_DIR<span style="color:rgb(190,192,194)"> </span><span style="color:rgb(214,149,69)">"</span><span style="color:rgb(138,96,44)">${QT_CORE_LIB}</span><span style="color:rgb(214,149,69)">"</span><span style="color:rgb(190,192,194)"> </span>DIRECTORY)</pre><pre style="margin-top:0px;margin-bottom:0px"><span style="font-style:italic;color:rgb(69,198,214)">list</span>(APPEND<span style="color:rgb(190,192,194)"> </span>LIBS_PATH<span style="color:rgb(190,192,194)"> </span><span style="color:rgb(214,149,69)">"</span><span style="color:rgb(138,96,44)">${QT_RUNTIME_DIR}</span><span style="color:rgb(214,149,69)">"</span>)</pre></div><div><br></div></div><div>If you are using VTK, there is already a variable:<br></div><div><div><pre style="margin-top:0px;margin-bottom:0px"><span style="font-style:italic;color:rgb(69,198,214)">list</span>(APPEND<span style="color:rgb(190,192,194)"> </span>LIBS_PATH<span style="color:rgb(190,192,194)"> </span><span style="color:rgb(214,149,69)">"</span><span style="color:rgb(138,96,44)">${VTK_RUNTIME_LIBRARY_DIRS}</span><span style="color:rgb(214,149,69)">"</span>)</pre></div><div><br></div><div>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. <br></div><br class="inbox-inbox-Apple-interchange-newline"></div><div><pre style="margin-top:0px;margin-bottom:0px"><span style="color:rgb(214,149,69)">execute_process(COMMAND</span><span style="color:rgb(190,192,194)"> </span><span style="color:rgb(214,149,69)">windeployqt.exe</span><span style="color:rgb(190,192,194)"> </span><span style="color:rgb(214,149,69)">--release</span><span style="color:rgb(190,192,194)"> </span><span style="color:rgb(214,149,69)">\"\${MAIN_APP}\")</span></pre></div><div><br></div><div>Workaround wrong tool detection using MinGW on Windows:<br><pre style="margin-top:0px;margin-bottom:0px"><span style="font-style:italic;color:rgb(69,198,214)">if</span>(WIN32<span style="color:rgb(190,192,194)"> </span>AND<span style="color:rgb(190,192,194)"> </span>NOT<span style="color:rgb(190,192,194)"> </span><span style="color:rgb(192,144,80)">MSVC</span>)</pre>
<pre style="margin-top:0px;margin-bottom:0px"><span style="color:rgb(190,192,194)"> </span><span style="font-style:italic;color:rgb(69,198,214)">set</span>(GP_TOOL<span style="color:rgb(190,192,194)"> </span><span style="color:rgb(214,149,69)">"objdump"</span>)</pre>
<pre style="margin-top:0px;margin-bottom:0px"><span style="font-style:italic;color:rgb(69,198,214)">endif</span>()</pre><pre style="margin-top:0px;margin-bottom:0px"><br></pre><pre style="margin-top:0px;margin-bottom:0px">install(CODE "\</pre><pre style="margin-top:0px;margin-bottom:0px">...</pre><div><pre style="margin-top:0px;margin-bottom:0px"><span style="color:rgb(190,192,194)"> </span><span style="color:rgb(214,149,69)">include(BundleUtilities)</span></pre>
<pre style="margin-top:0px;margin-bottom:0px"><span style="color:rgb(190,192,194)"> </span><span style="color:rgb(214,149,69)">set(gp_tool</span><span style="color:rgb(190,192,194)"> </span><span style="color:rgb(214,149,69)">\"</span><span style="color:rgb(138,96,44)">${GP_TOOL}</span><span style="color:rgb(214,149,69)">\")</span></pre><pre style="margin-top:0px;margin-bottom:0px"><span style="color:rgb(214,149,69)"> </span>fixup_bundle(\"\${MAIN_APP}\"<span style="font-family:sans-serif;color:rgb(190,192,194)"> </span><span style="font-family:sans-serif;color:rgb(214,149,69)">\"\"</span><span style="font-family:sans-serif;color:rgb(190,192,194)"> </span><span style="font-family:sans-serif;color:rgb(214,149,69)">\"</span><span style="font-family:sans-serif;color:rgb(138,96,44)">${LIBS_PATH}</span><span style="font-family:sans-serif;color:rgb(214,149,69)">\")</span></pre><pre style="margin-top:0px;margin-bottom:0px"><font color="#d69545">...</font></pre><pre style="margin-top:0px;margin-bottom:0px"><font color="#d69545"><br></font></pre><pre style="margin-top:0px;margin-bottom:0px">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</pre><pre style="margin-top:0px;margin-bottom:0px">to configure-time variables at install time. Unescaped '$' prefix</pre><pre style="margin-top:0px;margin-bottom:0px">will be replaced by its value at configure time, somewhat like</pre><pre style="margin-top:0px;margin-bottom:0px">a macro or a template.</pre><div><br></div><pre style="margin-top:0px;margin-bottom:0px">To see the generated script, look into ${CMAKE_BINARY_DIR} with</pre><pre style="margin-top:0px;margin-bottom:0px">the directory name corresponding to the CMakeLists.txt containing</pre><pre style="margin-top:0px;margin-bottom:0px">the install(CODE). Example:</pre><pre style="margin-top:0px;margin-bottom:0px"><br></pre><pre style="margin-top:0px;margin-bottom:0px">${CMAKE_SOURCE_DIR}/cmake/bundle/CMakeLists.txt </pre><pre style="margin-top:0px;margin-bottom:0px">-> ${CMAKE_BINARY_DIR}/cmake/bundle/cmake_install.cmake</pre><pre style="margin-top:0px;margin-bottom:0px"><br></pre><pre style="margin-top:0px;margin-bottom:0px">You can check the generated script, its very</pre><pre style="margin-top:0px;margin-bottom:0px">handy when things go wrong.</pre><pre style="margin-top:0px;margin-bottom:0px"><br></pre><pre style="margin-top:0px;margin-bottom:0px">Also, it is easier to put all libraries and binaries in their</pre><pre style="margin-top:0px;margin-bottom:0px">own directory. I have this near the begining of my project's</pre><pre style="margin-top:0px;margin-bottom:0px">CMakeLists.</pre><pre style="margin-top:0px;margin-bottom:0px"><br></pre><pre style="margin-top:0px;margin-bottom:0px"><pre style="margin-top:0px;margin-bottom:0px"><span style="font-style:italic;color:rgb(69,198,214)">set</span>(<span style="color:rgb(192,144,80)">CMAKE_ARCHIVE_OUTPUT_DIRECTORY</span><span style="color:rgb(190,192,194)"> </span><span style="color:rgb(138,96,44)">${</span><span style="color:rgb(192,144,80)">CMAKE_BINARY_DIR</span><span style="color:rgb(138,96,44)">}</span>/lib)</pre><pre style="margin-top:0px;margin-bottom:0px"><span style="font-style:italic;color:rgb(69,198,214)">set</span>(<span style="color:rgb(192,144,80)">CMAKE_LIBRARY_OUTPUT_DIRECTORY</span><span style="color:rgb(190,192,194)"> </span><span style="color:rgb(138,96,44)">${</span><span style="color:rgb(192,144,80)">CMAKE_BINARY_DIR</span><span style="color:rgb(138,96,44)">}</span>/lib)</pre><pre style="margin-top:0px;margin-bottom:0px"><span style="font-style:italic;color:rgb(69,198,214)">set</span>(<span style="color:rgb(192,144,80)">CMAKE_RUNTIME_OUTPUT_DIRECTORY</span><span style="color:rgb(190,192,194)"> </span><span style="color:rgb(138,96,44)">${</span><span style="color:rgb(192,144,80)">CMAKE_BINARY_DIR</span><span style="color:rgb(138,96,44)">}</span>/bin)</pre></pre><pre style="margin-top:0px;margin-bottom:0px"><br></pre><pre style="margin-top:0px;margin-bottom:0px">If you have some library that you don't want in your bundle,</pre><pre style="margin-top:0px;margin-bottom:0px">you might want to disable install for it, for instance,</pre><pre style="margin-top:0px;margin-bottom:0px">google test:</pre><pre style="margin-top:0px;margin-bottom:0px"><br></pre><pre style="margin-top:0px;margin-bottom:0px"><span style="font-style:italic;color:rgb(69,198,214)">add_subdirectory</span>(3rdparty/googletest/<span style="color:rgb(190,192,194)"> </span>EXCLUDE_FROM_ALL)</pre><pre style="margin-top:0px;margin-bottom:0px"><br></pre><pre style="margin-top:0px;margin-bottom:0px">I'm using "ntldd.exe -R" on Windows to check the dependencies manually<br></pre><pre style="margin-top:0px;margin-bottom:0px">(its very much like ldd on Linux). It is much more handy than</pre><pre style="margin-top:0px;margin-bottom:0px">dependency walker.</pre><pre style="margin-top:0px;margin-bottom:0px"><br></pre><pre style="margin-top:0px;margin-bottom:0px">Fixup_bundle is not magical either. The library dependencies must be</pre><pre style="margin-top:0px;margin-bottom:0px">known beforehand. It means that if you do some dlopen() tricks at</pre><pre style="margin-top:0px;margin-bottom:0px">runtime, fixup_bundle() cannot know that and you will have to install</pre><pre style="margin-top:0px;margin-bottom:0px">these libraries manually yourself. One notable example of this is</pre><pre style="margin-top:0px;margin-bottom:0px">Intel MKL using the Single Dynamic Library (mkl_rt). Using this</pre><pre style="margin-top:0px;margin-bottom:0px">library entry point simplifies the linking and will load the</pre><pre style="margin-top:0px;margin-bottom:0px">best library at runtime depending on the hardware. Fixup_bundle() will</pre><pre style="margin-top:0px;margin-bottom:0px">copy only mkl_rt and you have to copy the other mkl libraries to</pre><pre style="margin-top:0px;margin-bottom:0px">avoid runtime error.</pre><pre style="margin-top:0px;margin-bottom:0px"><br></pre><pre style="margin-top:0px;margin-bottom:0px"><pre style="margin-top:0px;margin-bottom:0px">Fixup bundle is tricky to put in place, but having a fixed list</pre><pre style="margin-top:0px;margin-bottom:0px">of libraries to copy is even more cumbersome and flaky. When</pre><pre style="margin-top:0px;margin-bottom:0px">supplied with the proper directories, the bundle is right every time.</pre></pre><pre style="margin-top:0px;margin-bottom:0px"><br></pre><pre style="margin-top:0px;margin-bottom:0px">Francis</pre><pre style="margin-top:0px;margin-bottom:0px"><br></pre></div><div class="gmail_quote"><div dir="ltr" class="gmail_attr">Le sam. 16 févr. 2019 à 04:04, Andreas Naumann <<a href="mailto:Andreas-Naumann@gmx.net">Andreas-Naumann@gmx.net</a>> a écrit :<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Dear CMakers,<br>
<br>
recently I tried to bundle an application in Windows. From the <br>
documentation [1] I see that I should provide the directories to the <br>
non-system libraries.<br>
<br>
But these information should be already in the properties of the <br>
targets, arent they? Is there any extension in cmake, that provides <br>
these paths?<br>
<br>
How do other users handle dependencies to external dlls?<br>
<br>
<br>
[1] <a href="https://cmake.org/cmake/help/v3.0/module/BundleUtilities.html" rel="noreferrer" target="_blank">https://cmake.org/cmake/help/v3.0/module/BundleUtilities.html</a><br>
<br>
Regards,<br>
Andreas<br>
<br>
-- <br>
<br>
Powered by <a href="http://www.kitware.com" rel="noreferrer" target="_blank">www.kitware.com</a><br>
<br>
Please keep messages on-topic and check the CMake FAQ at: <a href="http://www.cmake.org/Wiki/CMake_FAQ" rel="noreferrer" target="_blank">http://www.cmake.org/Wiki/CMake_FAQ</a><br>
<br>
Kitware offers various services to support the CMake community. For more information on each offering, please visit:<br>
<br>
CMake Support: <a href="http://cmake.org/cmake/help/support.html" rel="noreferrer" target="_blank">http://cmake.org/cmake/help/support.html</a><br>
CMake Consulting: <a href="http://cmake.org/cmake/help/consulting.html" rel="noreferrer" target="_blank">http://cmake.org/cmake/help/consulting.html</a><br>
CMake Training Courses: <a href="http://cmake.org/cmake/help/training.html" rel="noreferrer" target="_blank">http://cmake.org/cmake/help/training.html</a><br>
<br>
Visit other Kitware open-source projects at <a href="http://www.kitware.com/opensource/opensource.html" rel="noreferrer" target="_blank">http://www.kitware.com/opensource/opensource.html</a><br>
<br>
Follow this link to subscribe/unsubscribe:<br>
<a href="https://cmake.org/mailman/listinfo/cmake" rel="noreferrer" target="_blank">https://cmake.org/mailman/listinfo/cmake</a><br>
</blockquote></div></div></div>-- <br><div dir="ltr" class="gmail_signature" data-smartmail="gmail_signature"><div dir="ltr">Francis Giraldeau</div></div>