Personally, I find it much simpler just to expect the Path to include the 
locations of the DLL files as opposed to copying them.  (And I often write 
small batch scripts to set up this development environment, and then optionally 
start cmake-gui.exe / devenv.exe / etc.)
-- 
Daniel Schepler
________________________________________
From: CMake [cmake-boun...@cmake.org] on behalf of Marek Vojtko (Firaxis) 
[marek.voj...@firaxis.com]
Sent: Wednesday, February 21, 2018 7:20 PM
To: cmake@cmake.org
Subject: [CMake] Copying Shared Libraries (DLLs) Next to the Executable

Hi,

I need to copy external shared libraries (DLLs on Windows) next to the 
generated executable. Is calling "cmake -E copy_if_different" through a custom 
command added to the executable target still the best way to achieve this? 
CMake tracks include directories, compile definitions or options, link flags, 
etc. through its dependency system, but it doesn't provide an easy way to list 
/ copy all shared libraries a target depends on?

I am trying to follow the "new" CMake paradigms, using add_subdirectory(), 
set_target*() with PUBLIC/PRIVATE/INTERFACE scope, etc. to create a modular, 
re-usable setup, but that actively prevents me from using a custom command on 
the executable target. To wit:

App depends on Lib. Lib depends on several third-party, pre-built DLLs and 
encapsulates the logic of when to depend on them. The third-party, pre-built 
shared libraries (DLLs) are located through custom Find*.cmake modules and used 
as IMPORTED targets.

/CMakelists.txt
/App
    /CMakelists.txt
/Lib
    /CMakelists.txt

/CMakelists.txt
*************
set(CMAKE_MODULE_PATH "<my_modules>")
project("DLLTest")
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/Lib")
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/App")

/App/CMakelists.txt
*****************
add_executable(App WIN32 main.cpp)
target_link_libraries(App PRIVATE Lib)

/Lib/CMakelists.txt
****************
add_library(Lib STATIC lib.h lib.cpp)
target_include_directories(Lib PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")

if(Lib_NEEDS_DEPENDENCY)
    find_package(Dependency REQUIRED)
    target_link_libraries(Lib PUBLIC Dependency::Dependency)
endif()

FindDependency.cmake
********************
[snip]
add_library(Dependency::Dependency SHARED IMPORTED)
set_target_properties(Dependency::Dependency PROPERTIES
            INTERFACE_INCLUDE_DIRECTORIES "inc"
            IMPORTED_IMPLIB "dependency.lib"
            IMPORTED_LOCATION "dependency.dll"
)

In this setup, it is impossible to propagate a shared library (DLL) from Lib to 
App. This is because Lib and App have different BINARY_DIRs and Lib must create 
its target before App calls target_link_libraries(). That means that Lib does 
not know where App will generate its executable. If Lib is a SHARED target, I 
cannot set its RUNTIME_OUTPUT_DIRECTORY to be the same as App's. If Lib depends 
on IMPORTED targets (as is my case), I cannot create either a file(COPY) step, 
or an install(FILES) step, or even an add_custom_command() step in Lib to copy 
the shared library, because I don't know the destination.

The only solution, it would seem, is to add a custom command to App's target, 
because then I know where to copy the shared libraries to. But that means that 
App now has to know it needs to copy a shared library from a "hidden" 
dependency of Lib. App also needs to know about every SHARED or IMPORTED target 
Lib depends on, not to mention duplicate the logic in Lib's CMakelists.txt that 
decided whether Lib depends on Dependency in the first place.

I was looking into GetPrerequisites and FixupBundle, but both of those operate 
on an already existing executable and try to guess what shared libraries (DLLs) 
it might need. It feels silly to guess at something that CMake already knows 
(as the IMPORTED target sets the IMPORTED_IMPLIB and IMPORTED_LOCATION 
properties).

Setting a common CMAKE_RUNTIME_OUTPUT_DIRECTORY for both App and Lib is 
problematic if I have multiple executables in my root CMakelists.txt and they 
depend on different versions of the shared libraries or I have other name 
clashes.

Is there no automated way to get the list of shared libraries a target depends 
on?

Thanks,
Marek
--

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:
https://cmake.org/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:
https://cmake.org/mailman/listinfo/cmake

Reply via email to