Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you make add_custom_command configuration-specific on Windows?

Tags:

cmake

In order to run the unit tests in one of my projects, I have a custom command which copies the executable, libraries, and other related files to somewhere else so that they can be run with a specific setup rather than running them where they're built. On Linux, this is quite straightforward. But on Windows, I've hit a bit of a snag due to the fact that cmake appends the configuration name to the ouput directories (which I like in general, but it screws up what I'm doing in this case). It makes it hard to determine the paths to the generated libraries or executables. For instance, if I had a custom command which just copied the executable to another directory

set(EXE_PATH "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/exeName${CMAKE_EXECUTABLE_SUFFIX}")
set(NEW_EXE_PATH "${RUN_UNITTESTS_DIR}/exeName${CMAKE_EXECUTABLE_SUFFIX}")

add_custom_command(TARGET unitTests POST_BUILD
                   COMMAND ${CMAKE_COMMAND} ARGS -E copy "${EXE_PATH}" "${NEW_EXE_PATH}")

it's going to choke on Windows, because the executable isn't really in CMAKE_RUNTIME_OUTPUT_DIRECTORY. Depending on the configuration type, it's in either ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release or ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Debug. On Linux, that could be trivially fixed by using CMAKE_BUILD_TYPE and adding it to the path, but that doesn't work with Windows, because on Windows, cmake generates multiple configurations rather than just one. So, what I'd like to be able to do is something like

add_custom_command(TARGET unitTests POST_BUILD
                   debug
                   COMMAND ${CMAKE_COMMAND} ARGS -E copy "${DEBUG_EXE_PATH}" "${DEBUG_NEW_EXE}")

add_custom_command(TARGET unitTests POST_BUILD
                   release
                   COMMAND ${CMAKE_COMMAND} ARGS -E copy "${RELEASE_EXE_PATH}" "${RELEASE_NEW_EXE}")

and some cmake commands see to be able to do that (e.g. target_link_libraries), but as far as I can tell, add_custom_target doesn't provide that capability. So, the question is how I would do that? How can I make a custom command be configuration-specific on Windows?

like image 687
Jonathan M Davis Avatar asked Dec 21 '12 19:12

Jonathan M Davis


1 Answers

It could be solved with the help of the next "generator expressions" (CMake 2.8.10):

  • $<0:...> = empty string (ignores "...")
  • $<1:...> = content of "..."
  • $<CONFIG:cfg> = '1' if config is "cfg", else '0'

You can combine them to reach behaviour that you need (pseudocode):

if debug then ${DEBUG_EXE_PATH} elseif release then ${RELEASE_EXE_PATH}

which translates to:

$<$<CONFIG:debug>:${DEBUG_EXE_PATH}>$<$<CONFIG:release>:${RELEASE_EXE_PATH}>

So your string will look like:

add_custom_command(TARGET unitTests POST_BUILD
                       COMMAND ${CMAKE_COMMAND} ARGS -E copy "$<$<CONFIG:debug>:${DEBUG_EXE_PATH}>$<$<CONFIG:release>:${RELEASE_EXE_PATH}>" "$<$<CONFIG:debug>:${DEBUG_NEW_EXE}>$<$<CONFIG:release>:${RELEASE_NEW_EXE}>")

Details: CMake:add_custom_command

like image 143
Vladimir Ivanov Avatar answered Oct 03 '22 01:10

Vladimir Ivanov