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, lec...@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 <mailto:lec...@gmail.com>
*Envoyé le :*jeudi 4 mai 2017 08:37
*À : *Hendrik Sattler <mailto:p...@hendrik-sattler.de>; Louis-Paul
CORDIER <mailto:lp.cord...@dynamixyz.com>; Cmake Mailing List
<mailto:cmake@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 <p...@hendrik-sattler.de
<mailto:p...@hendrik-sattler.de>> a écrit :
Am 27. April 2017 10:43:50 MESZ schrieb Louis-Paul CORDIER
<lp.cord...@dynamixyz.com <mailto:lp.cord...@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 <http://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