Skip to content

Commit

Permalink
Merge #13: build: Add CMake-based build system (5 of N)
Browse files Browse the repository at this point in the history
8ee7537 cmake: Add `systemtap-sdt` optional package support (Hennadii Stepanov)
697c397 cmake: Add `libzmq` optional package support (Hennadii Stepanov)
b195c9c cmake: Add `libminiupnpc` optional package support (Hennadii Stepanov)
9587ed7 cmake: Add `libnatpmp` optional package support (Hennadii Stepanov)
ba50cad [FIXUP] cmake: Fix `check_evhttp_connection_get_peer` macro (Hennadii Stepanov)
9412a2e [FIXUP] cmake: Cleanup `AddBoostIfNeeded` module (Hennadii Stepanov)
15bcb8e cmake: Add `ccache` support (Hennadii Stepanov)
480c8cb cmake: Add `TristateOption` module (Hennadii Stepanov)

Pull request description:

  It was [suggested](#10 (comment)):

  > It might be helpful to get some more of the depends interactions hooked up as a next step

  Done in this PR.

  ---

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

  ---

  EXAMPLES:

  1. Cross-compiling for Windows:
  ```
  make -C depends HOST=x86_64-w64-mingw32 NO_QT=1 NO_WALLET=1
  cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=depends/x86_64-w64-mingw32/share/toolchain.cmake
  cmake --build build
  ```

  2. Cross-compiling for macOS (`arm64`, `x86_64`):
  ```
  make -C depends HOST=arm64-apple-darwin NO_QT=1 NO_WALLET=1
  cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=depends/arm64-apple-darwin/share/toolchain.cmake
  cmake --build build
  ```

  3. Building on macOS, arm64:
  - essential build tools:
  ```
  brew install cmake pkg-config
  ```
  - optional build tools:
  ```
  brew install ccache
  ```
  - essential dependencies:
  ```
  brew install boost libevent
  ```
  - optional dependencies:
  ```
  brew install libnatpmp miniupnpc zeromq
  ```
  - configure and build:
  ```
  cmake -S . -B build
  cmake --build build
  ```

  4. Building on Windows:

  - `ccache` is available [here](https://community.chocolatey.org/packages/ccache) or [here](https://ccache.dev/download.html) (also see a [note](#13 (comment))):
  ```
  choco install ccache --version=4.7.4
  ```

  - the [`vcpkg`](https://vcpkg.io) package manager is used to provide other dependencies:
  ```
  vcpkg --triplet=x64-windows-static install boost-multi-index boost-signals2 libevent miniupnpc zeromq
  ```

  - configure and build:
  ```
  cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-static
  cmake --build build -- -property:UseMultiToolTask=true -maxCpuCount
  ```

  ---

  **NOTE**

  As always, make sure your build tree is clean :)

ACKs for top commit:
  vasild:
    ACK 8ee7537
  theuni:
    ACK 8ee7537

Tree-SHA512: 36ebc63e73d507d86b154121b9bc5b8216554fd63f31808f257cefff7a1a104ce066f2b2cf9fdfc1828066d33cdc0b9ede4a81d8e6a7932de3adcb1f14674796
  • Loading branch information
hebasto committed Apr 19, 2023
2 parents 5b25bcd + 8ee7537 commit 2428f6c
Show file tree
Hide file tree
Showing 10 changed files with 311 additions and 13 deletions.
21 changes: 21 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,19 @@ 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)

# 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(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
)

if(CXX20)
set(CMAKE_CXX_STANDARD 20)
else()
Expand Down Expand Up @@ -113,6 +126,8 @@ include(cmake/secp256k1.cmake)
include(CheckStdFilesystem)
check_std_filesystem()

include(cmake/optional.cmake)

if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.14)
include(CheckPIESupported)
check_pie_supported(OUTPUT_VARIABLE check_pie_output LANGUAGES CXX)
Expand All @@ -133,6 +148,11 @@ message("Configure summary")
message("=================")
message("Executables:")
message(" bitcoind ............................ ${BUILD_DAEMON}")
message("Optional packages:")
message(" NAT-PMP ............................. ${WITH_NATPMP}")
message(" UPnP ................................ ${WITH_MINIUPNPC}")
message(" ZeroMQ .............................. ${WITH_ZMQ}")
message(" USDT tracing ........................ ${WITH_USDT}")
message("")
if(CMAKE_CROSSCOMPILING)
set(cross_status "TRUE, for ${CMAKE_SYSTEM_NAME}, ${CMAKE_SYSTEM_PROCESSOR}")
Expand Down Expand Up @@ -175,6 +195,7 @@ else()
message(" - LDFLAGS for shared libraries ....... ${CMAKE_SHARED_LINKER_FLAGS_RELEASE}")
endif()
message("Use assembly routines ................. ${ASM}")
message("Use ccache for compiling .............. ${CCACHE}")
message("\n")
if(configure_warnings)
message(" ******\n")
Expand Down
4 changes: 4 additions & 0 deletions cmake/bitcoin-config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@
/* 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

Expand Down
9 changes: 0 additions & 9 deletions cmake/module/AddBoostIfNeeded.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,6 @@ function(add_boost_if_needed)
directory and other added INTERFACE properties.
]=]

if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin" AND BREW_COMMAND)
execute_process(
COMMAND ${BREW_COMMAND} --prefix boost
OUTPUT_VARIABLE BOOST_ROOT
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
endif()

set(Boost_NO_BOOST_CMAKE ON)
find_package(Boost 1.64.0 REQUIRED)
set_target_properties(Boost::boost PROPERTIES IMPORTED_GLOBAL TRUE)
Expand Down
17 changes: 13 additions & 4 deletions cmake/module/AddLibeventIfNeeded.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
# 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)
# Check whether evhttp_connection_get_peer expects const char**.
# Fail if neither are available.
cmake_push_check_state(RESET)
set(CMAKE_REQUIRED_LIBRARIES ${target})
check_cxx_source_compiles("
#include <cstdint>
#include <event2/http.h>
Expand All @@ -18,6 +20,7 @@ macro(check_evhttp_connection_get_peer target)
}
" HAVE_EVHTTP_CONNECTION_GET_PEER_CONST_CHAR
)
cmake_pop_check_state()
target_compile_definitions(${target} INTERFACE
$<$<BOOL:${HAVE_EVHTTP_CONNECTION_GET_PEER_CONST_CHAR}>:HAVE_EVHTTP_CONNECTION_GET_PEER_CONST_CHAR=1>
)
Expand All @@ -38,14 +41,20 @@ function(add_libevent_if_needed)
endif()

include(CrossPkgConfig)
cross_pkg_check_modules(libevent REQUIRED libevent>=${libevent_minimum_version} IMPORTED_TARGET GLOBAL)
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
$<$<BOOL:${MINGW}>:iphlpapi;ssp;ws2_32>
)
add_library(libevent::libevent ALIAS PkgConfig::libevent)

if(NOT WIN32)
cross_pkg_check_modules(libevent_pthreads REQUIRED libevent_pthreads>=${libevent_minimum_version} IMPORTED_TARGET)
cross_pkg_check_modules(libevent_pthreads
REQUIRED IMPORTED_TARGET GLOBAL
libevent_pthreads>=${libevent_minimum_version}
)
endif()
endfunction()
84 changes: 84 additions & 0 deletions cmake/module/FindMiniUPnPc.cmake
Original file line number Diff line number Diff line change
@@ -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 $<$<PLATFORM_ID:Windows>:MINIUPNP_STATICLIB>
)
endif()

mark_as_advanced(
MiniUPnPc_INCLUDE_DIR
MiniUPnPc_LIBRARY
)
32 changes: 32 additions & 0 deletions cmake/module/FindNATPMP.cmake
Original file line number Diff line number Diff line change
@@ -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 $<$<PLATFORM_ID:Windows>:NATPMP_STATICLIB>
)
endif()

mark_as_advanced(
NATPMP_INCLUDE_DIR
NATPMP_LIBRARY
)
21 changes: 21 additions & 0 deletions cmake/module/TristateOption.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.

# 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()
108 changes: 108 additions & 0 deletions cmake/optional.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# 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_EXECUTABLE ccache)
if(CCACHE_EXECUTABLE)
set(CCACHE ON)
if(MSVC)
# See https://github.com/ccache/ccache/wiki/MS-Visual-Studio
set(MSVC_CCACHE_WRAPPER_CONTENT "\"${CCACHE_EXECUTABLE}\" \"${CMAKE_CXX_COMPILER}\"")
set(MSVC_CCACHE_WRAPPER_FILENAME wrapped-cl.bat)
file(WRITE ${CMAKE_BINARY_DIR}/${MSVC_CCACHE_WRAPPER_FILENAME} "${MSVC_CCACHE_WRAPPER_CONTENT} %*")
set(CMAKE_VS_GLOBALS
"CLToolExe=${MSVC_CCACHE_WRAPPER_FILENAME}"
"CLToolPath=${CMAKE_BINARY_DIR}"
"TrackFileAccess=false"
"UseMultiToolTask=true"
"DebugInformationFormat=OldStyle"
)
else()
list(APPEND CMAKE_C_COMPILER_LAUNCHER ${CCACHE_EXECUTABLE})
list(APPEND CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE_EXECUTABLE})
endif()
elseif(CCACHE STREQUAL "AUTO")
set(CCACHE OFF)
else()
message(FATAL_ERROR "ccache requested, but not found.")
endif()
mark_as_advanced(CCACHE_EXECUTABLE)
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)
set_property(TARGET PkgConfig::libzmq APPEND PROPERTY
INTERFACE_COMPILE_DEFINITIONS $<$<PLATFORM_ID:Windows>:ZMQ_STATIC>
)
set_property(TARGET PkgConfig::libzmq APPEND PROPERTY
INTERFACE_LINK_LIBRARIES $<$<PLATFORM_ID:Windows>: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()

include(CheckCXXSourceCompiles)
if(WITH_USDT)
check_cxx_source_compiles("
#include <sys/sdt.h>
int main()
{
DTRACE_PROBE(\"context\", \"event\");
}
" HAVE_USDT_H
)
if(HAVE_USDT_H)
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()
6 changes: 6 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ add_library(bitcoin_consensus OBJECT EXCLUDE_FROM_ALL
)
target_link_libraries(bitcoin_consensus PRIVATE 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.
Expand Down Expand Up @@ -186,6 +189,9 @@ target_link_libraries(bitcoin_node
Boost::headers
libevent::libevent
$<TARGET_NAME_IF_EXISTS:PkgConfig::libevent_pthreads>
$<TARGET_NAME_IF_EXISTS:NATPMP::NATPMP>
$<TARGET_NAME_IF_EXISTS:MiniUPnPc::MiniUPnPc>
$<TARGET_NAME_IF_EXISTS:bitcoin_zmq>
)


Expand Down
Loading

0 comments on commit 2428f6c

Please sign in to comment.