add_custom_target that DEPENDS on all and another target [duplicate] - cmake

I have a custom target, and I want it to depend on the default target (the one that is built with make).
add_custom_target(foo ....)
add_dependency(foo default_target_name_goes_here)
What is the name of the default target?
I've tried ALL, ALL_BUILD, MyProjectsName, DEFAULT,...
Finding anything in the CMake documentation is always an unsuccessful adventure...
UPDATE: it seems CMake was designed in such a way that this is extremely hard to fix/implement: bugreport getting +1's since 2009. Who indeed would like to have a custom target that depends on, for example, the all target? Or in other words: who does ever write make && make test?...

The default build target does not exist as a CMake target at CMake configure time. It is only exists in the generated build system. Therefore it is not possible to have the default target depend on a custom target.

I think a possible solution depends strongly on the use case. E.g. if this is for executing a test after the system has been build you would use CTest instead of calling make directly.
To your CMakeLists.txt you would add:
add_test(NAME foo COMMAND ...)
and then use CTest for building and executing:
ctest --build-and-test ...
More generally speaking and not considering the question of why you would like to do it - I think the best thing would be to just name and rely on concrete target dependencies instead of just taking ALL targets - I just wanted to add two possibilities to do what you wanted to do.
One would be to determine/track the list of all targets used as discussed here. This would look e.g. for library targets like this (getting your own/private GlobalTargetList):
macro(add_library _target)
_add_library(${_target} ${ARGN})
set_property(GLOBAL APPEND PROPERTY GlobalTargetList ${_target})
endmacro()
and use it at the end of your main CMakeLists.txt with
get_property(_allTargets GLOBAL PROPERTY GlobalTargetList)
add_dependencies(foo ${_allTargets})
Edit: Global BUILDSYSTEM_TARGETS property was released with CMake 3.7
The second - less favorable - approach does require that the foo target is not part of the ALL build (otherwise you end-up in an endless loop):
add_custom_target(foo)
set_target_properties(foo PROPERTIES EXCLUDE_FROM_ALL 1)
add_custom_command(
TARGET foo
PRE_BUILD
COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target ALL_BUILD --config $<CONFIGURATION>
)

Related

Why do we need one more add_custom_command in cmake? [duplicate]

In CMake semantics there is some sort of distinction between "targets" and commands" that is baffling me. In Makefiles, there is no such distinction:
targetname:dependency
command
i.e. Targets correspond to a generated file of the same name.
In CMake you have commands like "add_custom_command" and "add_custom_target" that have overlapping functionality, and even in the official documentation the semantics are confused, i.e. in "Mastering CMake, 5th edition", page 110 under "Adding a custom target":
The DEPENDS argument sets up a dependency between the custom target
and the custom commands.
My understanding is that targets (generated files) have dependencies (other files, generated or no), and a command to actually do the generation. It is nonsensical to say a target depends on a command. To make matters worse, there are two flavors of "add_custom_command" that either attach an additional command to an existing target, or spit the command out into the ether.
Can someone please explain why this distinction even exists?
Targets
In general, targets comprise executables or libraries which are defined by calling add_executable or add_library and which can have many properties set.
They can have dependencies on one another, which for targets such as these just means that dependent ones will be built after their dependencies.
However, you can also define "custom targets" via add_custom_target. From the docs:
Adds a target with the given name that executes the given commands. The target has no output file and is ALWAYS CONSIDERED OUT OF DATE even if the commands try to create a file with the name of the target. Use ADD_CUSTOM_COMMAND to generate a file with dependencies. By default nothing depends on the custom target. Use ADD_DEPENDENCIES to add dependencies to or from other targets.
So these are different from "normal" targets in that they don't represent things which will produce an exe or lib, but they still benefit from all the properties that targets can have, including having or being dependencies. They appear as a target which can be built (e.g. make MyCustomTarget or msbuild MyCustomTarget.vcxproj). When you build them, you're simply invoking the commands that have been set for them. If they have dependencies on other targets (normal or custom), then these will be built first.
Custom Commands
A custom command defined via add_custom_command is quite different in that it's not a "buildable" object, and doesn't have settable properties in the way that a target does - it's not a named object which can be explicitly referred to again after it's added in the CMakeLists.txt.
It is basically a command (or set of commands) which will be invoked before building a dependent target. That's all that "depends" really means here (at least that's how I view it) - it's just saying that if A depends on B, then B will be built/executed before A is built.
The dependees of a custom command can be either set explicitly using the add_custom_command(TARGET target ... form, or implicitly by creating targets which include the files generated via the add_custom_command(OUTPUT output1 ... form.
In the first case, every time target is built, the custom command is executed first.
In the second case, it's a little more complex. If the custom command has targets which depend on its output file (and the output file doesn't already exist), it is invoked before these dependent objects are built. The dependencies are implicitly created when you do e.g. add_library(MyLib output1.h ... ) where output1.h is a file generated via add_custom_command(OUTPUT output1.h ... ).
add_custom_command adds a callable function that can have defined outputs (using the OUTPUT and BYPRODUCTS arguments). It can also have dependencies that will be run before the function is called.
Notice that it does NOT do things that you may think it does due to strange documentation (the makefile examples are very misleading). In particular, it does not have any guarantees about numbers of times it executes. For example, imagine this:
add_custom_command(OUTPUT /tmp/touched COMMAND echo touch COMMAND touch /tmp/touched)
add_custom_target(touched-one ALL DEPENDS /tmp/touched)
add_custom_target(touched-two ALL DEPENDS /tmp/touched)
How many times will "touch" be printed? You don't know, since it's not specified anywhere; make -j2 will print it twice, probably, but it's timing-dependent:
Scanning dependencies of target touched-two
Scanning dependencies of target touched-one
[ 50%] Generating touched
touch
[100%] Generating touched
touch
[100%] Built target touched-two
[100%] Built target touched-one
But Ninja will only print it once, probably:
# rm -rf * && cmake -GNinja ../c ; cmake --build . -- -j 5
[1/1] Generating touched
touch
Usually, you'll do an add_custom_command to do some work and that defines an OUTPUT, and then you'll have an add_custom_target that depends on the output of the custom command. Anyone who wants the output depends on the target, and that does give you the guarantees you want.
Caveat: see this bug for an great example of why building cross-platform metabuild tools is REALLY HARD.

Do something for all targets

What is the best way to do additional stuff for all (binary) targets?
Examples:
I want to check that each library name follows a pattern.
I want to sign each executable.
I dont what the C/C++ developers to use nonstandard commands (like add_library2). I want them to use and learn the official CMake functions, but have them do additonal, project specific, stuff.
The built-in CMake functions add_library and add_executable can be overidden by defining CMake functions of the same name. E.g., to automatically sign all added executables add the following code:
function (add_executable _name)
_add_executable(${ARGV})
if (TARGET ${_name})
add_custom_command(TARGET ${_name} POST_BUILD
COMMAND sign_executable $<TARGET_FILE:${_name}>)
endif()
endfunction()
The original built-in add_executable can be invoked by prefixing it with an underscore character. The same pattern can be applied to add_library to check the name of the library.
You can overwrite any CMake command/function to extend its functionality, but please
Call Things by their Names
I strongly advocate to call the things by their names and not doing things implicitly. It will be easier for everybody using/maintaining/debugging your CMake based project.
If you want to sign your executable - and that's probably even platform specific - you create a function like add_post_build_step_sign_executable() which would add the appropriate post build steps:
add_executable(MyExe main.cpp)
if (WIN32)
add_post_build_step_sign_executable(MyExe)
endif()
And if you have to repeat yourself too often put that code snippet into a function like my_project_add_signed_executable() itself. It could still have the same parameter syntax as CMake's add_executable() command.
Runtime Checks vs. Static Code Analysis
Regarding library naming checks, I see this more like checking against your project's CMake script coding styles and would not use runtime checks for this.
For example you could use something like cmake-lint or your own external script to check for conformity.
References
How to frame the concept behind CMake?
cmake: get add_library() names
How to ensure consistent coding style for CMakeLists.txt and FindXXX.cmake

What does CMAKE_BUILD_TYPE affect, other than the compiler flag selection?

I know that if if we set -DCMAKE_BUILD_TYPE=Release (or Debug etc.), then the values of CMAKE_C_FLAGS_RELEASE and CMAKE_CXX_FLAGS_RELEASE will be appended to CMAKE_C_FLAGS and CMAKE_C_FLAGS respectively.
But is this the only effect of setting the build type? If not, what are the other effects?
Actually, build type affects on many things. Among them:
generator expressions:
Expression $<$<CONFIG:DEBUG>:XXX> will be expanded to XXX with CMAKE_BUILD_TYPE set to Debug and to nothing otherwise.
Because generator expressions can be used in a number of commands, setting build type affects all commands which uses expressions dependent on build type.
libraries added by target_link_libraries with debug keyword take an effect only in Debug build type.
Similar to optimized keyword.
(Implicitely, this uses generator expressions described above).
Some properies of IMPORTED libraries.
Properties like IMPORTED_LOCATION have config-specific variants, which are choosen dependent on configuration type.
Often IMPORTED libraries are created as a result of find_package() call, so your project may be linked with 3d-party project in configuration-dependent manner.
CONFIGURATION-specific part of install command.
Only those CONFIGURATION <conf> part are applies, which corresponds to active configuration.
Multi-configuration tools doesn't use CMAKE_BUILD_TYPE variable, but they still have a notion of the "build type". That build type is NOT known at configuration stage, when CMake parses CMakeLists.txt, it is set only when performing a build of the project. Nevertheless, this build type "retroactively" affects on all properties described above.
Also, with multi-configuration build tools selected build type is appended to the location of output artifacts, like executables and libraries (see e.g. description of RUNTIME_OUTPUT_DIRECTORY target's property).

Why does CMake make a distinction between a "target" and a "command"?

In CMake semantics there is some sort of distinction between "targets" and commands" that is baffling me. In Makefiles, there is no such distinction:
targetname:dependency
command
i.e. Targets correspond to a generated file of the same name.
In CMake you have commands like "add_custom_command" and "add_custom_target" that have overlapping functionality, and even in the official documentation the semantics are confused, i.e. in "Mastering CMake, 5th edition", page 110 under "Adding a custom target":
The DEPENDS argument sets up a dependency between the custom target
and the custom commands.
My understanding is that targets (generated files) have dependencies (other files, generated or no), and a command to actually do the generation. It is nonsensical to say a target depends on a command. To make matters worse, there are two flavors of "add_custom_command" that either attach an additional command to an existing target, or spit the command out into the ether.
Can someone please explain why this distinction even exists?
Targets
In general, targets comprise executables or libraries which are defined by calling add_executable or add_library and which can have many properties set.
They can have dependencies on one another, which for targets such as these just means that dependent ones will be built after their dependencies.
However, you can also define "custom targets" via add_custom_target. From the docs:
Adds a target with the given name that executes the given commands. The target has no output file and is ALWAYS CONSIDERED OUT OF DATE even if the commands try to create a file with the name of the target. Use ADD_CUSTOM_COMMAND to generate a file with dependencies. By default nothing depends on the custom target. Use ADD_DEPENDENCIES to add dependencies to or from other targets.
So these are different from "normal" targets in that they don't represent things which will produce an exe or lib, but they still benefit from all the properties that targets can have, including having or being dependencies. They appear as a target which can be built (e.g. make MyCustomTarget or msbuild MyCustomTarget.vcxproj). When you build them, you're simply invoking the commands that have been set for them. If they have dependencies on other targets (normal or custom), then these will be built first.
Custom Commands
A custom command defined via add_custom_command is quite different in that it's not a "buildable" object, and doesn't have settable properties in the way that a target does - it's not a named object which can be explicitly referred to again after it's added in the CMakeLists.txt.
It is basically a command (or set of commands) which will be invoked before building a dependent target. That's all that "depends" really means here (at least that's how I view it) - it's just saying that if A depends on B, then B will be built/executed before A is built.
The dependees of a custom command can be either set explicitly using the add_custom_command(TARGET target ... form, or implicitly by creating targets which include the files generated via the add_custom_command(OUTPUT output1 ... form.
In the first case, every time target is built, the custom command is executed first.
In the second case, it's a little more complex. If the custom command has targets which depend on its output file (and the output file doesn't already exist), it is invoked before these dependent objects are built. The dependencies are implicitly created when you do e.g. add_library(MyLib output1.h ... ) where output1.h is a file generated via add_custom_command(OUTPUT output1.h ... ).
add_custom_command adds a callable function that can have defined outputs (using the OUTPUT and BYPRODUCTS arguments). It can also have dependencies that will be run before the function is called.
Notice that it does NOT do things that you may think it does due to strange documentation (the makefile examples are very misleading). In particular, it does not have any guarantees about numbers of times it executes. For example, imagine this:
add_custom_command(OUTPUT /tmp/touched COMMAND echo touch COMMAND touch /tmp/touched)
add_custom_target(touched-one ALL DEPENDS /tmp/touched)
add_custom_target(touched-two ALL DEPENDS /tmp/touched)
How many times will "touch" be printed? You don't know, since it's not specified anywhere; make -j2 will print it twice, probably, but it's timing-dependent:
Scanning dependencies of target touched-two
Scanning dependencies of target touched-one
[ 50%] Generating touched
touch
[100%] Generating touched
touch
[100%] Built target touched-two
[100%] Built target touched-one
But Ninja will only print it once, probably:
# rm -rf * && cmake -GNinja ../c ; cmake --build . -- -j 5
[1/1] Generating touched
touch
Usually, you'll do an add_custom_command to do some work and that defines an OUTPUT, and then you'll have an add_custom_target that depends on the output of the custom command. Anyone who wants the output depends on the target, and that does give you the guarantees you want.
Caveat: see this bug for an great example of why building cross-platform metabuild tools is REALLY HARD.

CMake : Changing name of Visual Studio and Xcode exectuables depending on configuration in a project generated by CMake

What I need to do is to setup my excecutable name to be
program-debug for debug builds and
program-release(or whatever) for other builds
I want to do it in a true cross-platform way and what is also very important - I want to target XCode and VS2008 - so when I change configuration in a kind of drop-down list, it must also have correct names for output! I do no want to regenerate .vcproj or .xcodeproj with other -D option (but I will have to if will not found a solution)
AFAIK cmake variable CMAKE_BUILD_TYPE should work for make-based generators - in is evaluated at make time (Correct me if I am wrong)
Basically it is how to setup target options (not nessesary name) depending on configuration in some IDEs/build system. It can be too specific for overall cmake goals, but maybe you can help.
Thanks a lot!
Take a look at the list of target properties: One of those is the OUTPUT_NAME and OUTPUT_NAME_<CONFIG>. The last one can be set for each config-type (Debug, Release, MinSizeRel, etc.) You can set them on your program with set_target_properties, e.g.:
project( YourProject )
add_executable( myprogram ${YourSources} )
set_target_properties( myprogram PROPERTIES OUTPUT_NAME_DEBUG program-debug )
set_target_properties( myprogram PROPERTIES OUTPUT_NAME_RELEASE program-release )
Take care that you need to set RUNTIME_OUTPUT_NAME_<CONFIG> and/or LIBRARY_OUTPUT_NAME_<CONFIG> as well in some cases.