CMakeLists.txt raw

   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  # Ubuntu 22.04 LTS Jammy Jellyfish, https://wiki.ubuntu.com/Releases, EOSS in June 2027:
   6  #  - CMake 3.22.1, https://packages.ubuntu.com/jammy/cmake
   7  #
   8  # Centos Stream 9, https://www.centos.org/cl-vs-cs/#end-of-life, EOL in May 2027:
   9  #  - CMake 3.26.5, https://mirror.stream.centos.org/9-stream/AppStream/x86_64/os/Packages/
  10  cmake_minimum_required(VERSION 3.22)
  11  
  12  if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
  13    message(FATAL_ERROR "In-source builds are not allowed.")
  14  endif()
  15  
  16  if(POLICY CMP0171)
  17    # `codegen` is a reserved target name.
  18    # See: https://cmake.org/cmake/help/latest/policy/CMP0171.html
  19    cmake_policy(SET CMP0171 NEW)
  20  endif()
  21  
  22  # When adjusting CMake flag variables, we must not override those explicitly
  23  # set by the user. These are a subset of the CACHE_VARIABLES property.
  24  get_directory_property(precious_variables CACHE_VARIABLES)
  25  
  26  #=============================
  27  # Project / Package metadata
  28  #=============================
  29  set(CLIENT_NAME "Bitcoin Core")
  30  set(CLIENT_VERSION_MAJOR 31)
  31  set(CLIENT_VERSION_MINOR 99)
  32  set(CLIENT_VERSION_BUILD 0)
  33  set(CLIENT_VERSION_RC 0)
  34  set(CLIENT_VERSION_IS_RELEASE "false")
  35  set(COPYRIGHT_YEAR "2026")
  36  
  37  # During the enabling of the CXX and CXXOBJ languages, we modify
  38  # CMake's compiler/linker invocation strings by appending the content
  39  # of the user-defined `APPEND_*` variables, which allows overriding
  40  # any flag. We also ensure that the APPEND_* flags are considered
  41  # during CMake's tests, which use the `try_compile()` command.
  42  #
  43  # CMake's docs state that the `CMAKE_TRY_COMPILE_PLATFORM_VARIABLES`
  44  # variable "is meant to be set by CMake's platform information modules
  45  # for the current toolchain, or by a toolchain file." We do our best
  46  # to set it before the `project()` command.
  47  set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES
  48    CMAKE_CXX_COMPILE_OBJECT
  49    CMAKE_OBJCXX_COMPILE_OBJECT
  50    CMAKE_CXX_LINK_EXECUTABLE
  51  )
  52  
  53  project(BitcoinCore
  54    VERSION ${CLIENT_VERSION_MAJOR}.${CLIENT_VERSION_MINOR}.${CLIENT_VERSION_BUILD}
  55    DESCRIPTION "Bitcoin client software"
  56    HOMEPAGE_URL "https://bitcoincore.org/"
  57    LANGUAGES NONE
  58  )
  59  
  60  set(CLIENT_VERSION_STRING ${PROJECT_VERSION})
  61  if(CLIENT_VERSION_RC GREATER 0)
  62    string(APPEND CLIENT_VERSION_STRING "rc${CLIENT_VERSION_RC}")
  63  endif()
  64  
  65  set(COPYRIGHT_HOLDERS "The %s developers")
  66  set(COPYRIGHT_HOLDERS_FINAL "The ${CLIENT_NAME} developers")
  67  set(CLIENT_BUGREPORT "https://github.com/bitcoin/bitcoin/issues")
  68  
  69  #=============================
  70  # Language setup
  71  #=============================
  72  if(CMAKE_VERSION VERSION_LESS 4.2 AND CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND NOT CMAKE_HOST_APPLE)
  73    # We do not use the install_name_tool when cross-compiling for macOS.
  74    # However, CMake < 4.2 still searches for Apple's version of the tool,
  75    # which causes an error during configuration.
  76    # See:
  77    # - https://gitlab.kitware.com/cmake/cmake/-/issues/27069
  78    # - https://gitlab.kitware.com/cmake/cmake/-/merge_requests/10955
  79    # So disable this tool check in further enable_language() commands.
  80    set(CMAKE_INSTALL_NAME_TOOL "${CMAKE_COMMAND} -E true")
  81  endif()
  82  enable_language(CXX)
  83  
  84  set(CMAKE_CXX_STANDARD 20)
  85  set(CMAKE_CXX_STANDARD_REQUIRED ON)
  86  set(CMAKE_CXX_EXTENSIONS OFF)
  87  
  88  list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/module)
  89  include(ProcessConfigurations)
  90  
  91  # Flatten static lib dependencies.
  92  # Without this, if libfoo.a depends on libbar.a, libfoo's objects can't begin
  93  # to be compiled until libbar.a has been created.
  94  if (NOT DEFINED CMAKE_OPTIMIZE_DEPENDENCIES)
  95    set(CMAKE_OPTIMIZE_DEPENDENCIES TRUE)
  96  endif()
  97  
  98  #=============================
  99  # Configurable options
 100  #=============================
 101  include(CMakeDependentOption)
 102  # When adding a new option, end the <help_text> with a full stop for consistency.
 103  option(BUILD_BITCOIN_BIN "Build bitcoin executable." ON)
 104  option(BUILD_DAEMON "Build bitcoind executable." ON)
 105  option(BUILD_GUI "Build bitcoin-qt executable." OFF)
 106  option(BUILD_CLI "Build bitcoin-cli executable." ON)
 107  
 108  option(BUILD_TESTS "Build test_bitcoin and other unit test executables." ON)
 109  option(BUILD_TX "Build bitcoin-tx executable." ${BUILD_TESTS})
 110  option(BUILD_UTIL "Build bitcoin-util executable." ${BUILD_TESTS})
 111  cmake_dependent_option(BUILD_GUI_TESTS "Build test_bitcoin-qt executable." ON "BUILD_GUI;BUILD_TESTS" OFF)
 112  
 113  option(BUILD_UTIL_CHAINSTATE "Build experimental bitcoin-chainstate executable." OFF)
 114  option(BUILD_KERNEL_LIB "Build experimental bitcoinkernel library." ${BUILD_UTIL_CHAINSTATE})
 115  cmake_dependent_option(BUILD_KERNEL_TEST "Build tests for the experimental bitcoinkernel library." ON "BUILD_KERNEL_LIB" OFF)
 116  
 117  option(ENABLE_WALLET "Enable wallet." ON)
 118  cmake_dependent_option(BUILD_WALLET_TOOL "Build bitcoin-wallet tool." ${BUILD_TESTS} "ENABLE_WALLET" OFF)
 119  
 120  option(ENABLE_EXTERNAL_SIGNER "Enable external signer support." ON)
 121  option(WITH_ZMQ "Enable ZMQ notifications." OFF)
 122  cmake_dependent_option(ENABLE_IPC "Build multiprocess bitcoin-node and bitcoin-gui executables in addition to monolithic bitcoind and bitcoin-qt executables." ON "NOT WIN32" OFF)
 123  cmake_dependent_option(WITH_EXTERNAL_LIBMULTIPROCESS "Build with external libmultiprocess library instead of with local git subtree when ENABLE_IPC is enabled. This is not normally recommended, but can be useful for developing libmultiprocess itself." OFF "ENABLE_IPC" OFF)
 124  option(WITH_EMBEDDED_ASMAP "Embed default ASMap data." ON)
 125  option(WITH_USDT "Enable tracepoints for Userspace, Statically Defined Tracing." OFF)
 126  
 127  cmake_dependent_option(WITH_QRENCODE "Enable QR code support." ON "BUILD_GUI" OFF)
 128  cmake_dependent_option(WITH_DBUS "Enable DBus support." ON "NOT CMAKE_SYSTEM_NAME MATCHES \"(Windows|Darwin)\" AND BUILD_GUI" OFF)
 129  
 130  option(BUILD_BENCH "Build bench_bitcoin executable." OFF)
 131  option(BUILD_FUZZ_BINARY "Build fuzz binary." OFF)
 132  option(BUILD_FOR_FUZZING "Build for fuzzing. Enabling this will disable all other targets and override BUILD_FUZZ_BINARY." OFF)
 133  
 134  option(REDUCE_EXPORTS "Attempt to reduce exported symbols in the resulting executables." OFF)
 135  option(CMAKE_COMPILE_WARNING_AS_ERROR "Treat compiler warnings as errors." OFF)
 136  option(WITH_CCACHE "Attempt to use ccache for compiling." ON)
 137  
 138  option(INSTALL_MAN "Install man pages." ON)
 139  
 140  set(APPEND_CPPFLAGS "" CACHE STRING "Preprocessor flags that are appended to the command line after all other flags added by the build system. This variable is intended for debugging and special builds.")
 141  set(APPEND_CFLAGS "" CACHE STRING "C compiler flags that are appended to the command line after all other flags added by the build system. This variable is intended for debugging and special builds.")
 142  set(APPEND_CXXFLAGS "" CACHE STRING "(Objective) C++ compiler flags that are appended to the command line after all other flags added by the build system. This variable is intended for debugging and special builds.")
 143  set(APPEND_LDFLAGS "" CACHE STRING "Linker flags that are appended to the command line after all other flags added by the build system. This variable is intended for debugging and special builds.")
 144  # Appending to this low-level rule variables is the only way to
 145  # guarantee that the flags appear at the end of the command line.
 146  string(APPEND CMAKE_CXX_COMPILE_OBJECT " ${APPEND_CPPFLAGS} ${APPEND_CXXFLAGS}")
 147  string(APPEND CMAKE_CXX_CREATE_SHARED_LIBRARY " ${APPEND_LDFLAGS}")
 148  string(APPEND CMAKE_CXX_LINK_EXECUTABLE " ${APPEND_LDFLAGS}")
 149  
 150  # Check required C++ toolchain features early.
 151  include(CheckCXXFeatures)
 152  check_cxx_features()
 153  
 154  #=============================
 155  # Core interface library
 156  #=============================
 157  # The core_interface library aims to encapsulate common build flags.
 158  # It is a usage requirement for all targets except for secp256k1, which
 159  # gets its flags by other means.
 160  add_library(core_interface INTERFACE)
 161  add_library(core_interface_relwithdebinfo INTERFACE)
 162  add_library(core_interface_debug INTERFACE)
 163  target_link_libraries(core_interface INTERFACE
 164    $<$<CONFIG:RelWithDebInfo>:core_interface_relwithdebinfo>
 165    $<$<CONFIG:Debug>:core_interface_debug>
 166  )
 167  
 168  #=============================
 169  # Option interaction
 170  #=============================
 171  # Compute the final state of build options.
 172  # This must be done after all options have been initially set,
 173  # as some options (e.g., BUILD_FOR_FUZZING) may override or adjust others.
 174  # It must also come before any dependency checks to ensure that the set
 175  # of dependencies checked is consistent with the final option values,
 176  # that is, that all required, and only the required, dependencies are tested.
 177  if(BUILD_FOR_FUZZING)
 178    message(WARNING "BUILD_FOR_FUZZING=ON will disable all other targets and force BUILD_FUZZ_BINARY=ON.")
 179    set(BUILD_BITCOIN_BIN OFF)
 180    set(BUILD_DAEMON OFF)
 181    set(BUILD_CLI OFF)
 182    set(BUILD_TX OFF)
 183    set(BUILD_UTIL OFF)
 184    set(BUILD_UTIL_CHAINSTATE OFF)
 185    set(BUILD_KERNEL_LIB OFF)
 186    set(BUILD_KERNEL_TEST OFF)
 187    set(BUILD_WALLET_TOOL OFF)
 188    set(BUILD_GUI OFF)
 189    set(ENABLE_EXTERNAL_SIGNER OFF)
 190    set(WITH_ZMQ OFF)
 191    set(WITH_EMBEDDED_ASMAP OFF)
 192    set(BUILD_TESTS OFF)
 193    set(BUILD_GUI_TESTS OFF)
 194    set(BUILD_BENCH OFF)
 195    set(BUILD_FUZZ_BINARY ON)
 196  
 197    target_compile_definitions(core_interface INTERFACE
 198      FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
 199    )
 200  endif()
 201  
 202  #=============================
 203  # Check and set PIC/PIE
 204  #=============================
 205  set(configure_warnings)
 206  if(NOT CMAKE_SYSTEM_NAME STREQUAL "Generic")
 207  include(CheckLinkerSupportsPIE)
 208  # Set CMAKE_POSITION_INDEPENDENT_CODE early so it applies to all
 209  # subsequent checks, including dependency packages and tool flags.
 210  check_linker_supports_pie(configure_warnings)
 211  endif()
 212  
 213  #=============================
 214  # Find dependencies
 215  #=============================
 216  if(NOT CMAKE_SYSTEM_NAME STREQUAL "Generic")
 217  set(THREADS_PREFER_PTHREAD_FLAG ON)
 218  find_package(Threads REQUIRED)
 219  target_link_libraries(core_interface INTERFACE
 220    Threads::Threads
 221  )
 222  endif()
 223  
 224  if(NOT CMAKE_SYSTEM_NAME STREQUAL "Generic")
 225  include(AddBoostIfNeeded)
 226  add_boost_if_needed()
 227  endif()
 228  
 229  if(ENABLE_WALLET)
 230    if(VCPKG_TARGET_TRIPLET)
 231      # Use of the `unofficial::` namespace is a vcpkg package manager convention.
 232      find_package(unofficial-sqlite3 CONFIG REQUIRED)
 233      add_library(SQLite3::SQLite3 ALIAS unofficial::sqlite3::sqlite3)
 234    else()
 235      find_package(SQLite3 3.7.17 REQUIRED)
 236      if(NOT TARGET SQLite3::SQLite3) # CMake < 4.3
 237        add_library(SQLite3::SQLite3 ALIAS SQLite::SQLite3)
 238      endif()
 239    endif()
 240  endif()
 241  
 242  if(WITH_ZMQ)
 243    find_package(ZeroMQ 4.0.0 MODULE REQUIRED)
 244  endif()
 245  
 246  if(ENABLE_IPC AND WITH_EXTERNAL_LIBMULTIPROCESS)
 247    find_package(Libmultiprocess REQUIRED COMPONENTS Lib)
 248    find_package(LibmultiprocessNative REQUIRED COMPONENTS Bin
 249      NAMES Libmultiprocess
 250    )
 251  endif()
 252  
 253  if(WITH_USDT)
 254    find_package(USDT MODULE REQUIRED)
 255  endif()
 256  
 257  if(BUILD_GUI)
 258    set(qt_components Core Gui Widgets LinguistTools)
 259    if(ENABLE_WALLET)
 260      list(APPEND qt_components Network)
 261    endif()
 262    if(WITH_DBUS)
 263      list(APPEND qt_components DBus)
 264      set(USE_DBUS TRUE)
 265    endif()
 266    if(BUILD_GUI_TESTS)
 267      list(APPEND qt_components Test)
 268    endif()
 269    find_package(Qt 6.2 MODULE REQUIRED
 270      COMPONENTS ${qt_components}
 271    )
 272    unset(qt_components)
 273    if(WITH_QRENCODE)
 274      find_package(QRencode MODULE REQUIRED)
 275      set(USE_QRCODE TRUE)
 276    endif()
 277  endif()
 278  
 279  include(TryAppendCXXFlags)
 280  include(TryAppendLinkerFlag)
 281  
 282  # Redefine/adjust per-configuration flags.
 283  target_compile_definitions(core_interface_debug INTERFACE
 284    DEBUG
 285    DEBUG_LOCKORDER
 286    DEBUG_LOCKCONTENTION
 287    RPC_DOC_CHECK
 288    ABORT_ON_FAILED_ASSUME
 289  )
 290  
 291  if(WIN32)
 292    #[=[
 293    This build system supports two ways to build binaries for Windows.
 294  
 295    1. Building on Windows using MSVC.
 296    Implementation notes:
 297    - /DWIN32 and /D_WINDOWS definitions are included into the CMAKE_CXX_FLAGS_INIT
 298      and CMAKE_CXX_FLAGS_INIT variables by default.
 299    - A run-time library is selected using the CMAKE_MSVC_RUNTIME_LIBRARY variable.
 300    - MSVC-specific options, for example, /Zc:__cplusplus, are additionally required.
 301  
 302    2. Cross-compiling using MinGW.
 303    Implementation notes:
 304    - WIN32 and _WINDOWS definitions must be provided explicitly.
 305    - A run-time library must be specified explicitly using _MT definition.
 306    ]=]
 307  
 308    target_compile_definitions(core_interface INTERFACE
 309      _WIN32_WINNT=0x0A00
 310      _WIN32_IE=0x0A00
 311      WIN32_LEAN_AND_MEAN
 312      NOMINMAX
 313    )
 314  
 315    if(MSVC)
 316      if(VCPKG_TARGET_TRIPLET MATCHES "-static")
 317        set(msvc_library_linkage "")
 318      else()
 319        set(msvc_library_linkage "DLL")
 320      endif()
 321      set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>${msvc_library_linkage}")
 322      unset(msvc_library_linkage)
 323  
 324      target_compile_definitions(core_interface INTERFACE
 325        _UNICODE;UNICODE
 326      )
 327      target_compile_options(core_interface INTERFACE
 328        /utf-8
 329        /Zc:preprocessor
 330        /Zc:__cplusplus
 331        /sdl
 332      )
 333      target_link_options(core_interface INTERFACE
 334        # We embed our own manifests.
 335        /MANIFEST:NO
 336      )
 337      # Improve parallelism in MSBuild.
 338      # See: https://devblogs.microsoft.com/cppblog/improved-parallelism-in-msbuild/.
 339      list(APPEND CMAKE_VS_GLOBALS "UseMultiToolTask=true")
 340    endif()
 341  
 342    if(MINGW)
 343      target_compile_definitions(core_interface INTERFACE
 344        WIN32
 345        _WINDOWS
 346        _MT
 347      )
 348      # Avoid the use of aligned vector instructions when building for Windows.
 349      # See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54412.
 350      try_append_cxx_flags("-Wa,-muse-unaligned-vector-move" TARGET core_interface SKIP_LINK)
 351      try_append_linker_flag("-static" TARGET core_interface)
 352      # We support Windows 10+, however it's not possible to set these values accordingly,
 353      # due to a bug in mingw-w64. See https://sourceforge.net/p/mingw-w64/bugs/968/.
 354      # As a best effort, target Windows 8.
 355      try_append_linker_flag("-Wl,--major-subsystem-version,6" TARGET core_interface)
 356      try_append_linker_flag("-Wl,--minor-subsystem-version,2" TARGET core_interface)
 357    endif()
 358  
 359    # Workaround producing large object files, which cannot be handled by the assembler.
 360    # More likely to happen with no, or lower levels of optimisation.
 361    # See discussion in https://github.com/bitcoin/bitcoin/issues/28109.
 362    if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
 363      try_append_cxx_flags("/bigobj" TARGET core_interface_debug SKIP_LINK)
 364    else()
 365      try_append_cxx_flags("-Wa,-mbig-obj" TARGET core_interface_debug SKIP_LINK)
 366    endif()
 367  endif()
 368  
 369  # Use 64-bit off_t on 32-bit Linux.
 370  if (CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_SIZEOF_VOID_P EQUAL 4)
 371    # Ensure 64-bit offsets are used for filesystem accesses for 32-bit compilation.
 372    target_compile_definitions(core_interface INTERFACE
 373      _FILE_OFFSET_BITS=64
 374    )
 375  endif()
 376  
 377  if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
 378    target_compile_definitions(core_interface INTERFACE OBJC_OLD_DISPATCH_PROTOTYPES=0)
 379    # These flags are specific to ld64, and may cause issues with other linkers.
 380    # For example: GNU ld will interpret -dead_strip as -de and then try and use
 381    # "ad_strip" as the symbol for the entry point.
 382    try_append_linker_flag("-Wl,-dead_strip" TARGET core_interface)
 383    try_append_linker_flag("-Wl,-dead_strip_dylibs" TARGET core_interface)
 384    if(CMAKE_HOST_APPLE)
 385      try_append_linker_flag("-Wl,-headerpad_max_install_names" TARGET core_interface)
 386    endif()
 387  endif()
 388  
 389  # Define sanitize_interface with -fsanitize flags intended to apply to all
 390  # libraries and executables.
 391  add_library(sanitize_interface INTERFACE)
 392  target_link_libraries(core_interface INTERFACE sanitize_interface)
 393  if(SANITIZERS)
 394    # Transform list of sanitizers into -fsanitize flags, replacing "fuzzer" with
 395    # "fuzzer-no-link" in sanitize_interface flags, and moving "fuzzer" to
 396    # fuzzer_interface flags. If -DSANITIZERS=fuzzer is specified, the fuzz test
 397    # binary should be built with -fsanitize=fuzzer (so it can use libFuzzer's
 398    # main function), but libraries should be built with -fsanitize=fuzzer-no-link
 399    # (so they can be linked into other executables that have their own main
 400    # functions).
 401    string(REGEX REPLACE "(^|,)fuzzer($|,)" "\\1fuzzer-no-link\\2" sanitize_opts "${SANITIZERS}")
 402    set(fuzz_flag "")
 403    if(NOT sanitize_opts STREQUAL SANITIZERS)
 404      set(fuzz_flag "-fsanitize=fuzzer")
 405    endif()
 406  
 407    # First check if the compiler accepts flags. If an incompatible pair like
 408    # -fsanitize=address,thread is used here, this check will fail. This will also
 409    # fail if a bad argument is passed, e.g. -fsanitize=undfeined
 410    try_append_cxx_flags("-fsanitize=${sanitize_opts}" TARGET sanitize_interface
 411      RESULT_VAR cxx_supports_sanitizers
 412      SKIP_LINK
 413    )
 414    if(NOT cxx_supports_sanitizers)
 415      message(FATAL_ERROR "Compiler did not accept requested flags.")
 416    endif()
 417  
 418    # Some compilers (e.g. GCC) require additional libraries like libasan,
 419    # libtsan, libubsan, etc. Make sure linking still works with the sanitize
 420    # flag. This is a separate check so we can give a better error message when
 421    # the sanitize flags are supported by the compiler but the actual sanitizer
 422    # libs are missing.
 423    try_append_linker_flag("-fsanitize=${sanitize_opts}" VAR SANITIZER_LDFLAGS
 424      SOURCE "
 425        #include <cstdint>
 426        #include <cstddef>
 427        extern \"C\" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { return 0; }
 428        int main() { return 0; }
 429      "
 430      RESULT_VAR linker_supports_sanitizers
 431      NO_CACHE_IF_FAILED
 432    )
 433    if(NOT linker_supports_sanitizers)
 434      message(FATAL_ERROR "Linker did not accept requested flags, you are missing required libraries.")
 435    endif()
 436  endif()
 437  target_link_options(sanitize_interface INTERFACE ${SANITIZER_LDFLAGS})
 438  
 439  # Define fuzzer_interface with flags intended to apply to the fuzz test binary,
 440  # and perform a test compilation to determine correct value of
 441  # FUZZ_BINARY_LINKS_WITHOUT_MAIN_FUNCTION.
 442  if(BUILD_FUZZ_BINARY)
 443    include(CheckSourceCompilesWithFlags)
 444    check_cxx_source_compiles_with_flags("
 445        #include <cstdint>
 446        #include <cstddef>
 447        extern \"C\" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { return 0; }
 448        // No main() function.
 449      " FUZZ_BINARY_LINKS_WITHOUT_MAIN_FUNCTION
 450      LDFLAGS ${SANITIZER_LDFLAGS} ${fuzz_flag}
 451      LINK_LIBRARIES ${FUZZ_LIBS}
 452    )
 453    add_library(fuzzer_interface INTERFACE)
 454    target_link_options(fuzzer_interface INTERFACE ${fuzz_flag})
 455    target_link_libraries(fuzzer_interface INTERFACE ${FUZZ_LIBS})
 456  endif()
 457  
 458  include(cmake/introspection.cmake)
 459  
 460  include(cmake/ccache.cmake)
 461  
 462  add_library(warn_interface INTERFACE)
 463  target_link_libraries(core_interface INTERFACE warn_interface)
 464  if(MSVC)
 465    try_append_cxx_flags("/W3" TARGET warn_interface SKIP_LINK)
 466    try_append_cxx_flags("/wd4018" TARGET warn_interface SKIP_LINK)
 467    try_append_cxx_flags("/wd4146" TARGET warn_interface SKIP_LINK)
 468    try_append_cxx_flags("/wd4244" TARGET warn_interface SKIP_LINK)
 469    try_append_cxx_flags("/wd4267" TARGET warn_interface SKIP_LINK)
 470    try_append_cxx_flags("/wd4715" TARGET warn_interface SKIP_LINK)
 471    try_append_cxx_flags("/wd4805" TARGET warn_interface SKIP_LINK)
 472    target_compile_definitions(warn_interface INTERFACE
 473      _CRT_SECURE_NO_WARNINGS
 474      _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING
 475    )
 476  else()
 477    try_append_cxx_flags("-Wall" TARGET warn_interface SKIP_LINK)
 478    try_append_cxx_flags("-Wextra" TARGET warn_interface SKIP_LINK)
 479    try_append_cxx_flags("-Wgnu" TARGET warn_interface SKIP_LINK)
 480    try_append_cxx_flags("-Wcovered-switch-default" TARGET warn_interface SKIP_LINK)
 481    # Some compilers will ignore -Wformat-security without -Wformat, so just combine the two here.
 482    try_append_cxx_flags("-Wformat -Wformat-security" TARGET warn_interface SKIP_LINK)
 483    try_append_cxx_flags("-Wvla" TARGET warn_interface SKIP_LINK)
 484    try_append_cxx_flags("-Wshadow-field" TARGET warn_interface SKIP_LINK)
 485    try_append_cxx_flags("-Wthread-safety" TARGET warn_interface SKIP_LINK)
 486    try_append_cxx_flags("-Wthread-safety-pointer" TARGET warn_interface SKIP_LINK)
 487    try_append_cxx_flags("-Wloop-analysis" TARGET warn_interface SKIP_LINK)
 488    try_append_cxx_flags("-Wredundant-decls" TARGET warn_interface SKIP_LINK)
 489    try_append_cxx_flags("-Wunused-member-function" TARGET warn_interface SKIP_LINK)
 490    try_append_cxx_flags("-Wdate-time" TARGET warn_interface SKIP_LINK)
 491    try_append_cxx_flags("-Wconditional-uninitialized" TARGET warn_interface SKIP_LINK)
 492    try_append_cxx_flags("-Wduplicated-branches" TARGET warn_interface SKIP_LINK)
 493    try_append_cxx_flags("-Wduplicated-cond" TARGET warn_interface SKIP_LINK)
 494    try_append_cxx_flags("-Wlogical-op" TARGET warn_interface SKIP_LINK)
 495    try_append_cxx_flags("-Woverloaded-virtual" TARGET warn_interface SKIP_LINK)
 496    try_append_cxx_flags("-Wsuggest-override" TARGET warn_interface SKIP_LINK)
 497    try_append_cxx_flags("-Wimplicit-fallthrough" TARGET warn_interface SKIP_LINK)
 498    try_append_cxx_flags("-Wunreachable-code" TARGET warn_interface SKIP_LINK)
 499    try_append_cxx_flags("-Wdocumentation" TARGET warn_interface SKIP_LINK)
 500    try_append_cxx_flags("-Wself-assign" TARGET warn_interface SKIP_LINK)
 501    try_append_cxx_flags("-Wbidi-chars=any" TARGET warn_interface SKIP_LINK)
 502    try_append_cxx_flags("-Wundef" TARGET warn_interface SKIP_LINK)
 503    try_append_cxx_flags("-Wleading-whitespace=spaces" TARGET warn_interface SKIP_LINK)
 504    try_append_cxx_flags("-Wtrailing-whitespace=any" TARGET warn_interface SKIP_LINK)
 505  
 506    # Some compilers (gcc) ignore unknown -Wno-* options, but warn about all
 507    # unknown options if any other warning is produced. Test the -Wfoo case, and
 508    # set the -Wno-foo case if it works.
 509    try_append_cxx_flags("-Wunused-parameter" TARGET warn_interface SKIP_LINK
 510      IF_CHECK_PASSED "-Wno-unused-parameter"
 511    )
 512  endif()
 513  
 514  configure_file(cmake/script/Coverage.cmake Coverage.cmake USE_SOURCE_PERMISSIONS COPYONLY)
 515  configure_file(cmake/script/CoverageFuzz.cmake CoverageFuzz.cmake USE_SOURCE_PERMISSIONS COPYONLY)
 516  configure_file(cmake/script/CoverageInclude.cmake.in CoverageInclude.cmake USE_SOURCE_PERMISSIONS @ONLY)
 517  configure_file(cmake/script/cov_tool_wrapper.sh.in cov_tool_wrapper.sh.in USE_SOURCE_PERMISSIONS COPYONLY)
 518  configure_file(contrib/filter-lcov.py filter-lcov.py USE_SOURCE_PERMISSIONS COPYONLY)
 519  
 520  # Don't allow extended (non-ASCII) symbols in identifiers. This is easier for code review.
 521  try_append_cxx_flags("-fno-extended-identifiers" TARGET core_interface SKIP_LINK)
 522  
 523  # Set `-fmacro-prefix-map`, so that source file names are expanded without the
 524  # src prefix.
 525  try_append_cxx_flags("-fmacro-prefix-map=A=B" TARGET core_interface SKIP_LINK
 526    IF_CHECK_PASSED "-fmacro-prefix-map=${PROJECT_SOURCE_DIR}/src=."
 527  )
 528  
 529  # GCC versions 13.2 (and earlier) are subject to a class of bugs, see
 530  # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90348 and the meta bug
 531  # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111843. To work around that, set
 532  # -fstack-reuse=none for all gcc builds. (Only gcc understands this flag).
 533  try_append_cxx_flags("-fstack-reuse=none" TARGET core_interface)
 534  
 535  if(MSVC)
 536    try_append_linker_flag("/DYNAMICBASE" TARGET core_interface)
 537    try_append_linker_flag("/HIGHENTROPYVA" TARGET core_interface)
 538    try_append_linker_flag("/NXCOMPAT" TARGET core_interface)
 539  else()
 540  
 541    # _FORTIFY_SOURCE requires that there is some level of optimization,
 542    # otherwise it does nothing and just creates a compiler warning.
 543    try_append_cxx_flags("-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=3"
 544      RESULT_VAR cxx_supports_fortify_source
 545      SOURCE "int main() {
 546              # if !defined __OPTIMIZE__ || __OPTIMIZE__ <= 0
 547                #error
 548              #endif
 549              }"
 550    )
 551    if(cxx_supports_fortify_source)
 552      target_compile_options(core_interface INTERFACE
 553        -U_FORTIFY_SOURCE
 554        -D_FORTIFY_SOURCE=3
 555      )
 556    endif()
 557    unset(cxx_supports_fortify_source)
 558  
 559    try_append_cxx_flags("-Wstack-protector" TARGET core_interface SKIP_LINK)
 560    try_append_cxx_flags("-fstack-protector-all" TARGET core_interface)
 561    try_append_cxx_flags("-fcf-protection=full" TARGET core_interface)
 562  
 563    if(MINGW)
 564      # stack-clash-protection is a no-op for Windows.
 565      # See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90458 for more details.
 566    else()
 567      try_append_cxx_flags("-fstack-clash-protection" TARGET core_interface)
 568    endif()
 569  
 570    if(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64")
 571      if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
 572        try_append_cxx_flags("-mbranch-protection=bti" TARGET core_interface SKIP_LINK)
 573      else()
 574        try_append_cxx_flags("-mbranch-protection=standard" TARGET core_interface SKIP_LINK)
 575      endif()
 576    endif()
 577  
 578    try_append_linker_flag("-Wl,--enable-reloc-section" TARGET core_interface)
 579    try_append_linker_flag("-Wl,--dynamicbase" TARGET core_interface)
 580    try_append_linker_flag("-Wl,--nxcompat" TARGET core_interface)
 581    try_append_linker_flag("-Wl,--high-entropy-va" TARGET core_interface)
 582    try_append_linker_flag("-Wl,-z,relro" TARGET core_interface)
 583    try_append_linker_flag("-Wl,-z,now" TARGET core_interface)
 584    # TODO: This can be dropped once Bitcoin Core no longer supports
 585    #       NetBSD 10.0 or if upstream fix is backported.
 586    # NetBSD's dynamic linker ld.elf_so < 11.0 supports exactly 2
 587    # `PT_LOAD` segments and binaries linked with `-z separate-code`
 588    # have 4 `PT_LOAD` segments.
 589    # Relevant discussions:
 590    # - https://github.com/bitcoin/bitcoin/pull/28724#issuecomment-2589347934
 591    # - https://mail-index.netbsd.org/tech-userlevel/2023/01/05/msg013666.html
 592    if(CMAKE_SYSTEM_NAME STREQUAL "NetBSD" AND CMAKE_SYSTEM_VERSION VERSION_LESS 11.0)
 593      try_append_linker_flag("-Wl,-z,noseparate-code" TARGET core_interface)
 594    else()
 595      try_append_linker_flag("-Wl,-z,separate-code" TARGET core_interface)
 596    endif()
 597    if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
 598      try_append_linker_flag("-Wl,-fixup_chains" TARGET core_interface)
 599    endif()
 600  endif()
 601  
 602  if(REDUCE_EXPORTS)
 603    set(CMAKE_CXX_VISIBILITY_PRESET hidden)
 604    try_append_linker_flag("-Wl,--exclude-libs,ALL" TARGET core_interface)
 605    try_append_linker_flag("-Wl,-no_exported_symbols" VAR CMAKE_EXE_LINKER_FLAGS)
 606  endif()
 607  
 608  # Prefer Unix-style package components over frameworks on macOS.
 609  # This improves compatibility with Python version managers.
 610  set(Python3_FIND_FRAMEWORK LAST CACHE STRING "")
 611  # Search for generic names before more specialized ones. This
 612  # improves compatibility with Python version managers that use shims.
 613  set(Python3_FIND_UNVERSIONED_NAMES FIRST CACHE STRING "")
 614  mark_as_advanced(Python3_FIND_FRAMEWORK Python3_FIND_UNVERSIONED_NAMES)
 615  find_package(Python3 3.10 COMPONENTS Interpreter)
 616  if(NOT TARGET Python3::Interpreter)
 617    list(APPEND configure_warnings
 618      "Minimum required Python not found."
 619    )
 620  endif()
 621  
 622  target_compile_definitions(core_interface INTERFACE ${DEPENDS_COMPILE_DEFINITIONS})
 623  target_compile_definitions(core_interface_relwithdebinfo INTERFACE ${DEPENDS_COMPILE_DEFINITIONS_RELWITHDEBINFO})
 624  target_compile_definitions(core_interface_debug INTERFACE ${DEPENDS_COMPILE_DEFINITIONS_DEBUG})
 625  
 626  # If the {CXX,LD}FLAGS environment variables are defined during building depends
 627  # and configuring this build system, their content might be duplicated.
 628  if(DEFINED ENV{CXXFLAGS})
 629    deduplicate_flags(CMAKE_CXX_FLAGS)
 630  endif()
 631  if(DEFINED ENV{LDFLAGS})
 632    deduplicate_flags(CMAKE_EXE_LINKER_FLAGS)
 633  endif()
 634  
 635  if(BUILD_TESTS)
 636    enable_testing()
 637  endif()
 638  
 639  if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.29)
 640    # have "make test" depend on "make all"
 641    set(CMAKE_SKIP_TEST_ALL_DEPENDENCY FALSE)
 642  endif()
 643  
 644  add_subdirectory(test)
 645  add_subdirectory(doc)
 646  
 647  add_subdirectory(src)
 648  
 649  include(Maintenance)
 650  setup_split_debug_script()
 651  add_windows_deploy_target()
 652  add_macos_deploy_target()
 653  
 654  message("\n")
 655  message("Configure summary")
 656  message("=================")
 657  message("Executables:")
 658  message("  bitcoin ............................. ${BUILD_BITCOIN_BIN}")
 659  message("  bitcoind ............................ ${BUILD_DAEMON}")
 660  if(BUILD_DAEMON AND ENABLE_IPC)
 661    set(bitcoin_daemon_status ON)
 662  else()
 663    set(bitcoin_daemon_status OFF)
 664  endif()
 665  message("  bitcoin-node (multiprocess) ......... ${bitcoin_daemon_status}")
 666  message("  bitcoin-qt (GUI) .................... ${BUILD_GUI}")
 667  if(BUILD_GUI AND ENABLE_IPC)
 668    set(bitcoin_gui_status ON)
 669  else()
 670    set(bitcoin_gui_status OFF)
 671  endif()
 672  message("  bitcoin-gui (GUI, multiprocess) ..... ${bitcoin_gui_status}")
 673  message("  bitcoin-cli ......................... ${BUILD_CLI}")
 674  message("  bitcoin-tx .......................... ${BUILD_TX}")
 675  message("  bitcoin-util ........................ ${BUILD_UTIL}")
 676  message("  bitcoin-wallet ...................... ${BUILD_WALLET_TOOL}")
 677  message("  bitcoin-chainstate (experimental) ... ${BUILD_UTIL_CHAINSTATE}")
 678  message("  libbitcoinkernel (experimental) ..... ${BUILD_KERNEL_LIB}")
 679  message("  kernel-test (experimental) .......... ${BUILD_KERNEL_TEST}")
 680  message("Optional features:")
 681  message("  wallet support ...................... ${ENABLE_WALLET}")
 682  message("  external signer ..................... ${ENABLE_EXTERNAL_SIGNER}")
 683  message("  ZeroMQ .............................. ${WITH_ZMQ}")
 684  if(ENABLE_IPC)
 685    if (WITH_EXTERNAL_LIBMULTIPROCESS)
 686      set(ipc_status "ON (with external libmultiprocess)")
 687    else()
 688      set(ipc_status ON)
 689    endif()
 690  else()
 691    set(ipc_status OFF)
 692  endif()
 693  message("  IPC ................................. ${ipc_status}")
 694  message("  Embedded ASMap ...................... ${WITH_EMBEDDED_ASMAP}")
 695  message("  USDT tracing ........................ ${WITH_USDT}")
 696  message("  QR code (GUI) ....................... ${WITH_QRENCODE}")
 697  message("  DBus (GUI) .......................... ${WITH_DBUS}")
 698  message("Tests:")
 699  message("  test_bitcoin ........................ ${BUILD_TESTS}")
 700  message("  test_bitcoin-qt ..................... ${BUILD_GUI_TESTS}")
 701  message("  bench_bitcoin ....................... ${BUILD_BENCH}")
 702  message("  fuzz binary ......................... ${BUILD_FUZZ_BINARY}")
 703  message("")
 704  if(CMAKE_CROSSCOMPILING)
 705    set(cross_status "TRUE, for ${CMAKE_SYSTEM_NAME}, ${CMAKE_SYSTEM_PROCESSOR}")
 706  else()
 707    set(cross_status "FALSE")
 708  endif()
 709  message("Cross compiling ....................... ${cross_status}")
 710  message("C++ compiler .......................... ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}, ${CMAKE_CXX_COMPILER}")
 711  include(FlagsSummary)
 712  flags_summary()
 713  message("Treat compiler warnings as errors ..... ${CMAKE_COMPILE_WARNING_AS_ERROR}")
 714  message("Use ccache for compiling .............. ${WITH_CCACHE}")
 715  message("\n")
 716  if(configure_warnings)
 717      message("  ******\n")
 718      foreach(warning IN LISTS configure_warnings)
 719        message(WARNING "${warning}")
 720      endforeach()
 721      message("  ******\n")
 722      message(AUTHOR_WARNING "Warnings have been encountered!")
 723  endif()
 724  
 725  # We want all build properties to be encapsulated properly.
 726  include(WarnAboutGlobalProperties)
 727