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 (5 of N) #13

Merged
merged 8 commits into from
Apr 19, 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
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.
Comment on lines +46 to +47
Copy link

@vasild vasild Apr 17, 2023

Choose a reason for hiding this comment

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

What does "opt-in by default" mean? That there will be just two options to choose from (not 3): ON and OFF, that it will be ON by default and (it follows that) if the corresponding library is not found, then it will result in an error?

Choose a reason for hiding this comment

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

What does "opt-in by default" mean? .... that it will be ON by default

No. It means that basically all features/options will be OFF by default, and builders will have to actively opt-in to what they want. If they opt-in to something, and do not have the required libs/prerequisites, the build will error.

include(TristateOption)
tristate_option(CCACHE "Use ccache for compiling." "if ccache is found." AUTO)
Copy link

Choose a reason for hiding this comment

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

From @fanquake on #12:

Yea. We certainly wont be adopting this tri-state logic/machinery into our CMake build system long-term/at-merge-time. I'd consider it a regression to reimplement this Autotools behaviour. As for disabling certain "features" by default, yes, I think that is what we are going to do. It continues to make less & less sense to compile in stuff like this by default, let alone auto-opt-in builders to it, based on what happens to be installed on their systems at the time of compilation.

At this point I agree with that and I'd prefer to just never start with this tri-state stuff as it's quite not-cmake-like. But I realize I originally asked for 1:1 feature parity with autotools for the sake of review, so it's not really fair to ask for that change now.

How about a comment above with a loud warning that says "These tri-state options will be removed and most features will become opt-in by default before merging into master" ?

Copy link
Owner Author

Choose a reason for hiding this comment

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

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"
)
Comment on lines +11 to +22
Copy link
Owner Author

Choose a reason for hiding this comment

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

Apparently, this code does not work with cache 4.8 (

Going to investigate the issue, but I'm really hoping this won't be a blocker for this PR.

Copy link
Owner Author

Choose a reason for hiding this comment

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

ccache 4.8 is broken, ccache 4.7.4, 4.7.5 work fine.

Copy link

Choose a reason for hiding this comment

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

What/how is it broken in 4.8?

Copy link
Owner Author

Choose a reason for hiding this comment

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

Following https://github.com/ccache/ccache/wiki/MS-Visual-Studio literally for the simplest source code like "int main { return 0; }" works for 4.7, but 4.8 reports zero of "cacheable calls".

For example, https://cirrus-ci.com/task/6670364843966464.

Copy link

Choose a reason for hiding this comment

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

Has this been reported upstream?

Copy link
Owner Author

@hebasto hebasto Apr 12, 2023

Choose a reason for hiding this comment

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

Has this been reported upstream?

ccache/ccache#1262 is somewhat related.

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

Choose a reason for hiding this comment

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

zmq started shipping a cmake config file starting with v4.2.2.

Once we bump our zmq requirement in the future, we'll be able to use find_package(ZeroMQ). Mind adding a note?

Copy link
Owner Author

Choose a reason for hiding this comment

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

zmq started shipping a cmake config file starting with v4.2.2.

But not Ubuntu's libzmq3-dev packages, unfortunately.

Copy link

Choose a reason for hiding this comment

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

Still, mind adding a note that it's supported upstream and we'll be able to switch at some point in the future?

Copy link
Owner Author

Choose a reason for hiding this comment

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

Still, mind adding a note that it's supported upstream and we'll be able to switch at some point in the future?

Sure. I'll add it.

Copy link
Owner Author

Choose a reason for hiding this comment

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

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