From 7903bd5edc8c21b0bfe5fb29c114366de0969991 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sat, 2 Sep 2023 20:29:44 +0100 Subject: [PATCH 1/7] [FIXUP] Encapsulate common build flags into `core` interface library --- CMakeLists.txt | 43 +++++++++++++++++++++++++++++------- cmake/crc32c.cmake | 2 ++ cmake/leveldb.cmake | 2 +- cmake/minisketch.cmake | 3 +++ cmake/secp256k1.cmake | 2 ++ src/CMakeLists.txt | 14 +++++++++++- src/bench/CMakeLists.txt | 1 + src/crypto/CMakeLists.txt | 2 ++ src/test/CMakeLists.txt | 1 + src/test/util/CMakeLists.txt | 3 +++ src/util/CMakeLists.txt | 1 + src/wallet/CMakeLists.txt | 1 + src/zmq/CMakeLists.txt | 1 + 13 files changed, 66 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8731f56579772..95df5055fc4a4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -80,6 +80,10 @@ set(CMAKE_CXX_EXTENSIONS OFF) set(configure_warnings) +# The core interface library aims to encapsulate all common build flags. +# It is intended to be a usage requirement for all other targets. +add_library(core INTERFACE) + if(WIN32) #[=[ This build system supports two ways to build binaries for Windows. @@ -97,25 +101,39 @@ if(WIN32) - A run-time library must be specified explicitly using _MT definition. ]=] - add_compile_definitions(_WIN32_WINNT=0x0601 _WIN32_IE=0x0501 WIN32_LEAN_AND_MEAN NOMINMAX) + target_compile_definitions(core INTERFACE + _WIN32_WINNT=0x0601 + _WIN32_IE=0x0501 + WIN32_LEAN_AND_MEAN + NOMINMAX + ) if(MSVC) set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") - add_compile_options(/utf-8 /Zc:__cplusplus) + target_compile_options(core INTERFACE + /utf-8 + /Zc:__cplusplus + ) # Improve parallelism in MSBuild. # See: https://devblogs.microsoft.com/cppblog/improved-parallelism-in-msbuild/. list(APPEND CMAKE_VS_GLOBALS "UseMultiToolTask=true") endif() if(MINGW) - add_compile_definitions(WIN32 _WINDOWS _MT) + target_compile_definitions(core INTERFACE + WIN32 + _WINDOWS + _MT + ) # We require Windows 7 (NT 6.1) or later. add_link_options(-Wl,--major-subsystem-version,6 -Wl,--minor-subsystem-version,1) endif() endif() if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") - add_compile_definitions(MAC_OSX) + target_compile_definitions(core INTERFACE + MAC_OSX + ) endif() if(CMAKE_CROSSCOMPILING AND DEPENDS_ALLOW_HOST_PACKAGES) @@ -197,11 +215,20 @@ message("C compiler ............................ ${CMAKE_C_COMPILER}") message("CFLAGS ................................ ${CMAKE_C_FLAGS}") message("C++ compiler .......................... ${CMAKE_CXX_COMPILER}") message("CXXFLAGS .............................. ${CMAKE_CXX_FLAGS}") -get_directory_property(common_compile_options COMPILE_OPTIONS) -string(REPLACE ";" " " common_compile_options "${common_compile_options}") +get_target_property(common_compile_options core INTERFACE_COMPILE_OPTIONS) +if(common_compile_options) + list(JOIN common_compile_options " " common_compile_options) +else() + set(common_compile_options) +endif() +string(GENEX_STRIP "${common_compile_options}" common_compile_options) message("Common compile options ................ ${common_compile_options}") -get_directory_property(common_link_options LINK_OPTIONS) -string(REPLACE ";" " " common_link_options "${common_link_options}") +get_target_property(common_link_options core INTERFACE_LINK_OPTIONS) +if(common_link_options) + list(JOIN common_link_options " " common_link_options) +else() + set(common_link_options) +endif() message("Common link options ................... ${common_link_options}") if(DEFINED CMAKE_BUILD_TYPE) message("Build type:") diff --git a/cmake/crc32c.cmake b/cmake/crc32c.cmake index fa3e629dc1d0b..a1a64d12059a9 100644 --- a/cmake/crc32c.cmake +++ b/cmake/crc32c.cmake @@ -111,3 +111,5 @@ if(HAVE_ARM64_CRC32C) APPEND PROPERTY COMPILE_OPTIONS ${ARM_CRC_CXXFLAGS} ) endif() + +target_link_libraries(crc32c PRIVATE core) diff --git a/cmake/leveldb.cmake b/cmake/leveldb.cmake index e137ef461db02..d1c34024151fb 100644 --- a/cmake/leveldb.cmake +++ b/cmake/leveldb.cmake @@ -91,4 +91,4 @@ target_include_directories(leveldb #TODO: figure out how to filter out: # -Wconditional-uninitialized -Werror=conditional-uninitialized -Wsuggest-override -Werror=suggest-override -target_link_libraries(leveldb PRIVATE crc32c) +target_link_libraries(leveldb PRIVATE core crc32c) diff --git a/cmake/minisketch.cmake b/cmake/minisketch.cmake index 4d8e4b8af74df..aaa3e9bcd9910 100644 --- a/cmake/minisketch.cmake +++ b/cmake/minisketch.cmake @@ -69,3 +69,6 @@ target_link_libraries(minisketch minisketch_defs $ ) + +target_link_libraries(minisketch_clmul PRIVATE core) +target_link_libraries(minisketch PRIVATE core) diff --git a/cmake/secp256k1.cmake b/cmake/secp256k1.cmake index 38014b1cde4f5..562d4cbf3914a 100644 --- a/cmake/secp256k1.cmake +++ b/cmake/secp256k1.cmake @@ -50,3 +50,5 @@ target_compile_options(secp256k1 PRIVATE $<$:/wd4146 /wd4334> ) + +target_link_libraries(secp256k1 PRIVATE core) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4f95797409580..ff499979078b3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -27,7 +27,11 @@ add_library(bitcoin_consensus OBJECT EXCLUDE_FROM_ALL uint256.cpp util/strencodings.cpp ) -target_link_libraries(bitcoin_consensus PRIVATE secp256k1) +target_link_libraries(bitcoin_consensus + PRIVATE + core + secp256k1 +) if(WITH_ZMQ) add_subdirectory(zmq EXCLUDE_FROM_ALL) @@ -86,6 +90,7 @@ target_compile_definitions(bitcoin_common ) target_link_libraries(bitcoin_common PRIVATE + core bitcoin_consensus bitcoin_util univalue @@ -105,6 +110,7 @@ if(ENABLE_WALLET) wallet/wallettool.cpp ) target_link_libraries(bitcoin-wallet + core bitcoin_wallet bitcoin_common bitcoin_util @@ -211,6 +217,7 @@ else() endif() target_link_libraries(bitcoin_node PRIVATE + core bitcoin_common bitcoin_util leveldb @@ -233,6 +240,7 @@ if(BUILD_DAEMON) ) target_link_libraries(bitcoind PRIVATE + core bitcoin_node ) target_link_options(bitcoind @@ -248,6 +256,7 @@ add_library(bitcoin_cli STATIC EXCLUDE_FROM_ALL ) target_link_libraries(bitcoin_cli PUBLIC + core univalue ) @@ -256,6 +265,7 @@ target_link_libraries(bitcoin_cli if(BUILD_CLI) add_executable(bitcoin-cli bitcoin-cli.cpp) target_link_libraries(bitcoin-cli + core bitcoin_cli bitcoin_common bitcoin_util @@ -267,6 +277,7 @@ endif() if(BUILD_TX) add_executable(bitcoin-tx bitcoin-tx.cpp) target_link_libraries(bitcoin-tx + core bitcoin_common bitcoin_util univalue @@ -277,6 +288,7 @@ endif() if(BUILD_UTIL) add_executable(bitcoin-util bitcoin-util.cpp) target_link_libraries(bitcoin-util + core bitcoin_common bitcoin_util ) diff --git a/src/bench/CMakeLists.txt b/src/bench/CMakeLists.txt index dce546744b1b9..362d3922636a7 100644 --- a/src/bench/CMakeLists.txt +++ b/src/bench/CMakeLists.txt @@ -49,6 +49,7 @@ add_executable(bench_bitcoin ) target_link_libraries(bench_bitcoin + core test_util leveldb univalue diff --git a/src/crypto/CMakeLists.txt b/src/crypto/CMakeLists.txt index 3f191159a1506..b1005c8da3498 100644 --- a/src/crypto/CMakeLists.txt +++ b/src/crypto/CMakeLists.txt @@ -120,3 +120,5 @@ if(HAVE_ARM_SHANI) APPEND PROPERTY COMPILE_OPTIONS ${ARM_SHANI_CXXFLAGS} ) endif() + +target_link_libraries(bitcoin_crypto PRIVATE core) diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index f1e3e2938d226..8b1b6c020701b 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -134,6 +134,7 @@ add_executable(test_bitcoin ) target_link_libraries(test_bitcoin + core test_util bitcoin_cli bitcoin_node diff --git a/src/test/util/CMakeLists.txt b/src/test/util/CMakeLists.txt index 69d7ad02de2d2..d1de910212064 100644 --- a/src/test/util/CMakeLists.txt +++ b/src/test/util/CMakeLists.txt @@ -19,6 +19,7 @@ add_library(test_util STATIC EXCLUDE_FROM_ALL ) target_link_libraries(test_util PRIVATE + core bitcoin_common bitcoin_node leveldb @@ -32,3 +33,5 @@ if(ENABLE_WALLET) ../../wallet/test/util.cpp ) endif() + +target_link_libraries(test_util PRIVATE core) diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt index c567293088c4c..70de3c3d8e77c 100644 --- a/src/util/CMakeLists.txt +++ b/src/util/CMakeLists.txt @@ -50,6 +50,7 @@ target_compile_definitions(bitcoin_util target_link_libraries(bitcoin_util PRIVATE + core bitcoin_crypto univalue Threads::Threads diff --git a/src/wallet/CMakeLists.txt b/src/wallet/CMakeLists.txt index 319b8960dfb62..34a0379408dfa 100644 --- a/src/wallet/CMakeLists.txt +++ b/src/wallet/CMakeLists.txt @@ -34,6 +34,7 @@ add_library(bitcoin_wallet STATIC EXCLUDE_FROM_ALL ) target_link_libraries(bitcoin_wallet PRIVATE + core bitcoin_common univalue Boost::headers diff --git a/src/zmq/CMakeLists.txt b/src/zmq/CMakeLists.txt index 39cef32fceb42..228a802965e8e 100644 --- a/src/zmq/CMakeLists.txt +++ b/src/zmq/CMakeLists.txt @@ -15,6 +15,7 @@ target_compile_definitions(bitcoin_zmq ) target_link_libraries(bitcoin_zmq PRIVATE + core leveldb univalue $ From ae430cfa41a09d95aecc218116a7bb574b5655b4 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sat, 2 Sep 2023 18:12:43 +0100 Subject: [PATCH 2/7] cmake: Add `TryAppendCXXFlags` module --- cmake/module/TryAppendCXXFlags.cmake | 85 ++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 cmake/module/TryAppendCXXFlags.cmake diff --git a/cmake/module/TryAppendCXXFlags.cmake b/cmake/module/TryAppendCXXFlags.cmake new file mode 100644 index 0000000000000..50efc8f04294a --- /dev/null +++ b/cmake/module/TryAppendCXXFlags.cmake @@ -0,0 +1,85 @@ +# 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(CheckCXXSourceCompiles) + +#[=[ +Usage examples: + + try_append_cxx_flags(warn_cxx_flags "-Wformat -Wformat-security") + + + try_append_cxx_flags(warn_cxx_flags "-Wsuggest-override" + SOURCE "struct A { virtual void f(); }; struct B : A { void f() final; };" + ) + + + try_append_cxx_flags(sanitizers_cxx_flags "-fsanitize=${SANITIZERS}" RESULT_VAR cxx_supports_sanitizers) + if(NOT cxx_supports_sanitizers) + message(FATAL_ERROR "Compiler did not accept requested flags.") + endif() + + + try_append_cxx_flags(warn_cxx_flags "-Wunused-parameter" IF_CHECK_PASSED "-Wno-unused-parameter") + + + try_append_cxx_flags(error_cxx_flags "-Werror=return-type" + IF_CHECK_FAILED "-Wno-error=return-type" + SOURCE "#include \nint f(){ assert(false); }" + ) + + +In configuration output, this function prints a string by the following pattern: + + -- Performing Test CXX_SUPPORTS_[flags] + -- Performing Test CXX_SUPPORTS_[flags] - Success + +]=] +function(try_append_cxx_flags flags_var flags) + cmake_parse_arguments(PARSE_ARGV 2 + TACXXF # prefix + "" # options + "SOURCE;RESULT_VAR" # one_value_keywords + "IF_CHECK_PASSED;IF_CHECK_FAILED" # multi_value_keywords + ) + + string(MAKE_C_IDENTIFIER "${flags}" result) + string(TOUPPER "${result}" result) + set(result "CXX_SUPPORTS_${result}") + + # Every subsequent check_cxx_source_compiles(( ) run will re-use + # the cached result rather than performing the check again, even if the changes. + # Removing the cached result in order to force the check to be re-evaluated. + unset(${result} CACHE) + + if(NOT DEFINED TACXXF_SOURCE) + set(TACXXF_SOURCE "int main() { return 0; }") + endif() + + # This avoids running a linker. + set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) + set(CMAKE_REQUIRED_FLAGS "${flags} ${working_compiler_werror_flag}") + check_cxx_source_compiles("${TACXXF_SOURCE}" ${result}) + + if(${result}) + if(DEFINED TACXXF_IF_CHECK_PASSED) + string(STRIP "${${flags_var}} ${TACXXF_IF_CHECK_PASSED}" ${flags_var}) + else() + string(STRIP "${${flags_var}} ${flags}" ${flags_var}) + endif() + elseif(DEFINED TACXXF_IF_CHECK_FAILED) + string(STRIP "${${flags_var}} ${TACXXF_IF_CHECK_FAILED}" ${flags_var}) + endif() + set(${flags_var} "${${flags_var}}" PARENT_SCOPE) + set(${TACXXF_RESULT_VAR} "${${result}}" PARENT_SCOPE) +endfunction() + +if(MSVC) + set(warning_as_error_flag /WX) +else() + set(warning_as_error_flag -Werror) +endif() +try_append_cxx_flags(working_compiler_werror_flag ${warning_as_error_flag}) +unset(warning_as_error_flag) From e0621e943f33d2120ffcd2d907f963c0ee8c4a33 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sat, 2 Sep 2023 18:13:06 +0100 Subject: [PATCH 3/7] cmake: Add `TryAppendLinkerFlag` module --- cmake/module/TryAppendLinkerFlag.cmake | 80 ++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 cmake/module/TryAppendLinkerFlag.cmake diff --git a/cmake/module/TryAppendLinkerFlag.cmake b/cmake/module/TryAppendLinkerFlag.cmake new file mode 100644 index 0000000000000..4c3afa83b9f96 --- /dev/null +++ b/cmake/module/TryAppendLinkerFlag.cmake @@ -0,0 +1,80 @@ +# 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(CheckCXXSourceCompiles) + +#[=[ +Usage example: + + try_append_linker_flag(core "-Wl,--major-subsystem-version,6") + + +In configuration output, this function prints a string by the following pattern: + + -- Performing Test LINKER_SUPPORTS_[flag] + -- Performing Test LINKER_SUPPORTS_[flag] - Success + +]=] +function(try_append_linker_flag target flag) + cmake_parse_arguments(PARSE_ARGV 2 + TALF # prefix + "" # options + "SOURCE;RESULT_VAR" # one_value_keywords + "IF_CHECK_PASSED;IF_CHECK_FAILED" # multi_value_keywords + ) + + string(MAKE_C_IDENTIFIER "${flag}" result) + string(TOUPPER "${result}" result) + set(result "LINKER_SUPPORTS_${result}") + + # Every subsequent check_cxx_source_compiles(( ) run will re-use + # the cached result rather than performing the check again, even if the changes. + # Removing the cached result in order to force the check to be re-evaluated. + unset(${result} CACHE) + + if(NOT DEFINED TALF_SOURCE) + set(TALF_SOURCE "int main() { return 0; }") + endif() + + # This forces running a linker. + set(CMAKE_TRY_COMPILE_TARGET_TYPE EXECUTABLE) + + get_target_property(working_linker_werror_flag internal_werror INTERFACE_LINK_OPTIONS) + if(NOT working_linker_werror_flag) + set(working_linker_werror_flag) + endif() + if(CMAKE_VERSION VERSION_LESS 3.14) + set(CMAKE_REQUIRED_LIBRARIES ${flag} ${working_linker_werror_flag}) + else() + set(CMAKE_REQUIRED_LINK_OPTIONS ${flag} ${working_linker_werror_flag}) + endif() + + check_cxx_source_compiles("${TALF_SOURCE}" ${result}) + + if(${result}) + if(DEFINED TALF_IF_CHECK_PASSED) + target_link_options(${target} INTERFACE ${TALF_IF_CHECK_PASSED}) + else() + target_link_options(${target} INTERFACE ${flag}) + endif() + elseif(DEFINED TALF_IF_CHECK_FAILED) + target_link_options(${target} INTERFACE ${TALF_IF_CHECK_FAILED}) + endif() + + set(${TALF_RESULT_VAR} "${${result}}" PARENT_SCOPE) +endfunction() + +if(NOT TARGET internal_werror) + add_library(internal_werror INTERFACE) +endif() +if(MSVC) + set(warning_as_error_flag /WX) +elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + set(warning_as_error_flag -Wl,-fatal_warnings) +else() + set(warning_as_error_flag -Wl,--fatal-warnings) +endif() +try_append_linker_flag(internal_werror "${warning_as_error_flag}") +unset(warning_as_error_flag) From 37364700f69cb790b263b3b4879b8cb4589a96c1 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sat, 2 Sep 2023 17:54:39 +0100 Subject: [PATCH 4/7] cmake: Add platform-specific flags --- CMakeLists.txt | 21 ++++++++++++++++++++- depends/toolchain.cmake.in | 4 ++++ src/CMakeLists.txt | 4 ---- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 95df5055fc4a4..4b9f0c8bf26b8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -84,6 +84,8 @@ set(configure_warnings) # It is intended to be a usage requirement for all other targets. add_library(core INTERFACE) +include(TryAppendLinkerFlag) + if(WIN32) #[=[ This build system supports two ways to build binaries for Windows. @@ -126,14 +128,29 @@ if(WIN32) _MT ) # We require Windows 7 (NT 6.1) or later. - add_link_options(-Wl,--major-subsystem-version,6 -Wl,--minor-subsystem-version,1) + try_append_linker_flag(core "-Wl,--major-subsystem-version,6") + try_append_linker_flag(core "-Wl,--minor-subsystem-version,1") endif() endif() +# Use 64-bit off_t on 32-bit Linux. +if (CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_SIZEOF_VOID_P EQUAL 4) + # Ensure 64-bit offsets are used for filesystem accesses for 32-bit compilation. + target_compile_definitions(core INTERFACE + _FILE_OFFSET_BITS=64 + ) +endif() + if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") target_compile_definitions(core INTERFACE MAC_OSX ) + # These flags are specific to ld64, and may cause issues with other linkers. + # For example: GNU ld will interpret -dead_strip as -de and then try and use + # "ad_strip" as the symbol for the entry point. + try_append_linker_flag(core "-Wl,-dead_strip") + try_append_linker_flag(core "-Wl,-dead_strip_dylibs") + try_append_linker_flag(core "-Wl,-headerpad_max_install_names") endif() if(CMAKE_CROSSCOMPILING AND DEPENDS_ALLOW_HOST_PACKAGES) @@ -230,6 +247,8 @@ else() set(common_link_options) endif() message("Common link options ................... ${common_link_options}") +message("Linker flags for executables .......... ${CMAKE_EXE_LINKER_FLAGS}") +message("Linker flags for shared libraries ..... ${CMAKE_SHARED_LINKER_FLAGS}") if(DEFINED CMAKE_BUILD_TYPE) message("Build type:") message(" - CMAKE_BUILD_TYPE ................... ${CMAKE_BUILD_TYPE}") diff --git a/depends/toolchain.cmake.in b/depends/toolchain.cmake.in index 59c98d745209d..c64ac90e8fc9c 100644 --- a/depends/toolchain.cmake.in +++ b/depends/toolchain.cmake.in @@ -73,6 +73,10 @@ if(NOT CMAKE_OBJCXX_COMPILER) endif() set(CMAKE_OBJCXX_FLAGS_INIT "${DEPENDS_OBJCXX_COMPILER_FLAGS} @CPPFLAGS@ @CXXFLAGS@") +if(CMAKE_SYSTEM_NAME STREQUAL "Windows") + set(CMAKE_EXE_LINKER_FLAGS_INIT "-static") +endif() + set(CMAKE_AR "@AR@") set(CMAKE_RANLIB "@RANLIB@") set(CMAKE_STRIP "@STRIP@") diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ff499979078b3..84593f72bfb68 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -243,10 +243,6 @@ if(BUILD_DAEMON) core bitcoin_node ) - target_link_options(bitcoind - PRIVATE - $<$:-static> - ) endif() From 482e84404ab2afd9bdf7faaa1b624b5f4c3f763a Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sat, 2 Sep 2023 17:40:13 +0100 Subject: [PATCH 5/7] cmake: Warn about not encapsulated build properties --- CMakeLists.txt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4b9f0c8bf26b8..542296336635c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -280,3 +280,17 @@ if(configure_warnings) endforeach() message(" ******\n") endif() + +# We want all build properties to be encapsulated properly. +get_directory_property(global_compile_definitions COMPILE_DEFINITIONS) +if(global_compile_definitions) + message(AUTHOR_WARNING "The directory's COMPILE_DEFINITIONS property is not empty: ${global_compile_definitions}") +endif() +get_directory_property(global_compile_options COMPILE_OPTIONS) +if(global_compile_options) + message(AUTHOR_WARNING "The directory's COMPILE_OPTIONS property is not empty: ${global_compile_options}") +endif() +get_directory_property(global_link_options LINK_OPTIONS) +if(global_link_options) + message(AUTHOR_WARNING "The directory's LINK_OPTIONS property is not empty: ${global_link_options}") +endif() From 1a1dda5f1f05fb1ff59d05437fd00a0f8412de3d Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sat, 2 Sep 2023 18:35:58 +0100 Subject: [PATCH 6/7] [FIXUP] Evaluate flags set in depends _after_ config-specific flags --- CMakeLists.txt | 17 +++++++++++++---- depends/toolchain.cmake.in | 25 +++++++------------------ 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 542296336635c..59b1d16d67132 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -153,8 +153,13 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") try_append_linker_flag(core "-Wl,-headerpad_max_install_names") endif() -if(CMAKE_CROSSCOMPILING AND DEPENDS_ALLOW_HOST_PACKAGES) - list(APPEND CMAKE_FIND_ROOT_PATH "${CMAKE_SYSTEM_PREFIX_PATH}") +if(CMAKE_CROSSCOMPILING) + target_compile_definitions(core INTERFACE ${DEPENDS_COMPILE_DEFINITIONS}) + target_compile_options(core INTERFACE "$<$:${DEPENDS_C_COMPILER_FLAGS}>") + target_compile_options(core INTERFACE "$<$:${DEPENDS_CXX_COMPILER_FLAGS}>") + if(DEPENDS_ALLOW_HOST_PACKAGES) + list(APPEND CMAKE_FIND_ROOT_PATH "${CMAKE_SYSTEM_PREFIX_PATH}") + endif() endif() include(AddThreadsIfNeeded) @@ -229,9 +234,13 @@ get_directory_property(definitions COMPILE_DEFINITIONS) string(REPLACE ";" " " definitions "${definitions}") message("Preprocessor defined macros ........... ${definitions}") message("C compiler ............................ ${CMAKE_C_COMPILER}") -message("CFLAGS ................................ ${CMAKE_C_FLAGS}") +list(JOIN DEPENDS_C_COMPILER_FLAGS " " depends_c_flags) +string(STRIP "${CMAKE_C_FLAGS} ${depends_c_flags}" combined_c_flags) +message("CFLAGS ................................ ${combined_c_flags}") message("C++ compiler .......................... ${CMAKE_CXX_COMPILER}") -message("CXXFLAGS .............................. ${CMAKE_CXX_FLAGS}") +list(JOIN DEPENDS_CXX_COMPILER_FLAGS " " depends_cxx_flags) +string(STRIP "${CMAKE_CXX_FLAGS} ${depends_cxx_flags}" combined_cxx_flags) +message("CXXFLAGS .............................. ${combined_cxx_flags}") get_target_property(common_compile_options core INTERFACE_COMPILE_OPTIONS) if(common_compile_options) list(JOIN common_compile_options " " common_compile_options) diff --git a/depends/toolchain.cmake.in b/depends/toolchain.cmake.in index c64ac90e8fc9c..55896cc95c19b 100644 --- a/depends/toolchain.cmake.in +++ b/depends/toolchain.cmake.in @@ -37,11 +37,10 @@ if(NOT CMAKE_C_COMPILER) if(CMAKE_VERSION VERSION_LESS 3.19) set(DEPENDS_C_COMPILER_FLAGS ${CMAKE_C_COMPILER}) list(REMOVE_AT DEPENDS_C_COMPILER_FLAGS 0) - string(REPLACE ";" " " DEPENDS_C_COMPILER_FLAGS "${DEPENDS_C_COMPILER_FLAGS}") list(GET CMAKE_C_COMPILER 0 CMAKE_C_COMPILER) endif() + list(APPEND DEPENDS_C_COMPILER_FLAGS @CFLAGS@) endif() -set(CMAKE_C_FLAGS_INIT "${DEPENDS_C_COMPILER_FLAGS} @CPPFLAGS@ @CFLAGS@") if(NOT CMAKE_CXX_COMPILER) set(DEPENDS_CXX_COMPILER_WITH_LAUNCHER @CXX@) @@ -52,26 +51,16 @@ if(NOT CMAKE_CXX_COMPILER) if(CMAKE_VERSION VERSION_LESS 3.19) set(DEPENDS_CXX_COMPILER_FLAGS ${CMAKE_CXX_COMPILER}) list(REMOVE_AT DEPENDS_CXX_COMPILER_FLAGS 0) - string(REPLACE ";" " " DEPENDS_CXX_COMPILER_FLAGS "${DEPENDS_CXX_COMPILER_FLAGS}") list(GET CMAKE_CXX_COMPILER 0 CMAKE_CXX_COMPILER) endif() -endif() -set(CMAKE_CXX_FLAGS_INIT "${DEPENDS_CXX_COMPILER_FLAGS} @CPPFLAGS@ @CXXFLAGS@") + list(APPEND DEPENDS_CXX_COMPILER_FLAGS @CXXFLAGS@) -if(NOT CMAKE_OBJCXX_COMPILER) - set(DEPENDS_OBJCXX_COMPILER_WITH_LAUNCHER @CXX@) - split_compiler_launcher(DEPENDS_OBJCXX_COMPILER_WITH_LAUNCHER CMAKE_OBJCXX_COMPILER_LAUNCHER CMAKE_OBJCXX_COMPILER) - if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.21) - set(CMAKE_OBJCXX_LINKER_LAUNCHER ${CMAKE_OBJCXX_COMPILER_LAUNCHER}) - endif() - if(CMAKE_VERSION VERSION_LESS 3.19) - set(DEPENDS_OBJCXX_COMPILER_FLAGS ${CMAKE_OBJCXX_COMPILER}) - list(REMOVE_AT DEPENDS_OBJCXX_COMPILER_FLAGS 0) - string(REPLACE ";" " " DEPENDS_OBJCXX_COMPILER_FLAGS "${DEPENDS_OBJCXX_COMPILER_FLAGS}") - list(GET CMAKE_OBJCXX_COMPILER 0 CMAKE_OBJCXX_COMPILER) - endif() + set(CMAKE_OBJCXX_COMPILER ${CMAKE_CXX_COMPILER}) + set(CMAKE_OBJCXX_COMPILER_LAUNCHER ${CMAKE_CXX_COMPILER_LAUNCHER}) + set(CMAKE_OBJCXX_LINKER_LAUNCHER ${CMAKE_CXX_LINKER_LAUNCHER}) endif() -set(CMAKE_OBJCXX_FLAGS_INIT "${DEPENDS_OBJCXX_COMPILER_FLAGS} @CPPFLAGS@ @CXXFLAGS@") + +set(DEPENDS_COMPILE_DEFINITIONS @CPPFLAGS@) if(CMAKE_SYSTEM_NAME STREQUAL "Windows") set(CMAKE_EXE_LINKER_FLAGS_INIT "-static") From a65da0da78eeb8e7022c4ea49fec4ec1660a9735 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sat, 2 Sep 2023 17:45:09 +0100 Subject: [PATCH 7/7] cmake: Redefine configuration flags --- CMakeLists.txt | 71 ++++++++---- cmake/module/ProcessConfigurations.cmake | 136 +++++++++++++++++++++++ 2 files changed, 183 insertions(+), 24 deletions(-) create mode 100644 cmake/module/ProcessConfigurations.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 59b1d16d67132..12c5c31c9db93 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -84,6 +84,7 @@ set(configure_warnings) # It is intended to be a usage requirement for all other targets. add_library(core INTERFACE) +include(TryAppendCXXFlags) include(TryAppendLinkerFlag) if(WIN32) @@ -180,6 +181,47 @@ include(cmake/leveldb.cmake) include(cmake/minisketch.cmake) include(cmake/secp256k1.cmake) +include(ProcessConfigurations) +set_default_config(RelWithDebInfo) + +# Redefine configuration flags. +target_compile_definitions(core INTERFACE + $<$:DEBUG> + $<$:DEBUG_LOCKORDER> + $<$:DEBUG_LOCKCONTENTION> + $<$:RPC_DOC_CHECK> + $<$:ABORT_ON_FAILED_ASSUME> +) +# We leave assertions on. +if(MSVC) + remove_c_flag_from_all_configs(/DNDEBUG) + remove_cxx_flag_from_all_configs(/DNDEBUG) +else() + remove_c_flag_from_all_configs(-DNDEBUG) + remove_cxx_flag_from_all_configs(-DNDEBUG) + + # Prefer -O2 optimization level. (-O3 is CMake's default for Release for many compilers.) + replace_c_flag_in_config(Release -O3 -O2) + replace_cxx_flag_in_config(Release -O3 -O2) + + set(debug_c_flags "") + set(debug_cxx_flags "") + try_append_cxx_flags(debug_cxx_flags "-O0" RESULT_VAR compiler_supports_O0) + if(compiler_supports_O0) + string(STRIP "${debug_c_flags} -O0" debug_c_flags) + endif() + try_append_cxx_flags(debug_cxx_flags "-g3" RESULT_VAR compiler_supports_g3) + if(compiler_supports_g3) + string(STRIP "${debug_c_flags} -g3" debug_c_flags) + else() + try_append_cxx_flags(debug_cxx_flags "-g") + string(STRIP "${debug_c_flags} -g" debug_c_flags) + endif() + try_append_cxx_flags(debug_cxx_flags "-ftrapv") + set(CMAKE_C_FLAGS_DEBUG "${debug_c_flags}") + set(CMAKE_CXX_FLAGS_DEBUG "${debug_cxx_flags}") +endif() + include(cmake/optional.cmake) if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.14) @@ -203,6 +245,9 @@ add_subdirectory(test) include(cmake/tests.cmake) +get_target_property(definitions core INTERFACE_COMPILE_DEFINITIONS) +separate_by_configs(definitions) + message("\n") message("Configure summary") message("=================") @@ -230,9 +275,7 @@ else() set(cross_status "FALSE") endif() message("Cross compiling ....................... ${cross_status}") -get_directory_property(definitions COMPILE_DEFINITIONS) -string(REPLACE ";" " " definitions "${definitions}") -message("Preprocessor defined macros ........... ${definitions}") +message("Preprocessor defined macros ........... ${definitions_ALL}") message("C compiler ............................ ${CMAKE_C_COMPILER}") list(JOIN DEPENDS_C_COMPILER_FLAGS " " depends_c_flags) string(STRIP "${CMAKE_C_FLAGS} ${depends_c_flags}" combined_c_flags) @@ -258,27 +301,7 @@ endif() message("Common link options ................... ${common_link_options}") message("Linker flags for executables .......... ${CMAKE_EXE_LINKER_FLAGS}") message("Linker flags for shared libraries ..... ${CMAKE_SHARED_LINKER_FLAGS}") -if(DEFINED CMAKE_BUILD_TYPE) - message("Build type:") - message(" - CMAKE_BUILD_TYPE ................... ${CMAKE_BUILD_TYPE}") - string(TOUPPER "${CMAKE_BUILD_TYPE}" build_type) - message(" - CFLAGS ............................. ${CMAKE_C_FLAGS_${build_type}}") - message(" - CXXFLAGS ........................... ${CMAKE_CXX_FLAGS_${build_type}}") - message(" - LDFLAGS for executables ............ ${CMAKE_EXE_LINKER_FLAGS_${build_type}}") - message(" - LDFLAGS for shared libraries ....... ${CMAKE_SHARED_LINKER_FLAGS_${build_type}}") -else() - message("Available configurations .............. ${CMAKE_CONFIGURATION_TYPES}") - message("Debug configuration:") - message(" - CFLAGS ............................. ${CMAKE_C_FLAGS_DEBUG}") - message(" - CXXFLAGS ........................... ${CMAKE_CXX_FLAGS_DEBUG}") - message(" - LDFLAGS for executables ............ ${CMAKE_EXE_LINKER_FLAGS_DEBUG}") - message(" - LDFLAGS for shared libraries ....... ${CMAKE_SHARED_LINKER_FLAGS_DEBUG}") - message("Release configuration:") - message(" - CFLAGS ............................. ${CMAKE_C_FLAGS_RELEASE}") - message(" - CXXFLAGS ........................... ${CMAKE_CXX_FLAGS_RELEASE}") - message(" - LDFLAGS for executables ............ ${CMAKE_EXE_LINKER_FLAGS_RELEASE}") - message(" - LDFLAGS for shared libraries ....... ${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") -endif() +print_config_flags() message("Use assembly routines ................. ${ASM}") message("Use ccache for compiling .............. ${CCACHE}") message("\n") diff --git a/cmake/module/ProcessConfigurations.cmake b/cmake/module/ProcessConfigurations.cmake new file mode 100644 index 0000000000000..cb4a145190ef3 --- /dev/null +++ b/cmake/module/ProcessConfigurations.cmake @@ -0,0 +1,136 @@ +# 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/. + +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}) + if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.15) + list(PREPEND all_configs ${config}) + else() + set(all_configs ${config} ${all_configs}) + endif() + + 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) + 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() + endif() +endfunction() + +function(remove_c_flag_from_all_configs flag) + get_all_configs(all_configs) + foreach(config IN LISTS all_configs) + string(TOUPPER "${config}" config_uppercase) + set(flags "${CMAKE_C_FLAGS_${config_uppercase}}") + separate_arguments(flags) + list(FILTER flags EXCLUDE REGEX "${flag}") + list(JOIN flags " " new_flags) + set(CMAKE_C_FLAGS_${config_uppercase} "${new_flags}" PARENT_SCOPE) + endforeach() +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) + endforeach() +endfunction() + +function(replace_c_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_C_FLAGS_${config_uppercase}}") + set(CMAKE_C_FLAGS_${config_uppercase} "${new_flags}" PARENT_SCOPE) +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) +endfunction() + +function(separate_by_configs options) + list(JOIN ${options} " " ${options}_ALL) + string(GENEX_STRIP "${${options}_ALL}" ${options}_ALL) + set(${options}_ALL "${${options}_ALL}" PARENT_SCOPE) + + get_all_configs(all_configs) + foreach(config IN LISTS all_configs) + string(REGEX MATCHALL "\\$<\\$[^\n]*>" match "${${options}}") + list(JOIN match " " match) + string(REPLACE "\$<\$:" "" match "${match}") + string(REPLACE ">" "" match "${match}") + string(TOUPPER "${config}" conf_upper) + set(${options}_${conf_upper} "${match}" PARENT_SCOPE) + endforeach() +endfunction() + +function(print_config_flags) + macro(print_flags config) + string(TOUPPER "${config}" config_uppercase) + message(" - Preprocessor defined macros ........ ${definitions_${config_uppercase}}") + message(" - CFLAGS ............................. ${CMAKE_C_FLAGS_${config_uppercase}}") + message(" - CXXFLAGS ........................... ${CMAKE_CXX_FLAGS_${config_uppercase}}") + message(" - LDFLAGS for executables ............ ${CMAKE_EXE_LINKER_FLAGS_${config_uppercase}}") + message(" - LDFLAGS for shared libraries ....... ${CMAKE_SHARED_LINKER_FLAGS_${config_uppercase}}") + endmacro() + + get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) + if(is_multi_config) + list(JOIN CMAKE_CONFIGURATION_TYPES " " configs) + message("Available build types (configurations) ${configs}") + foreach(config IN LISTS CMAKE_CONFIGURATION_TYPES) + message("'${config}' build type (configuration):") + print_flags(${config}) + endforeach() + else() + message("Build type (configuration):") + message(" - CMAKE_BUILD_TYPE ................... ${CMAKE_BUILD_TYPE}") + print_flags(${CMAKE_BUILD_TYPE}) + endif() +endfunction()