Skip to content

Commit e728baa

Browse files
committed
cmake: Redefine/adjust per-configuration flags
1 parent aa13fa9 commit e728baa

File tree

2 files changed

+246
-21
lines changed

2 files changed

+246
-21
lines changed

CMakeLists.txt

+80-21
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,73 @@ include(cmake/leveldb.cmake)
224224
include(cmake/minisketch.cmake)
225225
include(cmake/secp256k1.cmake)
226226

227+
include(ProcessConfigurations)
228+
set_default_config(RelWithDebInfo)
229+
230+
# Redefine/adjust per-configuration flags.
231+
target_compile_definitions(core_depends_debug_interface INTERFACE
232+
DEBUG
233+
DEBUG_LOCKORDER
234+
DEBUG_LOCKCONTENTION
235+
RPC_DOC_CHECK
236+
ABORT_ON_FAILED_ASSUME
237+
)
238+
# We leave assertions on.
239+
if(MSVC)
240+
remove_c_flag_from_all_configs(/DNDEBUG)
241+
remove_cxx_flag_from_all_configs(/DNDEBUG)
242+
else()
243+
remove_c_flag_from_all_configs(-DNDEBUG)
244+
remove_cxx_flag_from_all_configs(-DNDEBUG)
245+
246+
# Adjust flags used by the C/CXX compiler during RELEASE builds.
247+
# Prefer -O2 optimization level. (-O3 is CMake's default for Release for many compilers.)
248+
replace_c_flag_in_config(Release -O3 -O2)
249+
replace_cxx_flag_in_config(Release -O3 -O2)
250+
251+
are_flags_overridden(CMAKE_CXX_FLAGS_DEBUG cxx_flags_debug_overridden)
252+
if(NOT cxx_flags_debug_overridden)
253+
# Redefine flags used by the CXX compiler during DEBUG builds.
254+
try_append_cxx_flags("-g3" RESULT_VAR compiler_supports_g3)
255+
if(compiler_supports_g3)
256+
replace_cxx_flag_in_config(Debug -g -g3)
257+
endif()
258+
259+
try_append_cxx_flags("-ftrapv" RESULT_VAR compiler_supports_ftrapv)
260+
if(compiler_supports_ftrapv)
261+
string(PREPEND CMAKE_CXX_FLAGS_DEBUG "-ftrapv ")
262+
endif()
263+
unset(compiler_supports_ftrapv)
264+
265+
string(PREPEND CMAKE_CXX_FLAGS_DEBUG "-O0 ")
266+
267+
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}"
268+
CACHE STRING
269+
"Flags used by the CXX compiler during DEBUG builds."
270+
FORCE
271+
)
272+
endif()
273+
unset(cxx_flags_debug_overridden)
274+
275+
are_flags_overridden(CMAKE_C_FLAGS_DEBUG c_flags_debug_overridden)
276+
if(NOT c_flags_debug_overridden)
277+
# Redefine flags used by the C compiler during DEBUG builds.
278+
if(compiler_supports_g3)
279+
replace_c_flag_in_config(Debug -g -g3)
280+
endif()
281+
282+
string(PREPEND CMAKE_C_FLAGS_DEBUG "-O0 ")
283+
284+
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}"
285+
CACHE STRING
286+
"Flags used by the C compiler during DEBUG builds."
287+
FORCE
288+
)
289+
endif()
290+
unset(compiler_supports_g3)
291+
unset(c_flags_debug_overridden)
292+
endif()
293+
227294
include(cmake/optional.cmake)
228295

229296
find_package(Python3 3.9 COMPONENTS Interpreter)
@@ -239,6 +306,18 @@ target_compile_definitions(core_base_interface INTERFACE ${DEPENDS_COMPILE_DEFIN
239306
target_compile_definitions(core_depends_release_interface INTERFACE ${DEPENDS_COMPILE_DEFINITIONS_RELWITHDEBINFO})
240307
target_compile_definitions(core_depends_debug_interface INTERFACE ${DEPENDS_COMPILE_DEFINITIONS_DEBUG})
241308

309+
# If {C,CXX,LD}FLAGS variables are defined during building depends and
310+
# configuring this build system, their content might be duplicated.
311+
if(DEFINED ENV{CFLAGS})
312+
deduplicate_flags(CMAKE_C_FLAGS)
313+
endif()
314+
if(DEFINED ENV{CXXFLAGS})
315+
deduplicate_flags(CMAKE_CXX_FLAGS)
316+
endif()
317+
if(DEFINED ENV{LDFLAGS})
318+
deduplicate_flags(CMAKE_EXE_LINKER_FLAGS)
319+
endif()
320+
242321
add_subdirectory(src)
243322
add_subdirectory(test)
244323

@@ -291,27 +370,7 @@ get_target_interface(common_link_options core_interface LINK_OPTIONS)
291370
message("Common link options ................... ${common_link_options}")
292371
message("Linker flags for executables .......... ${CMAKE_EXE_LINKER_FLAGS}")
293372
message("Linker flags for shared libraries ..... ${CMAKE_SHARED_LINKER_FLAGS}")
294-
if(DEFINED CMAKE_BUILD_TYPE)
295-
message("Build type:")
296-
message(" - CMAKE_BUILD_TYPE ................... ${CMAKE_BUILD_TYPE}")
297-
string(TOUPPER "${CMAKE_BUILD_TYPE}" build_type)
298-
message(" - CFLAGS ............................. ${CMAKE_C_FLAGS_${build_type}}")
299-
message(" - CXXFLAGS ........................... ${CMAKE_CXX_FLAGS_${build_type}}")
300-
message(" - LDFLAGS for executables ............ ${CMAKE_EXE_LINKER_FLAGS_${build_type}}")
301-
message(" - LDFLAGS for shared libraries ....... ${CMAKE_SHARED_LINKER_FLAGS_${build_type}}")
302-
else()
303-
message("Available configurations .............. ${CMAKE_CONFIGURATION_TYPES}")
304-
message("Debug configuration:")
305-
message(" - CFLAGS ............................. ${CMAKE_C_FLAGS_DEBUG}")
306-
message(" - CXXFLAGS ........................... ${CMAKE_CXX_FLAGS_DEBUG}")
307-
message(" - LDFLAGS for executables ............ ${CMAKE_EXE_LINKER_FLAGS_DEBUG}")
308-
message(" - LDFLAGS for shared libraries ....... ${CMAKE_SHARED_LINKER_FLAGS_DEBUG}")
309-
message("Release configuration:")
310-
message(" - CFLAGS ............................. ${CMAKE_C_FLAGS_RELEASE}")
311-
message(" - CXXFLAGS ........................... ${CMAKE_CXX_FLAGS_RELEASE}")
312-
message(" - LDFLAGS for executables ............ ${CMAKE_EXE_LINKER_FLAGS_RELEASE}")
313-
message(" - LDFLAGS for shared libraries ....... ${CMAKE_SHARED_LINKER_FLAGS_RELEASE}")
314-
endif()
373+
print_config_flags()
315374
message("Use ccache for compiling .............. ${WITH_CCACHE}")
316375
message("\n")
317376
if(configure_warnings)
+166
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
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+
else()
76+
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY
77+
STRINGS "${all_configs}"
78+
)
79+
if(NOT CMAKE_BUILD_TYPE)
80+
message(STATUS "Setting build type to \"${config}\" as none was specified")
81+
get_property(help_string CACHE CMAKE_BUILD_TYPE PROPERTY HELPSTRING)
82+
set(CMAKE_BUILD_TYPE "${config}" CACHE STRING "${help_string}" FORCE)
83+
endif()
84+
endif()
85+
endfunction()
86+
87+
function(remove_c_flag_from_all_configs flag)
88+
get_all_configs(all_configs)
89+
foreach(config IN LISTS all_configs)
90+
string(TOUPPER "${config}" config_uppercase)
91+
set(flags "${CMAKE_C_FLAGS_${config_uppercase}}")
92+
separate_arguments(flags)
93+
list(FILTER flags EXCLUDE REGEX "${flag}")
94+
list(JOIN flags " " new_flags)
95+
set(CMAKE_C_FLAGS_${config_uppercase} "${new_flags}" PARENT_SCOPE)
96+
set(CMAKE_C_FLAGS_${config_uppercase} "${new_flags}"
97+
CACHE STRING
98+
"Flags used by the C compiler during ${config_uppercase} builds."
99+
FORCE
100+
)
101+
endforeach()
102+
endfunction()
103+
104+
function(remove_cxx_flag_from_all_configs flag)
105+
get_all_configs(all_configs)
106+
foreach(config IN LISTS all_configs)
107+
string(TOUPPER "${config}" config_uppercase)
108+
set(flags "${CMAKE_CXX_FLAGS_${config_uppercase}}")
109+
separate_arguments(flags)
110+
list(FILTER flags EXCLUDE REGEX "${flag}")
111+
list(JOIN flags " " new_flags)
112+
set(CMAKE_CXX_FLAGS_${config_uppercase} "${new_flags}" PARENT_SCOPE)
113+
set(CMAKE_CXX_FLAGS_${config_uppercase} "${new_flags}"
114+
CACHE STRING
115+
"Flags used by the CXX compiler during ${config_uppercase} builds."
116+
FORCE
117+
)
118+
endforeach()
119+
endfunction()
120+
121+
function(replace_c_flag_in_config config old_flag new_flag)
122+
string(TOUPPER "${config}" config_uppercase)
123+
string(REGEX REPLACE "(^| )${old_flag}( |$)" "\\1${new_flag}\\2" new_flags "${CMAKE_C_FLAGS_${config_uppercase}}")
124+
set(CMAKE_C_FLAGS_${config_uppercase} "${new_flags}" PARENT_SCOPE)
125+
set(CMAKE_C_FLAGS_${config_uppercase} "${new_flags}"
126+
CACHE STRING
127+
"Flags used by the C compiler during ${config_uppercase} builds."
128+
FORCE
129+
)
130+
endfunction()
131+
132+
function(replace_cxx_flag_in_config config old_flag new_flag)
133+
string(TOUPPER "${config}" config_uppercase)
134+
string(REGEX REPLACE "(^| )${old_flag}( |$)" "\\1${new_flag}\\2" new_flags "${CMAKE_CXX_FLAGS_${config_uppercase}}")
135+
set(CMAKE_CXX_FLAGS_${config_uppercase} "${new_flags}" PARENT_SCOPE)
136+
set(CMAKE_CXX_FLAGS_${config_uppercase} "${new_flags}"
137+
CACHE STRING
138+
"Flags used by the CXX compiler during ${config_uppercase} builds."
139+
FORCE
140+
)
141+
endfunction()
142+
143+
function(print_config_flags)
144+
macro(print_flags config)
145+
string(TOUPPER "${config}" config_uppercase)
146+
message(" - Preprocessor defined macros ........ ${definitions_${config_uppercase}}")
147+
message(" - CFLAGS ............................. ${CMAKE_C_FLAGS_${config_uppercase}}")
148+
message(" - CXXFLAGS ........................... ${CMAKE_CXX_FLAGS_${config_uppercase}}")
149+
message(" - LDFLAGS for executables ............ ${CMAKE_EXE_LINKER_FLAGS_${config_uppercase}}")
150+
message(" - LDFLAGS for shared libraries ....... ${CMAKE_SHARED_LINKER_FLAGS_${config_uppercase}}")
151+
endmacro()
152+
153+
get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
154+
if(is_multi_config)
155+
list(JOIN CMAKE_CONFIGURATION_TYPES " " configs)
156+
message("Available build types (configurations) ${configs}")
157+
foreach(config IN LISTS CMAKE_CONFIGURATION_TYPES)
158+
message("'${config}' build type (configuration):")
159+
print_flags(${config})
160+
endforeach()
161+
else()
162+
message("Build type (configuration):")
163+
message(" - CMAKE_BUILD_TYPE ................... ${CMAKE_BUILD_TYPE}")
164+
print_flags(${CMAKE_BUILD_TYPE})
165+
endif()
166+
endfunction()

0 commit comments

Comments
 (0)