Calling a macro or a function at POST_BUILD step [duplicate] - cmake

This question already has an answer here:
How to call a CMake function from add_custom_target/command?
(1 answer)
Closed 3 years ago.
CMake's add_custom_command() allows one to run a command (through the COMMAND option) before or after building the target (using PRE_BUILD, PRE_LINK and POST_BUILD). The command can be an executable or external "script", but not a CMake macro/function.
Is there a similar command like add_custom_command(), which instead allows passing of a CMake function/macro and schedule it before/after a target was built?
If not, what options are there, besides implementing the COMMAND as a re-run of CMake with a flag that enables the functionality inside the function/macro?
[EDIT] The function/macro will take as input the CMake target name and a target specific directory path.

The command can be a CMake macro or function. You just have to encapsulate it in a CMake file. CMake's add_custom_command() supports running further CMake code as a script, with the -P option. You can pass arguments to the function using the -D option as well. For this example, we will pass two arguments, TARGET_NAME and TARGET_PATH:
# Define the executable target.
add_executable(MyExecutable ${MY_SRCS})
add_custom_command(TARGET MyExecutable
POST_BUILD
COMMAND ${CMAKE_COMMAND}
-DTARGET_NAME=MyExecutable
-DTARGET_PATH=${CMAKE_CURRENT_SOURCE_DIR}
-P ${CMAKE_SOURCE_DIR}/my_script.cmake
COMMENT "Running script..."
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
The my_script.cmake file can include one or more pre-defined CMake functions, then call those functions, with something like this:
include(my_function.cmake)
# Call the function, passing the arguments we defined in add_custom_command.
my_function(${TARGET_NAME} ${TARGET_PATH})
For completeness, the CMake function my_function could look like this:
# My CMake function.
function(my_function target_name target_path)
message("Target name: ${target_name}")
message("Target directory: ${target_path}")
endfunction()

Related

How to change the default target in Makefile generated by CMake

I want to produce a makefile through CMake not to set default_target as all.
Through Unix Makefiles generator option, CMake generates Makefile like this
default_target: all
.PHONY : default_target
In my case, I want to produce a document generated by doxygen when I call make all, excepting make.
cmake ..
make // build without doxygen
make all // build with doxygen
I want to build files to exclude Doxygen when make in shell
But, I want to build all of files when make all.
Therefore, I am looking for information how to change the default target in Makefile generated by CMake.
Doxygen is declared in CMakeLists.txt like this:
set(document_files ${.....}/document/html)
add_custom_target(doxygen ALL
DEPENDS ${document_files})
# Documentation command
add_custom_command(OUTPUT ${document_files}
COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT}
COMMAND ${CMAKE_COMMAND} -E touch ${document_files}
WORKING_DIRECTORY ${.....}/../docs
COMMENT "Generating API documentation with Doxygen"
VERBATIM )

CMake: dependecies of add_custom_command

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.

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.

CMake: Generated input dependency to configure_file

I would like to run configure_file() whose input file is generated using add_custom_command, through a custom dependency, before installing the output of configure_file.
I'm in reality using a ruby script to read a cmake formatted file, to extract
a few definitions which i can convert to Ruby constants in a separate library. Thus, i require the configure_file such that cmake can replace its internal variables in the ruby generated file, whose goal is to export these variables.
Thus far, I've attempted the following:
# Custom command to build the out.rb.in
add_custom_command (
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/output.rb.in"
COMMAND ruby ${CMAKE_CURRENT_SOURCE_DIR}/build_ruby_output.rb
-i ${CMAKE_CURRENT_SOURCE_DIR}/input.cmake
-o ${CMAKE_CURRENT_BINARY_DIR}/output.rb.in
)
# Custom target is required to build it
add_custom_target (
dummy_target_xxx ALL DEPENDS
"${CMAKE_CURRENT_BINARY_DIR}/output.rb.in"
)
configure_file (
"${CMAKE_CURRENT_BINARY_DIR}/output.rb.in"
"${CMAKE_CURRENT_BINARY_DIR}/output.rb"
)
install (
FILES "${CMAKE_CURRENT_BINARY_DIR}/output.rb"
DESTINATION "${RUBY_VENDOR_LIBDIR}/myvendor"
)
CMake complains with the error
CMake Error: File /home/user/myproject/build/output.rb.in does not exist.
CMake Error at CMakeLists.txt:35 (configure_file):
configure_file Problem configuring file
when running an out-of-tree build. Any ideas?
configure_file() is executed immediately at configuration step, while add_custom_command() add command to be executed(and dependency to be evaluated) at build step.
You may either replace add_custom_command with appropriate execute_process call, so your ruby script will be executed at configuration step, and its output file will be ready for configure_file.
Or you may replace configure_file with appropriate add_custom_command, so your file will be configured at build step, and will see dependencies. The problem here that you should explicitely pass CMake variables, used in "output.rb.in" file, to the configuration program, which can be, e.g.,
${CMAKE_COMMAND} [-D<var-definition>]+ -P <cmake-script-file-which-calls-configure_file>
In this particular case, it was sufficient to reorder to configuration operation, by performing configure_file() first, and pipe the output of this into the custom command.. I was merely thinking of the ordering all wrong.
I still do not have an answer for adding generated dependency to the input of configure_file()
Complete code
configure_file (
"${CMAKE_CURRENT_SOURCE_DIR}/input.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/output.rb.in"
)
# Custom command to build the output.rb
add_custom_command (
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/output.rb"
COMMAND ruby ${CMAKE_CURRENT_SOURCE_DIR}/build_ruby_output.rb
-i ${CMAKE_CURRENT_BINARY_DIR}/output.rb.in
-o ${CMAKE_CURRENT_BINARY_DIR}/output.rb
)
# Custom target is required to build it
add_custom_target (
dummy_target_xxx ALL DEPENDS
"${CMAKE_CURRENT_BINARY_DIR}/output.rb"
)
install (
FILES "${CMAKE_CURRENT_BINARY_DIR}/output.rb"
DESTINATION "${RUBY_VENDOR_LIBDIR}/myvendor"
)