Cannot copy folder in source dir to output dir - cmake

I want to copy a folder "obj_files" in my source dir to its output dir with the following code:
ADD_EXECUTABLE(projExec ${files_proj})
add_custom_command(TARGET projExec POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
${CMAKE_SOURCE_DIR}/obj_files $<TARGET_FILE_DIR:projExec>)
but it doesn't work. The "CMakeLists.txt" with above commands lies in a subdirectory to another project, hence the output dir is a subdir to that project's output dir. Is this something to consider when attempting to do what I am trying to? Anyways, the problem is that the directory simply is nowhere to be found in the output dirs of the projects. No error messages when configurating/generating, the folder simply isn't copied.

Related

Zip creation using CMake with no relative path

I want to bundle the build artifacts into a zip to deliver them on the delivery server. That for I integrated the zip creation into the CMake routine.
# zip the final release files into the build artifact
# call the zipping with 'cmake --build . --target zip' or 'make zip'
string(TIMESTAMP DATE_STRING %Y%m%d)
add_custom_target(zip
COMMAND ${CMAKE_COMMAND} -E tar "cfv" "${PROJECT_NAME}-${PROJECT_VERSION}-${CMAKE_CXX_COMPILER_ID}-${CMAKE_CXX_COMPILER_VERSION}-${DATE_STRING}.zip" "--format=zip" "--"
"${PROJECT_SOURCE_DIR}/bin/release/*")
The artifacts are bundeld into the bin/release folder in the ProjectSourceDir.
My problem is, that the zip file has the relative path to the files from my build directory. So all files are located under ../bin/release/ which is not what I want. I want to have the files in the "home folder" of the zip file.
I've found the solution to prepare the zip folder in my build folder, but thats something I think is very unpractical or looks dirty to me.
A WORKING_DIRECTORY can be specified to the add_custom command.
add_custom_target(zip
COMMAND ${CMAKE_COMMAND} -E tar cvf ${PROJECT_SOURCE_DIR}/${PROJECT_NAME}-${PROJECT_VERSION}-${CMAKE_CXX_COMPILER_ID}-${CMAKE_CXX_COMPILER_VERSION}-${DATE_STRING}.zip --format=zip .
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/bin/release
)
You don't need all that extra quoting as given in the example.

Copy File to Executable Directory Recopy on Modified

I'm trying to copy a file to the same directory where the executable ends up. This means including the configuration type "RelWithDebInfo" directory with Visual Studio. Any CMake variable such as "CMAKE_BINARY_DIR" and similar don't include this folder in the path.
add_executable(${PROJECT_NAME} main.cpp)
add_custom_command(
TARGET ${PROJECT_NAME}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/copy_this.txt copy_this.txt
COMMENT "Copying..."
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/copy_this.txt
)
The above code works but it doesn't cause the file to be recopied with it is modified. The only other solution I found where it does copy when it is to use add_custom_command(OUTPUT copy_this.txt ...) but it doesn't copy the file into the correct folder.
add_custom_command(
OUTPUT copy_this.txt # this expects the file to be in ${CMAKE_CURRENT_BINARY_DIR}
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/copy_this.txt copy_this.txt
COMMENT "Copying..."
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/copy_this.txt
)
add_custom_target(target_copy_this.txt DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/copy_this.txt)
add_dependencies(${PROJECT_NAME} target_copy_this.txt)
The add_custom_command needs to be updated to specify where the file needs to be copied. In both examples the file is copied into the current working directory because the path is not specified. Here is an example of how to copy to the home directory.
set(newloc ~)
add_custom_command(
OUTPUT ${newloc}/copy_this.txt
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/copy_this.txt ${newloc}/copy_this.txt
COMMENT "Copying to ${newloc}"
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/copy_this.txt
)
add_custom_target(target_copy_this.txt ALL DEPENDS copy_this.txt)
It seems that you want the file to be copied to where one of the targets winds up. In visual studio this could be ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR} or ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR} depending upon what else is going on in the CMakeLists.txt.
Using this example and setting newloc to ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR} you will get the following output:
cmake --build . --config RelWithDebInfo
CustomBuild:
Copying to C:/Users/ZZZ/Projects/test/bld/RelWithDebInfo

cmake and how to avoid unzip an archive multiple times

I am using the following cmake command to extract a zip file
${CMAKE_COMMAND} -E tar xkf
This unzip the file as it is.
I'd like to AVOID unzipping when the file has been already unzipped.
How can I do that? It seems that there is no option for that purpose.
Add an dependency.
The result of the unzip operation has to be used within a later build step. Add the dependency between the unzip and that build step.
Use add_custom_command to unzip files and copy them to the expected folder
Extend your target by a dependency to the extracted files
The following example shows this for the target TTNLIB.
Example:
add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/src/ttnbitvector.cpp
COMMAND ${CMAKE_COMMAND} -E tar xkf ${CMAKE_SOURCE_DIR}/external/ttnbitvector.cpp.zip -C ${CMAKE_SOURCE_DIR}/external
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/external/ttnbitvector.cpp ${CMAKE_SOURCE_DIR}/src/ttnbitvector.cpp
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/external
COMMENT Extract ${CMAKE_SOURCE_DIR}/src/ttnbitvector.cpp
)
add_library(TTNLIB SHARED ${SOURCES} ${CMAKE_SOURCE_DIR}/src/ttnbitvector.cpp)
Note: Read the documentation of add_custom_command
See cmake solutions for further information.

During build, how to create a directory for a file which is generated by some COMMAND?

I'm writing a custom command in CMake to convert a file to binary format at build time. However, the tool I'm using requires directory for a file to be pre-existed; it doesn't create a directory automatically.
Currently my CMake macro looks like this:
MACRO(ConvertToBinary _name)
ADD_CUSTOM_COMMAND(
OUTPUT ${CMAKE_BINARY_DIR}/${_name}.bin
COMMAND ${EXE_DIR}/toBinary -i ${CMAKE_CURRENT_SOURCE_DIR}/${_name} -o ${CMAKE_BINARY_DIR}/${_name}.bin
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${_name}
)
ENDMACRO(ConvertToBinary)
This macro doesn't work for _name parameter equal, e.g., to "test/sample.txt", because the tool is run with test/ folder under ${CMAKE_BINARY_DIR} being not existed.
How to create the directory before the tool, generating the file, is run?
I have tried to overcome the problem by pre-creating the file (and directory) with the help of CMake. So the tool will be run with the directory created, and can override the output file. I have tried the following:
MACRO(ConvertToBinary _name)
ADD_CUSTOM_COMMAND(
OUTPUT ${CMAKE_BINARY_DIR}/${_name}.bin
FILE(WRITE ${CMAKE_BINARY_DIR}/${_name}.bin "Dummy")
COMMAND ${EXE_DIR}/toBinary -i ${CMAKE_CURRENT_SOURCE_DIR}/${_name} -o ${CMAKE_BINARY_DIR}/${_name}.bin
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${_name}
)
ENDMACRO(ConvertToBinary)
But it did not work. I can't find information on how to create file at build time with CMake, so any help is appreciated.
In CMake you may extract directory component of the file and create this directory.
Below code can be used for a tool, which generates a file but doesn't create directory for it.
# Assume some tool generates file '${file}', but don't create directory for it.
#
# Extract directory component for a file
get_filename_component(_dir ${file} DIRECTORY)
add_custom_command(OUTPUT ${file}
COMMAND ${CMAKE_COMMAND} -E make_directory ${_dir} # Create output directory
COMMAND <tool-which-generates-file> ... ${file}
)
See also that question about ways for create a directory in CMake.

Copy file from source directory to binary directory using CMake

I'm trying to create a simple project on CLion. It uses CMake 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 version
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)
TARGET version
add_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?
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.
Both option are valid and targeting two different steps of your build:
file(COPY ... copies the file during the 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: Use CMake add_custom_command to generate source for another target
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})
I would suggest TARGET_FILE_DIR if you want the file to be copied to the same folder as your .exe file.
$
Directory of main file (.exe, .so.1.2, .a).
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.
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)
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)
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
)
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)