diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000000000..10b484bebdc7d --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,323 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# IMPORTANT: Changes which affect binary results may not be quietly gated +# by CMake version. +# +# Ubuntu 20.04 LTS Focal Fossa, https://wiki.ubuntu.com/Releases, EOSS in April 2025: +# - CMake 3.16.3, https://packages.ubuntu.com/focal/cmake +# +# Centos Stream 8, EOL in May 2024: +# - CMake 3.20.2, http://mirror.centos.org/centos/8-stream/AppStream/x86_64/os/Packages/ +# +# All policies known to the running version of CMake and introduced +# in the 3.28 version or earlier will be set to use NEW behavior. +# All policies introduced in later versions will be unset. +# See: https://cmake.org/cmake/help/latest/manual/cmake-policies.7.html +cmake_minimum_required(VERSION 3.16...3.28) + +project("Bitcoin Core" + VERSION 26.99.0 + DESCRIPTION "Bitcoin client software" + HOMEPAGE_URL "https://bitcoincore.org/" + LANGUAGES CXX ASM +) + +set(PACKAGE_NAME ${PROJECT_NAME}) +set(CLIENT_VERSION_IS_RELEASE "false") +set(COPYRIGHT_YEAR "2023") +set(COPYRIGHT_HOLDERS "The %s developers") +set(COPYRIGHT_HOLDERS_FINAL "The ${PROJECT_NAME} developers") +set(PACKAGE_BUGREPORT "https://github.com/bitcoin/bitcoin/issues") + +list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/module) + +# Configurable options. +# When adding a new option, end the with a full stop for consistency. +include(CMakeDependentOption) +option(BUILD_DAEMON "Build bitcoind executable." ON) +option(BUILD_CLI "Build bitcoin-cli executable." ON) +option(BUILD_TX "Build bitcoin-tx executable." ON) +option(BUILD_UTIL "Build bitcoin-util executable." ON) +option(ASM "Use assembly routines." ON) + +option(ENABLE_WALLET "Enable wallet." ON) +# TODO: These tri-state options will be removed and most features +# will become opt-in by default before merging into master. +include(TristateOption) +tristate_option(WITH_SQLITE "Enable SQLite wallet support." "if libsqlite3 is found." AUTO) +tristate_option(WITH_BDB "Enable Berkeley DB (BDB) wallet support." "if libdb_cxx is found." AUTO) +option(WARN_INCOMPATIBLE_BDB "Warn when using a Berkeley DB (BDB) version other than 4.8." ON) +cmake_dependent_option(BUILD_WALLET_TOOL "Build bitcoin-wallet tool." ON "ENABLE_WALLET" OFF) + +cmake_dependent_option(CXX20 "Enable compilation in C++20 mode." OFF "NOT MSVC" ON) +option(THREADLOCAL "Enable features that depend on the C++ thread_local keyword (currently just thread names in debug logs)." ON) + +tristate_option(CCACHE "Use ccache for compiling." "if ccache is found." AUTO) +tristate_option(WITH_NATPMP "Enable NAT-PMP." "if libnatpmp is found." AUTO) +tristate_option(WITH_MINIUPNPC "Enable UPnP." "if libminiupnpc is found." AUTO) +tristate_option(WITH_ZMQ "Enable ZMQ notifications." "if libzmq is found." AUTO) +tristate_option(WITH_USDT + "Enable tracepoints for Userspace, Statically Defined Tracing." + "if sys/sdt.h is found." + AUTO +) + +option(BUILD_TESTS "Build test_bitcoin executable." ON) +option(BUILD_BENCH "Build bench_bitcoin executable." ON) + +if(CXX20) + set(CMAKE_CXX_STANDARD 20) +else() + set(CMAKE_CXX_STANDARD 17) +endif() +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +set(configure_warnings) + +include(CheckPIESupported) +check_pie_supported(OUTPUT_VARIABLE check_pie_output LANGUAGES CXX) +if(CMAKE_CXX_LINK_PIE_SUPPORTED) + set(CMAKE_POSITION_INDEPENDENT_CODE ON) +else() + message(WARNING "PIE is not supported at link time: ${check_pie_output}") + list(APPEND configure_warnings "Position independent code disabled.") +endif() +unset(check_pie_output) + +# 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) + +include(TryAppendCXXFlags) +include(TryAppendLinkerFlag) + +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 + _WIN32_WINNT=0x0601 + _WIN32_IE=0x0501 + WIN32_LEAN_AND_MEAN + NOMINMAX + ) + + if(MSVC) + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") + 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) + target_compile_definitions(core INTERFACE + WIN32 + _WINDOWS + _MT + ) + try_append_linker_flag(core "-static") + # We require Windows 7 (NT 6.1) or later. + 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) + 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) +add_threads_if_needed() + +include(AddBoostIfNeeded) +add_boost_if_needed() + +include(CheckSourceCompilesAndLinks) + +include(AddLibeventIfNeeded) +add_libevent_if_needed() + +include(cmake/introspection.cmake) + +include(cmake/crc32c.cmake) +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) + +find_package(Python3 3.9 COMPONENTS Interpreter) +set(PYTHON_COMMAND ${Python3_EXECUTABLE}) + +add_subdirectory(src) +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("=================") +message("Executables:") +message(" bitcoind ............................ ${BUILD_DAEMON}") +message(" bitcoin-cli ......................... ${BUILD_CLI}") +message(" bitcoin-tx .......................... ${BUILD_TX}") +message(" bitcoin-util ........................ ${BUILD_UTIL}") +message(" bitcoin-wallet ...................... ${BUILD_WALLET_TOOL}") +message("Wallet support:") +message(" SQLite, descriptor wallets .......... ${WITH_SQLITE}") +message(" Berkeley DB, legacy wallets ......... ${WITH_BDB}") +message("Optional packages:") +message(" NAT-PMP ............................. ${WITH_NATPMP}") +message(" UPnP ................................ ${WITH_MINIUPNPC}") +message(" ZeroMQ .............................. ${WITH_ZMQ}") +message(" USDT tracing ........................ ${WITH_USDT}") +message("Tests:") +message(" test_bitcoin ........................ ${BUILD_TESTS}") +message(" bench_bitcoin ....................... ${BUILD_BENCH}") +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("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) +message("CFLAGS ................................ ${combined_c_flags}") +message("C++ compiler .......................... ${CMAKE_CXX_COMPILER}") +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) +else() + set(common_compile_options) +endif() +string(GENEX_STRIP "${common_compile_options}" common_compile_options) +message("Common compile options ................ ${common_compile_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}") +message("Linker flags for executables .......... ${CMAKE_EXE_LINKER_FLAGS}") +message("Linker flags for shared libraries ..... ${CMAKE_SHARED_LINKER_FLAGS}") +print_config_flags() +message("Use assembly routines ................. ${ASM}") +message("Use ccache for compiling .............. ${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. +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() diff --git a/cmake/bitcoin-config.h.in b/cmake/bitcoin-config.h.in new file mode 100644 index 0000000000000..ebbb97562cdb0 --- /dev/null +++ b/cmake/bitcoin-config.h.in @@ -0,0 +1,218 @@ +// Copyright (c) 2023 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_CONFIG_H + +#define BITCOIN_CONFIG_H + +/* Define this symbol if type char equals int8_t */ +#cmakedefine CHAR_EQUALS_INT8 1 + +/* Version Build */ +#define CLIENT_VERSION_BUILD @PROJECT_VERSION_PATCH@ + +/* Version is release */ +#define CLIENT_VERSION_IS_RELEASE @CLIENT_VERSION_IS_RELEASE@ + +/* Major version */ +#define CLIENT_VERSION_MAJOR @PROJECT_VERSION_MAJOR@ + +/* Minor version */ +#define CLIENT_VERSION_MINOR @PROJECT_VERSION_MINOR@ + +/* Copyright holder(s) before %s replacement */ +#define COPYRIGHT_HOLDERS "@COPYRIGHT_HOLDERS@" + +/* Copyright holder(s) */ +#define COPYRIGHT_HOLDERS_FINAL "@COPYRIGHT_HOLDERS_FINAL@" + +/* Replacement for %s in copyright holders string */ +#define COPYRIGHT_HOLDERS_SUBSTITUTION "@PROJECT_NAME@" + +/* Copyright year */ +#define COPYRIGHT_YEAR @COPYRIGHT_YEAR@ + +/* Define to 1 to enable tracepoints for Userspace, Statically Defined Tracing + */ +#cmakedefine ENABLE_TRACING 1 + +/* Define this symbol if you have __builtin_clzl */ +#cmakedefine HAVE_BUILTIN_CLZL 1 + +/* Define this symbol if you have __builtin_clzll */ +#cmakedefine HAVE_BUILTIN_CLZLL 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_BYTESWAP_H 1 + +/* Define to 1 if you have the declaration of `be16toh', and to 0 if you + don't. */ +#cmakedefine01 HAVE_DECL_BE16TOH + +/* Define to 1 if you have the declaration of `be32toh', and to 0 if you + don't. */ +#cmakedefine01 HAVE_DECL_BE32TOH + +/* Define to 1 if you have the declaration of `be64toh', and to 0 if you + don't. */ +#cmakedefine01 HAVE_DECL_BE64TOH + +/* Define to 1 if you have the declaration of `bswap_16', and to 0 if you + don't. */ +#cmakedefine01 HAVE_DECL_BSWAP_16 + +/* Define to 1 if you have the declaration of `bswap_32', and to 0 if you + don't. */ +#cmakedefine01 HAVE_DECL_BSWAP_32 + +/* Define to 1 if you have the declaration of `bswap_64', and to 0 if you + don't. */ +#cmakedefine01 HAVE_DECL_BSWAP_64 + +/* Define to 1 if you have the declaration of `fork', and to 0 if you don't. + */ +#cmakedefine01 HAVE_DECL_FORK + +/* Define to 1 if you have the declaration of `freeifaddrs', and to 0 if you + don't. */ +#cmakedefine01 HAVE_DECL_FREEIFADDRS + +/* Define to 1 if you have the declaration of `getifaddrs', and to 0 if you + don't. */ +#cmakedefine01 HAVE_DECL_GETIFADDRS + +/* Define to 1 if you have the declaration of `htobe16', and to 0 if you + don't. */ +#cmakedefine01 HAVE_DECL_HTOBE16 + +/* Define to 1 if you have the declaration of `htobe32', and to 0 if you + don't. */ +#cmakedefine01 HAVE_DECL_HTOBE32 + +/* Define to 1 if you have the declaration of `htobe64', and to 0 if you + don't. */ +#cmakedefine01 HAVE_DECL_HTOBE64 + +/* Define to 1 if you have the declaration of `htole16', and to 0 if you + don't. */ +#cmakedefine01 HAVE_DECL_HTOLE16 + +/* Define to 1 if you have the declaration of `htole32', and to 0 if you + don't. */ +#cmakedefine01 HAVE_DECL_HTOLE32 + +/* Define to 1 if you have the declaration of `htole64', and to 0 if you + don't. */ +#cmakedefine01 HAVE_DECL_HTOLE64 + +/* Define to 1 if you have the declaration of `le16toh', and to 0 if you + don't. */ +#cmakedefine01 HAVE_DECL_LE16TOH + +/* Define to 1 if you have the declaration of `le32toh', and to 0 if you + don't. */ +#cmakedefine01 HAVE_DECL_LE32TOH + +/* Define to 1 if you have the declaration of `le64toh', and to 0 if you + don't. */ +#cmakedefine01 HAVE_DECL_LE64TOH + +/* Define to 1 if you have the declaration of `pipe2', and to 0 if you don't. + */ +#cmakedefine01 HAVE_DECL_PIPE2 + +/* Define to 1 if you have the declaration of `setsid', and to 0 if you don't. + */ +#cmakedefine01 HAVE_DECL_SETSID + +/* Define if the visibility attribute is supported. */ +#cmakedefine HAVE_DEFAULT_VISIBILITY_ATTRIBUTE 1 + +/* Define if the dllexport attribute is supported. */ +#cmakedefine HAVE_DLLEXPORT_ATTRIBUTE 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ENDIAN_H 1 + +/* Define to 1 if fdatasync is available. */ +#cmakedefine HAVE_FDATASYNC 1 + +/* Define this symbol if the BSD getentropy system call is available with + sys/random.h */ +#cmakedefine HAVE_GETENTROPY_RAND 1 + +/* Define this symbol if gmtime_r is available */ +#cmakedefine HAVE_GMTIME_R 1 + +/* Define this symbol if you have malloc_info */ +#cmakedefine HAVE_MALLOC_INFO 1 + +/* Define this symbol if you have mallopt with M_ARENA_MAX */ +#cmakedefine HAVE_MALLOPT_ARENA_MAX 1 + +/* Define to 1 if O_CLOEXEC flag is available. */ +#cmakedefine01 HAVE_O_CLOEXEC + +/* Define this symbol if you have posix_fallocate */ +#cmakedefine HAVE_POSIX_FALLOCATE 1 + +/* Define this symbol to build code that uses getauxval) */ +#cmakedefine HAVE_STRONG_GETAUXVAL 1 + +/* Define this symbol if the BSD sysctl() is available */ +#cmakedefine HAVE_SYSCTL 1 + +/* Define this symbol if the BSD sysctl(KERN_ARND) is available */ +#cmakedefine HAVE_SYSCTL_ARND 1 + +/* Define to 1 if std::system or ::wsystem is available. */ +#cmakedefine HAVE_SYSTEM 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_ENDIAN_H 1 + +/* Define this symbol if the Linux getrandom system call is available */ +#cmakedefine HAVE_SYS_GETRANDOM 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_PRCTL_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_RESOURCES_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_VMMETER_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_VM_VM_PARAM_H 1 + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "@PACKAGE_BUGREPORT@" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "@PROJECT_NAME@" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "@PROJECT_HOMEPAGE_URL@" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "@PROJECT_VERSION@" + +/* Define to 1 if strerror_r returns char *. */ +#cmakedefine STRERROR_R_CHAR_P 1 + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#cmakedefine WORDS_BIGENDIAN 1 + +/* Define to 1 to enable wallet functions. */ +#cmakedefine ENABLE_WALLET 1 + +/* Define if SQLite support should be compiled in. */ +#cmakedefine USE_SQLITE + +/* Define if Berkeley DB (BDB) support should be compiled in. */ +#cmakedefine USE_BDB + +#endif //BITCOIN_CONFIG_H diff --git a/cmake/crc32c.cmake b/cmake/crc32c.cmake new file mode 100644 index 0000000000000..a1a64d12059a9 --- /dev/null +++ b/cmake/crc32c.cmake @@ -0,0 +1,115 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# This file is part of the transition from Autotools to CMake. Once CMake +# support has been merged we should switch to using the upstream CMake +# buildsystem. + +include(CheckCXXSourceCompiles) + +# Check for __builtin_prefetch support in the compiler. +check_cxx_source_compiles(" + int main() { + char data = 0; + const char* address = &data; + __builtin_prefetch(address, 0, 0); + return 0; + } + " HAVE_BUILTIN_PREFETCH +) + +# Check for _mm_prefetch support in the compiler. +check_cxx_source_compiles(" + #if defined(_MSC_VER) + #include + #else + #include + #endif + + int main() { + char data = 0; + const char* address = &data; + _mm_prefetch(address, _MM_HINT_NTA); + return 0; + } + " HAVE_MM_PREFETCH +) + +# Check for SSE4.2 support in the compiler. +if(MSVC) + set(SSE42_CXXFLAGS /arch:AVX) +else() + set(SSE42_CXXFLAGS -msse4.2) +endif() +check_cxx_source_compiles_with_flags("${SSE42_CXXFLAGS}" " + #include + #if defined(_MSC_VER) + #include + #elif defined(__GNUC__) && defined(__SSE4_2__) + #include + #endif + + int main() { + uint64_t l = 0; + l = _mm_crc32_u8(l, 0); + l = _mm_crc32_u32(l, 0); + l = _mm_crc32_u64(l, 0); + return l; + } + " HAVE_SSE42 +) + +# Check for ARMv8 w/ CRC and CRYPTO extensions support in the compiler. +set(ARM_CRC_CXXFLAGS -march=armv8-a+crc) +check_cxx_source_compiles_with_flags("${ARM_CRC_CXXFLAGS}" " + #include + #include + + int main() { + #ifdef __aarch64__ + __crc32cb(0, 0); __crc32ch(0, 0); __crc32cw(0, 0); __crc32cd(0, 0); + vmull_p64(0, 0); + #else + #error crc32c library does not support hardware acceleration on 32-bit ARM + #endif + return 0; + } + " HAVE_ARM64_CRC32C +) + +add_library(crc32c STATIC EXCLUDE_FROM_ALL + ${PROJECT_SOURCE_DIR}/src/crc32c/src/crc32c.cc + ${PROJECT_SOURCE_DIR}/src/crc32c/src/crc32c_portable.cc +) + +target_compile_definitions(crc32c + PRIVATE + HAVE_BUILTIN_PREFETCH=$ + HAVE_MM_PREFETCH=$ + HAVE_STRONG_GETAUXVAL=$ + HAVE_SSE42=$ + HAVE_ARM64_CRC32C=$ + BYTE_ORDER_BIG_ENDIAN=${WORDS_BIGENDIAN} +) + +target_include_directories(crc32c + PUBLIC + $ +) + +if(HAVE_SSE42) + target_sources(crc32c PRIVATE ${PROJECT_SOURCE_DIR}/src/crc32c/src/crc32c_sse42.cc) + set_property(SOURCE ${PROJECT_SOURCE_DIR}/src/crc32c/src/crc32c_sse42.cc + APPEND PROPERTY COMPILE_OPTIONS ${SSE42_CXXFLAGS} + ) +endif() + +if(HAVE_ARM64_CRC32C) + target_sources(crc32c PRIVATE ${PROJECT_SOURCE_DIR}/src/crc32c/src/crc32c_arm64.cc) + set_property(SOURCE ${PROJECT_SOURCE_DIR}/src/crc32c/src/crc32c_arm64.cc + APPEND PROPERTY COMPILE_OPTIONS ${ARM_CRC_CXXFLAGS} + ) +endif() + +target_link_libraries(crc32c PRIVATE core) diff --git a/cmake/introspection.cmake b/cmake/introspection.cmake new file mode 100644 index 0000000000000..0462ede322d6e --- /dev/null +++ b/cmake/introspection.cmake @@ -0,0 +1,269 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +include(CheckCXXSourceCompiles) +include(CheckCXXSymbolExists) +include(CheckIncludeFileCXX) +include(TestBigEndian) + +test_big_endian(WORDS_BIGENDIAN) + +# The following HAVE_{HEADER}_H variables go to the bitcoin-config.h header. +check_include_file_cxx(byteswap.h HAVE_BYTESWAP_H) +check_include_file_cxx(endian.h HAVE_ENDIAN_H) +check_include_file_cxx(sys/endian.h HAVE_SYS_ENDIAN_H) +check_include_file_cxx(sys/prctl.h HAVE_SYS_PRCTL_H) +check_include_file_cxx(sys/resources.h HAVE_SYS_RESOURCES_H) +check_include_file_cxx(sys/vmmeter.h HAVE_SYS_VMMETER_H) +check_include_file_cxx(vm/vm_param.h HAVE_VM_VM_PARAM_H) + +check_cxx_source_compiles(" + int main() + { + (void) __builtin_clzl(0); + } + " HAVE_BUILTIN_CLZL +) + +check_cxx_source_compiles(" + int main() + { + (void) __builtin_clzll(0); + } + " HAVE_BUILTIN_CLZLL +) + +check_cxx_symbol_exists(O_CLOEXEC "fcntl.h" HAVE_O_CLOEXEC) + +if(HAVE_BYTESWAP_H) + check_cxx_symbol_exists(bswap_16 "byteswap.h" HAVE_DECL_BSWAP_16) + check_cxx_symbol_exists(bswap_32 "byteswap.h" HAVE_DECL_BSWAP_32) + check_cxx_symbol_exists(bswap_64 "byteswap.h" HAVE_DECL_BSWAP_64) +endif() + +if(HAVE_ENDIAN_H OR HAVE_SYS_ENDIAN_H) + if(HAVE_ENDIAN_H) + set(ENDIAN_HEADER "endian.h") + else() + set(ENDIAN_HEADER "sys/endian.h") + endif() + check_cxx_symbol_exists(be16toh ${ENDIAN_HEADER} HAVE_DECL_BE16TOH) + check_cxx_symbol_exists(be32toh ${ENDIAN_HEADER} HAVE_DECL_BE32TOH) + check_cxx_symbol_exists(be64toh ${ENDIAN_HEADER} HAVE_DECL_BE64TOH) + check_cxx_symbol_exists(htobe16 ${ENDIAN_HEADER} HAVE_DECL_HTOBE16) + check_cxx_symbol_exists(htobe32 ${ENDIAN_HEADER} HAVE_DECL_HTOBE32) + check_cxx_symbol_exists(htobe64 ${ENDIAN_HEADER} HAVE_DECL_HTOBE64) + check_cxx_symbol_exists(htole16 ${ENDIAN_HEADER} HAVE_DECL_HTOLE16) + check_cxx_symbol_exists(htole32 ${ENDIAN_HEADER} HAVE_DECL_HTOLE32) + check_cxx_symbol_exists(htole64 ${ENDIAN_HEADER} HAVE_DECL_HTOLE64) + check_cxx_symbol_exists(le16toh ${ENDIAN_HEADER} HAVE_DECL_LE16TOH) + check_cxx_symbol_exists(le32toh ${ENDIAN_HEADER} HAVE_DECL_LE32TOH) + check_cxx_symbol_exists(le64toh ${ENDIAN_HEADER} HAVE_DECL_LE64TOH) +endif() + +check_include_file_cxx(unistd.h HAVE_UNISTD_H) +if(HAVE_UNISTD_H) + check_cxx_symbol_exists(fdatasync "unistd.h" HAVE_FDATASYNC) + check_cxx_symbol_exists(fork "unistd.h" HAVE_DECL_FORK) + check_cxx_symbol_exists(pipe2 "unistd.h" HAVE_DECL_PIPE2) + check_cxx_symbol_exists(setsid "unistd.h" HAVE_DECL_SETSID) +endif() + +check_include_file_cxx(sys/types.h HAVE_SYS_TYPES_H) +check_include_file_cxx(ifaddrs.h HAVE_IFADDRS_H) +if(HAVE_SYS_TYPES_H AND HAVE_IFADDRS_H) + check_cxx_symbol_exists(freeifaddrs "sys/types.h;ifaddrs.h" HAVE_DECL_FREEIFADDRS) + check_cxx_symbol_exists(getifaddrs "sys/types.h;ifaddrs.h" HAVE_DECL_GETIFADDRS) + # Illumos/SmartOS requires linking with -lsocket if + # using getifaddrs & freeifaddrs. + # See: https://github.com/bitcoin/bitcoin/pull/21486 + if(HAVE_DECL_GETIFADDRS AND HAVE_DECL_FREEIFADDRS) + set(check_socket_source " + #include + #include + + int main() { + struct ifaddrs* ifaddr; + getifaddrs(&ifaddr); + freeifaddrs(ifaddr); + } + ") + check_cxx_source_links("${check_socket_source}" IFADDR_LINKS_WITHOUT_LIBSOCKET) + if(NOT IFADDR_LINKS_WITHOUT_LIBSOCKET) + check_cxx_source_links_with_libs(socket "${check_socket_source}" IFADDR_NEEDS_LINK_TO_LIBSOCKET) + if(IFADDR_NEEDS_LINK_TO_LIBSOCKET) + link_libraries(socket) + else() + message(FATAL_ERROR "Cannot figure out how to use getifaddrs/freeifaddrs.") + endif() + endif() + endif() +endif() + +# Check for gmtime_r(), fallback to gmtime_s() if that is unavailable. +# Fail if neither are available. +check_cxx_source_compiles(" + #include + + int main() + { + gmtime_r((const time_t*)nullptr, (struct tm*)nullptr); + } + " HAVE_GMTIME_R +) +if(NOT HAVE_GMTIME_R) + check_cxx_source_compiles(" + #include + + int main() + { + gmtime_s((struct tm*)nullptr, (const time_t*)nullptr); + } + " HAVE_GMTIME_S + ) + if(NOT HAVE_GMTIME_S) + message(FATAL_ERROR "Both gmtime_r and gmtime_s are unavailable.") + endif() +endif() + +check_cxx_symbol_exists(std::system "cstdlib" HAVE_STD_SYSTEM) +check_cxx_symbol_exists(::_wsystem "stdlib.h" HAVE__WSYSTEM) +if(HAVE_STD_SYSTEM OR HAVE__WSYSTEM) + set(HAVE_SYSTEM 1) +endif() + +check_include_file_cxx(string.h HAVE_STRING_H) +if(HAVE_STRING_H) + check_cxx_source_compiles(" + #include + + int main() + { + char buf[100]; + char* p{strerror_r(0, buf, sizeof buf)}; + (void)p; + } + " STRERROR_R_CHAR_P + ) +endif() + +# Check for malloc_info (for memory statistics information in getmemoryinfo). +check_cxx_symbol_exists(malloc_info "malloc.h" HAVE_MALLOC_INFO) + +# Check for mallopt(M_ARENA_MAX) (to set glibc arenas). +check_cxx_source_compiles(" + #include + + int main() + { + mallopt(M_ARENA_MAX, 1); + } + " HAVE_MALLOPT_ARENA_MAX +) + +# Check for posix_fallocate(). +check_cxx_source_compiles(" + // same as in src/util/fs_helpers.cpp + #ifdef __linux__ + #ifdef _POSIX_C_SOURCE + #undef _POSIX_C_SOURCE + #endif + #define _POSIX_C_SOURCE 200112L + #endif // __linux__ + #include + + int main() + { + return posix_fallocate(0, 0, 0); + } + " HAVE_POSIX_FALLOCATE +) + +# Check for strong getauxval() support in the system headers. +check_cxx_source_compiles(" + #include + + int main() + { + getauxval(AT_HWCAP); + } + " HAVE_STRONG_GETAUXVAL +) + +# Check for different ways of gathering OS randomness: +# - Linux getrandom() +check_cxx_source_compiles(" + #include + #include + #include + + int main() + { + syscall(SYS_getrandom, nullptr, 32, 0); + } + " HAVE_SYS_GETRANDOM +) + +# - BSD getentropy() +check_cxx_symbol_exists(getentropy "unistd.h;sys/random.h" HAVE_GETENTROPY_RAND) + +# - BSD sysctl() +check_cxx_source_compiles(" + #include + #include + + #ifdef __linux__ + #error Don't use sysctl on Linux, it's deprecated even when it works + #endif + + int main() + { + sysctl(nullptr, 2, nullptr, nullptr, nullptr, 0); + } + " HAVE_SYSCTL +) + +# - BSD sysctl(KERN_ARND) +check_cxx_source_compiles(" + #include + #include + + #ifdef __linux__ + #error Don't use sysctl on Linux, it's deprecated even when it works + #endif + + int main() + { + static int name[2] = {CTL_KERN, KERN_ARND}; + sysctl(name, 2, nullptr, nullptr, nullptr, 0); + } + " HAVE_SYSCTL_ARND +) + +check_cxx_source_compiles(" + #include + #include + + int main() + { + static_assert(std::is_same::value); + } + " CHAR_EQUALS_INT8 +) + +check_cxx_source_compiles(" + int foo(void) __attribute__((visibility(\"default\"))); + int main(){} + " HAVE_DEFAULT_VISIBILITY_ATTRIBUTE +) + +check_cxx_source_compiles(" + __declspec(dllexport) int foo(void); + int main(){} + " HAVE_DLLEXPORT_ATTRIBUTE +) + +if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin") + find_program(BREW_COMMAND brew) +endif() diff --git a/cmake/leveldb.cmake b/cmake/leveldb.cmake new file mode 100644 index 0000000000000..d1c34024151fb --- /dev/null +++ b/cmake/leveldb.cmake @@ -0,0 +1,94 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# This file is part of the transition from Autotools to CMake. Once CMake +# support has been merged we should switch to using the upstream CMake +# buildsystem. + +include(CheckCXXSymbolExists) +check_cxx_symbol_exists(F_FULLFSYNC "fcntl.h" HAVE_FULLFSYNC) + +add_library(leveldb STATIC EXCLUDE_FROM_ALL + ${PROJECT_SOURCE_DIR}/src/leveldb/db/builder.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/db/c.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/db/db_impl.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/db/db_iter.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/db/dbformat.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/db/dumpfile.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/db/filename.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/db/log_reader.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/db/log_writer.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/db/memtable.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/db/repair.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/db/table_cache.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/db/version_edit.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/db/version_set.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/db/write_batch.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/table/block.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/table/block_builder.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/table/filter_block.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/table/format.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/table/iterator.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/table/merger.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/table/table.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/table/table_builder.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/table/two_level_iterator.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/util/arena.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/util/bloom.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/util/cache.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/util/coding.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/util/comparator.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/util/crc32c.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/util/env.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/util/filter_policy.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/util/hash.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/util/histogram.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/util/logging.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/util/options.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/util/status.cc + ${PROJECT_SOURCE_DIR}/src/leveldb/helpers/memenv/memenv.cc +) +if(WIN32) + target_sources(leveldb PRIVATE ${PROJECT_SOURCE_DIR}/src/leveldb/util/env_windows.cc) + set_property(SOURCE ${PROJECT_SOURCE_DIR}/src/leveldb/util/env_windows.cc + APPEND PROPERTY COMPILE_OPTIONS $<$,$>:/wd4722> + ) +else() + target_sources(leveldb PRIVATE ${PROJECT_SOURCE_DIR}/src/leveldb/util/env_posix.cc) +endif() + +target_compile_definitions(leveldb + PRIVATE + HAVE_SNAPPY=0 + HAVE_CRC32C=1 + HAVE_FDATASYNC=$ + HAVE_FULLFSYNC=$ + HAVE_O_CLOEXEC=$ + FALLTHROUGH_INTENDED=[[fallthrough]] + LEVELDB_IS_BIG_ENDIAN=${WORDS_BIGENDIAN} +) + +if(WIN32) + target_compile_definitions(leveldb + PRIVATE + LEVELDB_PLATFORM_WINDOWS + _UNICODE + UNICODE + __USE_MINGW_ANSI_STDIO=1 + ) +else() + target_compile_definitions(leveldb PRIVATE LEVELDB_PLATFORM_POSIX) +endif() + +target_include_directories(leveldb + PRIVATE + $ + PUBLIC + $ +) + +#TODO: figure out how to filter out: +# -Wconditional-uninitialized -Werror=conditional-uninitialized -Wsuggest-override -Werror=suggest-override + +target_link_libraries(leveldb PRIVATE core crc32c) diff --git a/cmake/minisketch.cmake b/cmake/minisketch.cmake new file mode 100644 index 0000000000000..9a61a7c9d9d6e --- /dev/null +++ b/cmake/minisketch.cmake @@ -0,0 +1,76 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# Check for clmul instructions support. +if(MSVC) + set(CLMUL_CXXFLAGS) +else() + set(CLMUL_CXXFLAGS -mpclmul) +endif() +check_cxx_source_compiles_with_flags("${CLMUL_CXXFLAGS}" " + #include + #include + + int main() + { + __m128i a = _mm_cvtsi64_si128((uint64_t)7); + __m128i b = _mm_clmulepi64_si128(a, a, 37); + __m128i c = _mm_srli_epi64(b, 41); + __m128i d = _mm_xor_si128(b, c); + uint64_t e = _mm_cvtsi128_si64(d); + return e == 0; + } + " HAVE_CLMUL +) + +add_library(minisketch_defs INTERFACE) +target_compile_definitions(minisketch_defs INTERFACE + DISABLE_DEFAULT_FIELDS + ENABLE_FIELD_32 + $<$,$>:HAVE_CLZ> +) + +if(HAVE_CLMUL) + add_library(minisketch_clmul OBJECT EXCLUDE_FROM_ALL + ${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/clmul_1byte.cpp + ${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/clmul_2bytes.cpp + ${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/clmul_3bytes.cpp + ${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/clmul_4bytes.cpp + ${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/clmul_5bytes.cpp + ${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/clmul_6bytes.cpp + ${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/clmul_7bytes.cpp + ${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/clmul_8bytes.cpp + ) + target_compile_definitions(minisketch_clmul PUBLIC HAVE_CLMUL) + target_compile_options(minisketch_clmul PRIVATE ${CLMUL_CXXFLAGS}) + target_link_libraries(minisketch_clmul + PRIVATE + core + minisketch_defs + ) +endif() + +add_library(minisketch STATIC EXCLUDE_FROM_ALL + ${PROJECT_SOURCE_DIR}/src/minisketch/src/minisketch.cpp + ${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/generic_1byte.cpp + ${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/generic_2bytes.cpp + ${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/generic_3bytes.cpp + ${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/generic_4bytes.cpp + ${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/generic_5bytes.cpp + ${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/generic_6bytes.cpp + ${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/generic_7bytes.cpp + ${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/generic_8bytes.cpp +) + +target_include_directories(minisketch + PUBLIC + $ +) + +target_link_libraries(minisketch + PRIVATE + core + minisketch_defs + $ +) diff --git a/cmake/module/AddBoostIfNeeded.cmake b/cmake/module/AddBoostIfNeeded.cmake new file mode 100644 index 0000000000000..e564404b29bc3 --- /dev/null +++ b/cmake/module/AddBoostIfNeeded.cmake @@ -0,0 +1,52 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +function(add_boost_if_needed) + #[=[ + TODO: Not all targets, which will be added in the future, require + Boost. Therefore, a proper check will be appropriate here. + + Implementation notes: + Although only Boost headers are used to build Bitcoin Core, + we still leverage a standard CMake's approach to handle + dependencies, i.e., the Boost::headers "library". + A command target_link_libraries(target PRIVATE Boost::headers) + will propagate Boost::headers usage requirements to the target. + For Boost::headers such usage requirements is an include + directory and other added INTERFACE properties. + ]=] + + set(Boost_NO_BOOST_CMAKE ON) + find_package(Boost 1.64.0 REQUIRED) + set_target_properties(Boost::headers PROPERTIES IMPORTED_GLOBAL TRUE) + target_compile_definitions(Boost::headers INTERFACE + # We don't use multi_index serialization. + BOOST_MULTI_INDEX_DISABLE_SERIALIZATION + ) + + if(BUILD_TESTS) + include(CheckCXXSourceCompiles) + set(CMAKE_REQUIRED_INCLUDES ${Boost_INCLUDE_DIR}) + check_cxx_source_compiles(" + #define BOOST_TEST_MAIN + #include + " HAVE_BOOST_INCLUDED_UNIT_TEST_H + ) + if(NOT HAVE_BOOST_INCLUDED_UNIT_TEST_H) + message(FATAL_ERROR "Building test_bitcoin executable requested but boost/test/included/unit_test.hpp header not available.") + endif() + + check_cxx_source_compiles(" + #define BOOST_TEST_MAIN + #include + #include + " HAVE_BOOST_UNIT_TEST_H + ) + if(NOT HAVE_BOOST_UNIT_TEST_H) + message(FATAL_ERROR "Building test_bitcoin executable requested but boost/test/unit_test.hpp header not available.") + endif() + endif() + + mark_as_advanced(Boost_INCLUDE_DIR) +endfunction() diff --git a/cmake/module/AddLibeventIfNeeded.cmake b/cmake/module/AddLibeventIfNeeded.cmake new file mode 100644 index 0000000000000..302d068fe916c --- /dev/null +++ b/cmake/module/AddLibeventIfNeeded.cmake @@ -0,0 +1,60 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# Check whether evhttp_connection_get_peer expects const char**. +# See https://github.com/libevent/libevent/commit/a18301a2bb160ff7c3ffaf5b7653c39ffe27b385 +macro(check_evhttp_connection_get_peer target) + cmake_push_check_state(RESET) + set(CMAKE_REQUIRED_LIBRARIES ${target}) + check_cxx_source_compiles(" + #include + #include + + int main() + { + evhttp_connection* conn = (evhttp_connection*)1; + const char* host; + uint16_t port; + evhttp_connection_get_peer(conn, &host, &port); + } + " HAVE_EVHTTP_CONNECTION_GET_PEER_CONST_CHAR + ) + cmake_pop_check_state() + target_compile_definitions(${target} INTERFACE + $<$:HAVE_EVHTTP_CONNECTION_GET_PEER_CONST_CHAR=1> + ) +endmacro() + +function(add_libevent_if_needed) + # TODO: Not all targets, which will be added in the future, + # require libevent. Therefore, a proper check will be + # appropriate here. + + set(libevent_minimum_version 2.1.8) + + if(MSVC) + find_package(Libevent ${libevent_minimum_version} REQUIRED COMPONENTS extra CONFIG) + check_evhttp_connection_get_peer(libevent::extra) + add_library(libevent::libevent ALIAS libevent::extra) + return() + endif() + + include(CrossPkgConfig) + cross_pkg_check_modules(libevent + REQUIRED IMPORTED_TARGET GLOBAL + libevent>=${libevent_minimum_version} + ) + check_evhttp_connection_get_peer(PkgConfig::libevent) + target_link_libraries(PkgConfig::libevent INTERFACE + $<$:iphlpapi;ssp;ws2_32> + ) + add_library(libevent::libevent ALIAS PkgConfig::libevent) + + if(NOT WIN32) + cross_pkg_check_modules(libevent_pthreads + REQUIRED IMPORTED_TARGET GLOBAL + libevent_pthreads>=${libevent_minimum_version} + ) + endif() +endfunction() diff --git a/cmake/module/AddThreadsIfNeeded.cmake b/cmake/module/AddThreadsIfNeeded.cmake new file mode 100644 index 0000000000000..2939f1a0c6fcb --- /dev/null +++ b/cmake/module/AddThreadsIfNeeded.cmake @@ -0,0 +1,42 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +function(add_threads_if_needed) + # TODO: Not all targets, which will be added in the future, + # require Threads. Therefore, a proper check will be + # appropriate here. + + if(CMAKE_C_COMPILER_LOADED) + message(FATAL_ERROR [=[ + To make FindThreads check C++ language features, C language must be + disabled. This is essential, at least, when cross-compiling for MinGW-w64 + because two different threading models are available. + ]=] ) + endif() + + set(THREADS_PREFER_PTHREAD_FLAG ON) + find_package(Threads REQUIRED) + set_target_properties(Threads::Threads PROPERTIES IMPORTED_GLOBAL TRUE) + + set(thread_local) + if(MINGW) + #[=[ + mingw32's implementation of thread_local has been shown to behave + erroneously under concurrent usage. + See: + - https://github.com/bitcoin/bitcoin/pull/15849 + - https://gist.github.com/jamesob/fe9a872051a88b2025b1aa37bfa98605 + ]=] + elseif(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") + #[=[ + FreeBSD's implementation of thread_local is buggy. + See: + - https://github.com/bitcoin/bitcoin/pull/16059 + - https://groups.google.com/d/msg/bsdmailinglist/22ncTZAbDp4/Dii_pII5AwAJ + ]=] + elseif(THREADLOCAL) + set(thread_local "$<$:HAVE_THREAD_LOCAL>") + endif() + set(THREAD_LOCAL_IF_AVAILABLE "${thread_local}" PARENT_SCOPE) +endfunction() diff --git a/cmake/module/CheckSourceCompilesAndLinks.cmake b/cmake/module/CheckSourceCompilesAndLinks.cmake new file mode 100644 index 0000000000000..2e5ab54e67e70 --- /dev/null +++ b/cmake/module/CheckSourceCompilesAndLinks.cmake @@ -0,0 +1,36 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +include(CheckCXXSourceCompiles) +include(CMakePushCheckState) + +# This avoids running the linker. +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) + +macro(check_cxx_source_links source) + set(CMAKE_TRY_COMPILE_TARGET_TYPE EXECUTABLE) + check_cxx_source_compiles("${source}" ${ARGN}) + set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) +endmacro() + +macro(check_cxx_source_compiles_with_flags flags source) + cmake_push_check_state(RESET) + string(REPLACE ";" " " CMAKE_REQUIRED_FLAGS "${flags}") + check_cxx_source_compiles("${source}" ${ARGN}) + cmake_pop_check_state() +endmacro() + +macro(check_cxx_source_links_with_flags flags source) + cmake_push_check_state(RESET) + string(REPLACE ";" " " CMAKE_REQUIRED_FLAGS "${flags}") + check_cxx_source_links("${source}" ${ARGN}) + cmake_pop_check_state() +endmacro() + +macro(check_cxx_source_links_with_libs libs source) + cmake_push_check_state(RESET) + set(CMAKE_REQUIRED_LIBRARIES "${libs}") + check_cxx_source_links("${source}" ${ARGN}) + cmake_pop_check_state() +endmacro() diff --git a/cmake/module/CrossPkgConfig.cmake b/cmake/module/CrossPkgConfig.cmake new file mode 100644 index 0000000000000..cbd6f3c27b288 --- /dev/null +++ b/cmake/module/CrossPkgConfig.cmake @@ -0,0 +1,49 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +find_package(PkgConfig REQUIRED) + +function(remove_isystem_from_include_directories_internal target) + #[=[ + A workaround for https://gitlab.kitware.com/cmake/cmake/-/issues/20652. + + When the pkg-config provides CFLAGS with -isystem options, for instance: + + $ pkg-config --cflags-only-I libzmq + -isystem /usr/include/mit-krb5 -I/usr/include/pgm-5.3 -I/usr/include/libxml2 + + an old CMake fails to parse them properly and the INTERFACE_INCLUDE_DIRECTORIES + property contains "-isystem" as a separated element: + + -isystem;/usr/include/mit-krb5;/usr/include/pgm-5.3;/usr/include/libxml2 + + which ends with an error "Imported target includes non-existent path". + + Fixing by removing the "-isystem" element from the INTERFACE_INCLUDE_DIRECTORIES. + ]=] + + get_target_property(include_directories ${target} INTERFACE_INCLUDE_DIRECTORIES) + if(include_directories) + list(REMOVE_ITEM include_directories -isystem) + set_target_properties(${target} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${include_directories}") + endif() +endfunction() + +macro(cross_pkg_check_modules prefix) + if(CMAKE_CROSSCOMPILING) + set(pkg_config_path_saved "$ENV{PKG_CONFIG_PATH}") + set(pkg_config_libdir_saved "$ENV{PKG_CONFIG_LIBDIR}") + set(ENV{PKG_CONFIG_PATH} ${PKG_CONFIG_PATH}) + set(ENV{PKG_CONFIG_LIBDIR} ${PKG_CONFIG_LIBDIR}) + pkg_check_modules(${prefix} ${ARGN}) + set(ENV{PKG_CONFIG_PATH} ${pkg_config_path_saved}) + set(ENV{PKG_CONFIG_LIBDIR} ${pkg_config_libdir_saved}) + else() + pkg_check_modules(${prefix} ${ARGN}) + endif() + + if(CMAKE_VERSION VERSION_LESS 3.17.3 AND TARGET PkgConfig::${prefix}) + remove_isystem_from_include_directories_internal(PkgConfig::${prefix}) + endif() +endmacro() diff --git a/cmake/module/FindBerkeleyDB.cmake b/cmake/module/FindBerkeleyDB.cmake new file mode 100644 index 0000000000000..712fcb3decfbd --- /dev/null +++ b/cmake/module/FindBerkeleyDB.cmake @@ -0,0 +1,87 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +if(CMAKE_HOST_APPLE) + execute_process( + COMMAND brew --prefix berkeley-db@4 + OUTPUT_VARIABLE bdb4_brew_prefix + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE + ) +endif() + +find_path(BerkeleyDB_INCLUDE_DIR + NAMES db.h + HINTS ${bdb4_brew_prefix}/include + PATH_SUFFIXES 4.8 48 4 db4 5 5.3 db5 +) + +if(BerkeleyDB_INCLUDE_DIR) + file( + STRINGS "${BerkeleyDB_INCLUDE_DIR}/db.h" version_strings + REGEX ".*DB_VERSION_(MAJOR|MINOR)[ \t]+[0-9]+.*" + ) + string(REGEX REPLACE ".*DB_VERSION_MAJOR[ \t]+([0-9]+).*" "\\1" BerkeleyDB_VERSION_MAJOR "${version_strings}") + string(REGEX REPLACE ".*DB_VERSION_MINOR[ \t]+([0-9]+).*" "\\1" BerkeleyDB_VERSION_MINOR "${version_strings}") + set(BerkeleyDB_VERSION ${BerkeleyDB_VERSION_MAJOR}.${BerkeleyDB_VERSION_MINOR}) +endif() + +if(MSVC) + cmake_path(GET BerkeleyDB_INCLUDE_DIR PARENT_PATH BerkeleyDB_IMPORTED_PATH) + find_library(BerkeleyDB_LIBRARY_DEBUG + NAMES libdb48 PATHS ${BerkeleyDB_IMPORTED_PATH}/debug/lib + NO_DEFAULT_PATH + ) + find_library(BerkeleyDB_LIBRARY_RELEASE + NAMES libdb48 PATHS ${BerkeleyDB_IMPORTED_PATH}/lib + NO_DEFAULT_PATH + ) + if(BerkeleyDB_LIBRARY_DEBUG OR BerkeleyDB_LIBRARY_RELEASE) + set(BerkeleyDB_required BerkeleyDB_IMPORTED_PATH) + endif() +else() + find_library(BerkeleyDB_LIBRARY + NAMES db_cxx-4.8 libdb48 db4_cxx db_cxx db_cxx-5 + HINTS ${bdb4_brew_prefix}/lib + ) + set(BerkeleyDB_required BerkeleyDB_LIBRARY) +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(BerkeleyDB + REQUIRED_VARS ${BerkeleyDB_required} BerkeleyDB_INCLUDE_DIR + VERSION_VAR BerkeleyDB_VERSION +) + +if(BerkeleyDB_FOUND AND NOT TARGET BerkeleyDB::BerkeleyDB) + add_library(BerkeleyDB::BerkeleyDB UNKNOWN IMPORTED) + set_target_properties(BerkeleyDB::BerkeleyDB PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${BerkeleyDB_INCLUDE_DIR}" + ) + if(MSVC) + if(BerkeleyDB_LIBRARY_DEBUG) + set_property(TARGET BerkeleyDB::BerkeleyDB APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG) + set_target_properties(BerkeleyDB::BerkeleyDB PROPERTIES + IMPORTED_LOCATION_DEBUG "${BerkeleyDB_LIBRARY_DEBUG}" + ) + endif() + if(BerkeleyDB_LIBRARY_RELEASE) + set_property(TARGET BerkeleyDB::BerkeleyDB APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) + set_target_properties(BerkeleyDB::BerkeleyDB PROPERTIES + IMPORTED_LOCATION_RELEASE "${BerkeleyDB_LIBRARY_RELEASE}" + ) + endif() + else() + set_target_properties(BerkeleyDB::BerkeleyDB PROPERTIES + IMPORTED_LOCATION "${BerkeleyDB_LIBRARY}" + ) + endif() +endif() + +mark_as_advanced( + BerkeleyDB_INCLUDE_DIR + BerkeleyDB_LIBRARY + BerkeleyDB_LIBRARY_DEBUG + BerkeleyDB_LIBRARY_RELEASE +) diff --git a/cmake/module/FindMiniUPnPc.cmake b/cmake/module/FindMiniUPnPc.cmake new file mode 100644 index 0000000000000..dd3a223104b1c --- /dev/null +++ b/cmake/module/FindMiniUPnPc.cmake @@ -0,0 +1,84 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +if(NOT MSVC) + include(CrossPkgConfig) + cross_pkg_check_modules(PC_MiniUPnPc QUIET miniupnpc) +endif() + +find_path(MiniUPnPc_INCLUDE_DIR + NAMES miniupnpc/miniupnpc.h + PATHS ${PC_MiniUPnPc_INCLUDE_DIRS} +) + +if(MiniUPnPc_INCLUDE_DIR) + file( + STRINGS "${MiniUPnPc_INCLUDE_DIR}/miniupnpc/miniupnpc.h" version_strings + REGEX "^#define[\t ]+MINIUPNPC_API_VERSION[\t ]+[0-9]+" + ) + string(REGEX REPLACE "^#define[\t ]+MINIUPNPC_API_VERSION[\t ]+([0-9]+)" "\\1" MiniUPnPc_API_VERSION "${version_strings}") + + # The minimum supported miniUPnPc API version is set to 17. This excludes + # versions with known vulnerabilities. + if(MiniUPnPc_API_VERSION GREATER_EQUAL 17) + set(MiniUPnPc_API_VERSION_OK TRUE) + endif() +endif() + +if(MSVC) + cmake_path(GET MiniUPnPc_INCLUDE_DIR PARENT_PATH MiniUPnPc_IMPORTED_PATH) + find_library(MiniUPnPc_LIBRARY_DEBUG + NAMES miniupnpc PATHS ${MiniUPnPc_IMPORTED_PATH}/debug/lib + NO_DEFAULT_PATH + ) + find_library(MiniUPnPc_LIBRARY_RELEASE + NAMES miniupnpc PATHS ${MiniUPnPc_IMPORTED_PATH}/lib + NO_DEFAULT_PATH + ) + set(MiniUPnPc_required MiniUPnPc_IMPORTED_PATH) +else() + find_library(MiniUPnPc_LIBRARY + NAMES miniupnpc + PATHS ${PC_MiniUPnPc_LIBRARY_DIRS} + ) + set(MiniUPnPc_required MiniUPnPc_LIBRARY) +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(MiniUPnPc + REQUIRED_VARS ${MiniUPnPc_required} MiniUPnPc_INCLUDE_DIR MiniUPnPc_API_VERSION_OK +) + +if(MiniUPnPc_FOUND AND NOT TARGET MiniUPnPc::MiniUPnPc) + add_library(MiniUPnPc::MiniUPnPc UNKNOWN IMPORTED) + set_target_properties(MiniUPnPc::MiniUPnPc PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${MiniUPnPc_INCLUDE_DIR}" + ) + if(MSVC) + if(MiniUPnPc_LIBRARY_DEBUG) + set_property(TARGET MiniUPnPc::MiniUPnPc APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG) + set_target_properties(MiniUPnPc::MiniUPnPc PROPERTIES + IMPORTED_LOCATION_DEBUG "${MiniUPnPc_LIBRARY_DEBUG}" + ) + endif() + if(MiniUPnPc_LIBRARY_RELEASE) + set_property(TARGET MiniUPnPc::MiniUPnPc APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) + set_target_properties(MiniUPnPc::MiniUPnPc PROPERTIES + IMPORTED_LOCATION_RELEASE "${MiniUPnPc_LIBRARY_RELEASE}" + ) + endif() + else() + set_target_properties(MiniUPnPc::MiniUPnPc PROPERTIES + IMPORTED_LOCATION "${MiniUPnPc_LIBRARY}" + ) + endif() + set_property(TARGET MiniUPnPc::MiniUPnPc PROPERTY + INTERFACE_COMPILE_DEFINITIONS USE_UPNP=1 $<$:MINIUPNP_STATICLIB> + ) +endif() + +mark_as_advanced( + MiniUPnPc_INCLUDE_DIR + MiniUPnPc_LIBRARY +) diff --git a/cmake/module/FindNATPMP.cmake b/cmake/module/FindNATPMP.cmake new file mode 100644 index 0000000000000..973fb9b0d06cd --- /dev/null +++ b/cmake/module/FindNATPMP.cmake @@ -0,0 +1,32 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +find_path(NATPMP_INCLUDE_DIR + NAMES natpmp.h +) + +find_library(NATPMP_LIBRARY + NAMES natpmp +) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(NATPMP + REQUIRED_VARS NATPMP_LIBRARY NATPMP_INCLUDE_DIR +) + +if(NATPMP_FOUND AND NOT TARGET NATPMP::NATPMP) + add_library(NATPMP::NATPMP UNKNOWN IMPORTED) + set_target_properties(NATPMP::NATPMP PROPERTIES + IMPORTED_LOCATION "${NATPMP_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${NATPMP_INCLUDE_DIR}" + ) + set_property(TARGET NATPMP::NATPMP PROPERTY + INTERFACE_COMPILE_DEFINITIONS USE_NATPMP=1 $<$:NATPMP_STATICLIB> + ) +endif() + +mark_as_advanced( + NATPMP_INCLUDE_DIR + NATPMP_LIBRARY +) diff --git a/cmake/module/GenerateHeaders.cmake b/cmake/module/GenerateHeaders.cmake new file mode 100644 index 0000000000000..d8714771b4f6d --- /dev/null +++ b/cmake/module/GenerateHeaders.cmake @@ -0,0 +1,21 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +function(generate_header_from_json json_source_relpath) + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${json_source_relpath}.h + COMMAND ${CMAKE_COMMAND} -DJSON_SOURCE_PATH=${CMAKE_CURRENT_SOURCE_DIR}/${json_source_relpath} -DHEADER_PATH=${CMAKE_CURRENT_BINARY_DIR}/${json_source_relpath}.h -P ${CMAKE_SOURCE_DIR}/cmake/script/GenerateHeaderFromJson.cmake + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${json_source_relpath} ${CMAKE_SOURCE_DIR}/cmake/script/GenerateHeaderFromJson.cmake + VERBATIM + ) +endfunction() + +function(generate_header_from_raw raw_source_relpath) + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${raw_source_relpath}.h + COMMAND ${CMAKE_COMMAND} -DRAW_SOURCE_PATH=${CMAKE_CURRENT_SOURCE_DIR}/${raw_source_relpath} -DHEADER_PATH=${CMAKE_CURRENT_BINARY_DIR}/${raw_source_relpath}.h -P ${CMAKE_SOURCE_DIR}/cmake/script/GenerateHeaderFromRaw.cmake + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${raw_source_relpath} ${CMAKE_SOURCE_DIR}/cmake/script/GenerateHeaderFromRaw.cmake + VERBATIM + ) +endfunction() diff --git a/cmake/module/ProcessConfigurations.cmake b/cmake/module/ProcessConfigurations.cmake new file mode 100644 index 0000000000000..99b6959171f06 --- /dev/null +++ b/cmake/module/ProcessConfigurations.cmake @@ -0,0 +1,132 @@ +# 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}) + list(PREPEND all_configs ${config}) + + 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() diff --git a/cmake/module/TristateOption.cmake b/cmake/module/TristateOption.cmake new file mode 100644 index 0000000000000..1bff5bd14aeb2 --- /dev/null +++ b/cmake/module/TristateOption.cmake @@ -0,0 +1,21 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# A tri-state option with three possible values: AUTO, OFF and ON (case-insensitive). +# TODO: This function will be removed before merging into master. +function(tristate_option variable description_text auto_means_on_condition_text default_value) + set(${variable} ${default_value} CACHE STRING + "${description_text} \"AUTO\" means \"ON\" ${auto_means_on_condition_text}" + ) + + set(expected_values AUTO OFF ON) + set_property(CACHE ${variable} PROPERTY STRINGS ${expected_values}) + + string(TOUPPER "${${variable}}" value) + if(NOT value IN_LIST expected_values) + message(FATAL_ERROR "${variable} value is \"${${variable}}\", but must be one of \"AUTO\", \"OFF\" or \"ON\".") + endif() + + set(${${variable}} ${value} PARENT_SCOPE) +endfunction() 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) diff --git a/cmake/module/TryAppendLinkerFlag.cmake b/cmake/module/TryAppendLinkerFlag.cmake new file mode 100644 index 0000000000000..5d22f940d34bf --- /dev/null +++ b/cmake/module/TryAppendLinkerFlag.cmake @@ -0,0 +1,77 @@ +# 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() + + set(CMAKE_REQUIRED_LINK_OPTIONS ${flag} ${working_linker_werror_flag}) + + 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) diff --git a/cmake/optional.cmake b/cmake/optional.cmake new file mode 100644 index 0000000000000..4ad779380cf4f --- /dev/null +++ b/cmake/optional.cmake @@ -0,0 +1,183 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# Optional features and packages. + +if(CCACHE) + find_program(CCACHE_COMMAND ccache) + if(CCACHE_COMMAND) + if(MSVC) + if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.24) + # ccache >= 4.8 requires compile batching turned off that is available since CMake 3.24. + # See https://github.com/ccache/ccache/wiki/MS-Visual-Studio + set(CCACHE ON) + set(MSVC_CCACHE_WRAPPER_CONTENT "\"${CCACHE_COMMAND}\" \"${CMAKE_CXX_COMPILER}\"") + set(MSVC_CCACHE_WRAPPER_FILENAME wrapped-cl.bat) + file(WRITE ${CMAKE_BINARY_DIR}/${MSVC_CCACHE_WRAPPER_FILENAME} "${MSVC_CCACHE_WRAPPER_CONTENT} %*") + list(APPEND CMAKE_VS_GLOBALS + "CLToolExe=${MSVC_CCACHE_WRAPPER_FILENAME}" + "CLToolPath=${CMAKE_BINARY_DIR}" + "DebugInformationFormat=OldStyle" + ) + set(CMAKE_VS_NO_COMPILE_BATCHING ON) + elseif(CCACHE STREQUAL "AUTO") + message(WARNING "ccache requested and found, but CMake >= 3.24 is required to use it properly. Disabling.\n" + "To skip ccache check, use \"-DCCACHE=OFF\".\n") + set(CCACHE OFF) + else() + message(FATAL_ERROR "ccache requested and found, but CMake >= 3.24 is required to use it properly.") + endif() + else() + set(CCACHE ON) + list(APPEND CMAKE_C_COMPILER_LAUNCHER ${CCACHE_COMMAND}) + list(APPEND CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE_COMMAND}) + endif() + elseif(CCACHE STREQUAL "AUTO") + set(CCACHE OFF) + else() + message(FATAL_ERROR "ccache requested, but not found.") + endif() + mark_as_advanced(CCACHE_COMMAND) +endif() + +if(WITH_NATPMP) + find_package(NATPMP MODULE) + if(NATPMP_FOUND) + set(WITH_NATPMP ON) + elseif(WITH_NATPMP STREQUAL "AUTO") + message(WARNING "libnatpmp not found, disabling.\n" + "To skip libnatpmp check, use \"-DWITH_NATPMP=OFF\".\n") + set(WITH_NATPMP OFF) + else() + message(FATAL_ERROR "libnatpmp requested, but not found.") + endif() +endif() + +if(WITH_MINIUPNPC) + find_package(MiniUPnPc MODULE) + if(MiniUPnPc_FOUND) + set(WITH_MINIUPNPC ON) + elseif(WITH_MINIUPNPC STREQUAL "AUTO") + message(WARNING "libminiupnpc not found, disabling.\n" + "To skip libminiupnpc check, use \"-DWITH_MINIUPNPC=OFF\".\n") + set(WITH_MINIUPNPC OFF) + else() + message(FATAL_ERROR "libminiupnpc requested, but not found.") + endif() +endif() + +if(WITH_ZMQ) + if(MSVC) + find_package(ZeroMQ CONFIG) + else() + # The ZeroMQ project has provided config files since v4.2.2. + # TODO: Switch to find_package(ZeroMQ) at some point in the future. + include(CrossPkgConfig) + cross_pkg_check_modules(libzmq IMPORTED_TARGET libzmq>=4) + if(libzmq_FOUND AND TARGET PkgConfig::libzmq) + target_compile_definitions(PkgConfig::libzmq INTERFACE + $<$:ZMQ_STATIC> + ) + target_link_libraries(PkgConfig::libzmq INTERFACE + $<$:iphlpapi;ws2_32> + ) + endif() + endif() + if(TARGET libzmq OR TARGET PkgConfig::libzmq) + set(WITH_ZMQ ON) + elseif(WITH_ZMQ STREQUAL "AUTO") + message(WARNING "libzmq not found, disabling.\n" + "To skip libzmq check, use \"-DWITH_ZMQ=OFF\".\n") + set(WITH_ZMQ OFF) + else() + message(FATAL_ERROR "libzmq requested, but not found.") + endif() +endif() + +if(WITH_USDT) + find_path(SystemTap_INCLUDE_DIR + NAMES sys/sdt.h + ) + mark_as_advanced(SystemTap_INCLUDE_DIR) + + if(SystemTap_INCLUDE_DIR) + include(CMakePushCheckState) + cmake_push_check_state(RESET) + + include(CheckCXXSourceCompiles) + set(CMAKE_REQUIRED_INCLUDES ${SystemTap_INCLUDE_DIR}) + check_cxx_source_compiles(" + #include + + int main() + { + DTRACE_PROBE(context, event); + int a, b, c, d, e, f, g; + DTRACE_PROBE7(context, event, a, b, c, d, e, f, g); + } + " HAVE_USDT_H + ) + + cmake_pop_check_state() + endif() + + if(HAVE_USDT_H) + target_include_directories(core INTERFACE + ${SystemTap_INCLUDE_DIR} + ) + set(ENABLE_TRACING TRUE) + set(WITH_USDT ON) + elseif(WITH_USDT STREQUAL "AUTO") + set(WITH_USDT OFF) + else() + message(FATAL_ERROR "sys/sdt.h requested, but not found.") + endif() +endif() + +if(ENABLE_WALLET) + if(WITH_SQLITE) + # TODO: Consider using the FindSQLite3 module after bumping + # the minimum required CMake version up to 3.14+. + if(MSVC) + # Use of the `unofficial::` namespace is a vcpkg package manager convention. + find_package(unofficial-sqlite3 CONFIG) + else() + include(CrossPkgConfig) + cross_pkg_check_modules(sqlite3 sqlite3>=3.7.17 IMPORTED_TARGET) + endif() + if(TARGET unofficial::sqlite3::sqlite3 OR TARGET PkgConfig::sqlite3) + set(WITH_SQLITE ON) + set(USE_SQLITE ON) + elseif(WITH_SQLITE STREQUAL "AUTO") + set(WITH_SQLITE OFF) + else() + message(FATAL_ERROR "SQLite requested, but not found.") + endif() + endif() + + if(WITH_BDB) + find_package(BerkeleyDB 4.8 MODULE) + if(BerkeleyDB_FOUND) + set(WITH_BDB ON) + set(USE_BDB ON) + if(NOT BerkeleyDB_VERSION VERSION_EQUAL 4.8) + message(WARNING "Found Berkeley DB (BDB) other than 4.8.") + if(WARN_INCOMPATIBLE_BDB) + message(WARNING "BDB (legacy) wallets opened by this build would not be portable!\n" + "If this is intended, pass \"-DWARN_INCOMPATIBLE_BDB=OFF\".\n" + "Passing \"-DWITH_BDB=OFF\" will suppress this warning.\n") + else() + message(WARNING "BDB (legacy) wallets opened by this build will not be portable!") + endif() + endif() + else() + message(WARNING "Berkeley DB (BDB) required for legacy wallet support, but not found.\n" + "Passing \"-DWITH_BDB=OFF\" will suppress this warning.\n") + set(WITH_BDB OFF) + endif() + endif() +else() + set(WITH_SQLITE OFF) + set(WITH_BDB OFF) +endif() diff --git a/cmake/script/GenerateHeaderFromJson.cmake b/cmake/script/GenerateHeaderFromJson.cmake new file mode 100644 index 0000000000000..c13c9b1d40b7d --- /dev/null +++ b/cmake/script/GenerateHeaderFromJson.cmake @@ -0,0 +1,24 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +file(READ ${JSON_SOURCE_PATH} hex_content HEX) +string(REGEX MATCHALL "([A-Za-z0-9][A-Za-z0-9])" bytes "${hex_content}") + +file(WRITE ${HEADER_PATH} "#include \n") +file(APPEND ${HEADER_PATH} "namespace json_tests{\n") +get_filename_component(json_source_basename ${JSON_SOURCE_PATH} NAME_WE) +file(APPEND ${HEADER_PATH} "static const std::string ${json_source_basename}{\n") + +set(i 0) +foreach(byte ${bytes}) + math(EXPR i "${i} + 1") + math(EXPR remainder "${i} % 8") + if(remainder EQUAL 0) + file(APPEND ${HEADER_PATH} "0x${byte},\n") + else() + file(APPEND ${HEADER_PATH} "0x${byte}, ") + endif() +endforeach() + +file(APPEND ${HEADER_PATH} "\n};};") diff --git a/cmake/script/GenerateHeaderFromRaw.cmake b/cmake/script/GenerateHeaderFromRaw.cmake new file mode 100644 index 0000000000000..82a3a3c3a3199 --- /dev/null +++ b/cmake/script/GenerateHeaderFromRaw.cmake @@ -0,0 +1,22 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +file(READ ${RAW_SOURCE_PATH} hex_content HEX) +string(REGEX MATCHALL "([A-Za-z0-9][A-Za-z0-9])" bytes "${hex_content}") + +get_filename_component(raw_source_basename ${RAW_SOURCE_PATH} NAME_WE) +file(WRITE ${HEADER_PATH} "static unsigned const char ${raw_source_basename}_raw[] = {\n") + +set(i 0) +foreach(byte ${bytes}) + math(EXPR i "${i} + 1") + math(EXPR remainder "${i} % 8") + if(remainder EQUAL 0) + file(APPEND ${HEADER_PATH} "0x${byte},\n") + else() + file(APPEND ${HEADER_PATH} "0x${byte}, ") + endif() +endforeach() + +file(APPEND ${HEADER_PATH} "\n};") diff --git a/cmake/secp256k1.cmake b/cmake/secp256k1.cmake new file mode 100644 index 0000000000000..d6c85a5400f24 --- /dev/null +++ b/cmake/secp256k1.cmake @@ -0,0 +1,56 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# This file is part of the transition from Autotools to CMake. Once CMake +# support has been merged we should switch to using the upstream CMake +# buildsystem. + +enable_language(C) +set(CMAKE_C_STANDARD 90) +set(CMAKE_C_EXTENSIONS OFF) + +if(ASM) + include(CheckCSourceCompiles) + check_c_source_compiles(" + #include + + int main() + { + uint64_t a = 11, tmp; + __asm__ __volatile__(\"movq $0x100000000,%1; mulq %%rsi\" : \"+a\"(a) : \"S\"(tmp) : \"cc\", \"%rdx\"); + } + " HAVE_64BIT_ASM + ) +endif() + +add_library(secp256k1 STATIC EXCLUDE_FROM_ALL + ${PROJECT_SOURCE_DIR}/src/secp256k1/src/secp256k1.c + ${PROJECT_SOURCE_DIR}/src/secp256k1/src/precomputed_ecmult.c + ${PROJECT_SOURCE_DIR}/src/secp256k1/src/precomputed_ecmult_gen.c +) + +target_compile_definitions(secp256k1 + PRIVATE + ECMULT_GEN_PREC_BITS=4 + ECMULT_WINDOW_SIZE=15 + ENABLE_MODULE_RECOVERY + ENABLE_MODULE_SCHNORRSIG + ENABLE_MODULE_EXTRAKEYS + ENABLE_MODULE_ELLSWIFT + $<$:USE_ASM_X86_64=1> + INTERFACE + $<$:SECP256K1_STATIC> +) + +target_include_directories(secp256k1 + PUBLIC + $ +) + +target_compile_options(secp256k1 + PRIVATE + $<$:/wd4146 /wd4334> +) + +target_link_libraries(secp256k1 PRIVATE core) diff --git a/cmake/tests.cmake b/cmake/tests.cmake new file mode 100644 index 0000000000000..598af496387d2 --- /dev/null +++ b/cmake/tests.cmake @@ -0,0 +1,55 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +include(CTest) + +if(TARGET bitcoin-util AND TARGET bitcoin-tx) + add_test(NAME util_test_runner + COMMAND ${CMAKE_COMMAND} -E env BITCOINUTIL=$ BITCOINTX=$ ${PYTHON_COMMAND} ${CMAKE_BINARY_DIR}/test/util/test_runner.py + ) +endif() + +add_test(NAME util_rpcauth_test + COMMAND ${PYTHON_COMMAND} ${CMAKE_BINARY_DIR}/test/util/rpcauth-test.py +) + +if(TARGET bench_bitcoin) + add_test(NAME bench_sanity_check_high_priority + COMMAND bench_bitcoin -sanity-check -priority-level=high + ) +endif() + +if(TARGET test_bitcoin) + function(add_boost_test source_dir source_file) + set(source_file_path ${source_dir}/${source_file}) + if(NOT EXISTS ${source_file_path}) + return() + endif() + + file(READ "${source_file_path}" source_file_content) + string(REGEX + MATCH "(BOOST_FIXTURE_TEST_SUITE|BOOST_AUTO_TEST_SUITE)\\(([A-Za-z0-9_]+)" + test_suite_macro "${source_file_content}" + ) + string(REGEX + REPLACE "(BOOST_FIXTURE_TEST_SUITE|BOOST_AUTO_TEST_SUITE)\\(" "" + test_suite_name "${test_suite_macro}" + ) + if(test_suite_name) + add_test(NAME ${test_suite_name}:${source_file} + COMMAND test_bitcoin --run_test=${test_suite_name} --catch_system_error=no + ) + endif() + endfunction() + + function(add_all_test_targets) + get_target_property(test_source_dir test_bitcoin SOURCE_DIR) + get_target_property(test_sources test_bitcoin SOURCES) + foreach(test_source ${test_sources}) + add_boost_test(${test_source_dir} ${test_source}) + endforeach() + endfunction() + + add_all_test_targets() +endif() diff --git a/depends/Makefile b/depends/Makefile index 3169117633503..ab17e43631fa4 100644 --- a/depends/Makefile +++ b/depends/Makefile @@ -191,6 +191,7 @@ $(host_arch)_$(host_os)_native_toolchain?=$($(host_os)_native_toolchain) include funcs.mk final_build_id_long+=$(shell $(build_SHA256SUM) config.site.in) +final_build_id_long+=$(shell $(build_SHA256SUM) toolchain.cmake.in) final_build_id+=$(shell echo -n "$(final_build_id_long)" | $(build_SHA256SUM) | cut -c-$(HASH_LENGTH)) $(host_prefix)/.stamp_$(final_build_id): $(native_packages) $(packages) rm -rf $(@D) @@ -259,6 +260,34 @@ $(host_prefix)/share/config.site : config.site.in $(host_prefix)/.stamp_$(final_ $< > $@ touch $@ +$(host_prefix)/share/toolchain.cmake : toolchain.cmake.in $(host_prefix)/.stamp_$(final_build_id) + @mkdir -p $(@D) + sed -e 's|@host_system@|$($(host_os)_cmake_system)|' \ + -e 's|@host_arch@|$(host_arch)|' \ + -e 's|@CC@|$(host_CC)|' \ + -e 's|@CXX@|$(host_CXX)|' \ + -e 's|@AR@|$(host_AR)|' \ + -e 's|@RANLIB@|$(host_RANLIB)|' \ + -e 's|@STRIP@|$(host_STRIP)|' \ + -e 's|@OBJCOPY@|$(host_OBJCOPY)|' \ + -e 's|@INSTALL_NAME_TOOL@|$(host_INSTALL_NAME_TOOL)|' \ + -e 's|@OTOOL@|$(host_OTOOL)|' \ + -e 's|@depends_prefix@|$(host_prefix)|' \ + -e 's|@CFLAGS@|$(strip $(host_CFLAGS) $(host_$(release_type)_CFLAGS))|' \ + -e 's|@CXXFLAGS@|$(strip $(host_CXXFLAGS) $(host_$(release_type)_CXXFLAGS))|' \ + -e 's|@CPPFLAGS@|$(strip $(host_CPPFLAGS) $(host_$(release_type)_CPPFLAGS))|' \ + -e 's|@allow_host_packages@|$(ALLOW_HOST_PACKAGES)|' \ + -e 's|@no_qt@|$(NO_QT)|' \ + -e 's|@no_qr@|$(NO_QR)|' \ + -e 's|@no_zmq@|$(NO_ZMQ)|' \ + -e 's|@no_wallet@|$(NO_WALLET)|' \ + -e 's|@no_bdb@|$(NO_BDB)|' \ + -e 's|@no_sqlite@|$(NO_SQLITE)|' \ + -e 's|@no_upnp@|$(NO_UPNP)|' \ + -e 's|@no_natpmp@|$(NO_NATPMP)|' \ + -e 's|@no_usdt@|$(NO_USDT)|' \ + $< > $@ + touch $@ define check_or_remove_cached mkdir -p $(BASE_CACHE)/$(host)/$(package) && cd $(BASE_CACHE)/$(host)/$(package); \ @@ -280,6 +309,7 @@ check-sources: @$(foreach package,$(all_packages),$(call check_or_remove_sources,$(package));) $(host_prefix)/share/config.site: check-packages +$(host_prefix)/share/toolchain.cmake: check-packages check-packages: check-sources @@ -289,7 +319,7 @@ clean-all: clean clean: @rm -rf $(WORK_PATH) $(BASE_CACHE) $(BUILD) *.log -install: check-packages $(host_prefix)/share/config.site +install: check-packages $(host_prefix)/share/config.site $(host_prefix)/share/toolchain.cmake download-one: check-sources $(all_sources) diff --git a/depends/toolchain.cmake.in b/depends/toolchain.cmake.in new file mode 100644 index 0000000000000..27949803299e8 --- /dev/null +++ b/depends/toolchain.cmake.in @@ -0,0 +1,133 @@ +# This file is expected to be highly volatile and may still change substantially. + +set(CMAKE_SYSTEM_NAME @host_system@) +set(CMAKE_SYSTEM_PROCESSOR @host_arch@) + +function(split_compiler_launcher env_compiler launcher compiler) + set(${launcher}) + list(GET ${env_compiler} 0 start_token) + if(start_token STREQUAL "env") + set(${compiler}) + set(env_arg_parsing TRUE) + foreach(token IN LISTS ${env_compiler}) + if(env_arg_parsing) + list(APPEND ${launcher} ${token}) + set(env_arg_parsing FALSE) + continue() + elseif(token STREQUAL "-u") + list(APPEND ${launcher} ${token}) + set(env_arg_parsing TRUE) + continue() + endif() + list(APPEND ${compiler} ${token}) + endforeach() + else() + set(${compiler} ${${env_compiler}}) + endif() + set(${launcher} ${${launcher}} PARENT_SCOPE) + set(${compiler} ${${compiler}} PARENT_SCOPE) +endfunction() + +if(NOT CMAKE_C_COMPILER) + set(DEPENDS_C_COMPILER_WITH_LAUNCHER @CC@) + split_compiler_launcher(DEPENDS_C_COMPILER_WITH_LAUNCHER CMAKE_C_COMPILER_LAUNCHER CMAKE_C_COMPILER) + if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.21) + set(CMAKE_C_LINKER_LAUNCHER ${CMAKE_C_COMPILER_LAUNCHER}) + endif() + if(CMAKE_VERSION VERSION_LESS 3.19) + set(mandatory_c_compiler_flags ${CMAKE_C_COMPILER}) + list(REMOVE_AT mandatory_c_compiler_flags 0) + list(JOIN mandatory_c_compiler_flags " " mandatory_c_compiler_flags) + set(CMAKE_C_FLAGS_INIT ${CMAKE_C_FLAGS_INIT} ${mandatory_c_compiler_flags}) + list(GET CMAKE_C_COMPILER 0 CMAKE_C_COMPILER) + endif() + set(DEPENDS_C_COMPILER_FLAGS @CFLAGS@) +endif() + +if(NOT CMAKE_CXX_COMPILER) + set(DEPENDS_CXX_COMPILER_WITH_LAUNCHER @CXX@) + split_compiler_launcher(DEPENDS_CXX_COMPILER_WITH_LAUNCHER CMAKE_CXX_COMPILER_LAUNCHER CMAKE_CXX_COMPILER) + if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.21) + set(CMAKE_CXX_LINKER_LAUNCHER ${CMAKE_CXX_COMPILER_LAUNCHER}) + endif() + if(CMAKE_VERSION VERSION_LESS 3.19) + # Handle CXX='clang++ -stdlib=libc++' properly. + # See: https://gitlab.kitware.com/cmake/cmake/-/merge_requests/4136. + set(mandatory_cxx_compiler_flags ${CMAKE_CXX_COMPILER}) + list(REMOVE_AT mandatory_cxx_compiler_flags 0) + list(JOIN mandatory_cxx_compiler_flags " " mandatory_cxx_compiler_flags) + set(CMAKE_CXX_FLAGS_INIT ${CMAKE_CXX_FLAGS_INIT} ${mandatory_cxx_compiler_flags}) + set(CMAKE_EXE_LINKER_FLAGS_INIT ${CMAKE_EXE_LINKER_FLAGS_INIT} ${mandatory_cxx_compiler_flags}) + list(GET CMAKE_CXX_COMPILER 0 CMAKE_CXX_COMPILER) + endif() + set(DEPENDS_CXX_COMPILER_FLAGS @CXXFLAGS@) + + 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(DEPENDS_COMPILE_DEFINITIONS @CPPFLAGS@) + +set(CMAKE_AR "@AR@") +set(CMAKE_RANLIB "@RANLIB@") +set(CMAKE_STRIP "@STRIP@") +set(CMAKE_OBJCOPY "@OBJCOPY@") +set(CMAKE_INSTALL_NAME_TOOL "@INSTALL_NAME_TOOL@") +set(OTOOL "@OTOOL@") + +set(CMAKE_FIND_ROOT_PATH "@depends_prefix@") +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) +set(PKG_CONFIG_PATH "@depends_prefix@/lib/pkgconfig") +if("@allow_host_packages@" STREQUAL "1") + set(DEPENDS_ALLOW_HOST_PACKAGES TRUE) +else() + set(DEPENDS_ALLOW_HOST_PACKAGES FALSE) + set(PKG_CONFIG_LIBDIR "${PKG_CONFIG_PATH}") +endif() +set(QT_TRANSLATIONS_DIR "@depends_prefix@/translations") + +if(NOT WITH_GUI AND "@no_qt@" STREQUAL "1") + set(WITH_GUI "no" CACHE STRING "") +endif() + +if(NOT WITH_QRENCODE AND "@no_qr@" STREQUAL "1") + set(WITH_QRENCODE OFF CACHE STRING "") +endif() + +if(NOT WITH_ZMQ AND "@no_zmq@" STREQUAL "1") + set(WITH_ZMQ OFF CACHE STRING "") +endif() + +if(NOT ENABLE_WALLET AND "@no_wallet@" STREQUAL "1") + set(ENABLE_WALLET OFF CACHE BOOL "") +endif() + +if(NOT WITH_BDB AND "@no_bdb@" STREQUAL "1") + set(WITH_BDB OFF CACHE STRING "") +endif() + +if(NOT WITH_SQLITE AND "@no_sqlite@" STREQUAL "1") + set(WITH_SQLITE OFF CACHE STRING "") +endif() + +if(NOT WITH_MINIUPNPC AND "@no_upnp@" STREQUAL "1") + set(WITH_MINIUPNPC OFF CACHE STRING "") +endif() + +if(NOT WITH_NATPMP AND "@no_natpmp@" STREQUAL "1") + set(WITH_NATPMP OFF CACHE STRING "") +endif() + +if(NOT WITH_USDT AND "@no_usdt@" STREQUAL "1") + set(WITH_USDT OFF CACHE STRING "") +endif() + +if(DEFINED ENV{PYTHONPATH}) + set(PYTHONPATH "@depends_prefix@/native/lib/python3/dist-packages:$ENV{PYTHONPATH}") +else() + set(PYTHONPATH "@depends_prefix@/native/lib/python3/dist-packages") +endif() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000000000..26366d8e628b0 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,304 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +configure_file(${CMAKE_SOURCE_DIR}/cmake/bitcoin-config.h.in config/bitcoin-config.h @ONLY) +add_compile_definitions(HAVE_CONFIG_H) +include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) + +add_subdirectory(crypto) +add_subdirectory(univalue) +add_subdirectory(util) + + +# Stable, backwards-compatible consensus functionality +# also exposed as a shared library and/or a static one. +add_library(bitcoin_consensus OBJECT EXCLUDE_FROM_ALL + arith_uint256.cpp + consensus/merkle.cpp + consensus/tx_check.cpp + hash.cpp + primitives/block.cpp + primitives/transaction.cpp + pubkey.cpp + script/interpreter.cpp + script/script.cpp + script/script_error.cpp + uint256.cpp + util/strencodings.cpp +) +target_link_libraries(bitcoin_consensus + PRIVATE + core + secp256k1 +) + +if(WITH_ZMQ) + add_subdirectory(zmq EXCLUDE_FROM_ALL) +endif() + +# Home for common functionality shared by different executables and libraries. +# Similar to `bitcoin_util` library, but higher-level. +add_library(bitcoin_common STATIC EXCLUDE_FROM_ALL + addresstype.cpp + base58.cpp + bech32.cpp + chainparams.cpp + coins.cpp + common/args.cpp + common/bloom.cpp + common/config.cpp + common/init.cpp + common/interfaces.cpp + common/run_command.cpp + common/settings.cpp + common/system.cpp + $<$:common/url.cpp> + compressor.cpp + core_read.cpp + core_write.cpp + deploymentinfo.cpp + external_signer.cpp + init/common.cpp + kernel/chainparams.cpp + key.cpp + key_io.cpp + merkleblock.cpp + net_types.cpp + netaddress.cpp + netbase.cpp + net_permissions.cpp + outputtype.cpp + policy/feerate.cpp + policy/policy.cpp + protocol.cpp + psbt.cpp + rpc/rawtransaction_util.cpp + rpc/request.cpp + rpc/external_signer.cpp + rpc/util.cpp + scheduler.cpp + script/descriptor.cpp + script/miniscript.cpp + script/sign.cpp + script/signingprovider.cpp + script/solver.cpp + warnings.cpp +) +target_compile_definitions(bitcoin_common + PRIVATE + ${THREAD_LOCAL_IF_AVAILABLE} +) +target_link_libraries(bitcoin_common + PRIVATE + core + bitcoin_consensus + bitcoin_util + univalue + secp256k1 + Boost::headers + $ +) + + +if(ENABLE_WALLET) + add_subdirectory(wallet) + + if(BUILD_WALLET_TOOL) + add_executable(bitcoin-wallet + bitcoin-wallet.cpp + init/bitcoin-wallet.cpp + wallet/wallettool.cpp + ) + target_link_libraries(bitcoin-wallet + core + bitcoin_wallet + bitcoin_common + bitcoin_util + Boost::headers + ) + endif() +endif() + + +# P2P and RPC server functionality used by `bitcoind` and `bitcoin-qt` executables. +add_library(bitcoin_node STATIC EXCLUDE_FROM_ALL + addrdb.cpp + addrman.cpp + banman.cpp + bip324.cpp + blockencodings.cpp + blockfilter.cpp + chain.cpp + consensus/tx_verify.cpp + dbwrapper.cpp + deploymentstatus.cpp + flatfile.cpp + headerssync.cpp + httprpc.cpp + httpserver.cpp + i2p.cpp + index/base.cpp + index/blockfilterindex.cpp + index/coinstatsindex.cpp + index/txindex.cpp + init.cpp + kernel/chain.cpp + kernel/checks.cpp + kernel/coinstats.cpp + kernel/context.cpp + kernel/cs_main.cpp + kernel/mempool_persist.cpp + kernel/mempool_removal_reason.cpp + mapport.cpp + net.cpp + net_processing.cpp + netgroup.cpp + node/abort.cpp + node/blockmanager_args.cpp + node/blockstorage.cpp + node/caches.cpp + node/chainstate.cpp + node/chainstatemanager_args.cpp + node/coin.cpp + node/coins_view_args.cpp + node/connection_types.cpp + node/context.cpp + node/database_args.cpp + node/eviction.cpp + node/interface_ui.cpp + node/interfaces.cpp + node/kernel_notifications.cpp + node/mempool_args.cpp + node/mempool_persist_args.cpp + node/miner.cpp + node/mini_miner.cpp + node/minisketchwrapper.cpp + node/peerman_args.cpp + node/psbt.cpp + node/transaction.cpp + node/txreconciliation.cpp + node/utxo_snapshot.cpp + node/validation_cache_args.cpp + noui.cpp + policy/fees.cpp + policy/fees_args.cpp + policy/packages.cpp + policy/rbf.cpp + policy/settings.cpp + pow.cpp + rest.cpp + rpc/blockchain.cpp + rpc/fees.cpp + rpc/mempool.cpp + rpc/mining.cpp + rpc/net.cpp + rpc/node.cpp + rpc/output_script.cpp + rpc/rawtransaction.cpp + rpc/server.cpp + rpc/server_util.cpp + rpc/signmessage.cpp + rpc/txoutproof.cpp + script/sigcache.cpp + shutdown.cpp + signet.cpp + timedata.cpp + torcontrol.cpp + txdb.cpp + txmempool.cpp + txorphanage.cpp + txrequest.cpp + validation.cpp + validationinterface.cpp + versionbits.cpp +) +if(ENABLE_WALLET) + target_sources(bitcoin_node PRIVATE wallet/init.cpp) + target_link_libraries(bitcoin_node PRIVATE bitcoin_wallet) +else() + target_sources(bitcoin_node PRIVATE dummywallet.cpp) +endif() +target_link_libraries(bitcoin_node + PRIVATE + core + bitcoin_common + bitcoin_util + leveldb + minisketch + univalue + Boost::headers + libevent::libevent + $ + $ + $ + $ +) + + +# Bitcoin Core bitcoind. +if(BUILD_DAEMON) + add_executable(bitcoind + bitcoind.cpp + init/bitcoind.cpp + ) + target_link_libraries(bitcoind + core + bitcoin_node + ) +endif() + + +add_library(bitcoin_cli STATIC EXCLUDE_FROM_ALL + compat/stdin.cpp + rpc/client.cpp +) +target_link_libraries(bitcoin_cli + PUBLIC + core + univalue +) + + +# Bitcoin Core RPC client +if(BUILD_CLI) + add_executable(bitcoin-cli bitcoin-cli.cpp) + target_link_libraries(bitcoin-cli + core + bitcoin_cli + bitcoin_common + bitcoin_util + libevent::libevent + ) +endif() + + +if(BUILD_TX) + add_executable(bitcoin-tx bitcoin-tx.cpp) + target_link_libraries(bitcoin-tx + core + bitcoin_common + bitcoin_util + univalue + ) +endif() + + +if(BUILD_UTIL) + add_executable(bitcoin-util bitcoin-util.cpp) + target_link_libraries(bitcoin-util + core + bitcoin_common + bitcoin_util + ) +endif() + + +add_subdirectory(test/util) +if(BUILD_BENCH) + add_subdirectory(bench) +endif() + +if(BUILD_TESTS) + add_subdirectory(test) +endif() diff --git a/src/bench/CMakeLists.txt b/src/bench/CMakeLists.txt new file mode 100644 index 0000000000000..3e9b144c77c70 --- /dev/null +++ b/src/bench/CMakeLists.txt @@ -0,0 +1,69 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +include(GenerateHeaders) +generate_header_from_raw(data/block413567.raw) + +add_executable(bench_bitcoin + bench_bitcoin.cpp + bench.cpp + data.cpp + nanobench.cpp + ${CMAKE_CURRENT_BINARY_DIR}/data/block413567.raw.h +# Benchmarks: + addrman.cpp + base58.cpp + bech32.cpp + bip324_ecdh.cpp + block_assemble.cpp + ccoins_caching.cpp + chacha20.cpp + checkblock.cpp + checkqueue.cpp + crypto_hash.cpp + descriptors.cpp + disconnected_transactions.cpp + duplicate_inputs.cpp + ellswift.cpp + examples.cpp + gcs_filter.cpp + hashpadding.cpp + load_external.cpp + lockedpool.cpp + logging.cpp + mempool_eviction.cpp + mempool_stress.cpp + merkle_root.cpp + peer_eviction.cpp + poly1305.cpp + pool.cpp + prevector.cpp + rollingbloom.cpp + rpc_blockchain.cpp + rpc_mempool.cpp + streams_findbyte.cpp + strencodings.cpp + util_time.cpp + verify_script.cpp + xor.cpp +) + +target_link_libraries(bench_bitcoin + core + test_util + leveldb + univalue + Boost::headers +) + +if(ENABLE_WALLET) + target_sources(bench_bitcoin + PRIVATE + coin_selection.cpp + wallet_balance.cpp + wallet_create_tx.cpp + wallet_loading.cpp + ) + target_link_libraries(bench_bitcoin bitcoin_wallet) +endif() diff --git a/src/crypto/CMakeLists.txt b/src/crypto/CMakeLists.txt new file mode 100644 index 0000000000000..8ac54980de6d4 --- /dev/null +++ b/src/crypto/CMakeLists.txt @@ -0,0 +1,124 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +if(ASM AND NOT MSVC) + # Check for SSE4.1 intrinsics. + set(SSE41_CXXFLAGS -msse4.1) + check_cxx_source_compiles_with_flags("${SSE41_CXXFLAGS}" " + #include + + int main() + { + __m128i l = _mm_set1_epi32(0); + return _mm_extract_epi32(l, 3); + } + " HAVE_SSE41 + ) + + # Check for AVX2 intrinsics. + set(AVX2_CXXFLAGS -mavx -mavx2) + check_cxx_source_compiles_with_flags("${AVX2_CXXFLAGS}" " + #include + + int main() + { + __m256i l = _mm256_set1_epi32(0); + return _mm256_extract_epi32(l, 7); + } + " HAVE_AVX2 + ) + + # Check for x86 SHA-NI intrinsics. + set(X86_SHANI_CXXFLAGS -msse4 -msha) + check_cxx_source_compiles_with_flags("${X86_SHANI_CXXFLAGS}" " + #include + + int main() + { + __m128i i = _mm_set1_epi32(0); + __m128i j = _mm_set1_epi32(1); + __m128i k = _mm_set1_epi32(2); + return _mm_extract_epi32(_mm_sha256rnds2_epu32(i, j, k), 0); + } + " HAVE_X86_SHANI + ) + + # Check for ARMv8 SHA-NI intrinsics. + set(ARM_SHANI_CXXFLAGS -march=armv8-a+crypto) + check_cxx_source_compiles_with_flags("${ARM_SHANI_CXXFLAGS}" " + #include + + int main() + { + uint32x4_t a, b, c; + vsha256h2q_u32(a, b, c); + vsha256hq_u32(a, b, c); + vsha256su0q_u32(a, b); + vsha256su1q_u32(a, b, c); + } + " HAVE_ARM_SHANI + ) +endif() + +include(CheckCXXSymbolExists) +check_cxx_symbol_exists(timingsafe_bcmp "string.h" HAVE_TIMINGSAFE_BCMP) + +# The `bitcoin_crypto` must be of an `OBJECT` type to include +# its object files into the output static library archives. +add_library(bitcoin_crypto OBJECT EXCLUDE_FROM_ALL + $<$:sha256_sse4.cpp> + aes.cpp + chacha20.cpp + chacha20poly1305.cpp + hkdf_sha256_32.cpp + hmac_sha256.cpp + hmac_sha512.cpp + poly1305.cpp + muhash.cpp + ripemd160.cpp + sha1.cpp + sha256.cpp + sha3.cpp + sha512.cpp + siphash.cpp +) +target_compile_definitions(bitcoin_crypto + PRIVATE + $<$:USE_ASM> + $<$:ENABLE_SSE41> + $<$:ENABLE_AVX2> + $<$:ENABLE_X86_SHANI> + $<$:ENABLE_ARM_SHANI> + $<$:HAVE_TIMINGSAFE_BCMP> +) + +if(HAVE_SSE41) + target_sources(bitcoin_crypto PRIVATE sha256_sse41.cpp) + set_property(SOURCE sha256_sse41.cpp + APPEND PROPERTY COMPILE_OPTIONS ${SSE41_CXXFLAGS} + ) +endif() + +if(HAVE_AVX2) + target_sources(bitcoin_crypto PRIVATE sha256_avx2.cpp) + set_property(SOURCE sha256_avx2.cpp + APPEND PROPERTY COMPILE_OPTIONS ${AVX2_CXXFLAGS} + ) +endif() + +if(HAVE_X86_SHANI) + target_sources(bitcoin_crypto PRIVATE sha256_x86_shani.cpp) + set_property(SOURCE sha256_x86_shani.cpp + APPEND PROPERTY COMPILE_OPTIONS ${X86_SHANI_CXXFLAGS} + ) +endif() + +if(HAVE_ARM_SHANI) + target_sources(bitcoin_crypto PRIVATE sha256_arm_shani.cpp) + set_property(SOURCE sha256_arm_shani.cpp + 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 new file mode 100644 index 0000000000000..eb3969672c3d3 --- /dev/null +++ b/src/test/CMakeLists.txt @@ -0,0 +1,176 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +include(GenerateHeaders) +generate_header_from_json(data/base58_encode_decode.json) +generate_header_from_json(data/bip341_wallet_vectors.json) +generate_header_from_json(data/blockfilters.json) +generate_header_from_json(data/key_io_invalid.json) +generate_header_from_json(data/key_io_valid.json) +generate_header_from_json(data/script_tests.json) +generate_header_from_json(data/sighash.json) +generate_header_from_json(data/tx_invalid.json) +generate_header_from_json(data/tx_valid.json) +generate_header_from_raw(data/asmap.raw) + +add_executable(test_bitcoin + main.cpp + $ + ${CMAKE_CURRENT_BINARY_DIR}/data/asmap.raw.h + ${CMAKE_CURRENT_BINARY_DIR}/data/base58_encode_decode.json.h + ${CMAKE_CURRENT_BINARY_DIR}/data/bip341_wallet_vectors.json.h + ${CMAKE_CURRENT_BINARY_DIR}/data/blockfilters.json.h + ${CMAKE_CURRENT_BINARY_DIR}/data/key_io_invalid.json.h + ${CMAKE_CURRENT_BINARY_DIR}/data/key_io_valid.json.h + ${CMAKE_CURRENT_BINARY_DIR}/data/script_tests.json.h + ${CMAKE_CURRENT_BINARY_DIR}/data/sighash.json.h + ${CMAKE_CURRENT_BINARY_DIR}/data/tx_invalid.json.h + ${CMAKE_CURRENT_BINARY_DIR}/data/tx_valid.json.h +# Tests: + addrman_tests.cpp + allocator_tests.cpp + amount_tests.cpp + argsman_tests.cpp + arith_uint256_tests.cpp + banman_tests.cpp + base32_tests.cpp + base58_tests.cpp + base64_tests.cpp + bech32_tests.cpp + bip32_tests.cpp + bip324_tests.cpp + blockchain_tests.cpp + blockencodings_tests.cpp + blockfilter_index_tests.cpp + blockfilter_tests.cpp + blockmanager_tests.cpp + bloom_tests.cpp + bswap_tests.cpp + checkqueue_tests.cpp + coins_tests.cpp + coinstatsindex_tests.cpp + compilerbug_tests.cpp + compress_tests.cpp + crypto_tests.cpp + cuckoocache_tests.cpp + dbwrapper_tests.cpp + denialofservice_tests.cpp + descriptor_tests.cpp + flatfile_tests.cpp + fs_tests.cpp + getarg_tests.cpp + hash_tests.cpp + headers_sync_chainwork_tests.cpp + httpserver_tests.cpp + i2p_tests.cpp + interfaces_tests.cpp + key_io_tests.cpp + key_tests.cpp + logging_tests.cpp + mempool_tests.cpp + merkle_tests.cpp + merkleblock_tests.cpp + miner_tests.cpp + miniminer_tests.cpp + miniscript_tests.cpp + minisketch_tests.cpp + multisig_tests.cpp + net_peer_eviction_tests.cpp + net_tests.cpp + netbase_tests.cpp + orphanage_tests.cpp + pmt_tests.cpp + policy_fee_tests.cpp + policyestimator_tests.cpp + pool_tests.cpp + pow_tests.cpp + prevector_tests.cpp + raii_event_tests.cpp + random_tests.cpp + rbf_tests.cpp + rest_tests.cpp + result_tests.cpp + reverselock_tests.cpp + rpc_tests.cpp + sanity_tests.cpp + scheduler_tests.cpp + script_p2sh_tests.cpp + script_parse_tests.cpp + script_segwit_tests.cpp + script_standard_tests.cpp + script_tests.cpp + scriptnum_tests.cpp + serfloat_tests.cpp + serialize_tests.cpp + settings_tests.cpp + sighash_tests.cpp + sigopcount_tests.cpp + skiplist_tests.cpp + sock_tests.cpp + streams_tests.cpp + sync_tests.cpp + system_tests.cpp + timedata_tests.cpp + torcontrol_tests.cpp + transaction_tests.cpp + translation_tests.cpp + txindex_tests.cpp + txpackage_tests.cpp + txreconciliation_tests.cpp + txrequest_tests.cpp + txvalidation_tests.cpp + txvalidationcache_tests.cpp + uint256_tests.cpp + util_tests.cpp + util_threadnames_tests.cpp + validation_block_tests.cpp + validation_chainstate_tests.cpp + validation_chainstatemanager_tests.cpp + validation_flush_tests.cpp + validation_tests.cpp + validationinterface_tests.cpp + versionbits_tests.cpp + xoroshiro128plusplus_tests.cpp +) + +target_link_libraries(test_bitcoin + core + test_util + bitcoin_cli + bitcoin_node + bitcoin_common + bitcoin_util + minisketch + leveldb + univalue + Boost::headers + libevent::libevent +) + +if(ENABLE_WALLET) + target_sources(test_bitcoin + PRIVATE + ../wallet/test/init_test_fixture.cpp + ../wallet/test/wallet_test_fixture.cpp + + ../wallet/test/coinselector_tests.cpp + ../wallet/test/feebumper_tests.cpp + ../wallet/test/group_outputs_tests.cpp + ../wallet/test/init_tests.cpp + ../wallet/test/ismine_tests.cpp + ../wallet/test/psbt_wallet_tests.cpp + ../wallet/test/rpc_util_tests.cpp + ../wallet/test/scriptpubkeyman_tests.cpp + ../wallet/test/spend_tests.cpp + ../wallet/test/wallet_crypto_tests.cpp + ../wallet/test/wallet_tests.cpp + ../wallet/test/wallet_transaction_tests.cpp + ../wallet/test/walletdb_tests.cpp + ../wallet/test/walletload_tests.cpp + ) + target_link_libraries(test_bitcoin bitcoin_wallet) + if(USE_BDB) + target_sources(test_bitcoin PRIVATE ../wallet/test/db_tests.cpp) + endif() +endif() diff --git a/src/test/compilerbug_tests.cpp b/src/test/compilerbug_tests.cpp index ef558c1e32269..4492a9686c766 100644 --- a/src/test/compilerbug_tests.cpp +++ b/src/test/compilerbug_tests.cpp @@ -6,6 +6,13 @@ BOOST_AUTO_TEST_SUITE(compilerbug_tests) +// At least one test case is required to avoid the "Test setup error: no test +// cases matching filter or all test cases were disabled" errror. +BOOST_AUTO_TEST_CASE(dummy) +{ + BOOST_CHECK(true); +} + #if defined(__GNUC__) // This block will also be built under clang, which is fine (as it supports noinline) void __attribute__ ((noinline)) set_one(unsigned char* ptr) diff --git a/src/test/util/CMakeLists.txt b/src/test/util/CMakeLists.txt new file mode 100644 index 0000000000000..cff9f6f0b0841 --- /dev/null +++ b/src/test/util/CMakeLists.txt @@ -0,0 +1,38 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +add_library(test_util STATIC EXCLUDE_FROM_ALL + blockfilter.cpp + coins.cpp + index.cpp + json.cpp + logging.cpp + mining.cpp + net.cpp + random.cpp + script.cpp + setup_common.cpp + str.cpp + transaction_utils.cpp + txmempool.cpp + validation.cpp +) +target_link_libraries(test_util + PRIVATE + core + bitcoin_common + bitcoin_node + leveldb + univalue + Boost::headers +) + +if(ENABLE_WALLET) + target_sources(test_util + PRIVATE + ../../wallet/test/util.cpp + ) +endif() + +target_link_libraries(test_util PRIVATE core) diff --git a/src/univalue/CMakeLists.txt b/src/univalue/CMakeLists.txt new file mode 100644 index 0000000000000..fdaa652dcfae3 --- /dev/null +++ b/src/univalue/CMakeLists.txt @@ -0,0 +1,17 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +add_library(univalue STATIC EXCLUDE_FROM_ALL + lib/univalue.cpp + lib/univalue_get.cpp + lib/univalue_read.cpp + lib/univalue_write.cpp +) + +target_include_directories(univalue + PUBLIC + $ +) + +target_link_libraries(univalue PRIVATE core) diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt new file mode 100644 index 0000000000000..bfde49080771c --- /dev/null +++ b/src/util/CMakeLists.txt @@ -0,0 +1,59 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +add_library(bitcoin_util STATIC EXCLUDE_FROM_ALL + asmap.cpp + batchpriority.cpp + bip32.cpp + bytevectorhash.cpp + chaintype.cpp + check.cpp + error.cpp + exception.cpp + fees.cpp + fs.cpp + fs_helpers.cpp + getuniquepath.cpp + hasher.cpp + message.cpp + moneystr.cpp + rbf.cpp + readwritefile.cpp + serfloat.cpp + signalinterrupt.cpp + sock.cpp + spanparsing.cpp + strencodings.cpp + string.cpp + syserror.cpp + thread.cpp + threadinterrupt.cpp + threadnames.cpp + time.cpp + tokenpipe.cpp + ../chainparamsbase.cpp + ../clientversion.cpp + ../logging.cpp + ../random.cpp + ../randomenv.cpp + ../streams.cpp + ../support/cleanse.cpp + ../support/lockedpool.cpp + ../sync.cpp +) + +target_compile_definitions(bitcoin_util + PRIVATE + ${THREAD_LOCAL_IF_AVAILABLE} + $<$:_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING> +) + +target_link_libraries(bitcoin_util + PRIVATE + core + bitcoin_crypto + univalue + Threads::Threads + $<$:ws2_32> +) diff --git a/src/wallet/CMakeLists.txt b/src/wallet/CMakeLists.txt new file mode 100644 index 0000000000000..34a0379408dfa --- /dev/null +++ b/src/wallet/CMakeLists.txt @@ -0,0 +1,57 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# Wallet functionality used by bitcoind and bitcoin-wallet executables. +add_library(bitcoin_wallet STATIC EXCLUDE_FROM_ALL + coincontrol.cpp + coinselection.cpp + context.cpp + crypter.cpp + db.cpp + dump.cpp + external_signer_scriptpubkeyman.cpp + feebumper.cpp + fees.cpp + interfaces.cpp + load.cpp + receive.cpp + rpc/addresses.cpp + rpc/backup.cpp + rpc/coins.cpp + rpc/encrypt.cpp + rpc/spend.cpp + rpc/signmessage.cpp + rpc/transactions.cpp + rpc/util.cpp + rpc/wallet.cpp + scriptpubkeyman.cpp + spend.cpp + transaction.cpp + wallet.cpp + walletdb.cpp + walletutil.cpp +) +target_link_libraries(bitcoin_wallet + PRIVATE + core + bitcoin_common + univalue + Boost::headers +) + +if(NOT USE_SQLITE AND NOT USE_BDB) + message(FATAL_ERROR "Wallet functionality requested but no BDB or SQLite support available.") +endif() +if(USE_SQLITE) + target_sources(bitcoin_wallet PRIVATE sqlite.cpp) + target_link_libraries(bitcoin_wallet + PRIVATE + $ + $ + ) +endif() +if(USE_BDB) + target_sources(bitcoin_wallet PRIVATE bdb.cpp salvage.cpp) + target_link_libraries(bitcoin_wallet PUBLIC BerkeleyDB::BerkeleyDB) +endif() diff --git a/src/zmq/CMakeLists.txt b/src/zmq/CMakeLists.txt new file mode 100644 index 0000000000000..228a802965e8e --- /dev/null +++ b/src/zmq/CMakeLists.txt @@ -0,0 +1,23 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +add_library(bitcoin_zmq STATIC + zmqabstractnotifier.cpp + zmqnotificationinterface.cpp + zmqpublishnotifier.cpp + zmqrpc.cpp + zmqutil.cpp +) +target_compile_definitions(bitcoin_zmq + INTERFACE + ENABLE_ZMQ=1 +) +target_link_libraries(bitcoin_zmq + PRIVATE + core + leveldb + univalue + $ + $ +) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000000000..fe832a92f26ba --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,48 @@ +# Copyright (c) 2023 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +function(create_test_config) + set(abs_top_srcdir ${PROJECT_SOURCE_DIR}) + set(abs_top_builddir ${PROJECT_BINARY_DIR}) + set(EXEEXT ${CMAKE_EXECUTABLE_SUFFIX}) + + macro(set_configure_variable var conf_var) + if(${var}) + set(${conf_var}_TRUE "") + else() + set(${conf_var}_TRUE "#") + endif() + endmacro() + + set_configure_variable(ENABLE_WALLET ENABLE_WALLET) + set_configure_variable(WITH_SQLITE USE_SQLITE) + set_configure_variable(WITH_BDB USE_BDB) + set_configure_variable(BUILD_CLI BUILD_BITCOIN_CLI) + set_configure_variable(BUILD_UTIL BUILD_BITCOIN_UTIL) + set_configure_variable(BUILD_WALLET_TOOL BUILD_BITCOIN_WALLET) + set_configure_variable(BUILD_DAEMON BUILD_BITCOIND_TRUE) + set_configure_variable(WITH_ZMQ ENABLE_ZMQ) + set_configure_variable(ENABLE_EXTERNAL_SIGNER ENABLE_EXTERNAL_SIGNER) + set_configure_variable(ENABLE_TRACING ENABLE_USDT_TRACEPOINTS) + + configure_file(config.ini.in config.ini @ONLY) +endfunction() + +create_test_config() + +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/functional) +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/fuzz) +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/util) + +function(create_test_script script) + if(MSVC) + file(CREATE_LINK ${CMAKE_CURRENT_SOURCE_DIR}/${script} ${CMAKE_CURRENT_BINARY_DIR}/${script} COPY_ON_ERROR) + else() + file(CREATE_LINK ${CMAKE_CURRENT_SOURCE_DIR}/${script} ${CMAKE_CURRENT_BINARY_DIR}/${script} COPY_ON_ERROR SYMBOLIC) + endif() +endfunction() + +foreach(script functional/test_runner.py fuzz/test_runner.py util/rpcauth-test.py util/test_runner.py) + create_test_script(${script}) +endforeach()