<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body text="#000000" bgcolor="#FFFFFF">
    <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">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:$">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>
  </body>
</html>