Skip to content

Commit 38604b7

Browse files
committed
Merge #7: build: Add CMake-based build system (3 of N)
a80fb45 cmake: Build `bitcoind` executable (Hennadii Stepanov) ffd10d1 cmake: Build `bitcoin_consensus` library (Hennadii Stepanov) d028a49 cmake: Build `bitcoin_util` static library (Hennadii Stepanov) 318dd82 cmake: Build `bitcoin_crypto` library (Hennadii Stepanov) e990724 cmake: Build `univalue` static library (Hennadii Stepanov) eb3546f cmake: Build `secp256k1` static library (Hennadii Stepanov) 0e2287c cmake: Build `minisketch` static library (Hennadii Stepanov) a06290e cmake: Add `CheckStdFilesystem` module (Hennadii Stepanov) 6317164 cmake: Add essential platform-specific definitions and options (Hennadii Stepanov) Pull request description: The parent PR: bitcoin#25797. The previous PRs in the staging branch: #5, #6. This PR adds the `bitcoind` build target with its dependencies. To get comparable binaries, one can use the following commands: - with CMake: ``` cmake -S . -B build -DCMAKE_CXX_FLAGS="-g -O2" cmake --build build ``` - with Autotools: ``` ./autogen.sh ./configure --disable-hardening --disable-wallet --disable-zmq --without-miniupnpc --without-natpmp --disable-usdt make clean make -C src bitcoind ``` --- **Windows-specific notes for reviewers** Windows MSVC builds use dependencies provided by the [vcpkg](https://vcpkg.io) package manager. To install them, run: ```cmd vcpkg --triplet=x64-windows-static install boost-multi-index boost-signals2 libevent ``` To configure, a toolchain file and a triplet must be specified: ```cmd cmake -G "Visual Studio 17 2022" -A x64 --toolchain C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-static -S . -B build ``` Then, build the `all` target as usual: ```cmd cmake --build build --config Debug ``` ACKs for top commit: TheCharlatan: ACK a80fb45 theuni: ACK a80fb45 Tree-SHA512: c37af3bf3975128acba0ef2ff0b13aab1fc44a5ec96b15bcbed1b42f1cc91c533c515762417becc31384839c3408ddafb567b7f9dd53c525e71070e78150d812
2 parents 16b6c2f + a80fb45 commit 38604b7

File tree

12 files changed

+729
-0
lines changed

12 files changed

+729
-0
lines changed

CMakeLists.txt

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,10 @@ list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/module)
3838
# Configurable options.
3939
# When adding a new option, end the <help_text> with a full stop for consistency.
4040
include(CMakeDependentOption)
41+
option(BUILD_DAEMON "Build bitcoind executable." ON)
42+
option(ASM "Use assembly routines." ON)
4143
cmake_dependent_option(CXX20 "Enable compilation in C++20 mode." OFF "NOT MSVC" ON)
44+
option(THREADLOCAL "Enable features that depend on the C++ thread_local keyword (currently just thread names in debug logs)." ON)
4245

4346
if(CXX20)
4447
set(CMAKE_CXX_STANDARD 20)
@@ -60,17 +63,70 @@ else()
6063
endif()
6164
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
6265

66+
if(WIN32)
67+
#[=[
68+
This build system supports two ways to build binaries for Windows.
69+
70+
1. Building on Windows using MSVC.
71+
Implementation notes:
72+
- /DWIN32 and /D_WINDOWS definitions are included into the CMAKE_CXX_FLAGS_INIT
73+
and CMAKE_CXX_FLAGS_INIT variables by default.
74+
- A run-time library is selected using the CMAKE_MSVC_RUNTIME_LIBRARY variable.
75+
- MSVC-specific options, for example, /Zc:__cplusplus, are additionally required.
76+
77+
2. Cross-compiling using MinGW.
78+
Implementation notes:
79+
- WIN32 and _WINDOWS definitions must be provided explicitly.
80+
- A run-time library must be specified explicitly using _MT definition.
81+
]=]
82+
83+
add_compile_definitions(_WIN32_WINNT=0x0601 _WIN32_IE=0x0501 WIN32_LEAN_AND_MEAN NOMINMAX)
84+
85+
if(MSVC)
86+
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
87+
add_compile_options(/utf-8 /Zc:__cplusplus)
88+
endif()
89+
90+
if(MINGW)
91+
add_compile_definitions(WIN32 _WINDOWS _MT)
92+
# We require Windows 7 (NT 6.1) or later.
93+
add_link_options(-Wl,--major-subsystem-version,6 -Wl,--minor-subsystem-version,1)
94+
endif()
95+
endif()
96+
97+
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
98+
add_compile_definitions(MAC_OSX)
99+
endif()
100+
101+
include(AddThreadsIfNeeded)
102+
add_threads_if_needed()
103+
104+
include(AddBoostIfNeeded)
105+
add_boost_if_needed()
106+
63107
include(CheckSourceCompilesAndLinks)
108+
109+
include(AddLibeventIfNeeded)
110+
add_libevent_if_needed()
111+
64112
include(cmake/introspection.cmake)
65113

66114
include(cmake/crc32c.cmake)
67115
include(cmake/leveldb.cmake)
116+
include(cmake/minisketch.cmake)
117+
include(cmake/secp256k1.cmake)
118+
119+
include(CheckStdFilesystem)
120+
check_std_filesystem()
68121

69122
add_subdirectory(src)
70123

71124
message("\n")
72125
message("Configure summary")
73126
message("=================")
127+
message("Executables:")
128+
message(" bitcoind ............................ ${BUILD_DAEMON}")
129+
message("")
74130
get_directory_property(definitions COMPILE_DEFINITIONS)
75131
string(REPLACE ";" " " definitions "${definitions}")
76132
message("Preprocessor defined macros ........... ${definitions}")
@@ -105,6 +161,7 @@ else()
105161
message(" - LDFLAGS for executables ............ ${CMAKE_EXE_LINKER_FLAGS_RELEASE}")
106162
message(" - LDFLAGS for shared libraries ....... ${CMAKE_SHARED_LINKER_FLAGS_RELEASE}")
107163
endif()
164+
message("Use assembly routines ................. ${ASM}")
108165
message("\n")
109166
if(configure_warnings)
110167
message(" ******\n")

cmake/introspection.cmake

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,3 +263,7 @@ check_cxx_source_compiles("
263263
int main(){}
264264
" HAVE_DLLEXPORT_ATTRIBUTE
265265
)
266+
267+
if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin")
268+
find_program(BREW_COMMAND brew)
269+
endif()

cmake/minisketch.cmake

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# Copyright (c) 2023 The Bitcoin Core developers
2+
# Distributed under the MIT software license, see the accompanying
3+
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
# Check for clmul instructions support.
6+
if(MSVC)
7+
set(CLMUL_CXXFLAGS)
8+
else()
9+
set(CLMUL_CXXFLAGS -mpclmul)
10+
endif()
11+
check_cxx_source_compiles_with_flags("${CLMUL_CXXFLAGS}" "
12+
#include <immintrin.h>
13+
#include <cstdint>
14+
15+
int main()
16+
{
17+
__m128i a = _mm_cvtsi64_si128((uint64_t)7);
18+
__m128i b = _mm_clmulepi64_si128(a, a, 37);
19+
__m128i c = _mm_srli_epi64(b, 41);
20+
__m128i d = _mm_xor_si128(b, c);
21+
uint64_t e = _mm_cvtsi128_si64(d);
22+
return e == 0;
23+
}
24+
" HAVE_CLMUL
25+
)
26+
27+
add_library(minisketch_defs INTERFACE)
28+
target_compile_definitions(minisketch_defs INTERFACE
29+
DISABLE_DEFAULT_FIELDS
30+
ENABLE_FIELD_32
31+
$<$<AND:$<BOOL:${HAVE_BUILTIN_CLZL}>,$<BOOL:${HAVE_BUILTIN_CLZLL}>>:HAVE_CLZ>
32+
)
33+
34+
if(HAVE_CLMUL)
35+
add_library(minisketch_clmul OBJECT EXCLUDE_FROM_ALL
36+
${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/clmul_1byte.cpp
37+
${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/clmul_2bytes.cpp
38+
${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/clmul_3bytes.cpp
39+
${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/clmul_4bytes.cpp
40+
${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/clmul_5bytes.cpp
41+
${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/clmul_6bytes.cpp
42+
${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/clmul_7bytes.cpp
43+
${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/clmul_8bytes.cpp
44+
)
45+
target_compile_definitions(minisketch_clmul PUBLIC HAVE_CLMUL)
46+
target_compile_options(minisketch_clmul PRIVATE ${CLMUL_CXXFLAGS})
47+
target_link_libraries(minisketch_clmul PRIVATE minisketch_defs)
48+
endif()
49+
50+
add_library(minisketch STATIC EXCLUDE_FROM_ALL
51+
${PROJECT_SOURCE_DIR}/src/minisketch/src/minisketch.cpp
52+
${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/generic_1byte.cpp
53+
${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/generic_2bytes.cpp
54+
${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/generic_3bytes.cpp
55+
${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/generic_4bytes.cpp
56+
${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/generic_5bytes.cpp
57+
${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/generic_6bytes.cpp
58+
${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/generic_7bytes.cpp
59+
${PROJECT_SOURCE_DIR}/src/minisketch/src/fields/generic_8bytes.cpp
60+
)
61+
62+
target_include_directories(minisketch
63+
PUBLIC
64+
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src/minisketch/include>
65+
)
66+
67+
target_link_libraries(minisketch
68+
PRIVATE
69+
minisketch_defs
70+
$<TARGET_NAME_IF_EXISTS:minisketch_clmul>
71+
)
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Copyright (c) 2023 The Bitcoin Core developers
2+
# Distributed under the MIT software license, see the accompanying
3+
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
function(add_boost_if_needed)
6+
#[=[
7+
TODO: Not all targets, which will be added in the future, require
8+
Boost. Therefore, a proper check will be appropriate here.
9+
10+
Implementation notes:
11+
Although only Boost headers are used to build Bitcoin Core,
12+
we still leverage a standard CMake's approach to handle
13+
dependencies, i.e., the Boost::headers "library".
14+
A command target_link_libraries(target PRIVATE Boost::headers)
15+
will propagate Boost::headers usage requirements to the target.
16+
For Boost::headers such usage requirements is an include
17+
directory and other added INTERFACE properties.
18+
]=]
19+
20+
if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin" AND BREW_COMMAND)
21+
execute_process(
22+
COMMAND ${BREW_COMMAND} --prefix boost
23+
OUTPUT_VARIABLE BOOST_ROOT
24+
ERROR_QUIET
25+
OUTPUT_STRIP_TRAILING_WHITESPACE
26+
)
27+
endif()
28+
29+
set(Boost_NO_BOOST_CMAKE ON)
30+
find_package(Boost 1.64.0 REQUIRED)
31+
set_target_properties(Boost::boost PROPERTIES IMPORTED_GLOBAL TRUE)
32+
target_compile_definitions(Boost::boost INTERFACE
33+
$<$<CONFIG:Debug>:BOOST_MULTI_INDEX_ENABLE_SAFE_MODE>
34+
)
35+
if(CMAKE_VERSION VERSION_LESS 3.15)
36+
add_library(Boost::headers ALIAS Boost::boost)
37+
endif()
38+
39+
mark_as_advanced(Boost_INCLUDE_DIR)
40+
endfunction()
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Copyright (c) 2023 The Bitcoin Core developers
2+
# Distributed under the MIT software license, see the accompanying
3+
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
macro(check_evhttp_connection_get_peer target)
6+
# Check whether evhttp_connection_get_peer expects const char**.
7+
# Fail if neither are available.
8+
check_cxx_source_compiles("
9+
#include <cstdint>
10+
#include <event2/http.h>
11+
12+
int main()
13+
{
14+
evhttp_connection* conn = (evhttp_connection*)1;
15+
const char* host;
16+
uint16_t port;
17+
evhttp_connection_get_peer(conn, &host, &port);
18+
}
19+
" HAVE_EVHTTP_CONNECTION_GET_PEER_CONST_CHAR
20+
)
21+
target_compile_definitions(${target} INTERFACE
22+
$<$<BOOL:${HAVE_EVHTTP_CONNECTION_GET_PEER_CONST_CHAR}>:HAVE_EVHTTP_CONNECTION_GET_PEER_CONST_CHAR=1>
23+
)
24+
endmacro()
25+
26+
function(add_libevent_if_needed)
27+
# TODO: Not all targets, which will be added in the future,
28+
# require libevent. Therefore, a proper check will be
29+
# appropriate here.
30+
31+
set(libevent_minimum_version 2.1.8)
32+
33+
if(MSVC)
34+
find_package(Libevent ${libevent_minimum_version} REQUIRED COMPONENTS extra CONFIG)
35+
check_evhttp_connection_get_peer(libevent::extra)
36+
add_library(libevent::libevent ALIAS libevent::extra)
37+
return()
38+
endif()
39+
40+
find_package(PkgConfig)
41+
pkg_check_modules(libevent REQUIRED libevent>=${libevent_minimum_version} IMPORTED_TARGET GLOBAL)
42+
check_evhttp_connection_get_peer(PkgConfig::libevent)
43+
target_link_libraries(PkgConfig::libevent INTERFACE
44+
$<$<BOOL:${MINGW}>:iphlpapi;ws2_32>
45+
)
46+
add_library(libevent::libevent ALIAS PkgConfig::libevent)
47+
48+
if(NOT WIN32)
49+
pkg_check_modules(libevent_pthreads REQUIRED libevent_pthreads>=${libevent_minimum_version} IMPORTED_TARGET)
50+
endif()
51+
endfunction()
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Copyright (c) 2023 The Bitcoin Core developers
2+
# Distributed under the MIT software license, see the accompanying
3+
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
function(add_threads_if_needed)
6+
# TODO: Not all targets, which will be added in the future,
7+
# require Threads. Therefore, a proper check will be
8+
# appropriate here.
9+
10+
set(THREADS_PREFER_PTHREAD_FLAG ON)
11+
find_package(Threads REQUIRED)
12+
13+
set(thread_local)
14+
if(MINGW)
15+
#[=[
16+
mingw32's implementation of thread_local has been shown to behave
17+
erroneously under concurrent usage.
18+
See:
19+
- https://github.com/bitcoin/bitcoin/pull/15849
20+
- https://gist.github.com/jamesob/fe9a872051a88b2025b1aa37bfa98605
21+
]=]
22+
elseif(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
23+
#[=[
24+
FreeBSD's implementation of thread_local is buggy.
25+
See:
26+
- https://github.com/bitcoin/bitcoin/pull/16059
27+
- https://groups.google.com/d/msg/bsdmailinglist/22ncTZAbDp4/Dii_pII5AwAJ
28+
]=]
29+
elseif(THREADLOCAL)
30+
set(thread_local "$<$<COMPILE_FEATURES:cxx_thread_local>:HAVE_THREAD_LOCAL>")
31+
endif()
32+
set(THREAD_LOCAL_IF_AVAILABLE "${thread_local}" PARENT_SCOPE)
33+
endfunction()
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Copyright (c) 2023 The Bitcoin Core developers
2+
# Distributed under the MIT software license, see the accompanying
3+
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
# GCC 8.x (libstdc++) requires -lstdc++fs
6+
# Clang 8.x (libc++) requires -lc++fs
7+
8+
function(check_std_filesystem)
9+
set(source "
10+
#include <filesystem>
11+
12+
int main()
13+
{
14+
(void)std::filesystem::current_path().root_name();
15+
}
16+
")
17+
18+
include(CheckCXXSourceCompiles)
19+
check_cxx_source_links("${source}" STD_FILESYSTEM_NO_EXTRA_LIBS_NEEDED)
20+
if(STD_FILESYSTEM_NO_EXTRA_LIBS_NEEDED)
21+
return()
22+
endif()
23+
24+
add_library(std_filesystem INTERFACE)
25+
check_cxx_source_links_with_libs(stdc++fs "${source}" STD_FILESYSTEM_NEEDS_LINK_TO_LIBSTDCXXFS)
26+
if(STD_FILESYSTEM_NEEDS_LINK_TO_LIBSTDCXXFS)
27+
target_link_libraries(std_filesystem INTERFACE stdc++fs)
28+
return()
29+
endif()
30+
check_cxx_source_links_with_libs(c++fs "${source}" STD_FILESYSTEM_NEEDS_LINK_TO_LIBCXXFS)
31+
if(STD_FILESYSTEM_NEEDS_LINK_TO_LIBCXXFS)
32+
target_link_libraries(std_filesystem INTERFACE c++fs)
33+
return()
34+
endif()
35+
message(FATAL_ERROR "Cannot figure out how to use std::filesystem.")
36+
endfunction()

cmake/secp256k1.cmake

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Copyright (c) 2023 The Bitcoin Core developers
2+
# Distributed under the MIT software license, see the accompanying
3+
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
# This file is part of the transition from Autotools to CMake. Once CMake
6+
# support has been merged we should switch to using the upstream CMake
7+
# buildsystem.
8+
9+
set(CMAKE_C_STANDARD 90)
10+
set(CMAKE_C_EXTENSIONS OFF)
11+
12+
include(CheckCSourceCompiles)
13+
check_c_source_compiles("
14+
#include <stdint.h>
15+
16+
int main()
17+
{
18+
uint64_t a = 11, tmp;
19+
__asm__ __volatile__(\"movq $0x100000000,%1; mulq %%rsi\" : \"+a\"(a) : \"S\"(tmp) : \"cc\", \"%rdx\");
20+
}
21+
" HAVE_64BIT_ASM
22+
)
23+
24+
add_library(secp256k1 STATIC EXCLUDE_FROM_ALL
25+
${PROJECT_SOURCE_DIR}/src/secp256k1/src/secp256k1.c
26+
${PROJECT_SOURCE_DIR}/src/secp256k1/src/precomputed_ecmult.c
27+
${PROJECT_SOURCE_DIR}/src/secp256k1/src/precomputed_ecmult_gen.c
28+
)
29+
30+
target_compile_definitions(secp256k1
31+
PRIVATE
32+
ECMULT_GEN_PREC_BITS=4
33+
ECMULT_WINDOW_SIZE=15
34+
ENABLE_MODULE_RECOVERY
35+
ENABLE_MODULE_SCHNORRSIG
36+
ENABLE_MODULE_EXTRAKEYS
37+
$<$<BOOL:${HAVE_64BIT_ASM}>:USE_ASM_X86_64=1>
38+
)
39+
40+
target_include_directories(secp256k1
41+
PUBLIC
42+
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src/secp256k1/include>
43+
)
44+
45+
target_compile_options(secp256k1
46+
PRIVATE
47+
$<$<CXX_COMPILER_ID:MSVC>:/wd4146 /wd4334>
48+
)

0 commit comments

Comments
 (0)