Skip to content

Commit

Permalink
Merge #15: build: Add CMake-based build system (6 of N)
Browse files Browse the repository at this point in the history
43123cf FIXUP: Same as PR27458 (Hennadii Stepanov)
2d8930e FIXUP: Same as PR27656 (Hennadii Stepanov)
a112470 cmake: Include CTest (Hennadii Stepanov)
cb19814 cmake: Build `test_bitcoin` executable (Hennadii Stepanov)
751453f cmake: Build `bench_bitcoin` executable (Hennadii Stepanov)
a2c3493 cmake: Add test config and runners (Hennadii Stepanov)
cb7dc94 test: Explicitly specify directory where to search tests for (Hennadii Stepanov)
2fd303f test: Make `util/test_runner.py` honor `BITCOINUTIL` and `BITCOINTX` (Hennadii Stepanov)
2e3721e cmake: Add wallet functionality (Hennadii Stepanov)
f944ccd cmake: Build `bitcoin-util` executable (Hennadii Stepanov)
d1c319d cmake: Build `bitcoin-tx` executable (Hennadii Stepanov)
1934755 cmake: Build `bitcoin-cli` executable (Hennadii Stepanov)
5fc2cee [FIXUP] cmake: Add workaround for https://gitlab.kitware.com/cmake/cmake/-/issues/20652 (Hennadii Stepanov)
b2bea9f [FIXUP] cmake: Consider `ASM` option when checking for `HAVE_64BIT_ASM` (Hennadii Stepanov)

Pull request description:

  The parent PR: bitcoin#25797.
  The previous PRs in the staging branch: #5, #6, #7, #10, #13.

  ---

  What is NEW:
  - `bitcoin-cli`
  - `bitcoin-tx`
  - `bitcoin-util`
  - wallet functionality and `bitcoin-wallet`
  - `bench_bitcoin`
  - `test_bitcoin`

  EXAMPLES:
  ```
  cmake -S . -B build
  cd build
  cmake --build . -j $(nproc)
  ctest -j $(nproc)
  ./test/functional/test_runner.py -j $(nproc)
  ```

  Using a multi-configuration generator (CMake 3.17+ is required):
  ```
  cmake -S . -B build -G "Ninja Multi-Config"
  cd build
  cmake --build . -j $(nproc)
  ctest -j $(nproc) -C Debug
  ```
  ---

  What to test:
  - old CMake versions, for example v3.13
  - multi-config generators, for example `-G "Ninja Multi-Config"`

  ---

  What to consider additionally:
  - is it worth to pull the "[test: Make util/test_runner.py honor BITCOINUTIL and BITCOINTX](268aca3)" commit to the main repo now?

  FWIW, we use the same approach for functional tests providing the `BITCOIND` environment variable when needed.

ACKs for top commit:
  TheCharlatan:
    ACK 43123cf

Tree-SHA512: a04cfca266bcde780528c915cb01f69189f36a0e1beb521fe75e4816ca4f9ab9440646529bbf2cbdfe76275debc5107ee2433e1027405094d3e8a74ec0d1d077
  • Loading branch information
hebasto committed Jul 7, 2023
2 parents d439a1b + 43123cf commit 3a1fe30
Show file tree
Hide file tree
Showing 19 changed files with 780 additions and 22 deletions.
34 changes: 32 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ project("Bitcoin Core"
LANGUAGES CXX ASM
)

set(PACKAGE_NAME ${PROJECT_NAME})
set(CLIENT_VERSION_IS_RELEASE "false")
set(COPYRIGHT_YEAR "2023")
set(COPYRIGHT_HOLDERS "The %s developers")
Expand All @@ -39,13 +40,23 @@ list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/module)
# When adding a new option, end the <help_text> 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)
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)

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)
Expand All @@ -56,6 +67,9 @@ tristate_option(WITH_USDT
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()
Expand Down Expand Up @@ -141,18 +155,34 @@ else()
endif()
endif()

find_package(Python3 3.8 COMPONENTS Interpreter)
set(PYTHON_COMMAND ${Python3_EXECUTABLE})

add_subdirectory(src)
add_subdirectory(test)

include(cmake/tests.cmake)

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}")
Expand Down
9 changes: 9 additions & 0 deletions cmake/bitcoin-config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -206,4 +206,13 @@
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
2 changes: 1 addition & 1 deletion cmake/introspection.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ check_cxx_source_compiles("

# Check for posix_fallocate().
check_cxx_source_compiles("
// same as in src/util/system.cpp
// same as in src/fs_helpers/system.cpp
#ifdef __linux__
#ifdef _POSIX_C_SOURCE
#undef _POSIX_C_SOURCE
Expand Down
19 changes: 16 additions & 3 deletions cmake/module/CrossPkgConfig.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,29 @@

find_package(PkgConfig REQUIRED)

macro(cross_pkg_check_modules)
function(remove_isystem_from_include_directories_internal target)
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(${ARGV})
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(${ARGV})
pkg_check_modules(${prefix} ${ARGN})
endif()

# A workaround for https://gitlab.kitware.com/cmake/cmake/-/issues/20652.
if(CMAKE_VERSION VERSION_LESS 3.17.3 AND TARGET PkgConfig::${prefix})
remove_isystem_from_include_directories_internal(PkgConfig::${prefix})
endif()
endmacro()
87 changes: 87 additions & 0 deletions cmake/module/FindBerkeleyDB.cmake
Original file line number Diff line number Diff line change
@@ -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
)
21 changes: 21 additions & 0 deletions cmake/module/GenerateHeaders.cmake
Original file line number Diff line number Diff line change
@@ -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}
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}
VERBATIM
)
endfunction()
44 changes: 43 additions & 1 deletion cmake/optional.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,9 @@ if(WITH_USDT)
int main()
{
DTRACE_PROBE(\"context\", \"event\");
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
)
Expand All @@ -106,3 +108,43 @@ if(WITH_USDT)
message(FATAL_ERROR "sys/sdt.h requested, but not found.")
endif()
endif()

if(ENABLE_WALLET)
if(WITH_SQLITE)
include(CrossPkgConfig)
cross_pkg_check_modules(sqlite sqlite3>=3.7.17 IMPORTED_TARGET)
if(sqlite_FOUND)
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()
23 changes: 23 additions & 0 deletions cmake/script/GenerateHeaderFromJson.cmake
Original file line number Diff line number Diff line change
@@ -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.

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} "namespace json_tests{\n")
get_filename_component(json_source_basename ${JSON_SOURCE_PATH} NAME_WE)
file(APPEND ${HEADER_PATH} "static unsigned const char ${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};};")
22 changes: 22 additions & 0 deletions cmake/script/GenerateHeaderFromRaw.cmake
Original file line number Diff line number Diff line change
@@ -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};")
24 changes: 13 additions & 11 deletions cmake/secp256k1.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,19 @@ enable_language(C)
set(CMAKE_C_STANDARD 90)
set(CMAKE_C_EXTENSIONS OFF)

include(CheckCSourceCompiles)
check_c_source_compiles("
#include <stdint.h>
int main()
{
uint64_t a = 11, tmp;
__asm__ __volatile__(\"movq $0x100000000,%1; mulq %%rsi\" : \"+a\"(a) : \"S\"(tmp) : \"cc\", \"%rdx\");
}
" HAVE_64BIT_ASM
)
if(ASM)
include(CheckCSourceCompiles)
check_c_source_compiles("
#include <stdint.h>
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
Expand Down

0 comments on commit 3a1fe30

Please sign in to comment.