bitcoin/CMakeLists.txt
Hennadii Stepanov 8287a7670b
cmake: Move APPEND_* variables logic to bitcoincore_enable_language
This change is required for the following commit.
2025-04-28 16:13:44 +01:00

712 lines
28 KiB
CMake

# 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/.
# Ubuntu 22.04 LTS Jammy Jellyfish, https://wiki.ubuntu.com/Releases, EOSS in June 2027:
# - CMake 3.22.1, https://packages.ubuntu.com/jammy/cmake
#
# Centos Stream 9, https://www.centos.org/cl-vs-cs/#end-of-life, EOL in May 2027:
# - CMake 3.26.5, https://mirror.stream.centos.org/9-stream/AppStream/x86_64/os/Packages/
cmake_minimum_required(VERSION 3.22)
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
message(FATAL_ERROR "In-source builds are not allowed.")
endif()
if(POLICY CMP0171)
# `codegen` is a reserved target name.
# See: https://cmake.org/cmake/help/latest/policy/CMP0171.html
cmake_policy(SET CMP0171 NEW)
endif()
#=============================
# Project / Package metadata
#=============================
set(CLIENT_NAME "Bitcoin Core")
set(CLIENT_VERSION_MAJOR 29)
set(CLIENT_VERSION_MINOR 99)
set(CLIENT_VERSION_BUILD 0)
set(CLIENT_VERSION_RC 0)
set(CLIENT_VERSION_IS_RELEASE "false")
set(COPYRIGHT_YEAR "2025")
# During the enabling of the CXX and CXXOBJ languages, we modify
# CMake's compiler/linker invocation strings by appending the content
# of the user-defined `APPEND_*` variables, which allows overriding
# any flag. We also ensure that the APPEND_* flags are considered
# during CMake's tests, which use the `try_compile()` command.
#
# CMake's docs state that the `CMAKE_TRY_COMPILE_PLATFORM_VARIABLES`
# variable "is meant to be set by CMake's platform information modules
# for the current toolchain, or by a toolchain file." We do our best
# to set it before the `project()` command.
set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES
CMAKE_CXX_COMPILE_OBJECT
CMAKE_OBJCXX_COMPILE_OBJECT
CMAKE_CXX_LINK_EXECUTABLE
)
project(BitcoinCore
VERSION ${CLIENT_VERSION_MAJOR}.${CLIENT_VERSION_MINOR}.${CLIENT_VERSION_BUILD}
DESCRIPTION "Bitcoin client software"
HOMEPAGE_URL "https://bitcoincore.org/"
LANGUAGES NONE
)
set(CLIENT_VERSION_STRING ${PROJECT_VERSION})
if(CLIENT_VERSION_RC GREATER 0)
string(APPEND CLIENT_VERSION_STRING "rc${CLIENT_VERSION_RC}")
endif()
set(COPYRIGHT_HOLDERS "The %s developers")
set(COPYRIGHT_HOLDERS_FINAL "The ${CLIENT_NAME} developers")
set(CLIENT_BUGREPORT "https://github.com/bitcoin/bitcoin/issues")
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/module)
#=============================
# Language setup
#=============================
include(EnableLanguage)
bitcoincore_enable_language(CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
include(ProcessConfigurations)
# Flatten static lib dependencies.
# Without this, if libfoo.a depends on libbar.a, libfoo's objects can't begin
# to be compiled until libbar.a has been created.
if (NOT DEFINED CMAKE_OPTIMIZE_DEPENDENCIES)
set(CMAKE_OPTIMIZE_DEPENDENCIES TRUE)
endif()
#=============================
# Configurable options
#=============================
include(CMakeDependentOption)
# When adding a new option, end the <help_text> with a full stop for consistency.
option(BUILD_DAEMON "Build bitcoind executable." ON)
option(BUILD_GUI "Build bitcoin-qt executable." OFF)
option(BUILD_CLI "Build bitcoin-cli executable." ON)
option(BUILD_TESTS "Build test_bitcoin and other unit test executables." ON)
option(BUILD_TX "Build bitcoin-tx executable." ${BUILD_TESTS})
option(BUILD_UTIL "Build bitcoin-util executable." ${BUILD_TESTS})
option(BUILD_UTIL_CHAINSTATE "Build experimental bitcoin-chainstate executable." OFF)
option(BUILD_KERNEL_LIB "Build experimental bitcoinkernel library." ${BUILD_UTIL_CHAINSTATE})
option(ENABLE_WALLET "Enable wallet." ON)
if(ENABLE_WALLET)
if(VCPKG_TARGET_TRIPLET)
# Use of the `unofficial::` namespace is a vcpkg package manager convention.
find_package(unofficial-sqlite3 CONFIG REQUIRED)
else()
find_package(SQLite3 3.7.17 REQUIRED)
endif()
endif()
option(WITH_BDB "Enable Berkeley DB (BDB) wallet support." OFF)
cmake_dependent_option(WARN_INCOMPATIBLE_BDB "Warn when using a Berkeley DB (BDB) version other than 4.8." ON "WITH_BDB" OFF)
if(WITH_BDB)
find_package(BerkeleyDB 4.8 MODULE REQUIRED)
set(USE_BDB ON)
if(NOT BerkeleyDB_VERSION VERSION_EQUAL 4.8)
message(WARNING "Found Berkeley DB (BDB) other than 4.8.\n"
"BDB (legacy) wallets opened by this build will not be portable!"
)
if(WARN_INCOMPATIBLE_BDB)
message(WARNING "If this is intended, pass \"-DWARN_INCOMPATIBLE_BDB=OFF\".\n"
"Passing \"-DWITH_BDB=OFF\" will suppress this warning."
)
endif()
endif()
endif()
cmake_dependent_option(BUILD_WALLET_TOOL "Build bitcoin-wallet tool." ${BUILD_TESTS} "ENABLE_WALLET" OFF)
option(REDUCE_EXPORTS "Attempt to reduce exported symbols in the resulting executables." OFF)
option(WERROR "Treat compiler warnings as errors." OFF)
option(WITH_CCACHE "Attempt to use ccache for compiling." ON)
option(WITH_ZMQ "Enable ZMQ notifications." OFF)
if(WITH_ZMQ)
find_package(ZeroMQ 4.0.0 MODULE REQUIRED)
endif()
option(WITH_USDT "Enable tracepoints for Userspace, Statically Defined Tracing." OFF)
if(WITH_USDT)
find_package(USDT MODULE REQUIRED)
endif()
cmake_dependent_option(ENABLE_EXTERNAL_SIGNER "Enable external signer support." ON "NOT WIN32" OFF)
cmake_dependent_option(WITH_QRENCODE "Enable QR code support." ON "BUILD_GUI" OFF)
if(WITH_QRENCODE)
find_package(QRencode MODULE REQUIRED)
set(USE_QRCODE TRUE)
endif()
cmake_dependent_option(WITH_DBUS "Enable DBus support." ON "CMAKE_SYSTEM_NAME STREQUAL \"Linux\" AND BUILD_GUI" OFF)
option(ENABLE_IPC "Build multiprocess bitcoin-node and bitcoin-gui executables in addition to monolithic bitcoind and bitcoin-qt executables. Requires libmultiprocess library. Experimental." OFF)
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)
if(ENABLE_IPC AND WITH_EXTERNAL_LIBMULTIPROCESS)
find_package(Libmultiprocess REQUIRED COMPONENTS Lib)
find_package(LibmultiprocessNative REQUIRED COMPONENTS Bin
NAMES Libmultiprocess
)
endif()
cmake_dependent_option(BUILD_GUI_TESTS "Build test_bitcoin-qt executable." ON "BUILD_GUI;BUILD_TESTS" OFF)
if(BUILD_GUI)
set(qt_components Core Gui Widgets LinguistTools)
if(ENABLE_WALLET)
list(APPEND qt_components Network)
endif()
if(WITH_DBUS)
list(APPEND qt_components DBus)
set(USE_DBUS TRUE)
endif()
if(BUILD_GUI_TESTS)
list(APPEND qt_components Test)
endif()
find_package(Qt 6.2 MODULE REQUIRED
COMPONENTS ${qt_components}
)
unset(qt_components)
endif()
option(BUILD_BENCH "Build bench_bitcoin executable." OFF)
option(BUILD_FUZZ_BINARY "Build fuzz binary." OFF)
option(BUILD_FOR_FUZZING "Build for fuzzing. Enabling this will disable all other targets and override BUILD_FUZZ_BINARY." OFF)
option(INSTALL_MAN "Install man pages." ON)
set(configure_warnings)
include(CheckLinkerSupportsPIE)
check_linker_supports_pie(configure_warnings)
# The core_interface library aims to encapsulate common build flags.
# It is a usage requirement for all targets except for secp256k1, which
# gets its flags by other means.
add_library(core_interface INTERFACE)
add_library(core_interface_relwithdebinfo INTERFACE)
add_library(core_interface_debug INTERFACE)
target_link_libraries(core_interface INTERFACE
$<$<CONFIG:RelWithDebInfo>:core_interface_relwithdebinfo>
$<$<CONFIG:Debug>:core_interface_debug>
)
if(BUILD_FOR_FUZZING)
message(WARNING "BUILD_FOR_FUZZING=ON will disable all other targets and force BUILD_FUZZ_BINARY=ON.")
set(BUILD_DAEMON OFF)
set(BUILD_CLI OFF)
set(BUILD_TX OFF)
set(BUILD_UTIL OFF)
set(BUILD_UTIL_CHAINSTATE OFF)
set(BUILD_KERNEL_LIB OFF)
set(BUILD_WALLET_TOOL OFF)
set(BUILD_GUI OFF)
set(ENABLE_EXTERNAL_SIGNER OFF)
set(WITH_ZMQ OFF)
set(BUILD_TESTS OFF)
set(BUILD_GUI_TESTS OFF)
set(BUILD_BENCH OFF)
set(BUILD_FUZZ_BINARY ON)
target_compile_definitions(core_interface INTERFACE
FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
)
endif()
include(TryAppendCXXFlags)
include(TryAppendLinkerFlag)
# Redefine/adjust per-configuration flags.
target_compile_definitions(core_interface_debug INTERFACE
DEBUG
DEBUG_LOCKORDER
DEBUG_LOCKCONTENTION
RPC_DOC_CHECK
ABORT_ON_FAILED_ASSUME
)
if(WIN32)
#[=[
This build system supports two ways to build binaries for Windows.
1. Building on Windows using MSVC.
Implementation notes:
- /DWIN32 and /D_WINDOWS definitions are included into the CMAKE_CXX_FLAGS_INIT
and CMAKE_CXX_FLAGS_INIT variables by default.
- A run-time library is selected using the CMAKE_MSVC_RUNTIME_LIBRARY variable.
- MSVC-specific options, for example, /Zc:__cplusplus, are additionally required.
2. Cross-compiling using MinGW.
Implementation notes:
- WIN32 and _WINDOWS definitions must be provided explicitly.
- A run-time library must be specified explicitly using _MT definition.
]=]
target_compile_definitions(core_interface INTERFACE
_WIN32_WINNT=0x0A00
_WIN32_IE=0x0A00
WIN32_LEAN_AND_MEAN
NOMINMAX
)
if(MSVC)
if(VCPKG_TARGET_TRIPLET MATCHES "-static")
set(msvc_library_linkage "")
else()
set(msvc_library_linkage "DLL")
endif()
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>${msvc_library_linkage}")
unset(msvc_library_linkage)
target_compile_definitions(core_interface INTERFACE
_UNICODE;UNICODE
)
target_compile_options(core_interface INTERFACE
/utf-8
/Zc:preprocessor
/Zc:__cplusplus
/sdl
)
# Improve parallelism in MSBuild.
# See: https://devblogs.microsoft.com/cppblog/improved-parallelism-in-msbuild/.
list(APPEND CMAKE_VS_GLOBALS "UseMultiToolTask=true")
endif()
if(MINGW)
target_compile_definitions(core_interface INTERFACE
WIN32
_WINDOWS
_MT
)
# Avoid the use of aligned vector instructions when building for Windows.
# See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54412.
try_append_cxx_flags("-Wa,-muse-unaligned-vector-move" TARGET core_interface SKIP_LINK)
try_append_linker_flag("-static" TARGET core_interface)
# We support Windows 10+, however it's not possible to set these values accordingly,
# due to a bug in mingw-w64. See https://sourceforge.net/p/mingw-w64/bugs/968/.
# As a best effort, target Windows 8.
try_append_linker_flag("-Wl,--major-subsystem-version,6" TARGET core_interface)
try_append_linker_flag("-Wl,--minor-subsystem-version,2" TARGET core_interface)
endif()
# Workaround producing large object files, which cannot be handled by the assembler.
# More likely to happen with no, or lower levels of optimisation.
# See discussion in https://github.com/bitcoin/bitcoin/issues/28109.
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
try_append_cxx_flags("/bigobj" TARGET core_interface_debug SKIP_LINK)
else()
try_append_cxx_flags("-Wa,-mbig-obj" TARGET core_interface_debug SKIP_LINK)
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 INTERFACE
_FILE_OFFSET_BITS=64
)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
target_compile_definitions(core_interface INTERFACE OBJC_OLD_DISPATCH_PROTOTYPES=0)
# 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("-Wl,-dead_strip" TARGET core_interface)
try_append_linker_flag("-Wl,-dead_strip_dylibs" TARGET core_interface)
if(CMAKE_HOST_APPLE)
try_append_linker_flag("-Wl,-headerpad_max_install_names" TARGET core_interface)
endif()
endif()
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
target_link_libraries(core_interface INTERFACE
Threads::Threads
)
# Define sanitize_interface with -fsanitize flags intended to apply to all
# libraries and executables.
add_library(sanitize_interface INTERFACE)
target_link_libraries(core_interface INTERFACE sanitize_interface)
if(SANITIZERS)
# Transform list of sanitizers into -fsanitize flags, replacing "fuzzer" with
# "fuzzer-no-link" in sanitize_interface flags, and moving "fuzzer" to
# fuzzer_interface flags. If -DSANITIZERS=fuzzer is specified, the fuzz test
# binary should be built with -fsanitize=fuzzer (so it can use libFuzzer's
# main function), but libraries should be built with -fsanitize=fuzzer-no-link
# (so they can be linked into other executables that have their own main
# functions).
string(REGEX REPLACE "(^|,)fuzzer($|,)" "\\1fuzzer-no-link\\2" sanitize_opts "${SANITIZERS}")
set(fuzz_flag "")
if(NOT sanitize_opts STREQUAL SANITIZERS)
set(fuzz_flag "-fsanitize=fuzzer")
endif()
# 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=${sanitize_opts}" TARGET sanitize_interface
RESULT_VAR cxx_supports_sanitizers
SKIP_LINK
)
if(NOT cxx_supports_sanitizers)
message(FATAL_ERROR "Compiler did not accept requested flags.")
endif()
# Some compilers (e.g. GCC) require additional libraries like libasan,
# libtsan, libubsan, etc. Make sure linking still works with the sanitize
# flag. This is a separate check so we can give a better error message when
# the sanitize flags are supported by the compiler but the actual sanitizer
# libs are missing.
try_append_linker_flag("-fsanitize=${sanitize_opts}" VAR SANITIZER_LDFLAGS
SOURCE "
#include <cstdint>
#include <cstddef>
extern \"C\" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { return 0; }
int main() { return 0; }
"
RESULT_VAR linker_supports_sanitizers
NO_CACHE_IF_FAILED
)
if(NOT linker_supports_sanitizers)
message(FATAL_ERROR "Linker did not accept requested flags, you are missing required libraries.")
endif()
endif()
target_link_options(sanitize_interface INTERFACE ${SANITIZER_LDFLAGS})
# Define fuzzer_interface with flags intended to apply to the fuzz test binary,
# and perform a test compilation to determine correct value of
# FUZZ_BINARY_LINKS_WITHOUT_MAIN_FUNCTION.
if(BUILD_FUZZ_BINARY)
include(CheckSourceCompilesWithFlags)
check_cxx_source_compiles_with_flags("
#include <cstdint>
#include <cstddef>
extern \"C\" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { return 0; }
// No main() function.
" FUZZ_BINARY_LINKS_WITHOUT_MAIN_FUNCTION
LDFLAGS ${SANITIZER_LDFLAGS} ${fuzz_flag}
LINK_LIBRARIES ${FUZZ_LIBS}
)
add_library(fuzzer_interface INTERFACE)
target_link_options(fuzzer_interface INTERFACE ${fuzz_flag})
target_link_libraries(fuzzer_interface INTERFACE ${FUZZ_LIBS})
endif()
include(AddBoostIfNeeded)
add_boost_if_needed()
if(BUILD_DAEMON OR BUILD_GUI OR BUILD_CLI OR BUILD_TESTS OR BUILD_BENCH OR BUILD_FUZZ_BINARY)
find_package(Libevent 2.1.8 MODULE REQUIRED)
endif()
include(cmake/introspection.cmake)
include(cmake/ccache.cmake)
add_library(warn_interface INTERFACE)
target_link_libraries(core_interface INTERFACE warn_interface)
if(MSVC)
try_append_cxx_flags("/W3" TARGET warn_interface SKIP_LINK)
try_append_cxx_flags("/wd4018" TARGET warn_interface SKIP_LINK)
try_append_cxx_flags("/wd4146" TARGET warn_interface SKIP_LINK)
try_append_cxx_flags("/wd4244" TARGET warn_interface SKIP_LINK)
try_append_cxx_flags("/wd4267" TARGET warn_interface SKIP_LINK)
try_append_cxx_flags("/wd4715" TARGET warn_interface SKIP_LINK)
try_append_cxx_flags("/wd4805" TARGET warn_interface SKIP_LINK)
target_compile_definitions(warn_interface INTERFACE
_CRT_SECURE_NO_WARNINGS
_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING
)
else()
try_append_cxx_flags("-Wall" TARGET warn_interface SKIP_LINK)
try_append_cxx_flags("-Wextra" TARGET warn_interface SKIP_LINK)
try_append_cxx_flags("-Wgnu" TARGET warn_interface SKIP_LINK)
# Some compilers will ignore -Wformat-security without -Wformat, so just combine the two here.
try_append_cxx_flags("-Wformat -Wformat-security" TARGET warn_interface SKIP_LINK)
try_append_cxx_flags("-Wvla" TARGET warn_interface SKIP_LINK)
try_append_cxx_flags("-Wshadow-field" TARGET warn_interface SKIP_LINK)
try_append_cxx_flags("-Wthread-safety" TARGET warn_interface SKIP_LINK)
try_append_cxx_flags("-Wloop-analysis" TARGET warn_interface SKIP_LINK)
try_append_cxx_flags("-Wredundant-decls" TARGET warn_interface SKIP_LINK)
try_append_cxx_flags("-Wunused-member-function" TARGET warn_interface SKIP_LINK)
try_append_cxx_flags("-Wdate-time" TARGET warn_interface SKIP_LINK)
try_append_cxx_flags("-Wconditional-uninitialized" TARGET warn_interface SKIP_LINK)
try_append_cxx_flags("-Wduplicated-branches" TARGET warn_interface SKIP_LINK)
try_append_cxx_flags("-Wduplicated-cond" TARGET warn_interface SKIP_LINK)
try_append_cxx_flags("-Wlogical-op" TARGET warn_interface SKIP_LINK)
try_append_cxx_flags("-Woverloaded-virtual" TARGET warn_interface SKIP_LINK)
try_append_cxx_flags("-Wsuggest-override" TARGET warn_interface SKIP_LINK)
try_append_cxx_flags("-Wimplicit-fallthrough" TARGET warn_interface SKIP_LINK)
try_append_cxx_flags("-Wunreachable-code" TARGET warn_interface SKIP_LINK)
try_append_cxx_flags("-Wdocumentation" TARGET warn_interface SKIP_LINK)
try_append_cxx_flags("-Wself-assign" TARGET warn_interface SKIP_LINK)
try_append_cxx_flags("-Wbidi-chars=any" TARGET warn_interface SKIP_LINK)
try_append_cxx_flags("-Wundef" TARGET warn_interface SKIP_LINK)
# Some compilers (gcc) ignore unknown -Wno-* options, but warn about all
# unknown options if any other warning is produced. Test the -Wfoo case, and
# set the -Wno-foo case if it works.
try_append_cxx_flags("-Wunused-parameter" TARGET warn_interface SKIP_LINK
IF_CHECK_PASSED "-Wno-unused-parameter"
)
endif()
configure_file(cmake/script/Coverage.cmake Coverage.cmake USE_SOURCE_PERMISSIONS COPYONLY)
configure_file(cmake/script/CoverageFuzz.cmake CoverageFuzz.cmake USE_SOURCE_PERMISSIONS COPYONLY)
configure_file(cmake/script/CoverageInclude.cmake.in CoverageInclude.cmake USE_SOURCE_PERMISSIONS @ONLY)
configure_file(cmake/script/cov_tool_wrapper.sh.in cov_tool_wrapper.sh.in USE_SOURCE_PERMISSIONS COPYONLY)
configure_file(contrib/filter-lcov.py filter-lcov.py USE_SOURCE_PERMISSIONS COPYONLY)
# Don't allow extended (non-ASCII) symbols in identifiers. This is easier for code review.
try_append_cxx_flags("-fno-extended-identifiers" TARGET core_interface SKIP_LINK)
# Avoiding the `-ffile-prefix-map` compiler option because it implies
# `-fcoverage-prefix-map` on Clang or `-fprofile-prefix-map` on GCC,
# which can cause issues with coverage builds, particularly when using
# Clang in the OSS-Fuzz environment due to its use of other options
# and a third party script, or with GCC.
try_append_cxx_flags("-fdebug-prefix-map=A=B" TARGET core_interface SKIP_LINK
IF_CHECK_PASSED "-fdebug-prefix-map=${PROJECT_SOURCE_DIR}/src=."
)
try_append_cxx_flags("-fmacro-prefix-map=A=B" TARGET core_interface SKIP_LINK
IF_CHECK_PASSED "-fmacro-prefix-map=${PROJECT_SOURCE_DIR}/src=."
)
# Currently all versions of gcc are subject to a class of bugs, see the
# gccbug_90348 test case (only reproduces on GCC 11 and earlier) and
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111843. To work around that, set
# -fstack-reuse=none for all gcc builds. (Only gcc understands this flag).
try_append_cxx_flags("-fstack-reuse=none" TARGET core_interface)
if(MSVC)
try_append_linker_flag("/DYNAMICBASE" TARGET core_interface)
try_append_linker_flag("/HIGHENTROPYVA" TARGET core_interface)
try_append_linker_flag("/NXCOMPAT" TARGET core_interface)
else()
# _FORTIFY_SOURCE requires that there is some level of optimization,
# otherwise it does nothing and just creates a compiler warning.
try_append_cxx_flags("-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=3"
RESULT_VAR cxx_supports_fortify_source
SOURCE "int main() {
# if !defined __OPTIMIZE__ || __OPTIMIZE__ <= 0
#error
#endif
}"
)
if(cxx_supports_fortify_source)
target_compile_options(core_interface INTERFACE
-U_FORTIFY_SOURCE
-D_FORTIFY_SOURCE=3
)
endif()
unset(cxx_supports_fortify_source)
try_append_cxx_flags("-Wstack-protector" TARGET core_interface SKIP_LINK)
try_append_cxx_flags("-fstack-protector-all" TARGET core_interface)
try_append_cxx_flags("-fcf-protection=full" TARGET core_interface)
if(MINGW)
# stack-clash-protection is a no-op for Windows.
# See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90458 for more details.
else()
try_append_cxx_flags("-fstack-clash-protection" TARGET core_interface)
endif()
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64")
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
try_append_cxx_flags("-mbranch-protection=bti" TARGET core_interface SKIP_LINK)
else()
try_append_cxx_flags("-mbranch-protection=standard" TARGET core_interface SKIP_LINK)
endif()
endif()
try_append_linker_flag("-Wl,--enable-reloc-section" TARGET core_interface)
try_append_linker_flag("-Wl,--dynamicbase" TARGET core_interface)
try_append_linker_flag("-Wl,--nxcompat" TARGET core_interface)
try_append_linker_flag("-Wl,--high-entropy-va" TARGET core_interface)
try_append_linker_flag("-Wl,-z,relro" TARGET core_interface)
try_append_linker_flag("-Wl,-z,now" TARGET core_interface)
# TODO: This can be dropped once Bitcoin Core no longer supports
# NetBSD 10.0 or if upstream fix is backported.
# NetBSD's dynamic linker ld.elf_so < 11.0 supports exactly 2
# `PT_LOAD` segments and binaries linked with `-z separate-code`
# have 4 `PT_LOAD` segments.
# Relevant discussions:
# - https://github.com/bitcoin/bitcoin/pull/28724#issuecomment-2589347934
# - https://mail-index.netbsd.org/tech-userlevel/2023/01/05/msg013666.html
if(CMAKE_SYSTEM_NAME STREQUAL "NetBSD" AND CMAKE_SYSTEM_VERSION VERSION_LESS 11.0)
try_append_linker_flag("-Wl,-z,noseparate-code" TARGET core_interface)
else()
try_append_linker_flag("-Wl,-z,separate-code" TARGET core_interface)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
try_append_linker_flag("-Wl,-fixup_chains" TARGET core_interface)
endif()
endif()
if(REDUCE_EXPORTS)
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
try_append_linker_flag("-Wl,--exclude-libs,ALL" TARGET core_interface)
try_append_linker_flag("-Wl,-no_exported_symbols" VAR CMAKE_EXE_LINKER_FLAGS)
endif()
if(WERROR)
if(MSVC)
set(werror_flag "/WX")
else()
set(werror_flag "-Werror")
endif()
try_append_cxx_flags(${werror_flag} TARGET core_interface SKIP_LINK RESULT_VAR compiler_supports_werror)
if(NOT compiler_supports_werror)
message(FATAL_ERROR "WERROR set but ${werror_flag} is not usable.")
endif()
unset(werror_flag)
endif()
# Prefer Unix-style package components over frameworks on macOS.
# This improves compatibility with Python version managers.
set(Python3_FIND_FRAMEWORK LAST CACHE STRING "")
# Search for generic names before more specialized ones. This
# improves compatibility with Python version managers that use shims.
set(Python3_FIND_UNVERSIONED_NAMES FIRST CACHE STRING "")
mark_as_advanced(Python3_FIND_FRAMEWORK Python3_FIND_UNVERSIONED_NAMES)
find_package(Python3 3.10 COMPONENTS Interpreter)
if(Python3_EXECUTABLE)
set(PYTHON_COMMAND ${Python3_EXECUTABLE})
else()
list(APPEND configure_warnings
"Minimum required Python not found. Utils and rpcauth tests are disabled."
)
endif()
target_compile_definitions(core_interface INTERFACE ${DEPENDS_COMPILE_DEFINITIONS})
target_compile_definitions(core_interface_relwithdebinfo INTERFACE ${DEPENDS_COMPILE_DEFINITIONS_RELWITHDEBINFO})
target_compile_definitions(core_interface_debug INTERFACE ${DEPENDS_COMPILE_DEFINITIONS_DEBUG})
# If the {CXX,LD}FLAGS environment variables are defined during building depends
# and configuring this build system, their content might be duplicated.
if(DEFINED ENV{CXXFLAGS})
deduplicate_flags(CMAKE_CXX_FLAGS)
endif()
if(DEFINED ENV{LDFLAGS})
deduplicate_flags(CMAKE_EXE_LINKER_FLAGS)
endif()
if(BUILD_TESTS)
enable_testing()
endif()
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.29)
# have "make test" depend on "make all"
set(CMAKE_SKIP_TEST_ALL_DEPENDENCY FALSE)
endif()
# TODO: The `CMAKE_SKIP_BUILD_RPATH` variable setting can be deleted
# in the future after reordering Guix script commands to
# perform binary checks after the installation step.
# Relevant discussions:
# - https://github.com/hebasto/bitcoin/pull/236#issuecomment-2183120953
# - https://github.com/bitcoin/bitcoin/pull/30312#issuecomment-2191235833
# NetBSD always requires runtime paths to be set for executables.
if(CMAKE_SYSTEM_NAME STREQUAL "NetBSD")
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
else()
set(CMAKE_SKIP_BUILD_RPATH TRUE)
set(CMAKE_SKIP_INSTALL_RPATH TRUE)
endif()
add_subdirectory(test)
add_subdirectory(doc)
add_subdirectory(src)
include(cmake/tests.cmake)
include(Maintenance)
setup_split_debug_script()
add_maintenance_targets()
add_windows_deploy_target()
add_macos_deploy_target()
message("\n")
message("Configure summary")
message("=================")
message("Executables:")
message(" bitcoind ............................ ${BUILD_DAEMON}")
if(BUILD_DAEMON AND ENABLE_IPC)
set(bitcoin_daemon_status ON)
else()
set(bitcoin_daemon_status OFF)
endif()
message(" bitcoin-node (multiprocess) ......... ${bitcoin_daemon_status}")
message(" bitcoin-qt (GUI) .................... ${BUILD_GUI}")
if(BUILD_GUI AND ENABLE_IPC)
set(bitcoin_gui_status ON)
else()
set(bitcoin_gui_status OFF)
endif()
message(" bitcoin-gui (GUI, multiprocess) ..... ${bitcoin_gui_status}")
message(" bitcoin-cli ......................... ${BUILD_CLI}")
message(" bitcoin-tx .......................... ${BUILD_TX}")
message(" bitcoin-util ........................ ${BUILD_UTIL}")
message(" bitcoin-wallet ...................... ${BUILD_WALLET_TOOL}")
message(" bitcoin-chainstate (experimental) ... ${BUILD_UTIL_CHAINSTATE}")
message(" libbitcoinkernel (experimental) ..... ${BUILD_KERNEL_LIB}")
message("Optional features:")
message(" wallet support ...................... ${ENABLE_WALLET}")
if(ENABLE_WALLET)
message(" - legacy wallets (Berkeley DB) ..... ${WITH_BDB}")
endif()
message(" external signer ..................... ${ENABLE_EXTERNAL_SIGNER}")
message(" ZeroMQ .............................. ${WITH_ZMQ}")
if(ENABLE_IPC)
if (WITH_EXTERNAL_LIBMULTIPROCESS)
set(ipc_status "ON (with external libmultiprocess)")
else()
set(ipc_status ON)
endif()
else()
set(ipc_status OFF)
endif()
message(" IPC ................................. ${ipc_status}")
message(" USDT tracing ........................ ${WITH_USDT}")
message(" QR code (GUI) ....................... ${WITH_QRENCODE}")
message(" DBus (GUI, Linux only) .............. ${WITH_DBUS}")
message("Tests:")
message(" test_bitcoin ........................ ${BUILD_TESTS}")
message(" test_bitcoin-qt ..................... ${BUILD_GUI_TESTS}")
message(" bench_bitcoin ....................... ${BUILD_BENCH}")
message(" fuzz binary ......................... ${BUILD_FUZZ_BINARY}")
message("")
if(CMAKE_CROSSCOMPILING)
set(cross_status "TRUE, for ${CMAKE_SYSTEM_NAME}, ${CMAKE_SYSTEM_PROCESSOR}")
else()
set(cross_status "FALSE")
endif()
message("Cross compiling ....................... ${cross_status}")
message("C++ compiler .......................... ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}, ${CMAKE_CXX_COMPILER}")
include(FlagsSummary)
flags_summary()
message("Treat compiler warnings as errors ..... ${WERROR}")
message("Use ccache for compiling .............. ${WITH_CCACHE}")
message("\n")
if(configure_warnings)
message(" ******\n")
foreach(warning IN LISTS configure_warnings)
message(WARNING "${warning}")
endforeach()
message(" ******\n")
endif()
# We want all build properties to be encapsulated properly.
include(WarnAboutGlobalProperties)