[CMake] How to set a preprocessor define for all build configurations except one ?

Michael Hertling mhertling at online.de
Sun Jun 12 21:53:08 EDT 2011


On 06/07/2011 07:05 PM, Glenn Coombs wrote:
> I want to have a preprocessor symbol (GEN_OUTFILES) defined for all build
> configurations except one (ReleaseNoOutfiles).  Before I added the
> ReleaseNoOutfiles configuration I just had this line in my top level
> CMakeLists.txt:
> 
> add_definitions(-DGEN_OUTFILES)
> 
> but now I have to have this complicated mess instead:
> 
> # Add preprocessor definition for GEN_OUTFILES to all project configurations
> except ReleaseNoOutfiles
> if (CMAKE_CONFIGURATION_TYPES)
>         string(TOUPPER "${CMAKE_CONFIGURATION_TYPES}"
> CMAKE_CONFIGURATION_TYPES_UPPER)
> else()
>         string(TOUPPER "${CMAKE_BUILD_TYPE}"
> CMAKE_CONFIGURATION_TYPES_UPPER)
> endif()
> 
> foreach(config ${CMAKE_CONFIGURATION_TYPES_UPPER})
>         if (NOT (${config} MATCHES "RELEASENOOUTFILES"))
>                 set_property(DIRECTORY APPEND PROPERTY
> COMPILE_DEFINITIONS_${config} GEN_OUTFILES)
>         endif()
> endforeach()
> 
> Is there a more elegant solution that I am missing ?  Ideally something
> like:
> 
> add_definitions(CONFIG=Debug;Release;RelWithDebInfo;MinSizeRel
> -DGEN_OUTFILES)
> 
> which I know doesn't exist but I really wish it did :-)

AFAIK, there's no other approach to take account of single- and multi-
config generators at the same time for this purpose, but perhaps, you
could design the loop a bit smarter:

FOREACH(i IN LISTS CMAKE_CONFIGURATION_TYPES ITEMS ${CMAKE_BUILD_TYPE})
    STRING(TOUPPER ${i} j)
    IF(NOT j MATCHES "RELEASENOOUTFILES")
        SET_PROPERTY(...)
    ENDIF()
ENDFOREACH()

Since CMAKE_CONFIGURATION_TYPES and CMAKE_BUILD_TYPE are mutually
exclusive and an empty list/item doesn't cause an iteration, this
should work as expected.

Alternatively, you might use

SET_PROPERTY(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS GEN_OUTFILES)
SET(CMAKE_C_FLAGS_RELEASENOOUTFILES -UGEN_OUTFILES)

and rely on the assumption that

(1) the FLAGS are mentioned after the COMPILE_DEFINITIONS, and
(2) the last -D/-U argument in the command line will take effect.

At least, GCC guarantees that (2) holds, but I have not found any
explicit assertion in the documentation that CMake guarantees (1),
though it seems to work in this way.

BTW, is an "inverted" logic an option, i.e. a preprocessor definition
NO_GEN_OUTFILES enabled for the RELEASENOOUTFILES configuration only?
This would be much easier and fit that configuration's intent better.

Regards,

Michael

> Initially I didn't have the if (CMAKE_CONFIGURATION_TYPES) check and it
> didn't work on linux.  Why is CMAKE_CONFIGURATION_TYPES empty for linux
> targets ?  I know that multiple build configs are not supported in the same
> tree like they are under Visual Studio but you can configure multiple build
> directories with CMAKE_BUILD_TYPE set to each value in
> CMAKE_CONFIGURATION_TYPES.  The code in CMakeLists.txt files would be more
> platform agnostic and easier to read if one could iterate over
> CMAKE_CONFIGURATION_TYPES on linux to set configuration specific variables
> like COMPILE_DEFINITIONS_XXX.
> 
> --
> Glenn


More information about the CMake mailing list