Zaak Beekman
2018-12-10 02:36:58 UTC
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
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