[CMake] DLL handling under CMake

Clément Gregoire lectem at gmail.com
Sat Aug 12 04:48:38 EDT 2017


Sorry for not answering before, cmake generator expressions do not work
with "if". It mostly only work with target_*** stuff.
That's why I'm using a custom target to evaluate the current target
properties and run a cmake script with those values.

Le lun. 17 juil. 2017 à 10:47, Louis-Paul CORDIER <lp.cordier at dynamixyz.com>
a écrit :

> Hi,
>
> 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.
>
> if(NOT TARGET "$<$<CONFIG:Release_Production>:Foo_lib>")
>   # will never go into this statement
> endif()
>
> Thanks,
>
> LP
> Le 04/07/2017 à 10:19, Louis-Paul CORDIER a écrit :
>
> Hi,
>
> 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.
>
> 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.
> Note: I still have an issue with this function. Indeed, if user uses
> Generator expressions for library dependencies, it will not work.
> e.g:
> add_library(Foo_lib IMPORTED GLOBAL)
> # ... set location properties
> target_link_libraries(${PROJECT_NAME} optimized
> $<$<CONFIG:Release_Production>:Foo_lib>)
>
> Any idea for a workaround? What do you think about this CMake code?
>
> 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.
>
>
>
> # This function scan all dependencies of a project recursively, and
> retrieve all shared
> # library associated with it.
> # Prerequisite: your upstream CMakeLists.txt must make use of
> add_library(foo SHARED IMPORTED GLOBAL),
> # and fill the following properties on the imported target:
> # set_target_properties(foo PROPERTIES IMPORTED_IMPLIB "path_to_foo.lib")
> # set_target_properties(foo PROPERTIES IMPORTED_LOCATION "path_to_foo.dll")
> # set_target_properties(foo PROPERTIES IMPORTED_LINK_DEPENDENT_LIBRARIES
> "path_to_dll_on_which_foo_depends.dll")
> # GLOBAL keyword is important as it allows downstream CMakeLists.txt to
> scan dependencies.
>
> # Input parameters:
> # dep_to_scan: your downstream project
> # config_to_scan: configuration to use for the scanning.
> # output_variable: variable in which the function stores the result.
>
> # Usage:
> # RECURSIVE_SCAN(my_app Release DLLS)
> #  install(FILES ${DLLS}
> #     DESTINATION release
> #     CONFIGURATIONS Release)
>
> set(COUNT 0)
> function(RECURSIVE_SCAN dep_to_scan config_to_scan output_variable)
>
>   MATH(EXPR COUNT "${COUNT}+1")
>   string(RANDOM LENGTH ${COUNT} ALPHABET "-" SPACES)
>
>   message("${SPACES} Scanning ${dep_to_scan}")
>   if(NOT TARGET ${dep_to_scan})
>     MATH(EXPR COUNT "${COUNT}-1")
>     #message("${dep_to_scan} Is not target")
>     return()
>   endif()
>
>
>   get_target_property(_is_imported ${dep_to_scan} IMPORTED)
>   if(_is_imported)
>
>     # We need to check if the imported library rely on other shared
> libraries.
>     get_target_property(_dependent_dll ${_lib}
> IMPORTED_LINK_DEPENDENT_LIBRARIES_${config_to_scan})
>     if(NOT _dependent_dll)
>       get_target_property(_dependent_dll ${_lib}
> IMPORTED_LINK_DEPENDENT_LIBRARIES)
>     endif()
>
>     if(_dependent_dll)
>       list(APPEND ${output_variable} ${_dependent_dll})
>     endif()
>
>
>     #Otherwise, check if it is a shared library. (LOCATION variable can be
>     # either .lib or DLL regarding of the type of library.)
>     get_target_property(_TYPE ${dep_to_scan} TYPE)
>
>     if(NOT _TYPE STREQUAL STATIC_LIBRARY)
>       get_target_property(_dll_found ${dep_to_scan}
> LOCATION_${config_to_scan})
>       if(_dll_found)
>         list(APPEND ${output_variable} ${_dll_found})
>       endif()
>
>     endif()
>
>     message("${SPACES}- DLL found: (${${output_variable}})")
>
>   endif(_is_imported)
>
>   get_target_property(_libraries ${dep_to_scan} INTERFACE_LINK_LIBRARIES)
>
>   if(_libraries)
>       foreach(_lib ${_libraries})
>         RECURSIVE_SCAN(${_lib} ${config_to_scan} ${output_variable})
>       endforeach()
>   endif()
>
>   # If we reach our first recursion, we need to clean the list of
>   # DLL in order to remove duplicates.
>   MATH(EXPR COUNT "${COUNT}-1")
>
>   if(${COUNT} EQUAL 0)
>     list(REMOVE_DUPLICATES ${output_variable})
>   endif()
>
>   set(${output_variable} ${${output_variable}} PARENT_SCOPE)
>
> endfunction(RECURSIVE_SCAN)
>
>
> Best regards,
>
> Louis-Paul CORDIER
> Le 04/05/2017 à 09:51, lectem at gmail.com a écrit :
>
> I managed to get it working by using an intermediate script.
>
> One might want to generate the script instead of using the « RUN_IT »
> variable trick.
>
> This was only tested on Windows, but seems to work fine.
>
> Put the following code in a xxxxxx.cmake file, include it from your
> CMakeLists.txt and enjoy.
>
>
>
>
>
> # This is a helper script to run BundleUtilities fixup_bundle as postbuild
>
> # for a target. The primary use case is to copy .DLLs to the build
> directory for
>
> # the Windows platform. It allows generator expressions to be used to
> determine
>
> # the binary location
>
> #
>
> # Usage : run_fixup(TARGET LIBS DIRS)
>
> # - TARGET : A cmake target
>
> # - See fixup_bundle for LIBS and DIRS arguments
>
>
>
> if(RUN_IT)
>
> # Script ran by the add_custom_command
>
>                 include(BundleUtilities)
>
>                 fixup_bundle("${TO_FIXUP_FILE}" "${TO_FIXUP_LIBS}"
> "${TO_FIXUP_DIRS}")
>
> # End of script ran by the add_custom_command
>
> else()
>
>
>
> set(THIS_FILE ${CMAKE_CURRENT_LIST_FILE})
>
> message(${THIS_FILE})
>
> function(run_fixup _target _libs _dirs)
>
>                 message(${THIS_FILE})
>
>                 add_custom_command(
>
>                                TARGET ${_target} POST_BUILD
>
>                                COMMAND ${CMAKE_COMMAND} -DRUN_IT:BOOL=ON
> -DTO_FIXUP_FILE=$<TARGET_FILE:${_target}> -DTO_FIXUP_LIBS=${_libs}
> -DTO_FIXUP_DIRS=${_dirs}  -P ${THIS_FILE}
>
>                                COMMENT "Fixing up dependencies for
> ${_target}"
>
>                                VERBATIM
>
>                 )
>
>
>
> endfunction()
>
>
>
> endif()
>
>
>
>
>
> *De : *Clément Gregoire <lectem at gmail.com>
> *Envoyé le :*jeudi 4 mai 2017 08:37
> *À : *Hendrik Sattler <post at hendrik-sattler.de>; Louis-Paul CORDIER
> <lp.cordier at dynamixyz.com>; Cmake Mailing List <cmake at cmake.org>
> *Objet :*Re: [CMake] DLL handling under CMake
>
>
>
> 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).
>
>
>
> Do you have a sample for this ?
>
> CMake would really benefit from having those features made more accessible
> instead of everyone having to write its own script
>
> Le sam. 29 avr. 2017 22:10, Hendrik Sattler <post at hendrik-sattler.de> a
> écrit :
>
>
>
> Am 27. April 2017 10:43:50 MESZ schrieb Louis-Paul CORDIER <
> lp.cordier at dynamixyz.com>:
> >This steps are tedious and I'm wondering if there is a mechanism that
> >exists or that have to be imagined to make the DLL nightmare end.
>
> 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.
>
> I use the same for copying DLL files to the output directory to ease
> debugging.
>
> The advantage is the inspection of the exe for really needed DLL files.
> This AUTOMATICALLY handles the case debug vs. release.
>
> HS
>
> --
> Diese Nachricht wurde von meinem Android-Mobiltelefon mit K-9 Mail
> gesendet.
> --
>
> 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:
> http://public.kitware.com/mailman/listinfo/cmake
>
>
>
>
>
> --
>
> 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:
> http://public.kitware.com/mailman/listinfo/cmake
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://public.kitware.com/pipermail/cmake/attachments/20170812/371ec182/attachment-0001.html>


More information about the CMake mailing list