CMake: dependecies of add_custom_command - cmake

Let's say I have a Python script which does something with just built executable. And I want CMake to rebuild that executable if the script was modified (actually it is enough to just re-run the script, but rebuild an executable is fine too).
add_executable(App src/main.cpp)
add_custom_command(
TARGET App
POST_BUILD
COMMAND "${Python3_EXECUTABLE}" ARGS "scripts/do_stuff.py" "$<TARGET_FILE:App>"
WORKING_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}"
)
How can I achieve that? add_custom_command with TARGET argument doesn't support DEPENDS argument. add_dependency(App "scripts/do_stuff.py") produces an error, because "scripts/do_stuff.py" is not a target, but just a file.
Running the script is very important for correct working of the executable so I don't want define completely separate target via add_custom_command allowing bypass script execution by building just App target.

actually it is enough to just re-run the script
So the executable does not depend on the script. So re-run the script, not the executable.
add_executable(app src/main.cpp)
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/did_do_stuff
COMMAND "${Python3_EXECUTABLE}" "scripts/do_stuff.py" "$<TARGET_FILE:app>"
COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/did_do_stuff
DEPENDS "$<TARGET_FILE:app>"
"${CMAKE_CURRENT_LIST_DIR}/scripts/do_stuff.py"
WORKING_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}"
)
add_custom_target(do_stuff
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/did_do_stuff
)
And build target do_stuff (or all) to run it.

Related

Cmake add_custom_command is never running

My question is very similar to cmake: add_custom_command / add_custom_target ignoring dependency
But the answer specified does not solve my issue, and also it is for a newer version of cmake (3.20)
I want some files (shader files) to be copied to the executable directory every time the shader source changes
So I have the following code in cmake:
add_custom_command(
OUTPUT ${CMAKE_BINARY_DIR}/Shaders.txt
COMMAND ${CMAKE_COMMAND} -E echo "Actually Copying shaders"
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/assets/ $<TARGET_FILE_DIR:Editor>/assets
COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_BINARY_DIR}/Shaders.txt
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/assets
)
add_custom_target(CopyShaders ALL DEPENDS ${CMAKE_BINARY_DIR}/Shaders.txt)
Now, as I understand, CopyShaders will always be built (since it is always out of date), but Shaders.txt should only be built once (after the shader source is changed), after which it is up to date
I'm trying to build the target CopyShaders using cmake --build build --target CopyShaders
If I'm using MinGW, then "Actually copying shaders" never gets printed if Shaders.txt is present, even if the assets folder containing the shaders has been modified
If I'm using MSVC, I get the following warning on the terminal:
warning MSB8064: Custom build for item "D:\Acads\Programming\opengl\SummerOfCode\build\CMakeFiles\05fb3856b7a5e1f6ce1ea66ca9091779\Shaders.txt.rule" succeeded, but specified dependency "d:\acads\programming\opengl\summerofcode\editor\assets" does not exist. This may cause incremental build to work incorrectly. [D:\Acads\Programming\opengl\SummerOfCode\build\Editor\CopyShaders.vcxproj]
Again, I do have the folder existing
I figured it out
DEPENDS should only take as input files, not folders
Replacing it with all the files inside /assets works

Run PowerShell or Shell script from CMake

I have a (power)shell script that generates a version file used in other source files in the project.
How can I "register" this script to be used with CMake in build time? Here is what I have tried:
function(version)
set(SRC version.h)
set(VERSION_CMD ${CMAKE_SOURCE_DIR}/fw_lib/version/version.ps1)
ADD_CUSTOM_TARGET(version DEPENDS ${SRC})
ADD_CUSTOM_COMMAND(
OUTPUT ${SRC} COMMAND ${VERSION_CMD}
${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR}
)
endfunction(version)
Note that ${CMAKE_SOURCE_DIR} and ${CMAKE_BINARY_DIR} are input arguments to the script.
I get the following error:
process_begin: CreateProcess(....) failed.
make (e=193): Error 193
How can I make this work?
Maybe it is too late, but for future:
# find Powershell executable
find_program(POWERSHELL_PATH NAMES powershell)
add_custom_command(
TARGET "program"
POST_BUILD
COMMAND ${POWERSHELL_PATH} "Some Powershell command")

Is there a command on CMake to started executable resulted from build?

I'm trying to write generic way to run executable resulted after build using CMake's way.
git clone git#github.com:gargamel/ihatesmurfs.git
cmake -E make_directory build
cmake -Sihatesmurfs -Bbuild
cmake --build build
cmake -E chdir build
Now I want to start executable but on *nix, it's like:
./output
and on Windows:
output.exe
Is there a way to escape this with any possible CMake command?
Expanding on my comment a bit, you can modify the CMakeLists.txt file of the project to include add_custom_command. If your CMake creates an executable named HateSmurfs, you can add the custom command to run the executable after compilation completes:
add_executable(HateSmurfs smurfs.cpp)
# Add this piece of code to run the executable after it is built.
add_custom_command(
TARGET HateSmurfs
POST_BUILD
COMMAND HateSmurfs
)
According to add_custom_command documentation:
COMMAND
If COMMAND specifies an executable target name (created by the add_executable() command) it will automatically be replaced by the location of the executable created at build time.

How to set library path for CTest when building package with dpkg-builpackage?

I'm using CTest in my project. I added simple script to run tests as POST_BUILD. Everything works fine when i build project with make.
The interesting part starts when I'm building package with dpkg-buildpackage. CTest seems to look for libraries in system directories instead of using a currently built one. Is there a way to tell CTest or dpkg-buildpackage to use a currently built library while executing tests?
CMake macro i use:
add_executable(example tests/example.cpp)
target_link_libraries(example my_lib)
enable_testing()
macro(add_unit_test target test)
list(APPEND tests ${test})
add_test(${target} ${test})
endmacro(add_unit_test)
add_unit_test(test_example example)
add_custom_target(all_tests ALL DEPENDS ${tests})
add_custom_command(
TARGET all_tests
COMMENT "Run tests"
POST_BUILD COMMAND ctest ARGS --output-on-failure
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
Okay, so i've figured it out.
Because my lib compiles in CMAKE_BINARY_DIR, all i needed is to add
LD_LIBRARY_PATH prorerty to every test in project.
So macro now looks like this:
macro(add_unit_test target test)
list(APPEND tests ${test})
add_test(${target} ${test})
set_property(TEST ${target} PROPERTY ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}")
endmacro(add_unit_test)

How to have cmake unpack my compiler

In order to ensure that my Linux builds are identical regardless of the distribution the build host uses, I have packaged up my compiler and the sysroot files into a relocatable tar file and checked that into source control.
So the first step in any build (or at least, a step that must be invoked before any compile step) must be to extract this tar file.
If I was using a makefile, this would be simple to do. However, the project is using cmake and I can't figure out any way to do it with cmake. It might even be that I need this extract step invoked before cmake starts to detect the compiler: I can hard-code the compiler name but if cmake fails if it can't find the compiler then I need the unpack to happen before that test.
Is this possible with cmake?
You can use execute_process to invoke cmake's cross-platform command mode (cmake -E tar). The command would be something like:
execute_process(COMMAND ${CMAKE_COMMAND} -E tar xvf MyCompiler.bz2)
The command which causes CMake to check for a valid compiler is project, so as long as you have your execute_process call before the project call, the unpacking will be done before the compiler check.