I'm using CMake. My application uses DLL version of wxWidgets. I'm outputing the apllication's exe file to the specific location within the project tree (e.g. project/bin). What is the best way to automate the process of copying 3rd party shared libraries to executable's directory?
Thx
It is quite possible that you could try to automate the creation of bundle using CPack.
Same as described for wxArt2D: here
Also in CMake you can use post-build events like this:
add_custom_command(TARGET ${LIBRARY_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different "${CMAKE_CURRENT_SOURCE_DIR}/Graphics/WaterEffect/background.jpg" "${WATER_EFFECT_TEXTURE_PATH}/background.jpg"
)
Related
Part of my source code is generated by a tool which is also built under our main project with a add_subdirectory. We execute this tool with a execute_process command. Clearly, if the tool is not built before we reach the execute_process statement it will fail.
I use a GLOB (file(GLOB...)) to find the source files generated. I do this because it is not possible to know beforehand how many files are generated, neither their names.
How do I force cmake to wait for the subproject to be compiled before the execute process? I would need something like a DEPENDS property for the execute_process but this option is not available.
# This subproject will source generator the tool
add_subdirectory(generator)
# I need something like: wait_for(generator)
execute_process(COMMAND generator ${CMAKE_SOURCE_DIR}/src)
file(GLOB GeneratedSources ${CMAKE_SOURCE_DIR}/src/*.cpp)
add_executable(mainprject.exe ${ProcessorSourceFiles}
Command execute_process executes its COMMAND immediately, at configuration stage. So it cannot be arranged after the executable is created with add_executable command: that executable will be built only at build stage.
You need to build subproject at configuration stage too. E.g. with
execute_process(COMMAND ${CMAKE_COMMAND}
-S ${CMAKE_SOURCE_DIR}/generator
-B ${CMAKE_BINARY_DIR}/generator
-G ${CMAKE_GENERATOR}
)
execute_process(COMMAND ${CMAKE_COMMAND}
--build ${CMAKE_BINARY_DIR}/generator
)
The first command invokes cmake for configure the 'generator' project, located under ${CMAKE_SOURCE_DIR}/generator directory. With -G option we use for subproject the same CMake generator, as one used for the main project.
The second command builds that project, so it produces generator executable.
After generator executable is created, you may use it for your project:
execute_process(COMMAND ${CMAKE_BINARY_DIR}/generator/<...>/generator ${CMAKE_SOURCE_DIR}/src)
Here you need to pass absolute path to the generator executable as the first parameter to COMMAND: CMake no longer have generator executable target, so it won't substitute its path automatically.
You will need to model this with target dependencies. The tool "generator" should be a cmake target. In that case use add_custom_target instead of execute_process somthing like this:
add_custom_target(generate_sources ALL COMMAND generator ${CMAKE_SOURCE_DIR}/src))
Then add a target dependency to "generator" using add_dependencies:
add_dependencies(generate_sources generator)
This will make sure your target "generate_sources", which runs the tool will only run during build after the target "generator" has been compiled.
The following is false, see the comments for more info:
Use add_dependencies to add a dependency from "mainproject.exe" to "generate_sources". Now this I have never tested, so take with a grain of salt: With CMake more recent than version 3.12, according to the entry on file, you should then be able to change your file command to:
file(GLOB GeneratedSources CONFIGURE_DEPENDS ${CMAKE_SOURCE_DIR}/src/*.cpp)
Which I interpret as this will re-glob the files during build if the directory changes.
What is the defacto way of handling implicit linking in CMake projects?
In windows, .dll's are linked during runtime, thus CMake only needs to link the .lib files during compilation. This is better done using find_package. However, during compilation, CMake never copies over the .dll corresponding to the linked .lib file to the linked executable's output path.
Is this something that CMake leaves up to the user?
It seems kind of messy, not to mention non-cross platform, to have to manually find dll's for each library you link and either manually copy them over to your output directory or write individual CMake commands, as shown below, to do this per package you find/library you link.
add_custom_command(
TARGET MyTarget POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${PROJECT_SOURCE_DIR}/libs/SDL2.dll"
$<TARGET_FILE_DIR:MyTarget>
)
The binary directory structure of my project is currently like this (Windows):
bin/mainProject/{Debug,Release}
bin/library1/{Debug,Release}
bin/library2/{Debug,Release}
...
bin/libraryN/{Debug,Release}
I'd like to copy the libraries library1lib.dll, ... libraryNlib.dll to the bin/mainProject/{Debug,Release} directory once they are build.
For CMake, I think this is doable using a post-build event, hence I've tried adding this to each of the libraries' CMakeLists.txt:
add_custom_command(TARGET library1 POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/library1lib.dll
${CMAKE_BINARY_DIR}/mainProject/${CMAKE_BUILD_TYPE}/
)
Currently, there are two issues:
${CMAKE_BUILD_TYPE} seems to be not defined, at least I get an empty string for that variable in the output window.
Is there a possibility to make that post-build event more generic? Like replacing the actual dll name with some variable?
You can make this more generic by using generator expressions:
add_custom_command(
TARGET library1
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
$<TARGET_FILE:library1>
$<TARGET_FILE_DIR:mainProject>/$<TARGET_FILE_NAME:library1>
)
Alternative
You could - if every dependency is build within your CMake project - also just give a common output path for all executables and DLLs with something like:
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/Out")
Note: The absolute path is required here because it would otherwise be relative to each targets default output path. And note that the configuration's sub-directory is appended by CMake automatically.
References
How to copy DLL files into the same folder as the executable using CMake?
I am working on CMake for generating the visual studio files. I would like to add the xyz.dll in the same folder where abc.exe is residing.
I had read somewhere that when i manually copy the xyz.dll file into the same folder where abc.exe is residing then the problem would be solved. But every time it is not possible.. I want to write the CMake command so that it will find the xyz.dll file and copy into the same folder where the abc.exe is residing..
Following mentioned are the paths where the .exe and .dll file is residing in my PC.
${MyWorkSpace_ROOT_DIR}/algoCommon/pthread/dll/xyz.dll
${MyWorkSpace_ROOT_DIR}/xml/addAlgo/.../cmakeOut.VS12/Debug/abc.exe
abc is my Project and i would like to confirm whether the following mentioned is wrong or not.
add_custom_command(TARGET abc PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${MyWorkSpace_ROOT_DIR}/algoCommon/pthread/dll"
$<{MyWorkSpace_ROOT_DIR}/xml/addAlgo/.../cmakeOut.VS12/Debug/:abc>)
If this is wrong kindly correct me.
If it is correct then I would like to ask few doubts..
will this command automatically copies the xyz.dll files into the folder abc.exe is residing or something else is happening here??
As Tsyvarev already commented - the destination expression is invalid. In addition, your source line is incomplete (until you want to copy the whole folder which needs another command)
The right command would be
add_custom_command(TARGET abc POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${MyWorkSpace_ROOT_DIR}/algoCommon/pthread/dll/xyz.dll"
$<TARGET_FILE_DIR:abc>)
in case you're building also the dll via cmake and you know the target name you could write
add_custom_command(TARGET abc POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_FILE:xyz>
$<TARGET_FILE_DIR:abc>)
where xyz is the target name of the dll
you might also have a look on this one:
How to copy DLL files into the same folder as the executable using CMake?
An addition to the answer above, as I needed to copy not only the target .dlls, but also all of its dependencies.
As of CMake 3.21 there's a generator pattern that works specifically for .dll targets and takes all the dependencies as well. Do note, that this only works on DLL platforms as per the documentation. Use it like so:
find_package(foo CONFIG REQUIRED) # package generated by install(EXPORT)
add_executable(exe main.c)
target_link_libraries(exe PRIVATE foo::foo foo::bar)
add_custom_command(TARGET exe POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_RUNTIME_DLLS:exe> $<TARGET_FILE_DIR:exe>
COMMAND_EXPAND_LISTS
)
Link to the official CMake TARGET_RUNTIME_DLLS documentation:
https://cmake.org/cmake/help/latest/manual/cmake-generator-expressions.7.html#genex:TARGET_RUNTIME_DLLS
In CMakeLists.txt have a library called "library.dll". I want to add a post build event to copy the resulting file to a different directory. The documentation says to use generator events, but it's not working:
add_custom_command(TARGET library.dll POST_BUILD COMMAND copy $<TARGET_FILE:library.dll> \"${SOME_DIR}/bin\")
I'm using CMake 2.8.3 to generate VC++ 2010 project files on Windows 7.
Try the following changes:
Add the VERBATIM option which ensures that all arguments to the command will be escaped properly.
Instead of using the Windows built-in copy command, invoke CMake in command mode which has a platform independent copy command built-in.
The modified command looks like this:
add_custom_command(TARGET library.dll POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:library.dll> ${SOME_DIR}/bin VERBATIM)