C++ – How to get current configuration (Release/Debug) in CMake for Visual Studio

ccmakevisual studiovisual studio 2010visual studio 2012

I am on Visual Studio 2013, CMake 3.5.1, Windows 10. I am trying to copy some files via CMake like below:

file(COPY ${IMAGES} DESTINATION ${CMAKE_BINARY_DIR}/bin/Release)

Is it possible to replace "Release" with a variable that represents the configuration like:

file(COPY ${IMAGES} DESTINATION ${CMAKE_BINARY_DIR}/bin/${Variable})

I attempted

file(COPY ${IMAGES} DESTINATION ${CMAKE_BINARY_DIR}/bin/${CMAKE_BUILD_TYPE})

but CMAKE_BUILD_TYPE is an empty string when I use message to print it out, I also attempted

file(COPY ${IMAGES} DESTINATION ${CMAKE_BINARY_DIR}/bin/$<CONFIGURATION>)

but for some reason file command cannot decipher $<CONFIGURATION> whereas command like

add_custom_target(run COMMAND ${CMAKE_BINARY_DIR}/bin/$<CONFIGURATION>/Test.exe)

can. What is the right way to extract whether visual studio is currently built in Release or Debug in CMake?

Best Answer

The file command is executed during CMake runtime, not during build time (i.e. VS runtime).

This also means, that the generator expressions (e.g. $<CONFIG>) can not be used, as these are evaluated during build time.
(Hint: As long as there is no explicit reference to the use of generator expressions for a particular command in the CMake docu, they are not supported by that command).

The reason, why ${CMAKE_BUILD_TYPE} is empty, is due to the reason that you probably haven't specified it on the invocation of CMake:

cmake -DCMAKE_BUILD_TYPE=Debug ..

However, using that, would mean that the build files are only generated for the Debug configuration. That's obviously not what you want.

To solve your problem: Using generator expressions is the right way, as you've already figured out with the use of add_custom_target (or add_custom_command).

You can use custom commands as dependencies for other "real" targets and you can specify post-/pre-build and pre-link commands for a specific target via add_custom_command.

As the docu states for the COMMAND argument of add_custom_command:

Arguments to COMMAND may use generator expressions. References to target names in generator expressions imply target-level dependencies, but NOT file-level dependencies. List target names with the DEPENDS option to add file-level dependencies.

To copy a file after a successful build of a target:

add_custom_command(TARGET myTarget POST_BUILD
                   COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${IMAGE1}" "${CMAKE_BINARY_DIR}/bin/$<CONFIG>/"
                   COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${IMAGE2}" "${CMAKE_BINARY_DIR}/bin/$<CONFIG>/"
)