Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

build: Add CMake-based build system (6 of N) #15

Merged
merged 14 commits into from
Jul 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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})
hebasto marked this conversation as resolved.
Show resolved Hide resolved

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)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens in the case of CFLAGS=-isystem foo -I bar ?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is all about how CMake handles the output of the pkg-config --cflags-only-I <package> command. All -I some_directory instances are handled fine.

For example, in a broken combo of CMake 3.16.6 + pkg-config 0.29.2, the value of the INTERFACE_INCLUDE_DIRECTORIES property of the imported PkgConfig::libzmq target is a list as follows:

-isystem;/usr/include/mit-krb5;/usr/include/pgm-5.3;/usr/include/libxml2

Compare to:

$ pkg-config --cflags-only-I libzmq
-isystem /usr/include/mit-krb5 -I/usr/include/pgm-5.3 -I/usr/include/libxml2

Therefore, to fix the bug, it is enough to just filter out "-isystem" from the INTERFACE_INCLUDE_DIRECTORIES list.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a note explaining what's happening here and what it's working around please? That's not clear to me from the code alone.

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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Out of curiosity, where did you get these from?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sources:

)

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
Loading