CMake/CPack: add_custom_command TARGET package POST_BUILD - cmake

Having the same problem as here described, I want to execute a shell script as a POST_BUILD command of TARGET "package". Target platform is Debian/Ubuntu.
I add following to the end of my CMakeLists:
add_custom_command(
TARGET package
POST_BUILD
COMMAND bash ${PROJECT_BINARY_DIR}/fixup_deb.sh
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
COMMENT "Fix file-permissions of md5sum files in debian package"
)
But this does not work. When I call "make package" the script doesn't change.
At the moment I have a workaround with a custom target:
add_custom_target(
correctDeb
COMMAND bash ${PROJECT_BINARY_DIR}/fixup_deb.sh
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
)
But it would be much more comfortable and more fail-safe for me if this would be automagically done when calling "make package".
By the way, generation of ${PROJECT_BINARY_DIR}/fixup_deb.sh works also well with:
configure_file( "${CMAKE_CURRENT_LIST_DIR}/debian/fixup_deb.sh.in" "${PROJECT_BINARY_DIR}/fixup_deb.sh" #ONLY IMMEDIATE )

Related

How to copy a file if modified and avoid rebuilding executables and libraries when running make all?

I want to copy a file from the source directory to the binary directory when running make or make all if the file has been modified. So if only this file has been modified, then no libraries or executables should be rebuilt when running make. Only the file should be copied. I tried several approaches, for example:
cmake_minimum_required(VERSION 3.18)
project(copy-file VERSION 1.0 DESCRIPTION "testing copy file if modified on make all")
set(FILE_PATH "some_dir/file.txt")
add_executable(hello hello.c)
#add_custom_command(
# OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${FILE_PATH}
# COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/${FILE_PATH} ${CMAKE_CURRENT_BINARY_DIR}/${FILE_PATH}
# MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/${FILE_PATH})
add_custom_command(
TARGET hello
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_SOURCE_DIR}/${FILE_PATH} ${CMAKE_CURRENT_BINARY_DIR}/${FILE_PATH})
#configure_file(${FILE_PATH} ${FILE_PATH} COPYONLY)
Unfortunately, this only copies file.txt (when running make) if hello.c has been modified. If hello.c has not been modified, but file.txt has been modified, nothing happens when I run make (whereas I expected the file to be copied from the source directory to the binary directory)
Here is a link to the source files I used for this minimal example.
Any ideas what I am missing?
Do not use POST_BUILD on a custom target. Specify input and output and let CMake take care of the dependency.
add_custom_command(
OUTPUT
${CMAKE_CURRENT_BINARY_DIR}/${FILE_PATH}
DEPENDS
${CMAKE_CURRENT_SOURCE_DIR}/${FILE_PATH}
COMMAND
${CMAKE_COMMAND} -E copy_if_different
${CMAKE_CURRENT_SOURCE_DIR}/${FILE_PATH}
${CMAKE_CURRENT_BINARY_DIR}/${FILE_PATH}
)
add_custom_target(copy DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${FILE_PATH})
Following the suggestion of #vre and adding copy_if_different instead of copy and then adding add_custom_target() that can be used with the custom command like this seems to work now:
cmake_minimum_required(VERSION 3.18)
project(copy-file VERSION 1.0 DESCRIPTION "testing copy file if modified on make all")
set(FILE_PATH "some_dir/file.txt")
add_executable(hello hello.c)
add_custom_target(copy ALL )
add_custom_command(
TARGET copy
PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${CMAKE_CURRENT_SOURCE_DIR}/${FILE_PATH} ${CMAKE_CURRENT_BINARY_DIR}/${FILE_PATH})

add_custom_command POST_BUILD to run shell script after 3 targets are built?

I have 3 targets in cmake added by add_executable()
I want to run a shell script after these 3 targets are done / built.
Usually, I do this for one target:
add_custom_command(TARGET TARGET1 POST_BUILD
VERBATIM
COMMAND SHELL_SCRIPT CALL HERE
)
But, how about if I want to run the script after 3 targets are built?
Doing the following will ensure the script is always executed only after the three executables are build:
add_executable(prog1 main1.cc)
add_executable(prog2 main2.cc)
add_executable(prog3 main3.cc)
add_custom_target(
ExecuteScript ALL
COMMAND ${CMAKE_COMMAND} -E echo "Executed after targets are built"
VERBATIM
)
add_dependencies(ExecuteScript prog1 prog2 prog3)

CMake add_custom_command ('POST_BUILD') 'DEPENDS' option is ignored

I have a library and a test projects on CMake, and I'm using this directory structure with two (project) CMakeLists.txt:
/
|- CMakeLists.txt
|- include/libName
|- src/...
|
|- test/
|- CMakeLists.txt
|- src/...
The outer project list defines the library, like:
add_library(libName ${SRC} ${INCLUDE})
And adds 'test' as subdirectory:
add_subdirectory(test)
The test project list defines the executable and a test, like:
add_executable(NameTest ${SRC})
target_link_libraries(NameTest libName)
add_test(NAME NameTest COMMAND NameTest)
The problem
I'm trying to build and execute the test program when the library is built. If any test fails, I want the build of the library fail too.
This is what I have (inside the outer lists file):
add_custom_command(
TARGET libName
POST_BUILD
COMMAND CTEST_OUTPUT_ON_FAILURE=1 ctest
DEPENDS NameTest # <- This is driving me crazy!
)
This command ignores completely if the target 'NameTest' is built, if there is a file with that name, or if not. I can't notice any difference if the whole 'DEPENDS' option is removed.
I even modified like:
add_custom_command(
TARGET libName
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo "Bip! Bip! Bip!"
DEPENDS this_is_not_an_existent_file_nor_target
)
And the command is triggered anyway. I'm not very sure about if this is the option I need, so:
Why is this not working?
How can I achieve my real purpose?
Thank you.
Edit: ctest will execute every test (add_test), but the NameTest executable (yet listed) must be built before calling it! Now would be built after the library, but before the 'POST_BUILD' custom command. It fails, of course.
I want CMake realize NameTest is necessary for running that custom command.
Edit: I find useful the Angew's answer, so I accepted his answer and refined it a little bit:
add_custom_command(
TARGET libName
POST_BUILD
COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target NameTest --config $<CONFIG>
COMMAND ${CMAKE_CTEST_COMMAND} -C $<CONFIG> --output-on-failure
)
Thank you!
1. Why is this not working?
Because you're mixing options from two distinct signatures of add_custom_command. DEPENDS comes from the form which is used to generate a file. TARGET and POST_BUILD are from the form which adds pre/post build commands to existing targets.
See the documentation of add_custom_command for more details on the two uses.
2. How can I achieve my real purpose?
I believe the following should do what you want to:
add_custom_command(
TARGET libName
POST_BUILD
COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target NameTest --config $<CONFIG>
COMMAND CTEST_OUTPUT_ON_FAILURE=1 ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target test --config $<CONFIG>
)

CMake command copy for symlink

I have following command:
add_custom_command(
TARGET Packaging POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
source_file
target_file )
Sometimes the source_file is a symlink. However, when it is copied, the referenced file is copied not the symlink.
How can I tell CMake command to copy the symlink as it is without de-referencing it?
It seems that there is no direct solution in CMake till now https://gitlab.kitware.com/cmake/cmake/issues/14609
A work around is to call a shell script that does the trick.
instead built-in "copy" you can use linux "cp" command with corresponded switches:
add_custom_command(
TARGET Packaging POST_BUILD
COMMAND cp -a -u
source_file
target_file )

Empty RUNTIME_OUTPUT_DIRECTORY

Working on a project using CMake. This project contains an executable and a python script. These two files should be compiled/copied in the same directory at build.
I try something like :
add_executable( ${myTarget} ${all_c_sources} )
add_custom_command(
TARGET ${myTarget} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${pythonScriptPath} ${RUNTIME_OUTPUT_DIRECTORY}/
)
The executable is well build in a default location like ${CMAKE_BINARY_DIR}/Debug but the copy of the python script failed :
c:\Program Files (x86)\CMake\bin\cmake.exe" -E copy C:/.../script.py /\r
My goal is to use CMake default behavior as mush as possible.
Is there a simple way to get the default output path ?
Thanks !
Something like this:
add_custom_command(TARGET ${LIBRARY_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_FILE:${LIBRARY_NAME}>
$<TARGET_FILE_DIR:${CMAKE_PROJECT_NAME}>/path/to/where/module/should/be
COMMENT "Copying file to Runtime directory: " $<TARGET_FILE:${LIBRARY_NAME}>
)
Adjust it to your needs.
Read about CMake Generator Expressions if you need to know more.