aboutsummaryrefslogtreecommitdiff
path: root/cmake/module/ProcessConfigurations.cmake
blob: 7e2fc0080e98ee6b2889ae946ff21627a2ec0886 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# Copyright (c) 2023-present The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or https://opensource.org/license/mit/.

include_guard(GLOBAL)

include(TryAppendCXXFlags)

macro(normalize_string string)
  string(REGEX REPLACE " +" " " ${string} "${${string}}")
  string(STRIP "${${string}}" ${string})
endmacro()

function(are_flags_overridden flags_var result_var)
  normalize_string(${flags_var})
  normalize_string(${flags_var}_INIT)
  if(${flags_var} STREQUAL ${flags_var}_INIT)
    set(${result_var} FALSE PARENT_SCOPE)
  else()
    set(${result_var} TRUE PARENT_SCOPE)
  endif()
endfunction()


# Removes duplicated flags. The relative order of flags is preserved.
# If duplicates are encountered, only the last instance is preserved.
function(deduplicate_flags flags)
  separate_arguments(${flags})
  list(REVERSE ${flags})
  list(REMOVE_DUPLICATES ${flags})
  list(REVERSE ${flags})
  list(JOIN ${flags} " " result)
  set(${flags} "${result}" PARENT_SCOPE)
endfunction()


function(get_all_configs output)
  get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
  if(is_multi_config)
    set(all_configs ${CMAKE_CONFIGURATION_TYPES})
  else()
    get_property(all_configs CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS)
    if(NOT all_configs)
      # See https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html#default-and-custom-configurations
      set(all_configs Debug Release RelWithDebInfo MinSizeRel)
    endif()
  endif()
  set(${output} "${all_configs}" PARENT_SCOPE)
endfunction()


#[=[
Set the default build configuration.

See: https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html#build-configurations.

On single-configuration generators, this function sets the CMAKE_BUILD_TYPE variable to
the default build configuration, which can be overridden by the user at configure time if needed.

On multi-configuration generators, this function rearranges the CMAKE_CONFIGURATION_TYPES list,
ensuring that the default build configuration appears first while maintaining the order of the
remaining configurations. The user can choose a build configuration at build time.
]=]
function(set_default_config config)
  get_all_configs(all_configs)
  if(NOT ${config} IN_LIST all_configs)
    message(FATAL_ERROR "The default config is \"${config}\", but must be one of ${all_configs}.")
  endif()

  list(REMOVE_ITEM all_configs ${config})
  list(PREPEND all_configs ${config})

  get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
  if(is_multi_config)
    get_property(help_string CACHE CMAKE_CONFIGURATION_TYPES PROPERTY HELPSTRING)
    set(CMAKE_CONFIGURATION_TYPES "${all_configs}" CACHE STRING "${help_string}" FORCE)
    # Also see https://gitlab.kitware.com/cmake/cmake/-/issues/19512.
    set(CMAKE_TRY_COMPILE_CONFIGURATION "${config}" PARENT_SCOPE)
  else()
    set_property(CACHE CMAKE_BUILD_TYPE PROPERTY
      STRINGS "${all_configs}"
    )
    if(NOT CMAKE_BUILD_TYPE)
      message(STATUS "Setting build type to \"${config}\" as none was specified")
      get_property(help_string CACHE CMAKE_BUILD_TYPE PROPERTY HELPSTRING)
      set(CMAKE_BUILD_TYPE "${config}" CACHE STRING "${help_string}" FORCE)
    endif()
    set(CMAKE_TRY_COMPILE_CONFIGURATION "${CMAKE_BUILD_TYPE}" PARENT_SCOPE)
  endif()
endfunction()

function(remove_cxx_flag_from_all_configs flag)
  get_all_configs(all_configs)
  foreach(config IN LISTS all_configs)
    string(TOUPPER "${config}" config_uppercase)
    set(flags "${CMAKE_CXX_FLAGS_${config_uppercase}}")
    separate_arguments(flags)
    list(FILTER flags EXCLUDE REGEX "${flag}")
    list(JOIN flags " " new_flags)
    set(CMAKE_CXX_FLAGS_${config_uppercase} "${new_flags}" PARENT_SCOPE)
    set(CMAKE_CXX_FLAGS_${config_uppercase} "${new_flags}"
      CACHE STRING
      "Flags used by the CXX compiler during ${config_uppercase} builds."
      FORCE
    )
  endforeach()
endfunction()

function(replace_cxx_flag_in_config config old_flag new_flag)
  string(TOUPPER "${config}" config_uppercase)
  string(REGEX REPLACE "(^| )${old_flag}( |$)" "\\1${new_flag}\\2" new_flags "${CMAKE_CXX_FLAGS_${config_uppercase}}")
  set(CMAKE_CXX_FLAGS_${config_uppercase} "${new_flags}" PARENT_SCOPE)
  set(CMAKE_CXX_FLAGS_${config_uppercase} "${new_flags}"
    CACHE STRING
    "Flags used by the CXX compiler during ${config_uppercase} builds."
    FORCE
  )
endfunction()

set_default_config(RelWithDebInfo)

# Redefine/adjust per-configuration flags.
target_compile_definitions(core_interface_debug INTERFACE
  DEBUG
  DEBUG_LOCKORDER
  DEBUG_LOCKCONTENTION
  RPC_DOC_CHECK
  ABORT_ON_FAILED_ASSUME
)
# We leave assertions on.
if(MSVC)
  remove_cxx_flag_from_all_configs(/DNDEBUG)
else()
  remove_cxx_flag_from_all_configs(-DNDEBUG)

  # Adjust flags used by the CXX compiler during RELEASE builds.
  # Prefer -O2 optimization level. (-O3 is CMake's default for Release for many compilers.)
  replace_cxx_flag_in_config(Release -O3 -O2)

  are_flags_overridden(CMAKE_CXX_FLAGS_DEBUG cxx_flags_debug_overridden)
  if(NOT cxx_flags_debug_overridden)
    # Redefine flags used by the CXX compiler during DEBUG builds.
    try_append_cxx_flags("-g3" RESULT_VAR compiler_supports_g3)
    if(compiler_supports_g3)
      replace_cxx_flag_in_config(Debug -g -g3)
    endif()
    unset(compiler_supports_g3)

    try_append_cxx_flags("-ftrapv" RESULT_VAR compiler_supports_ftrapv)
    if(compiler_supports_ftrapv)
      string(PREPEND CMAKE_CXX_FLAGS_DEBUG "-ftrapv ")
    endif()
    unset(compiler_supports_ftrapv)

    string(PREPEND CMAKE_CXX_FLAGS_DEBUG "-O0 ")

    set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}"
      CACHE STRING
      "Flags used by the CXX compiler during DEBUG builds."
      FORCE
    )
  endif()
  unset(cxx_flags_debug_overridden)
endif()

set(CMAKE_CXX_FLAGS_COVERAGE "-g -Og --coverage")
set(CMAKE_OBJCXX_FLAGS_COVERAGE "-g -Og --coverage")
set(CMAKE_EXE_LINKER_FLAGS_COVERAGE "--coverage")
set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE "--coverage")
get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if(is_multi_config)
  if(NOT "Coverage" IN_LIST CMAKE_CONFIGURATION_TYPES)
    list(APPEND CMAKE_CONFIGURATION_TYPES Coverage)
  endif()
endif()