DLL handling under CMake

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

DLL handling under CMake

Louis-Paul CORDIER
Hi,

I'm using CMake for a while now for cross-platform project.

In opposition to Linux, Windows does not have a library system
management through a repository system. I would say that 99% of
applications that have common libraries between them does not share the
runtimes. Each time, the .dll files are duplicated for each application.
We have to live with that, and to create proper CMakeLists.txt that can
handle DLL integration.

I think many of CMake users have the following pipeline on Windows:

1. Run CMake (this will execute some find_library to get the correct
.lib files)
2. Compile the application
3. Run the INSTALL target
4. Copy the .dll files into the output binary folder.
5. Package the application with the DLL inside (e.g innosetup)

Currently find_library does not search for runtime, but only for .lib.
So even if a developer is using find_library, he/she has to implement
some additional CMake code to retrieve the path to .dll files and copy
them using the install or the file CMake commands. I added my current
code for handling Qt library in my project at the end of this email. (I
put a huge part of it if someone want to reuse it). You will notice that
this code is handling the case where you are debugging using Visual
Studio, to avoid the missing .DLL issue.

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.

All the best

Louis-Paul Cordier


...

#Folder where compiled files for release/debug install will be placed
set(G3_RELEASE_DIR  "release")
set(G3_DEBUG_DIR "debug")

find_package(Qt5 ${QT5VC2015_VERSION} EXACT COMPONENTS Core OpenGL
Concurrent REQUIRED)

QT5_WRAP_UI(...)
QT5_WRAP_CPP(...)
target_include_directories(...)
target_compile_definitions(...)

#Add Qt libraries to the linker
target_link_libraries(${PROJECT_NAME}
   ${Qt5Widgets_LIBRARIES}
   ${Qt5OpenGL_LIBRARIES}
   ${Qt5Concurrent_LIBRARIES}
   )

if( WIN32 )
   SET(QT_DLL
       Qt5Core
       Qt5Gui
       Qt5Widgets
       Qt5OpenGL
       Qt5Concurrent
       )

     foreach( _file ${QT_DLL} )
       list( APPEND DLL_LIBRARIES  "${QT5_DIR}/bin/${_file}.dll" )
       list( APPEND DLL_LIBRARIES_D  "${QT5_DIR}/bin/${_file}d.dll" )
     endforeach( _file ${QT_DLL} )

     #TODO: add the platform libraries.

endif( WIN32 )

# I add other DLLs of other project's library by appending to
DLL_LIBRARIES and DLL_LIBRARIES_D

#Handle DLLs under Windows.
if(WIN32)

   set(DLL_LIBRARIES_PATH "")
   set(DLL_LIBRARIES_D_PATH "")

   #Process Release libraries.
   foreach( _file ${DLL_LIBRARIES} )

     # Convert path to CMake path to avoid escaping issues.
     file(TO_CMAKE_PATH ${_file} _file_cmake_path)

     #check file existance
     if(NOT EXISTS ${_file_cmake_path})
       message(FATAL_ERROR "Missing dll file: ${_file_cmake_path}")
     endif(NOT EXISTS ${_file_cmake_path})

     # Add the DLL to the installation process.
     install(FILES ${_file_cmake_path}
       DESTINATION ${G3_RELEASE_DIR}
       CONFIGURATIONS Release RelWithDebInfo MinSizeRel Release_CMT
Release_Net)

     # Extract the folder path of the DLL. It allows to add the folder
where the
     # DLLs are stored to the PATH environment of Visual Studio, in
order to avoid
     # copying DLL after each builds.
     if(MSVC)
       get_filename_component(_dll_folder ${_file} DIRECTORY)
       list(APPEND DLL_LIBRARIES_PATH ${_dll_folder})
     endif(MSVC)

   endforeach( _file ${DLL_LIBRARIES} )

   #Process Debug libraries.
   foreach( _file ${DLL_LIBRARIES_D} )

     # Convert path to CMake path to avoid escaping issues.
     file(TO_CMAKE_PATH ${_file} _file_cmake_path)

     #check file existance
     if(NOT EXISTS ${_file_cmake_path})
       message(FATAL_ERROR "Missing dll file: ${_file_cmake_path}")
     endif(NOT EXISTS ${_file_cmake_path})

     # Add the DLL to the installation process.
     install(FILES ${_file_cmake_path}
       DESTINATION ${G3_DEBUG_DIR}
       CONFIGURATIONS Debug)

     # Extract the folder path of the DLL. It allows to add the folder
where the
     # DLLs are stored to the PATH environment of Visual Studio, in
order to avoid
     # copying DLL after each builds.
     if(MSVC)
       get_filename_component(_dll_folder ${_file} DIRECTORY)
       list(APPEND DLL_LIBRARIES_PATH_D ${_dll_folder})
     endif(MSVC)

   endforeach( _file ${DLL_LIBRARIES_D} )

   if(MSVC)
     #Remove duplicate entries
     list(REMOVE_DUPLICATES DLL_LIBRARIES_PATH)
     list(REMOVE_DUPLICATES DLL_LIBRARIES_PATH_D)

     #Set architecture
     if(ARCH_X64)
       set(DLL_LIBRARIES_ARCH "x64")
     else(ARCH_X64)
       set(DLL_LIBRARIES_ARCH "Win32")
     endif(ARCH_X64)

     # The output file goes in the build dir.
     # @ONLY means only variables of the form @VAR@ will be substituted.
     # This method need DLL_LIBRARIES_ARCH, DLL_LIBRARIES_PATH and
DLL_LIBRARIES_PATH_D
     # variables to be set. DONT FORGET TO RESTART VISUAL STUDIO if DLL
paths changes, as
     # vcxproj.user files are loaded only once at Visual Studio startup.

     configure_file(project.vcxproj.user.in
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.vcxproj.user @ONLY)
   endif(MSVC)

endif(WIN32)

-------------------

NOTE:

For those who are wondering the content of project.vcxproj.user.in:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup
Condition="'$(Configuration)|$(Platform)'=='Release|@DLL_LIBRARIES_ARCH@'">
  <LocalDebuggerEnvironment>PATH=@DLL_LIBRARIES_PATH@;%PATH%</LocalDebuggerEnvironment>
  <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
  </PropertyGroup>

  <PropertyGroup
Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|@DLL_LIBRARIES_ARCH@'">

  <LocalDebuggerEnvironment>PATH=@DLL_LIBRARIES_PATH@;%PATH%</LocalDebuggerEnvironment>
  <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
  </PropertyGroup>

  <PropertyGroup
Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|@DLL_LIBRARIES_ARCH@'">

  <LocalDebuggerEnvironment>PATH=@DLL_LIBRARIES_PATH@;%PATH%</LocalDebuggerEnvironment>
  <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
  </PropertyGroup>

  <PropertyGroup
Condition="'$(Configuration)|$(Platform)'=='Debug|@DLL_LIBRARIES_ARCH@'">
  <LocalDebuggerEnvironment>PATH=@DLL_LIBRARIES_PATH_D@;%PATH%</LocalDebuggerEnvironment>
  <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
  </PropertyGroup>


</Project>


--
--

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
Reply | Threaded
Open this post in threaded view
|

Re: DLL handling under CMake

Nils Gladitz-2
On 04/27/2017 10:43 AM, Louis-Paul CORDIER wrote:

> I added my current code for handling Qt library in my project at the
> end of this email. (I put a huge part of it if someone want to reuse
> it). You will notice that this code is handling the case where you are
> debugging using Visual Studio, to avoid the missing .DLL issue.

FWIW in case of Qt5 you do not have to manually construct or guess DLL
locations.

You can retrieve the DLL locations from the imported targets (e.g.
"Qt5::Widgets") that Qt5 provides by querying the LOCATION_<CONFIG>
target properties (e.g. LOCATION_DEBUG or LOCATION_RELEASE).

Nils
--

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
Reply | Threaded
Open this post in threaded view
|

Re: DLL handling under CMake

Michael Jackson
In reply to this post by Louis-Paul CORDIER
Our project uses some custom cmake functions to gather the DLLs from 3rd
party libs (HDF5, TBB, Qt) and create custom targets to copy them to the
build directory and create install rules to copy them to the package
when it is created. Yes, they were tedious to write and get correct but
they seem to work. The Qt version was the easiest after we moved to Qt 5
since it is straight forward to get the locations. The HDF5 folks
recently updated their config file to have the same type of information.
TBB is odd, but relatively easy to guess the correct pattern.

I had a discussion about this topic yesterday and my pain point is that
a lot of the "Find**" modules really _need_ to also define the DLL
location instead of just where the link libs are at. From my little
world on Windows all the .dll files seem to be in a bin directory. So I
think that for each "Find***" those should define a few additional items:

FOO_IS_SHARED
FOO_BINARY_DIR

assuming of course that the proper FooConfig.cmake is not available.

--
Mike Jackson

PS:: http://www.github.com/bluequartzsoftware/cmp has our custom
scripts. It is mainly Qt focused but may have some gems in there that
you find valuable.

Louis-Paul CORDIER wrote:

> Hi,
>
> I'm using CMake for a while now for cross-platform project.
>
> In opposition to Linux, Windows does not have a library system
> management through a repository system. I would say that 99% of
> applications that have common libraries between them does not share the
> runtimes. Each time, the .dll files are duplicated for each application.
> We have to live with that, and to create proper CMakeLists.txt that can
> handle DLL integration.
>
> I think many of CMake users have the following pipeline on Windows:
>
> 1. Run CMake (this will execute some find_library to get the correct
> .lib files)
> 2. Compile the application
> 3. Run the INSTALL target
> 4. Copy the .dll files into the output binary folder.
> 5. Package the application with the DLL inside (e.g innosetup)
>
> Currently find_library does not search for runtime, but only for .lib.
> So even if a developer is using find_library, he/she has to implement
> some additional CMake code to retrieve the path to .dll files and copy
> them using the install or the file CMake commands. I added my current
> code for handling Qt library in my project at the end of this email. (I
> put a huge part of it if someone want to reuse it). You will notice that
> this code is handling the case where you are debugging using Visual
> Studio, to avoid the missing .DLL issue.
>
> 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.
>
> All the best
>
> Louis-Paul Cordier
>
>
> ...
>
> #Folder where compiled files for release/debug install will be placed
> set(G3_RELEASE_DIR "release")
> set(G3_DEBUG_DIR "debug")
>
> find_package(Qt5 ${QT5VC2015_VERSION} EXACT COMPONENTS Core OpenGL
> Concurrent REQUIRED)
>
> QT5_WRAP_UI(...)
> QT5_WRAP_CPP(...)
> target_include_directories(...)
> target_compile_definitions(...)
>
> #Add Qt libraries to the linker
> target_link_libraries(${PROJECT_NAME}
> ${Qt5Widgets_LIBRARIES}
> ${Qt5OpenGL_LIBRARIES}
> ${Qt5Concurrent_LIBRARIES}
> )
>
> if( WIN32 )
> SET(QT_DLL
> Qt5Core
> Qt5Gui
> Qt5Widgets
> Qt5OpenGL
> Qt5Concurrent
> )
>
> foreach( _file ${QT_DLL} )
> list( APPEND DLL_LIBRARIES "${QT5_DIR}/bin/${_file}.dll" )
> list( APPEND DLL_LIBRARIES_D "${QT5_DIR}/bin/${_file}d.dll" )
> endforeach( _file ${QT_DLL} )
>
> #TODO: add the platform libraries.
>
> endif( WIN32 )
>
> # I add other DLLs of other project's library by appending to
> DLL_LIBRARIES and DLL_LIBRARIES_D
>
> #Handle DLLs under Windows.
> if(WIN32)
>
> set(DLL_LIBRARIES_PATH "")
> set(DLL_LIBRARIES_D_PATH "")
>
> #Process Release libraries.
> foreach( _file ${DLL_LIBRARIES} )
>
> # Convert path to CMake path to avoid escaping issues.
> file(TO_CMAKE_PATH ${_file} _file_cmake_path)
>
> #check file existance
> if(NOT EXISTS ${_file_cmake_path})
> message(FATAL_ERROR "Missing dll file: ${_file_cmake_path}")
> endif(NOT EXISTS ${_file_cmake_path})
>
> # Add the DLL to the installation process.
> install(FILES ${_file_cmake_path}
> DESTINATION ${G3_RELEASE_DIR}
> CONFIGURATIONS Release RelWithDebInfo MinSizeRel Release_CMT Release_Net)
>
> # Extract the folder path of the DLL. It allows to add the folder where the
> # DLLs are stored to the PATH environment of Visual Studio, in order to
> avoid
> # copying DLL after each builds.
> if(MSVC)
> get_filename_component(_dll_folder ${_file} DIRECTORY)
> list(APPEND DLL_LIBRARIES_PATH ${_dll_folder})
> endif(MSVC)
>
> endforeach( _file ${DLL_LIBRARIES} )
>
> #Process Debug libraries.
> foreach( _file ${DLL_LIBRARIES_D} )
>
> # Convert path to CMake path to avoid escaping issues.
> file(TO_CMAKE_PATH ${_file} _file_cmake_path)
>
> #check file existance
> if(NOT EXISTS ${_file_cmake_path})
> message(FATAL_ERROR "Missing dll file: ${_file_cmake_path}")
> endif(NOT EXISTS ${_file_cmake_path})
>
> # Add the DLL to the installation process.
> install(FILES ${_file_cmake_path}
> DESTINATION ${G3_DEBUG_DIR}
> CONFIGURATIONS Debug)
>
> # Extract the folder path of the DLL. It allows to add the folder where the
> # DLLs are stored to the PATH environment of Visual Studio, in order to
> avoid
> # copying DLL after each builds.
> if(MSVC)
> get_filename_component(_dll_folder ${_file} DIRECTORY)
> list(APPEND DLL_LIBRARIES_PATH_D ${_dll_folder})
> endif(MSVC)
>
> endforeach( _file ${DLL_LIBRARIES_D} )
>
> if(MSVC)
> #Remove duplicate entries
> list(REMOVE_DUPLICATES DLL_LIBRARIES_PATH)
> list(REMOVE_DUPLICATES DLL_LIBRARIES_PATH_D)
>
> #Set architecture
> if(ARCH_X64)
> set(DLL_LIBRARIES_ARCH "x64")
> else(ARCH_X64)
> set(DLL_LIBRARIES_ARCH "Win32")
> endif(ARCH_X64)
>
> # The output file goes in the build dir.
> # @ONLY means only variables of the form @VAR@ will be substituted.
> # This method need DLL_LIBRARIES_ARCH, DLL_LIBRARIES_PATH and
> DLL_LIBRARIES_PATH_D
> # variables to be set. DONT FORGET TO RESTART VISUAL STUDIO if DLL paths
> changes, as
> # vcxproj.user files are loaded only once at Visual Studio startup.
>
> configure_file(project.vcxproj.user.in
> ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.vcxproj.user @ONLY)
> endif(MSVC)
>
> endif(WIN32)
>
> -------------------
>
> NOTE:
>
> For those who are wondering the content of project.vcxproj.user.in:
>
> <?xml version="1.0" encoding="utf-8"?>
> <Project ToolsVersion="4.0"
> xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
> <PropertyGroup
> Condition="'$(Configuration)|$(Platform)'=='Release|@DLL_LIBRARIES_ARCH@'">
> <LocalDebuggerEnvironment>PATH=@DLL_LIBRARIES_PATH@;%PATH%</LocalDebuggerEnvironment>
>
> <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
> </PropertyGroup>
>
> <PropertyGroup
> Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|@DLL_LIBRARIES_ARCH@'">
>
> <LocalDebuggerEnvironment>PATH=@DLL_LIBRARIES_PATH@;%PATH%</LocalDebuggerEnvironment>
>
> <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
> </PropertyGroup>
>
> <PropertyGroup
> Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|@DLL_LIBRARIES_ARCH@'">
>
> <LocalDebuggerEnvironment>PATH=@DLL_LIBRARIES_PATH@;%PATH%</LocalDebuggerEnvironment>
>
> <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
> </PropertyGroup>
>
> <PropertyGroup
> Condition="'$(Configuration)|$(Platform)'=='Debug|@DLL_LIBRARIES_ARCH@'">
> <LocalDebuggerEnvironment>PATH=@DLL_LIBRARIES_PATH_D@;%PATH%</LocalDebuggerEnvironment>
>
> <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
> </PropertyGroup>
>
>
> </Project>
>
>
--

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
Reply | Threaded
Open this post in threaded view
|

Re: DLL handling under CMake

Hendrik Sattler
In reply to this post by Louis-Paul CORDIER


Am 27. April 2017 10:43:50 MESZ schrieb Louis-Paul CORDIER <[hidden email]>:
>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
Reply | Threaded
Open this post in threaded view
|

Re: DLL handling under CMake

Lectem
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 <[hidden email]> a écrit :


Am 27. April 2017 10:43:50 MESZ schrieb Louis-Paul CORDIER <[hidden email]>:
>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
Reply | Threaded
Open this post in threaded view
|

Re: DLL handling under CMake

Lectem

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 : [hidden email]
Envoyé le :jeudi 4 mai 2017 08:37
À : [hidden email]; [hidden email]; [hidden email]
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 <[hidden email]> a écrit :



Am 27. April 2017 10:43:50 MESZ schrieb Louis-Paul CORDIER <[hidden email]>:
>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
Reply | Threaded
Open this post in threaded view
|

Re: DLL handling under CMake

Hendrik Sattler
Hi,

sorry for the delay. I see you already found a solution yourself.
Still, I want to share mine:
---------------------CopyPrerequisites.cmake--------------------
include ( GetPrerequisites )

if ( NOT DEFINED PREREQ_FILE )
   message ( FATAL_ERROR "PREREQ_FILE must be defined(${PREREQ_FILE})" )
endif ()

#
# Satisfy the find_file() search by common subdirs where .dll file can  
be found
#
foreach ( dir ${CMAKE_PREFIX_PATH} )
   list ( APPEND dirs ${dir}/bin )
endforeach ( dir )

get_filename_component ( COPY_DESTINATION "${PREREQ_FILE}" PATH )
get_prerequisites ( "${PREREQ_FILE}" COPY_FILES 1 1 "${dirs}"  
"${COPY_DESTINATION}" )

foreach ( COPY_FILE ${COPY_FILES} )
   if ( NOT IS_ABSOLUTE ${COPY_FILE} )
     set ( COPY_FILE_FULL )
     gp_resolve_item ( "${PREREQ_FILE}" "${COPY_FILE}" "${dirs}"  
"${COPY_DESTINATION}" COPY_FILE_FULL )
   else ()
     set ( COPY_FILE_FULL ${COPY_FILE} )
   endif ()
   if ( COPY_FILE_FULL )
     get_filename_component ( COPY_SOURCE_DIR "${COPY_FILE_FULL}" PATH )
     if ( NOT COPY_SOURCE_DIR MATCHES "^${COPY_DESTINATION}$" )
       message ( "Copying ${COPY_FILE_FULL} to output directory" )
       execute_process ( COMMAND "${CMAKE_COMMAND}" -E  
copy_if_different "${COPY_FILE_FULL}" "${COPY_DESTINATION}" )
     endif ()
   else ()
     message ( "Failed to find  ${COPY_FILE}" )
   endif ()
endforeach ( COPY_FILE )
----------------------------------------------------------

This can now be called from CMakeLists.txt:
if ( CMAKE_RUNTIME_OUTPUT_DIRECTORY )
   add_custom_command ( TARGET Gui POST_BUILD
     COMMAND ${CMAKE_COMMAND}
             "-DCMAKE_PREFIX_PATH:PATH=${SOME_SEARCH_DIRS}"
             "-DPREREQ_FILE=$<TARGET_FILE:MyTarget>"
             -P ${CMAKE_SOURCE_DIR}/CMakeModules/CopyPrerequisites.cmake
     VERBATIM
   )
endif ()

The variable SOME_SERACH_DIRS is filled with e.g. IMPORTED_LOCATION  
property values.
The same variable is used when calling INSTALL(CODE ".....  
fixup_bundle(...)" )

Regards,

HS

Zitat von [hidden email]:

> 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
> Envoyé le :jeudi 4 mai 2017 08:37
> À : Hendrik Sattler; Louis-Paul CORDIER; Cmake Mailing List
> 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  
> <[hidden email]> a écrit :
>
>
> Am 27. April 2017 10:43:50 MESZ schrieb Louis-Paul CORDIER  
> <[hidden email]>:
>> 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
Reply | Threaded
Open this post in threaded view
|

Re: DLL handling under CMake

Louis-Paul CORDIER
In reply to this post by Lectem

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, [hidden email] 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 : [hidden email]
Envoyé le :jeudi 4 mai 2017 08:37
À : [hidden email]; [hidden email]; [hidden email]
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 <[hidden email]> a écrit :



Am 27. April 2017 10:43:50 MESZ schrieb Louis-Paul CORDIER <[hidden email]>:
>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
Reply | Threaded
Open this post in threaded view
|

Re: DLL handling under CMake

Louis-Paul CORDIER

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, [hidden email] 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 : [hidden email]
Envoyé le :jeudi 4 mai 2017 08:37
À : [hidden email]; [hidden email]; [hidden email]
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 <[hidden email]> a écrit :



Am 27. April 2017 10:43:50 MESZ schrieb Louis-Paul CORDIER <[hidden email]>:
>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
Reply | Threaded
Open this post in threaded view
|

Re: DLL handling under CMake

Lectem

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 <[hidden email]> 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, [hidden email] 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 : [hidden email]
Envoyé le :jeudi 4 mai 2017 08:37
À : [hidden email]; [hidden email]; [hidden email]
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 <[hidden email]> a écrit :



Am 27. April 2017 10:43:50 MESZ schrieb Louis-Paul CORDIER <[hidden email]>:
>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

--

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