CMake: How to add a custom command that is only executed for one configuration?
Asked Answered
S

1

9

I want to add a cmake custom command that is only executed when the custom target is build in the Debug configuration while using the Visual Studio multi-config generator. Is there a clean way to do this?

In order to implement this, I first tried wrapping the whole command list in a generator expression like this.

add_custom_command(
    ...
    COMMAND $<$<CONFIG:Debug>:cmake;-E;echo;foo>
)

But this gives me a syntax error when the command is executed. After some trial-and-error I got the following hacky solution to work. This wraps each word of the command list in a generator expression like this.

add_custom_command(
    ...
    COMMAND $<IF:$<CONFIG:Debug>,cmake,echo>;$<IF:$<CONFIG:Debug>,-E, >;$<IF:$<CONFIG:Debug>,echo, >;$<IF:$<CONFIG:Debug>,foo, >
)

This executes the cmake -E echo foo command when compiling the Debug configuration and the dummy command echo " " " " " " for all other configurations.

This is quite ugly and the dummy command must be changed depending on the host system. On Linux it could be ":" ":" ":" ":". So Is there a cleaner way to do this?

Thank you for your time!

Siren answered 2/8, 2017 at 8:21 Comment(7)
Why not simply if (CMAKE_BUILD_TYPE STREQUAL "Debug") add_custom_command(...) endif()?Archle
or why not simply make two custom targets?Tongue
FYI, skypjack, CMAKE_BUILD_TYPE STREQUAL "Debug" is not valid for Visual Studio projects. The use of CONFIG is required in this case, but it is a build-type property since it is not know until then. You probably want to execute a cmake script in your add_custom_command and pass it the value of CONFIG with something like -DBUILD_CONFIG=$<CONFIG>. Then, in the script you can determine if BUILD_CONFIG equals "DEBUG", etc and act accordingly. That is slightly different than your request though.Communize
@Communize I've not put the comment in an answer for I'm not used to using VS actually. Thank you for the clarification.Archle
@Communize Ok, I see that that would work. However, it requires an extra script file and the overhead of starting an extra process. It would be nicer if cmake offered that functionality without adding the extra complexity.Siren
CMake can't offer that functionality. CMake is a build config generation tool. The build is done by the compilers. VS is a multi-configuration build tool. The only time the current configuration is known is at build time. The best CMake can do is add a build time command. It has no way of knowing what you will select when it comes time to run the build.Communize
@Communize Well they could make the first thing I tried work ''''COMMAND $<$<CONFIG:Debug>:cmake;-E;echo;foo>'''' by allowing lists within generator expressions and executing no commmand if the COMMAND argument is an empty string.Siren
B
7

Here is my piece of code (tested on several single- and multi-configuration platforms):

CMakeLists.txt

cmake_minimum_required(VERSION 3.8)

project(DebugEchoFoo NONE)

string(
    APPEND _cmd
    "$<IF:$<CONFIG:Debug>,"
        "${CMAKE_COMMAND};-E;echo;foo,"
        "${CMAKE_COMMAND};-E;echo_append"
    ">"
)

add_custom_target(
    ${PROJECT_NAME}
    ALL
    COMMAND "${_cmd}"
    COMMAND_EXPAND_LISTS
)

Note: COMMAND_EXPAND_LISTS is keyword is only available with CMake version >= 3.8

Reference

Begot answered 16/11, 2017 at 21:53 Comment(1)
Without having tested it, i mark your answer as correct. Now I only have to whait until we can use generator expressions in the OUTPUT (gitlab.kitware.com/cmake/cmake/issues/12877)Siren

© 2022 - 2024 — McMap. All rights reserved.