CMake add_custom_command() POST_BUILD generator expression expansion not working

1.2k Views Asked by At

I want to run a POST_BUILD action after the build (but only in the Debug configuration).

After reading add_custom_command docs and a possible solution I understood that I can "wrap" my COMMAND into $<CONFIG:Debug> generator expression (to be sure it's "empty" in Release mode).

I tried the following:

cmake_minimum_required(VERSION 3.18)

project(post-build CXX)
file(WRITE main.cxx "int main() {}")
add_executable(foo main.cxx)

add_custom_command(
  TARGET foo POST_BUILD
  COMMAND $<$<CONFIG:Debug>:${CMAKE_COMMAND} -E echo "hi there from debug build">
)

But this gives me the CMake configure-time warnings and a hard failure during a build-time (using Ninja generator):

(...) && "$<1:C:\Program Files\CMake\bin\cmake.exe" -E echo "hi there from debug build" >""
[build] The system cannot find the path specified.
[build] ninja: build stopped: subcommand failed.
[build] Build finished with exit code 1

I tried many possible quotes combinations (including escaped quotes):
COMMAND $<$<CONFIG:Debug>:"${CMAKE_COMMAND} -E echo \"hi there from debug build\"">
and
COMMAND "$<$<CONFIG:Debug>:${CMAKE_COMMAND} -E echo \"hi there from debug build\">" etc.

But even though it removed the configure-time warning, it still yields a hard error during the build-time.

Question: What would be the correct way to achieve what I want? Is it possible like this or there is a CMake limitation here?

(Note: if possible I'd like to keep the whole command be executed in one place. I am also aware of other workaround possible)

1

There are 1 best solutions below

0
On BEST ANSWER

Following the answer of Ben Boeckel here:

Spaces generally aren’t well-formed inside of genexes. You’ll need to replace the spaces with ; to make it parse properly (which is why you’re seeing half-expanded remnants in the build command).

And some discussion in the CMake mailing list (here), what finally worked for me was:

add_custom_command(
  TARGET foo POST_BUILD
  COMMAND "$<$<CONFIG:Debug>:${CMAKE_COMMAND};-E;echo;\"hi there from debug build\">"
  COMMAND_EXPAND_LISTS
)

(Notice the quotes aroung the whole genex, separation with semicolons, backquoting the string, and COMMAND_EXPAND_LISTS to get rid of semicolons in the output -- all-in-all definitely not the most pleasing thing to read)

Edit: This also works:

set(HELLO_FROM_DEBUG ${CMAKE_COMMAND} -E echo "hi there")

add_custom_command(
  TARGET foo POST_BUILD
  COMMAND "$<$<CONFIG:Debug>:${HELLO_FROM_DEBUG}>"
  COMMAND_EXPAND_LISTS
)