[CMake] Correct way to specify multiple build configurations for single config generators?

Zaak Beekman zbeekman at gmail.com
Sun Dec 9 21:36:58 EST 2018


I have been reading the *excellent* book "Professional CMake". The author,
Craig Scott, recommends the following best practices:

   - check the existence of `CMAKE_CONFIGURATION_TYPES` and only adding or
   pruning configurations if it's preset, *AFTER* your call to `project()`
   - do not set `CMAKE_CONFIGURATION_TYPES` and use the `STRINGS` property
   on `CMAKE_BUILD_TYPE` for single config generators
   - forcibly set the `CMAKE_BUILD_TYPE` cache variable if it is unset,
   otherwise check the passed `CMAKE_BUILD_TYPE` against allowable configs and
   throw an error if it differs
   - set `CMAKE_<LANG>_FLAGS_<CONFIG>` and
   `CMAKE_<TARGETTYPE>_LINKER_FLAGS_<CONFIG>` variables as cache variables for
   newly defined configuration

The problem I encounter is that, if I set
`-DCMAKE_BUILD_TYPE:STRING=<MY_CONFIG>` to CMake on the command line, then
CMake seems to initialize all of the `<MY_CONFIG>` cache variables to the
empty string *BEFORE* I can set them. All other custom configurations get
set to my specified default cache variable value.

What is the best practice for setting the new configuration's default flags?

I am aware of `CMAKE_USER_MAKE_RULES_OVERRIDE` and all of the
`CMAKE_<LANG|TARGET_TYPE>_FLAGS_<CONFIG>_INIT` variable, but as far as I
can tell, there is no access to knowing what compiler is being used, since
the compilers have yet to be probed. Is it possible to use the
`CMAKE_..._INIT` variables to set per-compiler flags some how?

Any answers or pointers here would be most appreciated.

FYI, Before being enlightened to some of the dangers or non-standard ways
of what I was doing, I would typically set `CMAKE_CONFIGURATION_TYPES`
*before* my call to `project()`. Something like this:

```cmake
set ( CMAKE_CONFIGURATION_TYPES "Debug" "Release" "MinSizeRel"
"RelWithDebInfo" "CodeCoverage" )
set ( CMAKE_BUILD_TYPE "Release"
  CACHE STRING "Select which configuration to build." )
set_property ( CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
${CMAKE_CONFIGURATION_TYPES} )
```

I would then call `project()` so that the compilers would be probed and I
could make specific flag choices based on the compiler being used, and set
those as Cache variables. Something like this:

```cmake
if ("${CMAKE_Fortran_COMPILER_ID}" MATCHES "GNU" )
  set(gfortran_compiler true)
  set ( CMAKE_C_FLAGS_CODECOVERAGE "-fprofile-arcs -ftest-coverage -O0"
    CACHE STRING "Code coverage C compiler flags")
  set ( CMAKE_Fortran_FLAGS_CODECOVERAGE "-fprofile-arcs -ftest-coverage
-O0"
    CACHE STRING "Code coverage Fortran compiler flags")
```

This seemed to work fine and specifying, e.g.,
`-DCMAKE_BUILD_TYPE:STRING=CodeCoverage`, the
`CMAKE_<LANG>_FLAGS_CODECOVERAGE` cache variable would be set to the
appropriate value.

Thanks for taking the time to read my question.

-Zaak
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://cmake.org/pipermail/cmake/attachments/20181209/caaf8896/attachment.html>


More information about the CMake mailing list