Copy file from source directory to binary directory using CMake
CmakeCmake Problem Overview
I'm trying to create a simple project on CLion. It uses CMake (I'm new here) to generate Makefiles to build project (or some sort of it)
All I need to is transfer some non-project file (some sort of resource file) to binary directory each time when I run the my code.
That file contains test data and application open it to read them. I tried several ways to do so:
-
Via
file(COPY ...
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/input.txt DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/input.txt
Looking good but it work just once and not recopy file after next run.
-
Via
add_custom_command
-
OUTPUT
versionadd_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/input.txt COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/input.txt ${CMAKE_CURRENT_BINARY_DIR}/input.txt)
-
TARGET
versionadd_custom_target(foo) add_custom_command( TARGET foo COMMAND ${CMAKE_COMMAND} copy ${CMAKE_CURRENT_BINARY_DIR}/test/input.txt ${CMAKE_SOURCE_DIR})
But no one of it work.
-
What am I doing wrong?
Cmake Solutions
Solution 1 - Cmake
You may consider using configure_file with the COPYONLY
option:
configure_file(<input> <output> COPYONLY)
Unlike file(COPY ...)
it creates a file-level dependency between input and output, that is:
> If the input file is modified the build system will re-run CMake to re-configure the file and generate the build system again.
Solution 2 - Cmake
both option are valid and targeting two different steps of your build:
file(COPY ...
copies the file in configuration step and only in this step. When you rebuild your project without having changed your cmake configuration, this command won't be executed.add_custom_command
is the preferred choice when you want to copy the file around on each build step.
The right version for your task would be:
add_custom_command(
TARGET foo POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_SOURCE_DIR}/test/input.txt
${CMAKE_CURRENT_BINARY_DIR}/input.txt)
you can choose between PRE_BUILD
, PRE_LINK
, POST_BUILD
best is you read the documentation of add_custom_command
an example on how to use the first version can be found here: https://stackoverflow.com/questions/11592098/use-cmake-add-custom-command-to-generate-source-for-another-target
Solution 3 - Cmake
The first of option you tried doesn't work for two reasons.
First, you forgot to close the parenthesis.
Second, the DESTINATION
should be a directory, not a file name. Assuming that you closed the parenthesis, the file would end up in a folder called input.txt
.
To make it work, just change it to
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/input.txt
DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
Solution 4 - Cmake
The suggested configure_file is probably the easiest solution. However, it will not rerun the copy command to if you manually deleted the file from the build directory. To also handle this case, the following works for me:
add_custom_target(copy-test-makefile ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/input.txt)
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/input.txt
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/input.txt
${CMAKE_CURRENT_BINARY_DIR}/input.txt
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/input.txt)
Solution 5 - Cmake
if you want to copy folder from currant directory to binary (build folder) folder
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/yourFolder/ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/yourFolder/)
then the syntexe is :
file(COPY pathSource DESTINATION pathDistination)
Solution 6 - Cmake
This is what I used to copy some resource files: the copy-files is an empty target to ignore errors
add_custom_target(copy-files ALL
COMMAND ${CMAKE_COMMAND} -E copy_directory
${CMAKE_BINARY_DIR}/SOURCEDIRECTORY
${CMAKE_BINARY_DIR}/DESTINATIONDIRECTORY
)
Solution 7 - Cmake
I would suggest TARGET_FILE_DIR
if you want the file to be copied to the same folder as your .exe file.
>
> $
add_custom_command(
TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_SOURCE_DIR}/input.txt
$<TARGET_FILE_DIR:${PROJECT_NAME}>)
In VS, this cmake script will copy input.txt to the same file as your final exe, no matter it's debug or release.
Solution 8 - Cmake
If you want to put the content of example
into install
folder after build:
code/
src/
example/
CMakeLists.txt
try add the following to your CMakeLists.txt
:
install(DIRECTORY example/ DESTINATION example)