Skip to content

Commit ca22536

Browse files
committed
Merge #82: cmake: Rework handling compiler flags
dbd2f7a depends: Amend handling flags environment variables (Hennadii Stepanov) 56ef358 [FIXUP] cmake: Fix flags handling (Hennadii Stepanov) Pull request description: 1. Use standard CMake's way to pass flags from depends to the main build system using `CMAKE_<LANGUAGE>_FLAGS_INIT` variables instead of custom `DEPENDS_<LANGUAGE>_COMPILER_FLAGS` ones. This guaranties using those flags during various checks at the configuration stage. 2. Setting flags is decoupled from setting compilers in the toolchain file. 3. Per-configuration flags are cached properly. 4. No longer needed to set `-DCMAKE_BUILD_TYPE=None` when building with depends. Fixes cross compilation for macOS. Allows the user to use `{C,CXX}FLAGS` environment variables for depends and the main build system without drawbacks/workarounds. The flags presentation in the summary (#82 (comment)) will be reworked in a separated PR. Top commit has no ACKs. Tree-SHA512: 9bdc670a62a9b10866b8bbbfbc19abf3ae1d3b8f4062f85a9437f63a878dd9bebec46670b91f8310c5c10673bb35940160172d0ec588d2f3c81788ae966c338b
2 parents e8bbd04 + dbd2f7a commit ca22536

File tree

6 files changed

+167
-66
lines changed

6 files changed

+167
-66
lines changed

CMakeLists.txt

+80-37
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,12 @@ add_library(core_interface INTERFACE)
114114
# include the warn_interface as subtree's warnings are not fixable
115115
# in our tree.
116116
add_library(core_base_interface INTERFACE)
117+
add_library(core_depends_release_interface INTERFACE)
118+
add_library(core_depends_debug_interface INTERFACE)
119+
target_link_libraries(core_base_interface INTERFACE
120+
$<$<CONFIG:RelWithDebInfo>:${core_depends_release_interface}>
121+
$<$<CONFIG:Debug>:${core_depends_debug_interface}>
122+
)
117123
target_link_libraries(core_interface INTERFACE core_base_interface)
118124

119125
if(FUZZ)
@@ -223,12 +229,6 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
223229
try_append_linker_flag("-Wl,-headerpad_max_install_names" TARGET core_base_interface)
224230
endif()
225231

226-
if(CMAKE_CROSSCOMPILING)
227-
target_compile_definitions(core_base_interface INTERFACE ${DEPENDS_COMPILE_DEFINITIONS})
228-
target_compile_options(core_base_interface INTERFACE "$<$<COMPILE_LANGUAGE:C>:${DEPENDS_C_COMPILER_FLAGS}>")
229-
target_compile_options(core_base_interface INTERFACE "$<$<COMPILE_LANGUAGE:CXX>:${DEPENDS_CXX_COMPILER_FLAGS}>")
230-
endif()
231-
232232
include(AddThreadsIfNeeded)
233233
add_threads_if_needed()
234234

@@ -280,10 +280,10 @@ include(cmake/leveldb.cmake)
280280
include(cmake/minisketch.cmake)
281281
include(cmake/secp256k1.cmake)
282282

283-
string(STRIP "${CMAKE_CXX_FLAGS}" cxx_flags)
284-
string(STRIP "${CMAKE_CXX_FLAGS_INIT}" cxx_flags_init)
285-
if(cxx_flags STREQUAL cxx_flags_init)
286-
# CMAKE_CXX_FLAGS are not overridden.
283+
include(ProcessConfigurations)
284+
are_flags_overridden(CMAKE_CXX_FLAGS cxx_flags_overridden)
285+
# TODO: Rework after https://github.com/bitcoin/bitcoin/pull/25972.
286+
if(NOT cxx_flags_overridden AND NOT CMAKE_CROSSCOMPILING)
287287
add_library(warn_interface INTERFACE)
288288
target_link_libraries(core_interface INTERFACE warn_interface)
289289
if(MSVC)
@@ -331,19 +331,17 @@ if(cxx_flags STREQUAL cxx_flags_init)
331331
)
332332
endif()
333333
endif()
334-
unset(cxx_flags)
335-
unset(cxx_flags_init)
334+
unset(cxx_flags_overridden)
336335

337-
include(ProcessConfigurations)
338336
set_default_config(RelWithDebInfo)
339337

340-
# Redefine configuration flags.
341-
target_compile_definitions(core_base_interface INTERFACE
342-
$<$<CONFIG:Debug>:DEBUG>
343-
$<$<CONFIG:Debug>:DEBUG_LOCKORDER>
344-
$<$<CONFIG:Debug>:DEBUG_LOCKCONTENTION>
345-
$<$<CONFIG:Debug>:RPC_DOC_CHECK>
346-
$<$<CONFIG:Debug>:ABORT_ON_FAILED_ASSUME>
338+
# Redefine/adjust per-configuration flags.
339+
target_compile_definitions(core_depends_debug_interface INTERFACE
340+
DEBUG
341+
DEBUG_LOCKORDER
342+
DEBUG_LOCKCONTENTION
343+
RPC_DOC_CHECK
344+
ABORT_ON_FAILED_ASSUME
347345
)
348346
# We leave assertions on.
349347
if(MSVC)
@@ -353,20 +351,52 @@ else()
353351
remove_c_flag_from_all_configs(-DNDEBUG)
354352
remove_cxx_flag_from_all_configs(-DNDEBUG)
355353

354+
# Adjust flags used by the C/CXX compiler during RELEASE builds.
356355
# Prefer -O2 optimization level. (-O3 is CMake's default for Release for many compilers.)
357356
replace_c_flag_in_config(Release -O3 -O2)
358357
replace_cxx_flag_in_config(Release -O3 -O2)
359358

360-
set(debug_flags)
361-
try_append_cxx_flags("-O0" VAR debug_flags)
362-
try_append_cxx_flags("-g3" VAR debug_flags RESULT_VAR compiler_supports_g3)
363-
if(NOT compiler_supports_g3)
364-
try_append_cxx_flags("-g" VAR debug_flags)
359+
are_flags_overridden(CMAKE_CXX_FLAGS_DEBUG cxx_flags_debug_overridden)
360+
if(NOT cxx_flags_debug_overridden)
361+
# Redefine flags used by the CXX compiler during DEBUG builds.
362+
try_append_cxx_flags("-g3" RESULT_VAR compiler_supports_g3)
363+
if(compiler_supports_g3)
364+
replace_cxx_flag_in_config(Debug -g -g3)
365+
endif()
366+
367+
try_append_cxx_flags("-ftrapv" RESULT_VAR compiler_supports_ftrapv)
368+
if(compiler_supports_ftrapv)
369+
string(PREPEND CMAKE_CXX_FLAGS_DEBUG "-ftrapv ")
370+
endif()
371+
unset(compiler_supports_ftrapv)
372+
373+
string(PREPEND CMAKE_CXX_FLAGS_DEBUG "-O0 ")
374+
375+
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}"
376+
CACHE STRING
377+
"Flags used by the CXX compiler during DEBUG builds."
378+
FORCE
379+
)
365380
endif()
366-
set(CMAKE_C_FLAGS_DEBUG "${debug_flags}")
367-
try_append_cxx_flags("-ftrapv" VAR debug_flags)
368-
set(CMAKE_CXX_FLAGS_DEBUG "${debug_flags}")
369-
unset(debug_flags)
381+
unset(cxx_flags_debug_overridden)
382+
383+
are_flags_overridden(CMAKE_C_FLAGS_DEBUG c_flags_debug_overridden)
384+
if(NOT c_flags_debug_overridden)
385+
# Redefine flags used by the C compiler during DEBUG builds.
386+
if(compiler_supports_g3)
387+
replace_c_flag_in_config(Debug -g -g3)
388+
endif()
389+
390+
string(PREPEND CMAKE_C_FLAGS_DEBUG "-O0 ")
391+
392+
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}"
393+
CACHE STRING
394+
"Flags used by the C compiler during DEBUG builds."
395+
FORCE
396+
)
397+
endif()
398+
unset(compiler_supports_g3)
399+
unset(c_flags_debug_overridden)
370400
endif()
371401

372402
include(cmake/optional_qt.cmake)
@@ -452,6 +482,21 @@ else()
452482
)
453483
endif()
454484

485+
if(CMAKE_CROSSCOMPILING)
486+
target_compile_definitions(core_base_interface INTERFACE ${DEPENDS_COMPILE_DEFINITIONS})
487+
target_compile_definitions(core_depends_release_interface INTERFACE ${DEPENDS_COMPILE_DEFINITIONS_RELWITHDEBINFO})
488+
target_compile_definitions(core_depends_debug_interface INTERFACE ${DEPENDS_COMPILE_DEFINITIONS_DEBUG})
489+
490+
# If {C,CXX}FLAGS variables are defined during building depends and
491+
# configuring this build system, their content might be duplicated.
492+
if(DEFINED ENV{CFLAGS})
493+
deduplicate_flags(CMAKE_C_FLAGS)
494+
endif()
495+
if(DEFINED ENV{CXXFLAGS})
496+
deduplicate_flags(CMAKE_CXX_FLAGS)
497+
endif()
498+
endif()
499+
455500
add_subdirectory(src)
456501
add_subdirectory(test)
457502

@@ -462,9 +507,11 @@ setup_split_debug_script()
462507
add_maintenance_targets()
463508
add_windows_deploy_target()
464509

510+
465511
include(GetTargetInterface)
466512
get_target_interface(definitions core_interface COMPILE_DEFINITIONS)
467-
separate_by_configs(definitions)
513+
get_target_interface(definitions_RELWITHDEBINFO core_depends_release_interface COMPILE_DEFINITIONS)
514+
get_target_interface(definitions_DEBUG core_depends_debug_interface COMPILE_DEFINITIONS)
468515

469516
message("\n")
470517
message("Configure summary")
@@ -500,15 +547,11 @@ else()
500547
set(cross_status "FALSE")
501548
endif()
502549
message("Cross compiling ....................... ${cross_status}")
503-
message("Preprocessor defined macros ........... ${definitions_ALL}")
550+
message("Preprocessor defined macros ........... ${definitions}")
504551
message("C compiler ............................ ${CMAKE_C_COMPILER}")
505-
list(JOIN DEPENDS_C_COMPILER_FLAGS " " depends_c_flags)
506-
string(STRIP "${CMAKE_C_FLAGS} ${depends_c_flags}" combined_c_flags)
507-
message("CFLAGS ................................ ${combined_c_flags}")
552+
message("CFLAGS ................................ ${CMAKE_C_FLAGS}")
508553
message("C++ compiler .......................... ${CMAKE_CXX_COMPILER}")
509-
list(JOIN DEPENDS_CXX_COMPILER_FLAGS " " depends_cxx_flags)
510-
string(STRIP "${CMAKE_CXX_FLAGS} ${depends_cxx_flags}" combined_cxx_flags)
511-
message("CXXFLAGS .............................. ${combined_cxx_flags}")
554+
message("CXXFLAGS .............................. ${CMAKE_CXX_FLAGS}")
512555
get_target_interface(common_compile_options core_interface COMPILE_OPTIONS)
513556
message("Common compile options ................ ${common_compile_options}")
514557
get_target_interface(common_link_options core_interface LINK_OPTIONS)

cmake/module/GetTargetInterface.cmake

+1-3
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,7 @@ include_guard(GLOBAL)
88
function(get_target_interface var target property)
99
get_target_property(result ${target} INTERFACE_${property})
1010
if(result)
11-
if(NOT ${property} STREQUAL "COMPILE_DEFINITIONS")
12-
string(GENEX_STRIP "${result}" result)
13-
endif()
11+
string(GENEX_STRIP "${result}" result)
1412
list(JOIN result " " result)
1513
else()
1614
set(result)

cmake/module/ProcessConfigurations.cmake

+50-17
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,36 @@
22
# Distributed under the MIT software license, see the accompanying
33
# file COPYING or https://opensource.org/license/mit/.
44

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+
535
function(get_all_configs output)
636
get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
737
if(is_multi_config)
@@ -63,6 +93,11 @@ function(remove_c_flag_from_all_configs flag)
6393
list(FILTER flags EXCLUDE REGEX "${flag}")
6494
list(JOIN flags " " new_flags)
6595
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+
)
66101
endforeach()
67102
endfunction()
68103

@@ -75,36 +110,34 @@ function(remove_cxx_flag_from_all_configs flag)
75110
list(FILTER flags EXCLUDE REGEX "${flag}")
76111
list(JOIN flags " " new_flags)
77112
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+
)
78118
endforeach()
79119
endfunction()
80120

81121
function(replace_c_flag_in_config config old_flag new_flag)
82122
string(TOUPPER "${config}" config_uppercase)
83123
string(REGEX REPLACE "(^| )${old_flag}( |$)" "\\1${new_flag}\\2" new_flags "${CMAKE_C_FLAGS_${config_uppercase}}")
84124
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+
)
85130
endfunction()
86131

87132
function(replace_cxx_flag_in_config config old_flag new_flag)
88133
string(TOUPPER "${config}" config_uppercase)
89134
string(REGEX REPLACE "(^| )${old_flag}( |$)" "\\1${new_flag}\\2" new_flags "${CMAKE_CXX_FLAGS_${config_uppercase}}")
90135
set(CMAKE_CXX_FLAGS_${config_uppercase} "${new_flags}" PARENT_SCOPE)
91-
endfunction()
92-
93-
function(separate_by_configs options)
94-
list(JOIN ${options} " " ${options}_ALL)
95-
string(GENEX_STRIP "${${options}_ALL}" ${options}_ALL)
96-
string(STRIP "${${options}_ALL}" ${options}_ALL)
97-
set(${options}_ALL "${${options}_ALL}" PARENT_SCOPE)
98-
99-
get_all_configs(all_configs)
100-
foreach(config IN LISTS all_configs)
101-
string(REGEX MATCHALL "\\$<\\$<CONFIG:${config}>:[^<>\n]*>" match "${${options}}")
102-
list(JOIN match " " match)
103-
string(REPLACE "\$<\$<CONFIG:${config}>:" "" match "${match}")
104-
string(REPLACE ">" "" match "${match}")
105-
string(TOUPPER "${config}" conf_upper)
106-
set(${options}_${conf_upper} "${match}" PARENT_SCOPE)
107-
endforeach()
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+
)
108141
endfunction()
109142

110143
function(print_config_flags)

depends/Makefile

+9-3
Original file line numberDiff line numberDiff line change
@@ -273,9 +273,15 @@ $(host_prefix)/share/toolchain.cmake : toolchain.cmake.in $(host_prefix)/.stamp_
273273
-e 's|@INSTALL_NAME_TOOL@|$(host_INSTALL_NAME_TOOL)|' \
274274
-e 's|@OTOOL@|$(host_OTOOL)|' \
275275
-e 's|@depends_prefix@|$(host_prefix)|' \
276-
-e 's|@CFLAGS@|$(strip $(host_CFLAGS) $(host_$(release_type)_CFLAGS))|' \
277-
-e 's|@CXXFLAGS@|$(strip $(host_CXXFLAGS) $(host_$(release_type)_CXXFLAGS))|' \
278-
-e 's|@CPPFLAGS@|$(strip $(host_CPPFLAGS) $(host_$(release_type)_CPPFLAGS))|' \
276+
-e 's|@CFLAGS@|$(strip $(host_CFLAGS))|' \
277+
-e 's|@CFLAGS_RELEASE@|$(strip $(host_release_CFLAGS))|' \
278+
-e 's|@CFLAGS_DEBUG@|$(strip $(host_debug_CFLAGS))|' \
279+
-e 's|@CXXFLAGS@|$(strip $(host_CXXFLAGS))|' \
280+
-e 's|@CXXFLAGS_RELEASE@|$(strip $(host_release_CXXFLAGS))|' \
281+
-e 's|@CXXFLAGS_DEBUG@|$(strip $(host_debug_CXXFLAGS))|' \
282+
-e 's|@CPPFLAGS@|$(strip $(host_CPPFLAGS))|' \
283+
-e 's|@CPPFLAGS_RELEASE@|$(strip $(host_release_CPPFLAGS))|' \
284+
-e 's|@CPPFLAGS_DEBUG@|$(strip $(host_debug_CPPFLAGS))|' \
279285
-e 's|@no_qt@|$(NO_QT)|' \
280286
-e 's|@no_qr@|$(NO_QR)|' \
281287
-e 's|@no_zmq@|$(NO_ZMQ)|' \

depends/hosts/default.mk

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ endef
2828

2929
define add_host_flags_func
3030
ifeq ($(filter $(origin $1),undefined default),)
31-
$(host_arch)_$(host_os)_$1 =
32-
$(host_arch)_$(host_os)_$(release_type)_$1 = $($1)
31+
$(host_arch)_$(host_os)_$1 = $($1)
32+
$(host_arch)_$(host_os)_$(release_type)_$1 =
3333
else
3434
$(host_arch)_$(host_os)_$1 += $($(host_os)_$1)
3535
$(host_arch)_$(host_os)_$(release_type)_$1 += $($(host_os)_$(release_type)_$1)

depends/toolchain.cmake.in

+25-4
Original file line numberDiff line numberDiff line change
@@ -32,25 +32,46 @@ function(split_compiler_launcher env_compiler launcher compiler)
3232
set(${compiler} ${${compiler}} PARENT_SCOPE)
3333
endfunction()
3434

35-
if(NOT CMAKE_C_COMPILER)
35+
if(NOT DEFINED CMAKE_C_FLAGS_INIT)
36+
set(CMAKE_C_FLAGS_INIT "@CFLAGS@")
37+
endif()
38+
if(NOT DEFINED CMAKE_C_FLAGS_RELWITHDEBINFO_INIT)
39+
set(CMAKE_C_FLAGS_RELWITHDEBINFO_INIT "@CFLAGS_RELEASE@")
40+
endif()
41+
if(NOT DEFINED CMAKE_C_FLAGS_DEBUG_INIT)
42+
set(CMAKE_C_FLAGS_DEBUG_INIT "@CFLAGS_DEBUG@")
43+
endif()
44+
45+
if(NOT DEFINED CMAKE_C_COMPILER)
3646
set(DEPENDS_C_COMPILER_WITH_LAUNCHER @CC@)
3747
split_compiler_launcher(DEPENDS_C_COMPILER_WITH_LAUNCHER CMAKE_C_COMPILER_LAUNCHER CMAKE_C_COMPILER)
3848
set(CMAKE_C_LINKER_LAUNCHER ${CMAKE_C_COMPILER_LAUNCHER})
39-
set(DEPENDS_C_COMPILER_FLAGS @CFLAGS@)
4049
endif()
4150

42-
if(NOT CMAKE_CXX_COMPILER)
51+
if(NOT DEFINED CMAKE_CXX_FLAGS_INIT)
52+
set(CMAKE_CXX_FLAGS_INIT "@CXXFLAGS@")
53+
endif()
54+
if(NOT DEFINED CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT)
55+
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT "@CXXFLAGS_RELEASE@")
56+
endif()
57+
if(NOT DEFINED CMAKE_CXX_FLAGS_DEBUG_INIT)
58+
set(CMAKE_CXX_FLAGS_DEBUG_INIT "@CXXFLAGS_DEBUG@")
59+
endif()
60+
61+
if(NOT DEFINED CMAKE_CXX_COMPILER)
4362
set(DEPENDS_CXX_COMPILER_WITH_LAUNCHER @CXX@)
4463
split_compiler_launcher(DEPENDS_CXX_COMPILER_WITH_LAUNCHER CMAKE_CXX_COMPILER_LAUNCHER CMAKE_CXX_COMPILER)
4564
set(CMAKE_CXX_LINKER_LAUNCHER ${CMAKE_CXX_COMPILER_LAUNCHER})
46-
set(DEPENDS_CXX_COMPILER_FLAGS @CXXFLAGS@)
4765

4866
set(CMAKE_OBJCXX_COMPILER ${CMAKE_CXX_COMPILER})
4967
set(CMAKE_OBJCXX_COMPILER_LAUNCHER ${CMAKE_CXX_COMPILER_LAUNCHER})
5068
set(CMAKE_OBJCXX_LINKER_LAUNCHER ${CMAKE_CXX_LINKER_LAUNCHER})
5169
endif()
5270

71+
# The DEPENDS_COMPILE_DEFINITIONS* variables are to be treated as lists.
5372
set(DEPENDS_COMPILE_DEFINITIONS @CPPFLAGS@)
73+
set(DEPENDS_COMPILE_DEFINITIONS_RELWITHDEBINFO @CPPFLAGS_RELEASE@)
74+
set(DEPENDS_COMPILE_DEFINITIONS_DEBUG @CPPFLAGS_DEBUG@)
5475

5576
set(CMAKE_AR "@AR@")
5677
set(CMAKE_RANLIB "@RANLIB@")

0 commit comments

Comments
 (0)