I have target for shared and want it to run command after build ONLY if the Target output file changed, or same for me if build is updating.
In my example command runes every time when I build project, but I need it to run Only if after build Target output file changed
cmake_minimum_required(VERSION 3.21)
project(myexp)
add_library(Example SHARED source.cpp)
set_target_properties(Example PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bin$<0:>"
)
add_custom_command(TARGET Example POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:Example> ${CMAKE_CURRENT_SOURCE_DIR}/new
DEPENDS Example
)
DEPENDS doesnt work here
from documentation - add_custom_command
The second signature adds a custom command to a target such as a library or executable.
This is useful for performing an operation before or after building the target.
The command becomes part of the target and will only execute when the target itself is
built.
If the target is already built, the command will not execute.
maybe my understanding of this is wrong
is there a way to Multi-OUTPUT
THANK YOU
Related
I am running into a problem where I want to run a bash script to modify the headers inside the framework. Please see below minimal example.
cmake_minimum_required(VERSION 3.20)
project(example)
add_library(${PROJECT_NAME} A.cpp A.h)
set_target_properties(${PROJECT_NAME} PROPERTIES FRAMEWORK TRUE PUBLIC_HEADER
A.h)
add_custom_command(
TARGET ${PROJECT_NAME}
POST_BUILD
WORKING_DIRECTORY $<TARGET_FILE_DIR:${PROJECT_NAME}>/Headers
COMMAND bash ${CMAKE_SOURCE_DIR}/do_something_to_the_headers_in_framework.sh)
However, this sometimes works correctly and sometimes it works incorrectly, and I am 99% sure it is because once the target is built, cmake internally runs a POST_BUILD add_custom_command that copies the headers into the framework. Therefore, there is no guarantee which POST_BUILD command runs first, if the command that copies the headers into the framework runs first, then the result will be correct. On the flip side, if my do_something_to_the_headers_in_framework.sh got executed first, the result will be incorrect.
Is there a way to append new POST_BUILD commands to existing ones so we can ensure the POST_BUILD commands are executed in the desired order?
I'm trying to automatically call editbin with some options from within a cmake script after the executable has been build. So far without any luck.
is there any example for using editbin in cmake?
is there an example for using any executable in cmake after an executable has been build?
You can use add_custom_command for build events, that is, it will be executed each time you build your target.
From the docs:
A POST_BUILD event may be used to post-process a binary after linking. For example, the code:
add_executable(myExe myExe.c)
add_custom_command(
TARGET myExe POST_BUILD
COMMAND someHasher -i "$<TARGET_FILE:myExe>"
-o "$<TARGET_FILE:myExe>.hash"
VERBATIM)
will run someHasher to produce a .hash file next to the executable after linking.
As for VERBATIM:
All arguments to the commands will be escaped properly for the build tool so that the invoked command receives each argument unchanged. Note that one level of escapes is still used by the CMake language processor before add_custom_command even sees the arguments. Use of VERBATIM is recommended as it enables correct behavior. When VERBATIM is not given the behavior is platform specific because there is no protection of tool-specific special characters.
So in your case you first need to find an executble for editbin and then add your command:
add_custom_command(TARGET target_name POST_BUILD
COMMAND "${editbin_exe} $<TARGET_FILE:target_name>")
Where $<TARGET_FILE:target_name> is a generator expression which yields a path to the output binary file of target target_name.
In cmake there is custom commands, which can run PRE_BUILD or PRE_LINK or POST_BUILD.
However, on most platforms, except Visual Studio apparently, PRE_BUILD and PRE_LINK are idendical.
There are plenty of posts here about this issue, all stating this fact but noone giving a possible solution to "acutally PRE BUILD do something".
I for example need to run a bash script which will create some headers (c and c++ headers) automatically, and the source depends on them being A.) available and B.) defining certain things.
Is there an alternative to the custom command in cmake? How is it possible to execute something before the cmake process takes over and starts compiling things?
add_custom_command(TARGET ${PROJECT_NAME}
PRE_BUILD <---------------------------------------- THIS IS PRE_LINK unfortunatelly!
COMMAND ../my_bash_script.sh
DEPENDS ${PROJECT_NAME}
VERBATIM
)
I am trying to embed the build date into a source file, so that every time a specific target gets built, the embedded date is refreshed, without regenerating every time the overall project built.
I.e. I have a header file builddate.h that is generated by a command that has a set of #defines. This header file is then included from other source files.
My first attempt was this:
add_custom_target(builddate COMMAND <command that generates header file>)
add_library(mylibrary ...)
add_dependencies(mylibrary builddate)
This correctly generates the header file, however the header file is generated every time, regardless of whether the mylibrary target needs to be rebuilt.
Trying with a custom command instead, i.e.
add_custom_command(OUTPUT builddate.h COMMAND <command that generates header file>)
add_library(mylibrary ... builddate.h)
correctly generates the header once, but if the mylibrary target is rebuilt, the header is not regenerated as builddate.h is already up to date.
This feels like something that should be reasonably common, but I cannot figure out what incantation of custom commands and targets will give me the desired effect. What I want is to call the command every time the mylibrary target is built, without spurious rebuilds if nothing has changed or if unrelated targets (such as executables using mylibrary) are built.
Using a PRE_BUILD custom command would sound like a good idea, but the docs state that this gets invoked just prior to PRE_LINK commands for generators other than Visual Studio, i.e. after sources are compiled. This seems like it would make this unsuitable for this purpose, as the header is needed while compiling the sources.
Found an old thread at https://cmake.org/pipermail/cmake/2010-October/040247.html suggesting to call CMake's --build for a target as a PRE_LINK command:
# This is the library that I want to build
add_library(mylibrary ...)
# Set up a library that contains the code depending on the build date
# Use an OBJECT library because we don't need it to be a full static lib
# we just want to build some source that would "normally" have been part of mylibrary
add_library(builddate OBJECT EXCLUDE_FROM_ALL codethatusesbuilddate.cpp)
# Add a PRE_LINK command for mylibrary so that prior to linking we
# 1. Generate the builddate.h header
# 2. Call CMake to build the builddate library we just set up
add_custom_command(
TARGET mylibrary PRE_LINK
COMMAND <command that generates builddate.h>
COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target builddate
)
# We also need to link with the library
# NOTE: uses the generator expression to link with the output files rather than the target
# to avoid CMake setting up a dependency from builddate to mylibrary which I think
# would cause builddate to be built prior to building mylibrary, but at that point we
# haven't generated the header yet. Which we could fix, but then we'd just build it twice
target_link_libraries(mylibrary PRIVATE $<TARGET_OBJECTS:builddate>)
This feels a little awkward, but it seems to work.
Footnote: Generating the header is easily done using CMake, i.e. first configure_file or similar to create a CMake script that does the generation, then invoke ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/generated_cmake_file.cmake as the command to generate the header.
Some time ago, I wrote a cmake makro. It adds custom command to generate version.cpp in current build directory by executing Cversion.cmake.
The generation of file is executed only when dependencies have changed.
With cmake-generator-expressions dependencies are set to dependencies of target minus its own (files).
It could be improved by adding libs dependencies to also generate anew version file.
macro(add_versioning T)
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/version.cpp"
COMMAND ${CMAKE_COMMAND} "-DCMAKE_CURRENT_BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR}"
-P "${PROJECT_SOURCE_DIR}/Version/CVersion.cmake"
MAIN_DEPENDENCY "${PROJECT_SOURCE_DIR}/Version/version.cpp.in"
DEPENDS "$<FILTER:$<TARGET_OBJECTS:${T}>,EXCLUDE,version.cpp.+$>")
target_include_directories(${T} PUBLIC "${PROJECT_SOURCE_DIR}/Version")
target_sources(${T} PUBLIC "${PROJECT_SOURCE_DIR}/Version/version.h" PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/version.cpp")
endmacro()
Part of my source code is generated by a tool which is also built under our main project with a add_subdirectory. We execute this tool with a execute_process command. Clearly, if the tool is not built before we reach the execute_process statement it will fail.
I use a GLOB (file(GLOB...)) to find the source files generated. I do this because it is not possible to know beforehand how many files are generated, neither their names.
How do I force cmake to wait for the subproject to be compiled before the execute process? I would need something like a DEPENDS property for the execute_process but this option is not available.
# This subproject will source generator the tool
add_subdirectory(generator)
# I need something like: wait_for(generator)
execute_process(COMMAND generator ${CMAKE_SOURCE_DIR}/src)
file(GLOB GeneratedSources ${CMAKE_SOURCE_DIR}/src/*.cpp)
add_executable(mainprject.exe ${ProcessorSourceFiles}
Command execute_process executes its COMMAND immediately, at configuration stage. So it cannot be arranged after the executable is created with add_executable command: that executable will be built only at build stage.
You need to build subproject at configuration stage too. E.g. with
execute_process(COMMAND ${CMAKE_COMMAND}
-S ${CMAKE_SOURCE_DIR}/generator
-B ${CMAKE_BINARY_DIR}/generator
-G ${CMAKE_GENERATOR}
)
execute_process(COMMAND ${CMAKE_COMMAND}
--build ${CMAKE_BINARY_DIR}/generator
)
The first command invokes cmake for configure the 'generator' project, located under ${CMAKE_SOURCE_DIR}/generator directory. With -G option we use for subproject the same CMake generator, as one used for the main project.
The second command builds that project, so it produces generator executable.
After generator executable is created, you may use it for your project:
execute_process(COMMAND ${CMAKE_BINARY_DIR}/generator/<...>/generator ${CMAKE_SOURCE_DIR}/src)
Here you need to pass absolute path to the generator executable as the first parameter to COMMAND: CMake no longer have generator executable target, so it won't substitute its path automatically.
You will need to model this with target dependencies. The tool "generator" should be a cmake target. In that case use add_custom_target instead of execute_process somthing like this:
add_custom_target(generate_sources ALL COMMAND generator ${CMAKE_SOURCE_DIR}/src))
Then add a target dependency to "generator" using add_dependencies:
add_dependencies(generate_sources generator)
This will make sure your target "generate_sources", which runs the tool will only run during build after the target "generator" has been compiled.
The following is false, see the comments for more info:
Use add_dependencies to add a dependency from "mainproject.exe" to "generate_sources". Now this I have never tested, so take with a grain of salt: With CMake more recent than version 3.12, according to the entry on file, you should then be able to change your file command to:
file(GLOB GeneratedSources CONFIGURE_DEPENDS ${CMAKE_SOURCE_DIR}/src/*.cpp)
Which I interpret as this will re-glob the files during build if the directory changes.