<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body text="#000000" bgcolor="#FFFFFF">
<p>Hi,</p>
<p>I bump this question again for DLL library handling. Still I have
the issue with my dependency "scanner" in my previous email that
can't evaluate if a target with a generator expression is a valid
one or not.<br>
</p>
<p>if(NOT TARGET
"$<$<CONFIG:Release_Production>:Foo_lib>")<br>
# will never go into this statement<br>
endif()<br>
</p>
<p>Thanks,</p>
<p>LP<br>
</p>
<div class="moz-cite-prefix">Le 04/07/2017 à 10:19, Louis-Paul
CORDIER a écrit :<br>
</div>
<blockquote type="cite"
cite="mid:612ed9d4-61ce-b3a2-2a39-887deeceb3b2@dynamixyz.com">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<p>Hi,</p>
<p>Thank you very much for this code snippet. However I don't like
the fixup_bundle function, as it takes the first dll that it
found to be linked against.<br>
</p>
<p>I also did a try with a dependency scanning function. It is
quiet long to write, but I guess it is the cleanest way to
handle DLL under Windows.<br>
Note: I still have an issue with this function. Indeed, if user
uses Generator expressions for library dependencies, it will not
work.<br>
e.g:<br>
add_library(Foo_lib IMPORTED GLOBAL)<br>
# ... set location properties<br>
target_link_libraries(${PROJECT_NAME} optimized
$<$<CONFIG:Release_Production>:Foo_lib>)</p>
<p>Any idea for a workaround? What do you think about this CMake
code?</p>
<p>Also, I would see a real benefit to add a
LINK_DEPENDENT_LIBRARIES property (inspired of
IMPORTED_LINK_DEPENDENT_LIBRARIES) to each target that could be
automatically filled by each target_link_libraries() calls.<br>
</p>
<p><br>
</p>
<p><br>
</p>
<p># This function scan all dependencies of a project recursively,
and retrieve all shared<br>
# library associated with it.<br>
# Prerequisite: your upstream CMakeLists.txt must make use of
add_library(foo SHARED IMPORTED GLOBAL),<br>
# and fill the following properties on the imported target:<br>
# set_target_properties(foo PROPERTIES IMPORTED_IMPLIB
"path_to_foo.lib")<br>
# set_target_properties(foo PROPERTIES IMPORTED_LOCATION
"path_to_foo.dll")<br>
# set_target_properties(foo PROPERTIES
IMPORTED_LINK_DEPENDENT_LIBRARIES
"path_to_dll_on_which_foo_depends.dll")<br>
# GLOBAL keyword is important as it allows downstream
CMakeLists.txt to scan dependencies.</p>
<p># Input parameters:<br>
# dep_to_scan: your downstream project<br>
# config_to_scan: configuration to use for the scanning.<br>
# output_variable: variable in which the function stores the
result.<br>
<br>
# Usage: <br>
# RECURSIVE_SCAN(my_app Release DLLS)<br>
# install(FILES ${DLLS}<br>
# DESTINATION release <br>
# CONFIGURATIONS Release)<br>
</p>
<p>set(COUNT 0)<br>
function(RECURSIVE_SCAN dep_to_scan config_to_scan
output_variable)<br>
<br>
MATH(EXPR COUNT "${COUNT}+1")<br>
string(RANDOM LENGTH ${COUNT} ALPHABET "-" SPACES)<br>
<br>
message("${SPACES} Scanning ${dep_to_scan}")<br>
if(NOT TARGET ${dep_to_scan})<br>
MATH(EXPR COUNT "${COUNT}-1")<br>
#message("${dep_to_scan} Is not target")<br>
return()<br>
endif()<br>
<br>
<br>
get_target_property(_is_imported ${dep_to_scan} IMPORTED)<br>
if(_is_imported)<br>
<br>
# We need to check if the imported library rely on other
shared libraries.<br>
get_target_property(_dependent_dll ${_lib}
IMPORTED_LINK_DEPENDENT_LIBRARIES_${config_to_scan})<br>
if(NOT _dependent_dll)<br>
get_target_property(_dependent_dll ${_lib}
IMPORTED_LINK_DEPENDENT_LIBRARIES)<br>
endif()<br>
<br>
if(_dependent_dll)<br>
list(APPEND ${output_variable} ${_dependent_dll})<br>
endif()<br>
<br>
<br>
#Otherwise, check if it is a shared library. (LOCATION
variable can be <br>
# either .lib or DLL regarding of the type of library.)<br>
get_target_property(_TYPE ${dep_to_scan} TYPE)<br>
<br>
if(NOT _TYPE STREQUAL STATIC_LIBRARY)<br>
get_target_property(_dll_found ${dep_to_scan}
LOCATION_${config_to_scan}) <br>
if(_dll_found)<br>
list(APPEND ${output_variable} ${_dll_found})<br>
endif()<br>
<br>
endif()<br>
<br>
message("${SPACES}- DLL found: (${${output_variable}})")<br>
<br>
endif(_is_imported)<br>
<br>
get_target_property(_libraries ${dep_to_scan}
INTERFACE_LINK_LIBRARIES)<br>
<br>
if(_libraries)<br>
foreach(_lib ${_libraries})<br>
RECURSIVE_SCAN(${_lib} ${config_to_scan}
${output_variable})<br>
endforeach()<br>
endif()<br>
<br>
# If we reach our first recursion, we need to clean the list
of<br>
# DLL in order to remove duplicates.<br>
MATH(EXPR COUNT "${COUNT}-1")<br>
<br>
if(${COUNT} EQUAL 0)<br>
list(REMOVE_DUPLICATES ${output_variable})<br>
endif()<br>
<br>
set(${output_variable} ${${output_variable}} PARENT_SCOPE)<br>
<br>
endfunction(RECURSIVE_SCAN)<br>
</p>
<p><br>
</p>
<p>Best regards,</p>
<p>Louis-Paul CORDIER<br>
</p>
<div class="moz-cite-prefix">Le 04/05/2017 à 09:51, <a
class="moz-txt-link-abbreviated"
href="mailto:lectem@gmail.com" moz-do-not-send="true">lectem@gmail.com</a>
a écrit :<br>
</div>
<blockquote type="cite"
cite="mid:590add90.925c1c0a.632e2.33a2@mx.google.com">
<meta http-equiv="Content-Type" content="text/html;
charset=utf-8">
<meta name="Generator" content="Microsoft Word 15 (filtered
medium)">
<style><!--
/* Font Definitions */
@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0cm;
margin-bottom:.0001pt;
font-size:11.0pt;
font-family:"Calibri",sans-serif;}
a:link, span.MsoHyperlink
{mso-style-priority:99;
color:blue;
text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
{mso-style-priority:99;
color:#954F72;
text-decoration:underline;}
.MsoChpDefault
{mso-style-type:export-only;}
@page WordSection1
{size:612.0pt 792.0pt;
margin:70.85pt 70.85pt 70.85pt 70.85pt;}
div.WordSection1
{page:WordSection1;}
--></style>
<div class="WordSection1">
<p class="MsoNormal">I managed to get it working by using an
intermediate script.</p>
<p class="MsoNormal">One might want to generate the script
instead of using the « RUN_IT » variable trick.</p>
<p class="MsoNormal">This was only tested on Windows, but
seems to work fine.</p>
<p class="MsoNormal">Put the following code in a xxxxxx.cmake
file, include it from your CMakeLists.txt and enjoy.</p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"># This is a helper script to run
BundleUtilities fixup_bundle as postbuild</p>
<p class="MsoNormal"># for a target. The primary use case is
to copy .DLLs to the build directory for</p>
<p class="MsoNormal"># the Windows platform. It allows
generator expressions to be used to determine</p>
<p class="MsoNormal"># the binary location</p>
<p class="MsoNormal">#</p>
<p class="MsoNormal"># Usage : run_fixup(TARGET LIBS DIRS)</p>
<p class="MsoNormal"># - TARGET : A cmake target</p>
<p class="MsoNormal"># - See fixup_bundle for LIBS and DIRS
arguments</p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">if(RUN_IT)</p>
<p class="MsoNormal"># Script ran by the add_custom_command</p>
<p class="MsoNormal"> include(BundleUtilities)</p>
<p class="MsoNormal">
fixup_bundle("${TO_FIXUP_FILE}" "${TO_FIXUP_LIBS}"
"${TO_FIXUP_DIRS}")</p>
<p class="MsoNormal"># End of script ran by the
add_custom_command</p>
<p class="MsoNormal">else()</p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">set(THIS_FILE ${CMAKE_CURRENT_LIST_FILE})</p>
<p class="MsoNormal">message(${THIS_FILE})</p>
<p class="MsoNormal">function(run_fixup _target _libs _dirs)</p>
<p class="MsoNormal"> message(${THIS_FILE})</p>
<p class="MsoNormal"> add_custom_command(</p>
<p class="MsoNormal"> TARGET
${_target} POST_BUILD</p>
<p class="MsoNormal"> COMMAND
${CMAKE_COMMAND} -DRUN_IT:BOOL=ON
-DTO_FIXUP_FILE=$<TARGET_<a class="moz-txt-link-freetext"
href="FILE:$" moz-do-not-send="true">FILE:$</a>{_target}>
-DTO_FIXUP_LIBS=${_libs} -DTO_FIXUP_DIRS=${_dirs} -P
${THIS_FILE}</p>
<p class="MsoNormal"> COMMENT
"Fixing up dependencies for ${_target}"</p>
<p class="MsoNormal"> VERBATIM</p>
<p class="MsoNormal"> )</p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">endfunction()</p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">endif()</p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<div
style="mso-element:para-border-div;border:none;border-top:solid
#E1E1E1 1.0pt;padding:3.0pt 0cm 0cm 0cm">
<p class="MsoNormal" style="border:none;padding:0cm"><b>De :
</b><a href="mailto:lectem@gmail.com"
moz-do-not-send="true">Clément Gregoire</a><br>
<b>Envoyé le :</b>jeudi 4 mai 2017 08:37<br>
<b>À : </b><a href="mailto:post@hendrik-sattler.de"
moz-do-not-send="true">Hendrik Sattler</a>; <a
href="mailto:lp.cordier@dynamixyz.com"
moz-do-not-send="true">Louis-Paul CORDIER</a>; <a
href="mailto:cmake@cmake.org" moz-do-not-send="true">Cmake
Mailing List</a><br>
<b>Objet :</b>Re: [CMake] DLL handling under CMake</p>
</div>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">I'd also be interested in this. I saw an
old mail in the ML about this, but it seems fixup_bundle is
old and cant use generator expressions, making it hard to
use (I don't want to hardcode the executable path).<o:p></o:p></p>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">Do you have a sample for this ?</p>
</div>
<div>
<p class="MsoNormal" style="margin-bottom:12.0pt">CMake
would really benefit from having those features made more
accessible instead of everyone having to write its own
script </p>
<div>
<div>
<p class="MsoNormal">Le sam. 29 avr. 2017 22:10, Hendrik
Sattler <<a href="mailto:post@hendrik-sattler.de"
moz-do-not-send="true">post@hendrik-sattler.de</a>>
a écrit :</p>
</div>
</div>
</div>
<p class="MsoNormal" style="margin-left:4.8pt"><br>
<br>
Am 27. April 2017 10:43:50 MESZ schrieb Louis-Paul CORDIER
<<a href="mailto:lp.cordier@dynamixyz.com"
target="_blank" moz-do-not-send="true">lp.cordier@dynamixyz.com</a>>:<br>
>This steps are tedious and I'm wondering if there is a
mechanism that<br>
>exists or that have to be imagined to make the DLL
nightmare end.<br>
<br>
I use BundleUtilities to achieve the copying of DLL files to
the installation directory. The main problem for this is to
enumerate the needed directories.<br>
<br>
I use the same for copying DLL files to the output directory
to ease debugging.<br>
<br>
The advantage is the inspection of the exe for really needed
DLL files. This AUTOMATICALLY handles the case debug vs.
release.<br>
<br>
HS<br>
<br>
--<br>
Diese Nachricht wurde von meinem Android-Mobiltelefon mit
K-9 Mail gesendet.<br>
--<br>
<br>
Powered by <a href="http://www.kitware.com" target="_blank"
moz-do-not-send="true">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" target="_blank"
moz-do-not-send="true">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"
target="_blank" moz-do-not-send="true">http://cmake.org/cmake/help/support.html</a><br>
CMake Consulting: <a
href="http://cmake.org/cmake/help/consulting.html"
target="_blank" moz-do-not-send="true">http://cmake.org/cmake/help/consulting.html</a><br>
CMake Training Courses: <a
href="http://cmake.org/cmake/help/training.html"
target="_blank" moz-do-not-send="true">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"
target="_blank" moz-do-not-send="true">http://www.kitware.com/opensource/opensource.html</a><br>
<br>
Follow this link to subscribe/unsubscribe:<br>
<a href="http://public.kitware.com/mailman/listinfo/cmake"
target="_blank" moz-do-not-send="true">http://public.kitware.com/mailman/listinfo/cmake</a></p>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
</blockquote>
<br>
</blockquote>
<br>
</body>
</html>