ProcessConfigurations.cmake raw

   1  # Copyright (c) 2023-present The Bitcoin Core developers
   2  # Distributed under the MIT software license, see the accompanying
   3  # file COPYING or https://opensource.org/license/mit/.
   4  
   5  include_guard(GLOBAL)
   6  
   7  macro(normalize_string string)
   8    string(REGEX REPLACE " +" " " ${string} "${${string}}")
   9    string(STRIP "${${string}}" ${string})
  10  endmacro()
  11  
  12  function(are_flags_overridden flags_var result_var)
  13    normalize_string(${flags_var})
  14    normalize_string(${flags_var}_INIT)
  15    if(${flags_var} STREQUAL ${flags_var}_INIT)
  16      set(${result_var} FALSE PARENT_SCOPE)
  17    else()
  18      set(${result_var} TRUE PARENT_SCOPE)
  19    endif()
  20  endfunction()
  21  
  22  
  23  # Removes duplicated flags. The relative order of flags is preserved.
  24  # If duplicates are encountered, only the last instance is preserved.
  25  function(deduplicate_flags flags)
  26    separate_arguments(${flags})
  27    list(REVERSE ${flags})
  28    list(REMOVE_DUPLICATES ${flags})
  29    list(REVERSE ${flags})
  30    list(JOIN ${flags} " " result)
  31    set(${flags} "${result}" PARENT_SCOPE)
  32  endfunction()
  33  
  34  
  35  function(get_all_configs output)
  36    get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
  37    if(is_multi_config)
  38      set(all_configs ${CMAKE_CONFIGURATION_TYPES})
  39    else()
  40      get_property(all_configs CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS)
  41      if(NOT all_configs)
  42        # See https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html#default-and-custom-configurations
  43        set(all_configs Debug Release RelWithDebInfo MinSizeRel)
  44      endif()
  45    endif()
  46    set(${output} "${all_configs}" PARENT_SCOPE)
  47  endfunction()
  48  
  49  
  50  #[=[
  51  Set the default build configuration.
  52  
  53  See: https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html#build-configurations.
  54  
  55  On single-configuration generators, this function sets the CMAKE_BUILD_TYPE variable to
  56  the default build configuration, which can be overridden by the user at configure time if needed.
  57  
  58  On multi-configuration generators, this function rearranges the CMAKE_CONFIGURATION_TYPES list,
  59  ensuring that the default build configuration appears first while maintaining the order of the
  60  remaining configurations. The user can choose a build configuration at build time.
  61  ]=]
  62  function(set_default_config config)
  63    get_all_configs(all_configs)
  64    if(NOT ${config} IN_LIST all_configs)
  65      message(FATAL_ERROR "The default config is \"${config}\", but must be one of ${all_configs}.")
  66    endif()
  67  
  68    list(REMOVE_ITEM all_configs ${config})
  69    list(PREPEND all_configs ${config})
  70  
  71    get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
  72    if(is_multi_config)
  73      get_property(help_string CACHE CMAKE_CONFIGURATION_TYPES PROPERTY HELPSTRING)
  74      set(CMAKE_CONFIGURATION_TYPES "${all_configs}" CACHE STRING "${help_string}" FORCE)
  75      # Also see https://gitlab.kitware.com/cmake/cmake/-/issues/19512.
  76      set(CMAKE_TRY_COMPILE_CONFIGURATION "${config}" PARENT_SCOPE)
  77    else()
  78      set_property(CACHE CMAKE_BUILD_TYPE PROPERTY
  79        STRINGS "${all_configs}"
  80      )
  81      if(NOT CMAKE_BUILD_TYPE)
  82        message(STATUS "Setting build type to \"${config}\" as none was specified")
  83        get_property(help_string CACHE CMAKE_BUILD_TYPE PROPERTY HELPSTRING)
  84        set(CMAKE_BUILD_TYPE "${config}" CACHE STRING "${help_string}" FORCE)
  85      endif()
  86      set(CMAKE_TRY_COMPILE_CONFIGURATION "${CMAKE_BUILD_TYPE}" PARENT_SCOPE)
  87    endif()
  88  endfunction()
  89  
  90  function(remove_cxx_flag_from_all_configs flag)
  91    get_all_configs(all_configs)
  92    foreach(config IN LISTS all_configs)
  93      string(TOUPPER "${config}" config_uppercase)
  94      set(flags "${CMAKE_CXX_FLAGS_${config_uppercase}}")
  95      separate_arguments(flags)
  96      list(FILTER flags EXCLUDE REGEX "${flag}")
  97      list(JOIN flags " " new_flags)
  98      set(CMAKE_CXX_FLAGS_${config_uppercase} "${new_flags}" PARENT_SCOPE)
  99      set(CMAKE_CXX_FLAGS_${config_uppercase} "${new_flags}"
 100        CACHE STRING
 101        "Flags used by the CXX compiler during ${config_uppercase} builds."
 102        FORCE
 103      )
 104    endforeach()
 105  endfunction()
 106  
 107  function(replace_cxx_flag_in_config config old_flag new_flag)
 108    string(TOUPPER "CMAKE_CXX_FLAGS_${config}" var_name)
 109    if("${var_name}" IN_LIST precious_variables)
 110      return()
 111    endif()
 112    string(REGEX REPLACE "(^| )${old_flag}( |$)" "\\1${new_flag}\\2" ${var_name} "${${var_name}}")
 113    set(${var_name} "${${var_name}}" PARENT_SCOPE)
 114    set_property(CACHE ${var_name} PROPERTY VALUE "${${var_name}}")
 115  endfunction()
 116  
 117  set_default_config(RelWithDebInfo)
 118  
 119  include(TryAppendCXXFlags)
 120  
 121  # We leave assertions on.
 122  if(MSVC)
 123    remove_cxx_flag_from_all_configs(/DNDEBUG)
 124  else()
 125    remove_cxx_flag_from_all_configs(-DNDEBUG)
 126  
 127    # Adjust flags used by the CXX compiler during RELEASE builds.
 128    # Prefer -O2 optimization level. (-O3 is CMake's default for Release for many compilers.)
 129    replace_cxx_flag_in_config(Release -O3 -O2)
 130  
 131    are_flags_overridden(CMAKE_CXX_FLAGS_DEBUG cxx_flags_debug_overridden)
 132    if(NOT cxx_flags_debug_overridden)
 133      # Redefine flags used by the CXX compiler during DEBUG builds.
 134      try_append_cxx_flags("-g3" RESULT_VAR compiler_supports_g3)
 135      if(compiler_supports_g3)
 136        replace_cxx_flag_in_config(Debug -g -g3)
 137      endif()
 138      unset(compiler_supports_g3)
 139  
 140      try_append_cxx_flags("-ftrapv" RESULT_VAR compiler_supports_ftrapv)
 141      if(compiler_supports_ftrapv)
 142        string(PREPEND CMAKE_CXX_FLAGS_DEBUG "-ftrapv ")
 143      endif()
 144      unset(compiler_supports_ftrapv)
 145  
 146      string(PREPEND CMAKE_CXX_FLAGS_DEBUG "-O0 ")
 147  
 148      set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}"
 149        CACHE STRING
 150        "Flags used by the CXX compiler during DEBUG builds."
 151        FORCE
 152      )
 153    endif()
 154    unset(cxx_flags_debug_overridden)
 155  endif()
 156  
 157  set(CMAKE_CXX_FLAGS_COVERAGE "-g -Og --coverage")
 158  set(CMAKE_OBJCXX_FLAGS_COVERAGE "-g -Og --coverage")
 159  set(CMAKE_EXE_LINKER_FLAGS_COVERAGE "--coverage")
 160  set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE "--coverage")
 161  get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
 162  if(is_multi_config)
 163    if(NOT "Coverage" IN_LIST CMAKE_CONFIGURATION_TYPES)
 164      list(APPEND CMAKE_CONFIGURATION_TYPES Coverage)
 165    endif()
 166  endif()
 167