25

I'm trying to add a custom build type for my CMake configuration targeting code coverage.

The method I've tried so far is from the FAQ entry about it in the CMake wiki site. However, I can't make it work.

Here is my code, using CMake 2.8.5:

message("* Adding build types...")
if(CMAKE_CONFIGURATION_TYPES)
   list(APPEND CMAKE_CONFIGURATION_TYPES CodeCoverage)
   list(REMOVE_DUPLICATES CMAKE_CONFIGURATION_TYPES)
   set(CMAKE_CONFIGURATION_TYPES "${CMAKE_CONFIGURATION_TYPES}" CACHE STRING
       "Add the configurations that we need"
       FORCE)
   message("  Available build types are now : ${CMAKE_CONFIGURATION_TYPES}")
else()
   message("  XXX custom build types are not allowed...")
endif()

And I get "XXX custom build types are not allowed..."...

Offirmo
  • 18,962
  • 12
  • 76
  • 97

2 Answers2

31

Found the problem : there is a confusion between adding custom builds and custom configurations :

  • configurations are for special tools like Visual Studio or XCode
  • build types are a much rawer feature

So to add a custom build type, there is no need to manipulate the CMAKE_CONFIGURATION_TYPES variable at all. Just set the corresponding variables and start using it, as explained :

SET(GCC_DEBUG_FLAGS "-g -Wall")

# Add new build types
message("* Adding build types...")
SET(CMAKE_CXX_FLAGS_COVERAGE
    "${GCC_DEBUG_FLAGS} -fprofile-arcs -ftest-coverage"
    CACHE STRING "Flags used by the C++ compiler during coverage builds."
    FORCE )
SET(CMAKE_C_FLAGS_COVERAGE
    "${GCC_DEBUG_FLAGS} -fprofile-arcs -ftest-coverage"
    CACHE STRING "Flags used by the C compiler during coverage builds."
    FORCE )
SET(CMAKE_EXE_LINKER_FLAGS_COVERAGE
    ""
    CACHE STRING "Flags used for linking binaries during coverage builds."
    FORCE )
SET(CMAKE_SHARED_LINKER_FLAGS_COVERAGE
    ""
    CACHE STRING "Flags used by the shared libraries linker during coverage builds."
    FORCE )
MARK_AS_ADVANCED(
    CMAKE_CXX_FLAGS_COVERAGE
    CMAKE_C_FLAGS_COVERAGE
    CMAKE_EXE_LINKER_FLAGS_COVERAGE
    CMAKE_SHARED_LINKER_FLAGS_COVERAGE )

We may also want to udate the help string (along with setting the default build type by the way) :

IF(NOT CMAKE_BUILD_TYPE)
   SET(CMAKE_BUILD_TYPE Debug
       CACHE STRING "Choose the type of build : None Debug Release RelWithDebInfo MinSizeRel Coverage."
       FORCE)
ENDIF(NOT CMAKE_BUILD_TYPE)
message("* Current build type is : ${CMAKE_BUILD_TYPE}")

A bit of warning about trying to inherit default options from another build type doing this :

SET(CMAKE_CXX_FLAGS_COVERAGE
    "${CMAKE_CXX_FLAGS_DEBUG} -fprofile-arcs -ftest-coverage"
    CACHE STRING "Flags used by the C++ compiler during coverage builds."
    FORCE )

This is a bad idea because the extra options keep being appended every time the config is sourced again (every time you change something in it).

Josiah
  • 1,072
  • 6
  • 15
Offirmo
  • 18,962
  • 12
  • 76
  • 97
  • 3
    You can inherit default options from another build type, but you should not @set(..CACHE...FORCE)@ the composite variable, or you will see this appending behaviour. The variable value that gets propagated into your Makefile does not have to be cached. – mabraham Aug 01 '13 at 21:21
  • 9
    A more recent answer [here](http://stackoverflow.com/a/24470998/1938798) gives a more complete and technically correct explanation of this topic. – Craig Scott Nov 19 '16 at 08:27
  • I don't understand the "correct" explanation. This one is clear and concise. – midenok Feb 23 '23 at 09:05
  • "_This is a bad idea because the extra options keep being appended every time the config is sourced again (every time you change something in it)._" I don't see why that would happen in the code you have shown. – starball Mar 23 '23 at 21:59
0

Your if-else went to the else block because that's exactly what's supposed to happen. See the if() command docs for basic expressions. CMAKE_CONFIGURATION_TYPES is not a boolean constant in CMake and it's not a quoted string, so the variable path is taken, and the variable CMAKE_CONFIGURATION_TYPES is typically not defined to a value that evaluates to a falsy constant (unless you did that manually, which I can't see a reason why anyone would ever do).

Note that you don't have to modify CMAKE_CONFIGURATION_TYPES to define a custom build type. The purpose of the variable is to list configurations to generate for a buildsystem when using a multi-config generator.

To define a custom build/configuration type, all you need to do is what is already stated one section down in the wiki page you linked- I.e. define the variables as you would like them which are named in the reference documentation with template names containing "<CONFIG>" (cmake --help-variable-list | grep "<CONFIG>").

starball
  • 20,030
  • 7
  • 43
  • 238