diff --git a/CMakeLists.txt b/CMakeLists.txt index f5aa0ca1653b0..a69b236cb37b1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -198,11 +198,11 @@ add_library(core_interface INTERFACE) # include the warn_interface as subtree's warnings are not fixable # in our tree. add_library(core_base_interface INTERFACE) -add_library(core_depends_release_interface INTERFACE) -add_library(core_depends_debug_interface INTERFACE) +add_library(core_interface_relwithdebinfo INTERFACE) +add_library(core_interface_debug INTERFACE) target_link_libraries(core_base_interface INTERFACE - $<$:core_depends_release_interface> - $<$:core_depends_debug_interface> + $<$:core_interface_relwithdebinfo> + $<$:core_interface_debug> ) target_link_libraries(core_interface INTERFACE core_base_interface) @@ -321,13 +321,11 @@ endif() include(AddThreadsIfNeeded) add_threads_if_needed() -add_library(sanitizing_interface INTERFACE) -target_link_libraries(core_base_interface INTERFACE sanitizing_interface) if(SANITIZERS) # First check if the compiler accepts flags. If an incompatible pair like # -fsanitize=address,thread is used here, this check will fail. This will also # fail if a bad argument is passed, e.g. -fsanitize=undfeined - try_append_cxx_flags("-fsanitize=${SANITIZERS}" TARGET sanitizing_interface + try_append_cxx_flags("-fsanitize=${SANITIZERS}" TARGET core_base_interface RESULT_VAR cxx_supports_sanitizers SKIP_LINK ) @@ -354,7 +352,7 @@ if(SANITIZERS) message(FATAL_ERROR "Linker did not accept requested flags, you are missing required libraries.") endif() endif() -target_link_options(sanitizing_interface INTERFACE ${SANITIZER_LDFLAGS}) +target_link_options(core_base_interface INTERFACE ${SANITIZER_LDFLAGS}) include(AddBoostIfNeeded) add_boost_if_needed() @@ -421,7 +419,7 @@ include(ProcessConfigurations) set_default_config(RelWithDebInfo) # Redefine/adjust per-configuration flags. -target_compile_definitions(core_depends_debug_interface INTERFACE +target_compile_definitions(core_interface_debug INTERFACE DEBUG DEBUG_LOCKORDER DEBUG_LOCKCONTENTION @@ -513,7 +511,7 @@ try_append_cxx_flags("-fstack-reuse=none" TARGET core_base_interface) if(ENABLE_HARDENING) add_library(hardening_interface INTERFACE) - target_link_libraries(core_base_interface INTERFACE hardening_interface) + target_link_libraries(core_interface INTERFACE hardening_interface) if(MSVC) try_append_linker_flag("/DYNAMICBASE" TARGET hardening_interface) try_append_linker_flag("/HIGHENTROPYVA" TARGET hardening_interface) @@ -582,8 +580,8 @@ else() endif() target_compile_definitions(core_base_interface INTERFACE ${DEPENDS_COMPILE_DEFINITIONS}) -target_compile_definitions(core_depends_release_interface INTERFACE ${DEPENDS_COMPILE_DEFINITIONS_RELWITHDEBINFO}) -target_compile_definitions(core_depends_debug_interface INTERFACE ${DEPENDS_COMPILE_DEFINITIONS_DEBUG}) +target_compile_definitions(core_interface_relwithdebinfo INTERFACE ${DEPENDS_COMPILE_DEFINITIONS_RELWITHDEBINFO}) +target_compile_definitions(core_interface_debug INTERFACE ${DEPENDS_COMPILE_DEFINITIONS_DEBUG}) # If {C,CXX,LD}FLAGS variables are defined during building depends and # configuring this build system, their content might be duplicated. @@ -609,12 +607,6 @@ add_maintenance_targets() add_windows_deploy_target() add_macos_deploy_target() - -include(GetTargetInterface) -get_target_interface(definitions core_interface COMPILE_DEFINITIONS) -get_target_interface(definitions_RELWITHDEBINFO core_depends_release_interface COMPILE_DEFINITIONS) -get_target_interface(definitions_DEBUG core_depends_debug_interface COMPILE_DEFINITIONS) - message("\n") message("Configure summary") message("=================") @@ -660,18 +652,10 @@ else() set(cross_status "FALSE") endif() message("Cross compiling ....................... ${cross_status}") -message("Preprocessor defined macros ........... ${definitions}") message("C compiler ............................ ${CMAKE_C_COMPILER_ID} ${CMAKE_C_COMPILER_VERSION}, ${CMAKE_C_COMPILER}") -message("CFLAGS ................................ ${CMAKE_C_FLAGS} ${APPEND_CPPFLAGS} ${APPEND_CFLAGS}") message("C++ compiler .......................... ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}, ${CMAKE_CXX_COMPILER}") -message("CXXFLAGS .............................. ${CMAKE_CXX_FLAGS} ${APPEND_CPPFLAGS} ${APPEND_CXXFLAGS}") -get_target_interface(common_compile_options core_interface COMPILE_OPTIONS) -message("Common compile options ................ ${common_compile_options}") -get_target_interface(common_link_options core_interface LINK_OPTIONS) -message("Common link options ................... ${common_link_options}") -message("Linker flags for executables .......... ${CMAKE_EXE_LINKER_FLAGS} ${APPEND_LDFLAGS}") -message("Linker flags for shared libraries ..... ${CMAKE_SHARED_LINKER_FLAGS} ${APPEND_LDFLAGS}") -print_config_flags() +include(FlagsSummary) +flags_summary() message("Attempt to harden executables ......... ${ENABLE_HARDENING}") message("Treat compiler warnings as errors ..... ${WERROR}") message("Use ccache for compiling .............. ${WITH_CCACHE}") diff --git a/cmake/crc32c.cmake b/cmake/crc32c.cmake index a6f8c96169328..4d6d5915dcc8b 100644 --- a/cmake/crc32c.cmake +++ b/cmake/crc32c.cmake @@ -85,7 +85,10 @@ target_compile_definitions(crc32c_common INTERFACE HAVE_STRONG_GETAUXVAL=$ BYTE_ORDER_BIG_ENDIAN=$ ) -target_link_libraries(crc32c_common INTERFACE core_base_interface) +target_link_libraries(crc32c_common INTERFACE + core_base_interface + hardening_interface +) add_library(crc32c STATIC EXCLUDE_FROM_ALL ${PROJECT_SOURCE_DIR}/src/crc32c/src/crc32c.cc diff --git a/cmake/leveldb.cmake b/cmake/leveldb.cmake index 46421fd4ca4cb..2d4a1e950e81b 100644 --- a/cmake/leveldb.cmake +++ b/cmake/leveldb.cmake @@ -96,6 +96,7 @@ endif() target_link_libraries(leveldb PRIVATE core_base_interface + hardening_interface nowarn_leveldb_interface crc32c ) diff --git a/cmake/minisketch.cmake b/cmake/minisketch.cmake index 2573b2b1b2bee..92c58c10be526 100644 --- a/cmake/minisketch.cmake +++ b/cmake/minisketch.cmake @@ -55,6 +55,7 @@ if(HAVE_CLMUL) target_link_libraries(minisketch_clmul PRIVATE core_base_interface + hardening_interface minisketch_common ) set_target_properties(minisketch_clmul PROPERTIES @@ -82,6 +83,7 @@ target_include_directories(minisketch target_link_libraries(minisketch PRIVATE core_base_interface + hardening_interface minisketch_common $ ) diff --git a/cmake/module/FlagsSummary.cmake b/cmake/module/FlagsSummary.cmake new file mode 100644 index 0000000000000..b3e9a5ed65910 --- /dev/null +++ b/cmake/module/FlagsSummary.cmake @@ -0,0 +1,84 @@ +# Copyright (c) 2024-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) + +function(indent_message header content indent_num) + if(indent_num GREATER 0) + string(REPEAT " " ${indent_num} indentation) + string(REPEAT "." ${indent_num} tail) + string(REGEX REPLACE "${tail}$" "" header "${header}") + endif() + message("${indentation}${header} ${content}") +endfunction() + +# Print tools' flags on best-effort. Include the abstracted +# CMake flags that we touch ourselves. +function(print_flags_per_config config indent_num) + string(TOUPPER "${config}" config_uppercase) + + include(GetTargetInterface) + get_target_interface(definitions ${config} core_interface COMPILE_DEFINITIONS) + indent_message("Preprocessor defined macros ..........." "${definitions}" ${indent_num}) + + string(STRIP "${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${config_uppercase}}" combined_c_flags) + string(STRIP "${combined_c_flags} ${CMAKE_C${CMAKE_C_STANDARD}_STANDARD_COMPILE_OPTION}" combined_c_flags) + if(CMAKE_POSITION_INDEPENDENT_CODE) + string(JOIN " " combined_c_flags ${combined_c_flags} ${CMAKE_C_COMPILE_OPTIONS_PIC}) + endif() + get_target_interface(core_c_flags ${config} core_base_interface COMPILE_OPTIONS) + string(STRIP "${combined_c_flags} ${core_c_flags}" combined_c_flags) + string(STRIP "${combined_c_flags} ${APPEND_CPPFLAGS}" combined_c_flags) + string(STRIP "${combined_c_flags} ${APPEND_CFLAGS}" combined_c_flags) + indent_message("C compiler flags ......................" "${combined_c_flags}" ${indent_num}) + + string(STRIP "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${config_uppercase}}" combined_cxx_flags) + string(STRIP "${combined_cxx_flags} ${CMAKE_CXX${CMAKE_CXX_STANDARD}_STANDARD_COMPILE_OPTION}" combined_cxx_flags) + if(CMAKE_POSITION_INDEPENDENT_CODE) + string(JOIN " " combined_cxx_flags ${combined_cxx_flags} ${CMAKE_CXX_COMPILE_OPTIONS_PIC}) + endif() + get_target_interface(core_cxx_flags ${config} core_interface COMPILE_OPTIONS) + string(STRIP "${combined_cxx_flags} ${core_cxx_flags}" combined_cxx_flags) + string(STRIP "${combined_cxx_flags} ${APPEND_CPPFLAGS}" combined_cxx_flags) + string(STRIP "${combined_cxx_flags} ${APPEND_CXXFLAGS}" combined_cxx_flags) + indent_message("C++ compiler flags ...................." "${combined_cxx_flags}" ${indent_num}) + + string(STRIP "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${config_uppercase}}" combined_linker_flags) + string(STRIP "${combined_linker_flags} ${CMAKE_EXE_LINKER_FLAGS}" combined_linker_flags) + get_target_interface(common_link_options ${config} core_interface LINK_OPTIONS) + string(STRIP "${combined_linker_flags} ${common_link_options}" combined_linker_flags) + if(CMAKE_CXX_LINK_PIE_SUPPORTED) + string(JOIN " " combined_linker_flags ${combined_linker_flags} ${CMAKE_CXX_LINK_OPTIONS_PIE}) + endif() + string(STRIP "${combined_linker_flags} ${APPEND_LDFLAGS}" combined_linker_flags) + indent_message("Linker flags .........................." "${combined_linker_flags}" ${indent_num}) +endfunction() + +function(flags_summary) + get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) + if(is_multi_config) + list(JOIN CMAKE_CONFIGURATION_TYPES ", " configs) + message("Available build configurations ........ ${configs}") + if(CMAKE_GENERATOR MATCHES "Visual Studio") + set(default_config "Debug") + else() + list(GET CMAKE_CONFIGURATION_TYPES 0 default_config) + endif() + message("Default build configuration ........... ${default_config}") + foreach(config IN LISTS CMAKE_CONFIGURATION_TYPES) + message("") + message("'${config}' build configuration:") + print_flags_per_config(${config} 2) + endforeach() + else() + message("CMAKE_BUILD_TYPE ...................... ${CMAKE_BUILD_TYPE}") + print_flags_per_config(${CMAKE_BUILD_TYPE} 0) + endif() + message("") + message([=[ +NOTE: The summary above may not exactly match the final applied build flags + if any additional CMAKE_* or environment variables have been modified. + To see the exact flags applied, build with the --verbose option. +]=]) +endfunction() diff --git a/cmake/module/GetTargetInterface.cmake b/cmake/module/GetTargetInterface.cmake index f55354fd61b2a..1e455d456b419 100644 --- a/cmake/module/GetTargetInterface.cmake +++ b/cmake/module/GetTargetInterface.cmake @@ -4,11 +4,35 @@ include_guard(GLOBAL) -# Get target's interface properties recursively. -function(get_target_interface var target property) +# Evaluates config-specific generator expressions in a list. +# Recognizable patterns are: +# - $<$:[value]> +# - $<$>:[value]> +function(evaluate_generator_expressions list config) + set(input ${${list}}) + set(result) + foreach(token IN LISTS input) + if(token MATCHES "\\$<\\$]+)>:([^>]+)>") + if(CMAKE_MATCH_1 STREQUAL config) + list(APPEND result ${CMAKE_MATCH_2}) + endif() + elseif(token MATCHES "\\$<\\$]+)>>:([^>]+)>") + if(NOT CMAKE_MATCH_1 STREQUAL config) + list(APPEND result ${CMAKE_MATCH_2}) + endif() + else() + list(APPEND result ${token}) + endif() + endforeach() + set(${list} ${result} PARENT_SCOPE) +endfunction() + + +# Gets target's interface properties recursively. +function(get_target_interface var config target property) get_target_property(result ${target} INTERFACE_${property}) if(result) - string(GENEX_STRIP "${result}" result) + evaluate_generator_expressions(result "${config}") list(JOIN result " " result) else() set(result) @@ -16,9 +40,10 @@ function(get_target_interface var target property) get_target_property(dependencies ${target} INTERFACE_LINK_LIBRARIES) if(dependencies) + evaluate_generator_expressions(dependencies "${config}") foreach(dependency IN LISTS dependencies) if(TARGET ${dependency}) - get_target_interface(dep_result ${dependency} ${property}) + get_target_interface(dep_result "${config}" ${dependency} ${property}) string(STRIP "${result} ${dep_result}" result) endif() endforeach() diff --git a/cmake/module/ProcessConfigurations.cmake b/cmake/module/ProcessConfigurations.cmake index d460e65fa3783..d5895497deb26 100644 --- a/cmake/module/ProcessConfigurations.cmake +++ b/cmake/module/ProcessConfigurations.cmake @@ -139,28 +139,3 @@ function(replace_cxx_flag_in_config config old_flag new_flag) FORCE ) 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()