<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>