aboutsummaryrefslogtreecommitdiff
path: root/cmake/module
diff options
context:
space:
mode:
Diffstat (limited to 'cmake/module')
-rw-r--r--cmake/module/AddBoostIfNeeded.cmake78
-rw-r--r--cmake/module/AddWindowsResources.cmake14
-rw-r--r--cmake/module/CheckSourceCompilesAndLinks.cmake39
-rw-r--r--cmake/module/FindBerkeleyDB.cmake133
-rw-r--r--cmake/module/FindLibevent.cmake80
-rw-r--r--cmake/module/FindMiniUPnPc.cmake84
-rw-r--r--cmake/module/FindQt.cmake66
-rw-r--r--cmake/module/FindUSDT.cmake64
-rw-r--r--cmake/module/FlagsSummary.cmake74
-rw-r--r--cmake/module/GenerateHeaders.cmake21
-rw-r--r--cmake/module/GenerateSetupNsi.cmake18
-rw-r--r--cmake/module/GetTargetInterface.cmake53
-rw-r--r--cmake/module/Maintenance.cmake151
-rw-r--r--cmake/module/ProcessConfigurations.cmake175
-rw-r--r--cmake/module/TestAppendRequiredLibraries.cmake92
-rw-r--r--cmake/module/TryAppendCXXFlags.cmake125
-rw-r--r--cmake/module/TryAppendLinkerFlag.cmake78
-rw-r--r--cmake/module/WarnAboutGlobalProperties.cmake36
18 files changed, 1381 insertions, 0 deletions
diff --git a/cmake/module/AddBoostIfNeeded.cmake b/cmake/module/AddBoostIfNeeded.cmake
new file mode 100644
index 0000000000..ecd0d6f2ab
--- /dev/null
+++ b/cmake/module/AddBoostIfNeeded.cmake
@@ -0,0 +1,78 @@
+# Copyright (c) 2023-present The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or https://opensource.org/license/mit/.
+
+function(add_boost_if_needed)
+ #[=[
+ TODO: Not all targets, which will be added in the future, require
+ Boost. Therefore, a proper check will be appropriate here.
+
+ Implementation notes:
+ Although only Boost headers are used to build Bitcoin Core,
+ we still leverage a standard CMake's approach to handle
+ dependencies, i.e., the Boost::headers "library".
+ A command target_link_libraries(target PRIVATE Boost::headers)
+ will propagate Boost::headers usage requirements to the target.
+ For Boost::headers such usage requirements is an include
+ directory and other added INTERFACE properties.
+ ]=]
+
+ # We cannot rely on find_package(Boost ...) to work properly without
+ # Boost_NO_BOOST_CMAKE set until we require a more recent Boost because
+ # upstream did not ship proper CMake files until 1.82.0.
+ # Until then, we rely on CMake's FindBoost module.
+ # See: https://cmake.org/cmake/help/latest/policy/CMP0167.html
+ if(POLICY CMP0167)
+ cmake_policy(SET CMP0167 OLD)
+ endif()
+ set(Boost_NO_BOOST_CMAKE ON)
+ find_package(Boost 1.73.0 REQUIRED)
+ mark_as_advanced(Boost_INCLUDE_DIR)
+ set_target_properties(Boost::headers PROPERTIES IMPORTED_GLOBAL TRUE)
+ target_compile_definitions(Boost::headers INTERFACE
+ # We don't use multi_index serialization.
+ BOOST_MULTI_INDEX_DISABLE_SERIALIZATION
+ )
+ if(DEFINED VCPKG_TARGET_TRIPLET)
+ # Workaround for https://github.com/microsoft/vcpkg/issues/36955.
+ target_compile_definitions(Boost::headers INTERFACE
+ BOOST_NO_USER_CONFIG
+ )
+ endif()
+
+ # Prevent use of std::unary_function, which was removed in C++17,
+ # and will generate warnings with newer compilers for Boost
+ # older than 1.80.
+ # See: https://github.com/boostorg/config/pull/430.
+ set(CMAKE_REQUIRED_DEFINITIONS -DBOOST_NO_CXX98_FUNCTION_BASE)
+ set(CMAKE_REQUIRED_INCLUDES ${Boost_INCLUDE_DIR})
+ include(CMakePushCheckState)
+ cmake_push_check_state()
+ include(TryAppendCXXFlags)
+ set(CMAKE_REQUIRED_FLAGS ${working_compiler_werror_flag})
+ set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
+ check_cxx_source_compiles("
+ #include <boost/config.hpp>
+ " NO_DIAGNOSTICS_BOOST_NO_CXX98_FUNCTION_BASE
+ )
+ cmake_pop_check_state()
+ if(NO_DIAGNOSTICS_BOOST_NO_CXX98_FUNCTION_BASE)
+ target_compile_definitions(Boost::headers INTERFACE
+ BOOST_NO_CXX98_FUNCTION_BASE
+ )
+ else()
+ set(CMAKE_REQUIRED_DEFINITIONS)
+ endif()
+
+ # Some package managers, such as vcpkg, vendor Boost.Test separately
+ # from the rest of the headers, so we have to check for it individually.
+ if(BUILD_TESTS AND DEFINED VCPKG_TARGET_TRIPLET)
+ list(APPEND CMAKE_REQUIRED_DEFINITIONS -DBOOST_TEST_NO_MAIN)
+ include(CheckIncludeFileCXX)
+ check_include_file_cxx(boost/test/included/unit_test.hpp HAVE_BOOST_INCLUDED_UNIT_TEST_H)
+ if(NOT HAVE_BOOST_INCLUDED_UNIT_TEST_H)
+ message(FATAL_ERROR "Building test_bitcoin executable requested but boost/test/included/unit_test.hpp header not available.")
+ endif()
+ endif()
+
+endfunction()
diff --git a/cmake/module/AddWindowsResources.cmake b/cmake/module/AddWindowsResources.cmake
new file mode 100644
index 0000000000..a9b4f51f73
--- /dev/null
+++ b/cmake/module/AddWindowsResources.cmake
@@ -0,0 +1,14 @@
+# Copyright (c) 2024-present The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or https://opensource.org/license/mit/.
+
+include_guard(GLOBAL)
+
+macro(add_windows_resources target rc_file)
+ if(WIN32)
+ target_sources(${target} PRIVATE ${rc_file})
+ set_property(SOURCE ${rc_file}
+ APPEND PROPERTY COMPILE_DEFINITIONS WINDRES_PREPROC
+ )
+ endif()
+endmacro()
diff --git a/cmake/module/CheckSourceCompilesAndLinks.cmake b/cmake/module/CheckSourceCompilesAndLinks.cmake
new file mode 100644
index 0000000000..88c897d524
--- /dev/null
+++ b/cmake/module/CheckSourceCompilesAndLinks.cmake
@@ -0,0 +1,39 @@
+# Copyright (c) 2023-present The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or https://opensource.org/license/mit/.
+
+include_guard(GLOBAL)
+include(CheckCXXSourceCompiles)
+include(CMakePushCheckState)
+
+# This avoids running the linker.
+set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
+
+macro(check_cxx_source_links source)
+ set(CMAKE_TRY_COMPILE_TARGET_TYPE EXECUTABLE)
+ check_cxx_source_compiles("${source}" ${ARGN})
+ set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
+endmacro()
+
+macro(check_cxx_source_compiles_with_flags flags source)
+ cmake_push_check_state(RESET)
+ set(CMAKE_REQUIRED_FLAGS ${flags})
+ list(JOIN CMAKE_REQUIRED_FLAGS " " CMAKE_REQUIRED_FLAGS)
+ check_cxx_source_compiles("${source}" ${ARGN})
+ cmake_pop_check_state()
+endmacro()
+
+macro(check_cxx_source_links_with_flags flags source)
+ cmake_push_check_state(RESET)
+ set(CMAKE_REQUIRED_FLAGS ${flags})
+ list(JOIN CMAKE_REQUIRED_FLAGS " " CMAKE_REQUIRED_FLAGS)
+ check_cxx_source_links("${source}" ${ARGN})
+ cmake_pop_check_state()
+endmacro()
+
+macro(check_cxx_source_links_with_libs libs source)
+ cmake_push_check_state(RESET)
+ set(CMAKE_REQUIRED_LIBRARIES "${libs}")
+ check_cxx_source_links("${source}" ${ARGN})
+ cmake_pop_check_state()
+endmacro()
diff --git a/cmake/module/FindBerkeleyDB.cmake b/cmake/module/FindBerkeleyDB.cmake
new file mode 100644
index 0000000000..03a3cce10c
--- /dev/null
+++ b/cmake/module/FindBerkeleyDB.cmake
@@ -0,0 +1,133 @@
+# Copyright (c) 2023-present The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or https://opensource.org/license/mit/.
+
+#[=======================================================================[
+FindBerkeleyDB
+--------------
+
+Finds the Berkeley DB headers and library.
+
+Imported Targets
+^^^^^^^^^^^^^^^^
+
+This module provides imported target ``BerkeleyDB::BerkeleyDB``, if
+Berkeley DB has been found.
+
+Result Variables
+^^^^^^^^^^^^^^^^
+
+This module defines the following variables:
+
+``BerkeleyDB_FOUND``
+ "True" if Berkeley DB found.
+
+``BerkeleyDB_VERSION``
+ The MAJOR.MINOR version of Berkeley DB found.
+
+#]=======================================================================]
+
+set(_BerkeleyDB_homebrew_prefix)
+if(CMAKE_HOST_APPLE)
+ find_program(HOMEBREW_EXECUTABLE brew)
+ if(HOMEBREW_EXECUTABLE)
+ # The Homebrew package manager installs the berkeley-db* packages as
+ # "keg-only", which means they are not symlinked into the default prefix.
+ # To find such a package, the find_path() and find_library() commands
+ # need additional path hints that are computed by Homebrew itself.
+ execute_process(
+ COMMAND ${HOMEBREW_EXECUTABLE} --prefix berkeley-db@4
+ OUTPUT_VARIABLE _BerkeleyDB_homebrew_prefix
+ ERROR_QUIET
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
+ endif()
+endif()
+
+find_path(BerkeleyDB_INCLUDE_DIR
+ NAMES db_cxx.h
+ HINTS ${_BerkeleyDB_homebrew_prefix}/include
+ PATH_SUFFIXES 4.8 48 db4.8 4 db4 5.3 db5.3 5 db5
+)
+mark_as_advanced(BerkeleyDB_INCLUDE_DIR)
+unset(_BerkeleyDB_homebrew_prefix)
+
+if(NOT BerkeleyDB_LIBRARY)
+ if(VCPKG_TARGET_TRIPLET)
+ # The vcpkg package manager installs the berkeleydb package with the same name
+ # of release and debug libraries. Therefore, the default search paths set by
+ # vcpkg's toolchain file cannot be used to search libraries as the debug one
+ # will always be found.
+ set(CMAKE_FIND_USE_CMAKE_PATH FALSE)
+ endif()
+
+ get_filename_component(_BerkeleyDB_lib_hint "${BerkeleyDB_INCLUDE_DIR}" DIRECTORY)
+
+ find_library(BerkeleyDB_LIBRARY_RELEASE
+ NAMES db_cxx-4.8 db4_cxx db48 db_cxx-5.3 db_cxx-5 db_cxx libdb48
+ NAMES_PER_DIR
+ HINTS ${_BerkeleyDB_lib_hint}
+ PATH_SUFFIXES lib
+ )
+ mark_as_advanced(BerkeleyDB_LIBRARY_RELEASE)
+
+ find_library(BerkeleyDB_LIBRARY_DEBUG
+ NAMES db_cxx-4.8 db4_cxx db48 db_cxx-5.3 db_cxx-5 db_cxx libdb48
+ NAMES_PER_DIR
+ HINTS ${_BerkeleyDB_lib_hint}
+ PATH_SUFFIXES debug/lib
+ )
+ mark_as_advanced(BerkeleyDB_LIBRARY_DEBUG)
+
+ unset(_BerkeleyDB_lib_hint)
+ unset(CMAKE_FIND_USE_CMAKE_PATH)
+
+ include(SelectLibraryConfigurations)
+ select_library_configurations(BerkeleyDB)
+ # The select_library_configurations() command sets BerkeleyDB_FOUND, but we
+ # want the one from the find_package_handle_standard_args() command below.
+ unset(BerkeleyDB_FOUND)
+endif()
+
+if(BerkeleyDB_INCLUDE_DIR)
+ file(STRINGS "${BerkeleyDB_INCLUDE_DIR}/db.h" _BerkeleyDB_version_strings REGEX "^#define[\t ]+DB_VERSION_(MAJOR|MINOR|PATCH)[ \t]+[0-9]+.*")
+ string(REGEX REPLACE ".*#define[\t ]+DB_VERSION_MAJOR[ \t]+([0-9]+).*" "\\1" _BerkeleyDB_version_major "${_BerkeleyDB_version_strings}")
+ string(REGEX REPLACE ".*#define[\t ]+DB_VERSION_MINOR[ \t]+([0-9]+).*" "\\1" _BerkeleyDB_version_minor "${_BerkeleyDB_version_strings}")
+ string(REGEX REPLACE ".*#define[\t ]+DB_VERSION_PATCH[ \t]+([0-9]+).*" "\\1" _BerkeleyDB_version_patch "${_BerkeleyDB_version_strings}")
+ unset(_BerkeleyDB_version_strings)
+ # The MAJOR.MINOR.PATCH version will be logged in the following find_package_handle_standard_args() command.
+ set(_BerkeleyDB_full_version ${_BerkeleyDB_version_major}.${_BerkeleyDB_version_minor}.${_BerkeleyDB_version_patch})
+ set(BerkeleyDB_VERSION ${_BerkeleyDB_version_major}.${_BerkeleyDB_version_minor})
+ unset(_BerkeleyDB_version_major)
+ unset(_BerkeleyDB_version_minor)
+ unset(_BerkeleyDB_version_patch)
+endif()
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(BerkeleyDB
+ REQUIRED_VARS BerkeleyDB_LIBRARY BerkeleyDB_INCLUDE_DIR
+ VERSION_VAR _BerkeleyDB_full_version
+)
+unset(_BerkeleyDB_full_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(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()
+ 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()
+endif()
diff --git a/cmake/module/FindLibevent.cmake b/cmake/module/FindLibevent.cmake
new file mode 100644
index 0000000000..901a4f3bd4
--- /dev/null
+++ b/cmake/module/FindLibevent.cmake
@@ -0,0 +1,80 @@
+# Copyright (c) 2024-present The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or https://opensource.org/license/mit/.
+
+#[=======================================================================[
+FindLibevent
+------------
+
+Finds the Libevent headers and libraries.
+
+This is a wrapper around find_package()/pkg_check_modules() commands that:
+ - facilitates searching in various build environments
+ - prints a standard log message
+
+#]=======================================================================]
+
+# Check whether evhttp_connection_get_peer expects const char**.
+# See https://github.com/libevent/libevent/commit/a18301a2bb160ff7c3ffaf5b7653c39ffe27b385
+function(check_evhttp_connection_get_peer target)
+ include(CMakePushCheckState)
+ cmake_push_check_state(RESET)
+ set(CMAKE_REQUIRED_LIBRARIES ${target})
+ include(CheckCXXSourceCompiles)
+ check_cxx_source_compiles("
+ #include <cstdint>
+ #include <event2/http.h>
+
+ int main()
+ {
+ evhttp_connection* conn = (evhttp_connection*)1;
+ const char* host;
+ uint16_t port;
+ evhttp_connection_get_peer(conn, &host, &port);
+ }
+ " HAVE_EVHTTP_CONNECTION_GET_PEER_CONST_CHAR
+ )
+ cmake_pop_check_state()
+ set(HAVE_EVHTTP_CONNECTION_GET_PEER_CONST_CHAR ${HAVE_EVHTTP_CONNECTION_GET_PEER_CONST_CHAR} PARENT_SCOPE)
+endfunction()
+
+
+include(FindPackageHandleStandardArgs)
+if(VCPKG_TARGET_TRIPLET)
+ find_package(Libevent ${Libevent_FIND_VERSION} NO_MODULE QUIET
+ COMPONENTS extra
+ )
+ find_package_handle_standard_args(Libevent
+ REQUIRED_VARS Libevent_DIR
+ VERSION_VAR Libevent_VERSION
+ )
+ check_evhttp_connection_get_peer(libevent::extra)
+ add_library(libevent::libevent ALIAS libevent::extra)
+ mark_as_advanced(Libevent_DIR)
+ mark_as_advanced(_event_h)
+ mark_as_advanced(_event_lib)
+else()
+ find_package(PkgConfig REQUIRED)
+ pkg_check_modules(libevent QUIET
+ IMPORTED_TARGET
+ libevent>=${Libevent_FIND_VERSION}
+ )
+ set(_libevent_required_vars libevent_LIBRARY_DIRS libevent_FOUND)
+ if(NOT WIN32)
+ pkg_check_modules(libevent_pthreads QUIET
+ IMPORTED_TARGET
+ libevent_pthreads>=${Libevent_FIND_VERSION}
+ )
+ list(APPEND _libevent_required_vars libevent_pthreads_FOUND)
+ endif()
+ find_package_handle_standard_args(Libevent
+ REQUIRED_VARS ${_libevent_required_vars}
+ VERSION_VAR libevent_VERSION
+ )
+ unset(_libevent_required_vars)
+ check_evhttp_connection_get_peer(PkgConfig::libevent)
+ add_library(libevent::libevent ALIAS PkgConfig::libevent)
+ if(NOT WIN32)
+ add_library(libevent::pthreads ALIAS PkgConfig::libevent_pthreads)
+ endif()
+endif()
diff --git a/cmake/module/FindMiniUPnPc.cmake b/cmake/module/FindMiniUPnPc.cmake
new file mode 100644
index 0000000000..34b94f05f1
--- /dev/null
+++ b/cmake/module/FindMiniUPnPc.cmake
@@ -0,0 +1,84 @@
+# Copyright (c) 2023-present The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or https://opensource.org/license/mit/.
+
+if(NOT MSVC)
+ find_package(PkgConfig REQUIRED)
+ 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
+)
diff --git a/cmake/module/FindQt.cmake b/cmake/module/FindQt.cmake
new file mode 100644
index 0000000000..2e43294a99
--- /dev/null
+++ b/cmake/module/FindQt.cmake
@@ -0,0 +1,66 @@
+# Copyright (c) 2024-present The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or https://opensource.org/license/mit/.
+
+#[=======================================================================[
+FindQt
+------
+
+Finds the Qt headers and libraries.
+
+This is a wrapper around find_package() command that:
+ - facilitates searching in various build environments
+ - prints a standard log message
+
+#]=======================================================================]
+
+set(_qt_homebrew_prefix)
+if(CMAKE_HOST_APPLE)
+ find_program(HOMEBREW_EXECUTABLE brew)
+ if(HOMEBREW_EXECUTABLE)
+ execute_process(
+ COMMAND ${HOMEBREW_EXECUTABLE} --prefix qt@${Qt_FIND_VERSION_MAJOR}
+ OUTPUT_VARIABLE _qt_homebrew_prefix
+ ERROR_QUIET
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
+ endif()
+endif()
+
+# Save CMAKE_FIND_ROOT_PATH_MODE_LIBRARY state.
+unset(_qt_find_root_path_mode_library_saved)
+if(DEFINED CMAKE_FIND_ROOT_PATH_MODE_LIBRARY)
+ set(_qt_find_root_path_mode_library_saved ${CMAKE_FIND_ROOT_PATH_MODE_LIBRARY})
+endif()
+
+# The Qt config files internally use find_library() calls for all
+# dependencies to ensure their availability. In turn, the find_library()
+# inspects the well-known locations on the file system; therefore, it must
+# be able to find platform-specific system libraries, for example:
+# /usr/x86_64-w64-mingw32/lib/libm.a or /usr/arm-linux-gnueabihf/lib/libm.a.
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH)
+
+find_package(Qt${Qt_FIND_VERSION_MAJOR} ${Qt_FIND_VERSION}
+ COMPONENTS ${Qt_FIND_COMPONENTS}
+ HINTS ${_qt_homebrew_prefix}
+ PATH_SUFFIXES Qt${Qt_FIND_VERSION_MAJOR} # Required on OpenBSD systems.
+)
+unset(_qt_homebrew_prefix)
+
+# Restore CMAKE_FIND_ROOT_PATH_MODE_LIBRARY state.
+if(DEFINED _qt_find_root_path_mode_library_saved)
+ set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ${_qt_find_root_path_mode_library_saved})
+ unset(_qt_find_root_path_mode_library_saved)
+else()
+ unset(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY)
+endif()
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(Qt
+ REQUIRED_VARS Qt${Qt_FIND_VERSION_MAJOR}_DIR
+ VERSION_VAR Qt${Qt_FIND_VERSION_MAJOR}_VERSION
+)
+
+foreach(component IN LISTS Qt_FIND_COMPONENTS ITEMS "")
+ mark_as_advanced(Qt${Qt_FIND_VERSION_MAJOR}${component}_DIR)
+endforeach()
diff --git a/cmake/module/FindUSDT.cmake b/cmake/module/FindUSDT.cmake
new file mode 100644
index 0000000000..0ba9a58fc1
--- /dev/null
+++ b/cmake/module/FindUSDT.cmake
@@ -0,0 +1,64 @@
+# Copyright (c) 2024-present The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or https://opensource.org/license/mit/.
+
+#[=======================================================================[
+FindUSDT
+--------
+
+Finds the Userspace, Statically Defined Tracing header(s).
+
+Imported Targets
+^^^^^^^^^^^^^^^^
+
+This module provides imported target ``USDT::headers``, if
+USDT has been found.
+
+Result Variables
+^^^^^^^^^^^^^^^^
+
+This module defines the following variables:
+
+``USDT_FOUND``
+ "True" if USDT found.
+
+#]=======================================================================]
+
+find_path(USDT_INCLUDE_DIR
+ NAMES sys/sdt.h
+)
+mark_as_advanced(USDT_INCLUDE_DIR)
+
+if(USDT_INCLUDE_DIR)
+ include(CMakePushCheckState)
+ cmake_push_check_state(RESET)
+
+ include(CheckCXXSourceCompiles)
+ set(CMAKE_REQUIRED_INCLUDES ${USDT_INCLUDE_DIR})
+ check_cxx_source_compiles("
+ #include <sys/sdt.h>
+
+ int main()
+ {
+ 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
+ )
+
+ cmake_pop_check_state()
+endif()
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(USDT
+ REQUIRED_VARS USDT_INCLUDE_DIR HAVE_USDT_H
+)
+
+if(USDT_FOUND AND NOT TARGET USDT::headers)
+ add_library(USDT::headers INTERFACE IMPORTED)
+ set_target_properties(USDT::headers PROPERTIES
+ INTERFACE_INCLUDE_DIRECTORIES "${USDT_INCLUDE_DIR}"
+ )
+ set(ENABLE_TRACING TRUE)
+endif()
diff --git a/cmake/module/FlagsSummary.cmake b/cmake/module/FlagsSummary.cmake
new file mode 100644
index 0000000000..91d1df90d9
--- /dev/null
+++ b/cmake/module/FlagsSummary.cmake
@@ -0,0 +1,74 @@
+# Copyright (c) 2024-present The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or https://opensource.org/license/mit/.
+
+include_guard(GLOBAL)
+
+function(indent_message header content indent_num)
+ if(indent_num GREATER 0)
+ string(REPEAT " " ${indent_num} indentation)
+ string(REPEAT "." ${indent_num} tail)
+ string(REGEX REPLACE "${tail}$" "" header "${header}")
+ endif()
+ message("${indentation}${header} ${content}")
+endfunction()
+
+# Print tools' flags on best-effort. Include the abstracted
+# CMake flags that we touch ourselves.
+function(print_flags_per_config config indent_num)
+ string(TOUPPER "${config}" config_uppercase)
+
+ include(GetTargetInterface)
+ get_target_interface(definitions "${config}" core_interface COMPILE_DEFINITIONS)
+ indent_message("Preprocessor defined macros ..........." "${definitions}" ${indent_num})
+
+ string(STRIP "${CMAKE_CXX_COMPILER_ARG1} ${CMAKE_CXX_FLAGS}" combined_cxx_flags)
+ string(STRIP "${combined_cxx_flags} ${CMAKE_CXX_FLAGS_${config_uppercase}}" combined_cxx_flags)
+ string(STRIP "${combined_cxx_flags} ${CMAKE_CXX${CMAKE_CXX_STANDARD}_STANDARD_COMPILE_OPTION}" combined_cxx_flags)
+ if(CMAKE_POSITION_INDEPENDENT_CODE)
+ string(JOIN " " combined_cxx_flags ${combined_cxx_flags} ${CMAKE_CXX_COMPILE_OPTIONS_PIC})
+ endif()
+ get_target_interface(core_cxx_flags "${config}" core_interface COMPILE_OPTIONS)
+ string(STRIP "${combined_cxx_flags} ${core_cxx_flags}" combined_cxx_flags)
+ string(STRIP "${combined_cxx_flags} ${APPEND_CPPFLAGS}" combined_cxx_flags)
+ string(STRIP "${combined_cxx_flags} ${APPEND_CXXFLAGS}" combined_cxx_flags)
+ indent_message("C++ compiler flags ...................." "${combined_cxx_flags}" ${indent_num})
+
+ string(STRIP "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${config_uppercase}}" combined_linker_flags)
+ string(STRIP "${combined_linker_flags} ${CMAKE_EXE_LINKER_FLAGS}" combined_linker_flags)
+ get_target_interface(common_link_options "${config}" core_interface LINK_OPTIONS)
+ string(STRIP "${combined_linker_flags} ${common_link_options}" combined_linker_flags)
+ if(CMAKE_CXX_LINK_PIE_SUPPORTED)
+ string(JOIN " " combined_linker_flags ${combined_linker_flags} ${CMAKE_CXX_LINK_OPTIONS_PIE})
+ endif()
+ string(STRIP "${combined_linker_flags} ${APPEND_LDFLAGS}" combined_linker_flags)
+ indent_message("Linker flags .........................." "${combined_linker_flags}" ${indent_num})
+endfunction()
+
+function(flags_summary)
+ get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
+ if(is_multi_config)
+ list(JOIN CMAKE_CONFIGURATION_TYPES ", " configs)
+ message("Available build configurations ........ ${configs}")
+ if(CMAKE_GENERATOR MATCHES "Visual Studio")
+ set(default_config "Debug")
+ else()
+ list(GET CMAKE_CONFIGURATION_TYPES 0 default_config)
+ endif()
+ message("Default build configuration ........... ${default_config}")
+ foreach(config IN LISTS CMAKE_CONFIGURATION_TYPES)
+ message("")
+ message("'${config}' build configuration:")
+ print_flags_per_config("${config}" 2)
+ endforeach()
+ else()
+ message("CMAKE_BUILD_TYPE ...................... ${CMAKE_BUILD_TYPE}")
+ print_flags_per_config("${CMAKE_BUILD_TYPE}" 0)
+ endif()
+ message("")
+ message([=[
+NOTE: The summary above may not exactly match the final applied build flags
+ if any additional CMAKE_* or environment variables have been modified.
+ To see the exact flags applied, build with the --verbose option.
+]=])
+endfunction()
diff --git a/cmake/module/GenerateHeaders.cmake b/cmake/module/GenerateHeaders.cmake
new file mode 100644
index 0000000000..c69007acb6
--- /dev/null
+++ b/cmake/module/GenerateHeaders.cmake
@@ -0,0 +1,21 @@
+# Copyright (c) 2023-present The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or https://opensource.org/license/mit/.
+
+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 ${PROJECT_SOURCE_DIR}/cmake/script/GenerateHeaderFromJson.cmake
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${json_source_relpath} ${PROJECT_SOURCE_DIR}/cmake/script/GenerateHeaderFromJson.cmake
+ VERBATIM
+ )
+endfunction()
+
+function(generate_header_from_raw raw_source_relpath raw_namespace)
+ 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 -DRAW_NAMESPACE=${raw_namespace} -P ${PROJECT_SOURCE_DIR}/cmake/script/GenerateHeaderFromRaw.cmake
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${raw_source_relpath} ${PROJECT_SOURCE_DIR}/cmake/script/GenerateHeaderFromRaw.cmake
+ VERBATIM
+ )
+endfunction()
diff --git a/cmake/module/GenerateSetupNsi.cmake b/cmake/module/GenerateSetupNsi.cmake
new file mode 100644
index 0000000000..3c358c5495
--- /dev/null
+++ b/cmake/module/GenerateSetupNsi.cmake
@@ -0,0 +1,18 @@
+# Copyright (c) 2023-present The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or https://opensource.org/license/mit/.
+
+function(generate_setup_nsi)
+ set(abs_top_srcdir ${PROJECT_SOURCE_DIR})
+ set(abs_top_builddir ${PROJECT_BINARY_DIR})
+ set(PACKAGE_URL ${PROJECT_HOMEPAGE_URL})
+ set(PACKAGE_TARNAME "bitcoin")
+ set(BITCOIN_GUI_NAME "bitcoin-qt")
+ set(BITCOIN_DAEMON_NAME "bitcoind")
+ set(BITCOIN_CLI_NAME "bitcoin-cli")
+ set(BITCOIN_TX_NAME "bitcoin-tx")
+ set(BITCOIN_WALLET_TOOL_NAME "bitcoin-wallet")
+ set(BITCOIN_TEST_NAME "test_bitcoin")
+ set(EXEEXT ${CMAKE_EXECUTABLE_SUFFIX})
+ configure_file(${PROJECT_SOURCE_DIR}/share/setup.nsi.in ${PROJECT_BINARY_DIR}/bitcoin-win64-setup.nsi USE_SOURCE_PERMISSIONS @ONLY)
+endfunction()
diff --git a/cmake/module/GetTargetInterface.cmake b/cmake/module/GetTargetInterface.cmake
new file mode 100644
index 0000000000..1e455d456b
--- /dev/null
+++ b/cmake/module/GetTargetInterface.cmake
@@ -0,0 +1,53 @@
+# Copyright (c) 2023-present The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or https://opensource.org/license/mit/.
+
+include_guard(GLOBAL)
+
+# Evaluates config-specific generator expressions in a list.
+# Recognizable patterns are:
+# - $<$<CONFIG:[config]>:[value]>
+# - $<$<NOT:$<CONFIG:[config]>>:[value]>
+function(evaluate_generator_expressions list config)
+ set(input ${${list}})
+ set(result)
+ foreach(token IN LISTS input)
+ if(token MATCHES "\\$<\\$<CONFIG:([^>]+)>:([^>]+)>")
+ if(CMAKE_MATCH_1 STREQUAL config)
+ list(APPEND result ${CMAKE_MATCH_2})
+ endif()
+ elseif(token MATCHES "\\$<\\$<NOT:\\$<CONFIG:([^>]+)>>:([^>]+)>")
+ if(NOT CMAKE_MATCH_1 STREQUAL config)
+ list(APPEND result ${CMAKE_MATCH_2})
+ endif()
+ else()
+ list(APPEND result ${token})
+ endif()
+ endforeach()
+ set(${list} ${result} PARENT_SCOPE)
+endfunction()
+
+
+# Gets target's interface properties recursively.
+function(get_target_interface var config target property)
+ get_target_property(result ${target} INTERFACE_${property})
+ if(result)
+ evaluate_generator_expressions(result "${config}")
+ list(JOIN result " " result)
+ else()
+ set(result)
+ endif()
+
+ get_target_property(dependencies ${target} INTERFACE_LINK_LIBRARIES)
+ if(dependencies)
+ evaluate_generator_expressions(dependencies "${config}")
+ foreach(dependency IN LISTS dependencies)
+ if(TARGET ${dependency})
+ get_target_interface(dep_result "${config}" ${dependency} ${property})
+ string(STRIP "${result} ${dep_result}" result)
+ endif()
+ endforeach()
+ endif()
+
+ set(${var} "${result}" PARENT_SCOPE)
+endfunction()
diff --git a/cmake/module/Maintenance.cmake b/cmake/module/Maintenance.cmake
new file mode 100644
index 0000000000..456419b722
--- /dev/null
+++ b/cmake/module/Maintenance.cmake
@@ -0,0 +1,151 @@
+# Copyright (c) 2023-present The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or https://opensource.org/license/mit/.
+
+include_guard(GLOBAL)
+
+function(setup_split_debug_script)
+ if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux")
+ set(OBJCOPY ${CMAKE_OBJCOPY})
+ set(STRIP ${CMAKE_STRIP})
+ configure_file(
+ contrib/devtools/split-debug.sh.in split-debug.sh
+ FILE_PERMISSIONS OWNER_READ OWNER_EXECUTE
+ GROUP_READ GROUP_EXECUTE
+ WORLD_READ
+ @ONLY
+ )
+ endif()
+endfunction()
+
+function(add_maintenance_targets)
+ if(NOT PYTHON_COMMAND)
+ return()
+ endif()
+
+ if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
+ set(exe_format MACHO)
+ elseif(WIN32)
+ set(exe_format PE)
+ else()
+ set(exe_format ELF)
+ endif()
+
+ # In CMake, the components of the compiler invocation are separated into distinct variables:
+ # - CMAKE_CXX_COMPILER: the full path to the compiler binary itself (e.g., /usr/bin/clang++).
+ # - CMAKE_CXX_COMPILER_ARG1: a string containing initial compiler options (e.g., --target=x86_64-apple-darwin -nostdlibinc).
+ # By concatenating these variables, we form the complete command line to be passed to a Python script via the CXX environment variable.
+ string(STRIP "${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1}" cxx_compiler_command)
+ add_custom_target(test-security-check
+ COMMAND ${CMAKE_COMMAND} -E env CXX=${cxx_compiler_command} CXXFLAGS=${CMAKE_CXX_FLAGS} LDFLAGS=${CMAKE_EXE_LINKER_FLAGS} ${PYTHON_COMMAND} ${PROJECT_SOURCE_DIR}/contrib/devtools/test-security-check.py TestSecurityChecks.test_${exe_format}
+ COMMAND ${CMAKE_COMMAND} -E env CXX=${cxx_compiler_command} CXXFLAGS=${CMAKE_CXX_FLAGS} LDFLAGS=${CMAKE_EXE_LINKER_FLAGS} ${PYTHON_COMMAND} ${PROJECT_SOURCE_DIR}/contrib/devtools/test-symbol-check.py TestSymbolChecks.test_${exe_format}
+ VERBATIM
+ )
+
+ foreach(target IN ITEMS bitcoind bitcoin-qt bitcoin-cli bitcoin-tx bitcoin-util bitcoin-wallet test_bitcoin bench_bitcoin)
+ if(TARGET ${target})
+ list(APPEND executables $<TARGET_FILE:${target}>)
+ endif()
+ endforeach()
+
+ add_custom_target(check-symbols
+ COMMAND ${CMAKE_COMMAND} -E echo "Running symbol and dynamic library checks..."
+ COMMAND ${PYTHON_COMMAND} ${PROJECT_SOURCE_DIR}/contrib/devtools/symbol-check.py ${executables}
+ VERBATIM
+ )
+
+ if(ENABLE_HARDENING)
+ add_custom_target(check-security
+ COMMAND ${CMAKE_COMMAND} -E echo "Checking binary security..."
+ COMMAND ${PYTHON_COMMAND} ${PROJECT_SOURCE_DIR}/contrib/devtools/security-check.py ${executables}
+ VERBATIM
+ )
+ else()
+ add_custom_target(check-security)
+ endif()
+endfunction()
+
+function(add_windows_deploy_target)
+ if(MINGW AND TARGET bitcoin-qt AND TARGET bitcoind AND TARGET bitcoin-cli AND TARGET bitcoin-tx AND TARGET bitcoin-wallet AND TARGET bitcoin-util AND TARGET test_bitcoin)
+ # TODO: Consider replacing this code with the CPack NSIS Generator.
+ # See https://cmake.org/cmake/help/latest/cpack_gen/nsis.html
+ include(GenerateSetupNsi)
+ generate_setup_nsi()
+ add_custom_command(
+ OUTPUT ${PROJECT_BINARY_DIR}/bitcoin-win64-setup.exe
+ COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/release
+ COMMAND ${CMAKE_STRIP} $<TARGET_FILE:bitcoin-qt> -o ${PROJECT_BINARY_DIR}/release/$<TARGET_FILE_NAME:bitcoin-qt>
+ COMMAND ${CMAKE_STRIP} $<TARGET_FILE:bitcoind> -o ${PROJECT_BINARY_DIR}/release/$<TARGET_FILE_NAME:bitcoind>
+ COMMAND ${CMAKE_STRIP} $<TARGET_FILE:bitcoin-cli> -o ${PROJECT_BINARY_DIR}/release/$<TARGET_FILE_NAME:bitcoin-cli>
+ COMMAND ${CMAKE_STRIP} $<TARGET_FILE:bitcoin-tx> -o ${PROJECT_BINARY_DIR}/release/$<TARGET_FILE_NAME:bitcoin-tx>
+ COMMAND ${CMAKE_STRIP} $<TARGET_FILE:bitcoin-wallet> -o ${PROJECT_BINARY_DIR}/release/$<TARGET_FILE_NAME:bitcoin-wallet>
+ COMMAND ${CMAKE_STRIP} $<TARGET_FILE:bitcoin-util> -o ${PROJECT_BINARY_DIR}/release/$<TARGET_FILE_NAME:bitcoin-util>
+ COMMAND ${CMAKE_STRIP} $<TARGET_FILE:test_bitcoin> -o ${PROJECT_BINARY_DIR}/release/$<TARGET_FILE_NAME:test_bitcoin>
+ COMMAND makensis -V2 ${PROJECT_BINARY_DIR}/bitcoin-win64-setup.nsi
+ VERBATIM
+ )
+ add_custom_target(deploy DEPENDS ${PROJECT_BINARY_DIR}/bitcoin-win64-setup.exe)
+ endif()
+endfunction()
+
+function(add_macos_deploy_target)
+ if(CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND TARGET bitcoin-qt)
+ set(macos_app "Bitcoin-Qt.app")
+ # Populate Contents subdirectory.
+ configure_file(${PROJECT_SOURCE_DIR}/share/qt/Info.plist.in ${macos_app}/Contents/Info.plist NO_SOURCE_PERMISSIONS)
+ file(CONFIGURE OUTPUT ${macos_app}/Contents/PkgInfo CONTENT "APPL????")
+ # Populate Contents/Resources subdirectory.
+ file(CONFIGURE OUTPUT ${macos_app}/Contents/Resources/empty.lproj CONTENT "")
+ configure_file(${PROJECT_SOURCE_DIR}/src/qt/res/icons/bitcoin.icns ${macos_app}/Contents/Resources/bitcoin.icns NO_SOURCE_PERMISSIONS COPYONLY)
+ file(CONFIGURE OUTPUT ${macos_app}/Contents/Resources/Base.lproj/InfoPlist.strings
+ CONTENT "{ CFBundleDisplayName = \"@PACKAGE_NAME@\"; CFBundleName = \"@PACKAGE_NAME@\"; }"
+ )
+
+ add_custom_command(
+ OUTPUT ${PROJECT_BINARY_DIR}/${macos_app}/Contents/MacOS/Bitcoin-Qt
+ COMMAND ${CMAKE_COMMAND} --install ${PROJECT_BINARY_DIR} --config $<CONFIG> --component GUI --prefix ${macos_app}/Contents/MacOS --strip
+ COMMAND ${CMAKE_COMMAND} -E rename ${macos_app}/Contents/MacOS/bin/$<TARGET_FILE_NAME:bitcoin-qt> ${macos_app}/Contents/MacOS/Bitcoin-Qt
+ COMMAND ${CMAKE_COMMAND} -E rm -rf ${macos_app}/Contents/MacOS/bin
+ VERBATIM
+ )
+
+ string(REPLACE " " "-" osx_volname ${PACKAGE_NAME})
+ if(CMAKE_HOST_APPLE)
+ add_custom_command(
+ OUTPUT ${PROJECT_BINARY_DIR}/${osx_volname}.zip
+ COMMAND ${PYTHON_COMMAND} ${PROJECT_SOURCE_DIR}/contrib/macdeploy/macdeployqtplus ${macos_app} ${osx_volname} -translations-dir=${QT_TRANSLATIONS_DIR} -zip
+ DEPENDS ${PROJECT_BINARY_DIR}/${macos_app}/Contents/MacOS/Bitcoin-Qt
+ VERBATIM
+ )
+ add_custom_target(deploydir
+ DEPENDS ${PROJECT_BINARY_DIR}/${osx_volname}.zip
+ )
+ add_custom_target(deploy
+ DEPENDS ${PROJECT_BINARY_DIR}/${osx_volname}.zip
+ )
+ else()
+ add_custom_command(
+ OUTPUT ${PROJECT_BINARY_DIR}/dist/${macos_app}/Contents/MacOS/Bitcoin-Qt
+ COMMAND OBJDUMP=${CMAKE_OBJDUMP} ${PYTHON_COMMAND} ${PROJECT_SOURCE_DIR}/contrib/macdeploy/macdeployqtplus ${macos_app} ${osx_volname} -translations-dir=${QT_TRANSLATIONS_DIR}
+ DEPENDS ${PROJECT_BINARY_DIR}/${macos_app}/Contents/MacOS/Bitcoin-Qt
+ VERBATIM
+ )
+ add_custom_target(deploydir
+ DEPENDS ${PROJECT_BINARY_DIR}/dist/${macos_app}/Contents/MacOS/Bitcoin-Qt
+ )
+
+ find_program(ZIP_COMMAND zip REQUIRED)
+ add_custom_command(
+ OUTPUT ${PROJECT_BINARY_DIR}/dist/${osx_volname}.zip
+ WORKING_DIRECTORY dist
+ COMMAND ${PROJECT_SOURCE_DIR}/cmake/script/macos_zip.sh ${ZIP_COMMAND} ${osx_volname}.zip
+ VERBATIM
+ )
+ add_custom_target(deploy
+ DEPENDS ${PROJECT_BINARY_DIR}/dist/${osx_volname}.zip
+ )
+ endif()
+ add_dependencies(deploydir bitcoin-qt)
+ add_dependencies(deploy deploydir)
+ endif()
+endfunction()
diff --git a/cmake/module/ProcessConfigurations.cmake b/cmake/module/ProcessConfigurations.cmake
new file mode 100644
index 0000000000..7e2fc0080e
--- /dev/null
+++ b/cmake/module/ProcessConfigurations.cmake
@@ -0,0 +1,175 @@
+# Copyright (c) 2023-present The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or https://opensource.org/license/mit/.
+
+include_guard(GLOBAL)
+
+include(TryAppendCXXFlags)
+
+macro(normalize_string string)
+ string(REGEX REPLACE " +" " " ${string} "${${string}}")
+ string(STRIP "${${string}}" ${string})
+endmacro()
+
+function(are_flags_overridden flags_var result_var)
+ normalize_string(${flags_var})
+ normalize_string(${flags_var}_INIT)
+ if(${flags_var} STREQUAL ${flags_var}_INIT)
+ set(${result_var} FALSE PARENT_SCOPE)
+ else()
+ set(${result_var} TRUE PARENT_SCOPE)
+ endif()
+endfunction()
+
+
+# Removes duplicated flags. The relative order of flags is preserved.
+# If duplicates are encountered, only the last instance is preserved.
+function(deduplicate_flags flags)
+ separate_arguments(${flags})
+ list(REVERSE ${flags})
+ list(REMOVE_DUPLICATES ${flags})
+ list(REVERSE ${flags})
+ list(JOIN ${flags} " " result)
+ set(${flags} "${result}" PARENT_SCOPE)
+endfunction()
+
+
+function(get_all_configs output)
+ get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
+ if(is_multi_config)
+ set(all_configs ${CMAKE_CONFIGURATION_TYPES})
+ else()
+ get_property(all_configs CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS)
+ if(NOT all_configs)
+ # See https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html#default-and-custom-configurations
+ set(all_configs Debug Release RelWithDebInfo MinSizeRel)
+ endif()
+ endif()
+ set(${output} "${all_configs}" PARENT_SCOPE)
+endfunction()
+
+
+#[=[
+Set the default build configuration.
+
+See: https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html#build-configurations.
+
+On single-configuration generators, this function sets the CMAKE_BUILD_TYPE variable to
+the default build configuration, which can be overridden by the user at configure time if needed.
+
+On multi-configuration generators, this function rearranges the CMAKE_CONFIGURATION_TYPES list,
+ensuring that the default build configuration appears first while maintaining the order of the
+remaining configurations. The user can choose a build configuration at build time.
+]=]
+function(set_default_config config)
+ get_all_configs(all_configs)
+ if(NOT ${config} IN_LIST all_configs)
+ message(FATAL_ERROR "The default config is \"${config}\", but must be one of ${all_configs}.")
+ endif()
+
+ list(REMOVE_ITEM all_configs ${config})
+ list(PREPEND all_configs ${config})
+
+ get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
+ if(is_multi_config)
+ get_property(help_string CACHE CMAKE_CONFIGURATION_TYPES PROPERTY HELPSTRING)
+ set(CMAKE_CONFIGURATION_TYPES "${all_configs}" CACHE STRING "${help_string}" FORCE)
+ # Also see https://gitlab.kitware.com/cmake/cmake/-/issues/19512.
+ set(CMAKE_TRY_COMPILE_CONFIGURATION "${config}" PARENT_SCOPE)
+ else()
+ set_property(CACHE CMAKE_BUILD_TYPE PROPERTY
+ STRINGS "${all_configs}"
+ )
+ if(NOT CMAKE_BUILD_TYPE)
+ message(STATUS "Setting build type to \"${config}\" as none was specified")
+ get_property(help_string CACHE CMAKE_BUILD_TYPE PROPERTY HELPSTRING)
+ set(CMAKE_BUILD_TYPE "${config}" CACHE STRING "${help_string}" FORCE)
+ endif()
+ set(CMAKE_TRY_COMPILE_CONFIGURATION "${CMAKE_BUILD_TYPE}" PARENT_SCOPE)
+ endif()
+endfunction()
+
+function(remove_cxx_flag_from_all_configs flag)
+ get_all_configs(all_configs)
+ foreach(config IN LISTS all_configs)
+ string(TOUPPER "${config}" config_uppercase)
+ set(flags "${CMAKE_CXX_FLAGS_${config_uppercase}}")
+ separate_arguments(flags)
+ list(FILTER flags EXCLUDE REGEX "${flag}")
+ list(JOIN flags " " new_flags)
+ set(CMAKE_CXX_FLAGS_${config_uppercase} "${new_flags}" PARENT_SCOPE)
+ set(CMAKE_CXX_FLAGS_${config_uppercase} "${new_flags}"
+ CACHE STRING
+ "Flags used by the CXX compiler during ${config_uppercase} builds."
+ FORCE
+ )
+ endforeach()
+endfunction()
+
+function(replace_cxx_flag_in_config config old_flag new_flag)
+ string(TOUPPER "${config}" config_uppercase)
+ string(REGEX REPLACE "(^| )${old_flag}( |$)" "\\1${new_flag}\\2" new_flags "${CMAKE_CXX_FLAGS_${config_uppercase}}")
+ set(CMAKE_CXX_FLAGS_${config_uppercase} "${new_flags}" PARENT_SCOPE)
+ set(CMAKE_CXX_FLAGS_${config_uppercase} "${new_flags}"
+ CACHE STRING
+ "Flags used by the CXX compiler during ${config_uppercase} builds."
+ FORCE
+ )
+endfunction()
+
+set_default_config(RelWithDebInfo)
+
+# Redefine/adjust per-configuration flags.
+target_compile_definitions(core_interface_debug INTERFACE
+ DEBUG
+ DEBUG_LOCKORDER
+ DEBUG_LOCKCONTENTION
+ RPC_DOC_CHECK
+ ABORT_ON_FAILED_ASSUME
+)
+# We leave assertions on.
+if(MSVC)
+ remove_cxx_flag_from_all_configs(/DNDEBUG)
+else()
+ remove_cxx_flag_from_all_configs(-DNDEBUG)
+
+ # Adjust flags used by the CXX compiler during RELEASE builds.
+ # Prefer -O2 optimization level. (-O3 is CMake's default for Release for many compilers.)
+ replace_cxx_flag_in_config(Release -O3 -O2)
+
+ are_flags_overridden(CMAKE_CXX_FLAGS_DEBUG cxx_flags_debug_overridden)
+ if(NOT cxx_flags_debug_overridden)
+ # Redefine flags used by the CXX compiler during DEBUG builds.
+ try_append_cxx_flags("-g3" RESULT_VAR compiler_supports_g3)
+ if(compiler_supports_g3)
+ replace_cxx_flag_in_config(Debug -g -g3)
+ endif()
+ unset(compiler_supports_g3)
+
+ try_append_cxx_flags("-ftrapv" RESULT_VAR compiler_supports_ftrapv)
+ if(compiler_supports_ftrapv)
+ string(PREPEND CMAKE_CXX_FLAGS_DEBUG "-ftrapv ")
+ endif()
+ unset(compiler_supports_ftrapv)
+
+ string(PREPEND CMAKE_CXX_FLAGS_DEBUG "-O0 ")
+
+ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}"
+ CACHE STRING
+ "Flags used by the CXX compiler during DEBUG builds."
+ FORCE
+ )
+ endif()
+ unset(cxx_flags_debug_overridden)
+endif()
+
+set(CMAKE_CXX_FLAGS_COVERAGE "-g -Og --coverage")
+set(CMAKE_OBJCXX_FLAGS_COVERAGE "-g -Og --coverage")
+set(CMAKE_EXE_LINKER_FLAGS_COVERAGE "--coverage")
+set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE "--coverage")
+get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
+if(is_multi_config)
+ if(NOT "Coverage" IN_LIST CMAKE_CONFIGURATION_TYPES)
+ list(APPEND CMAKE_CONFIGURATION_TYPES Coverage)
+ endif()
+endif()
diff --git a/cmake/module/TestAppendRequiredLibraries.cmake b/cmake/module/TestAppendRequiredLibraries.cmake
new file mode 100644
index 0000000000..5352102c7a
--- /dev/null
+++ b/cmake/module/TestAppendRequiredLibraries.cmake
@@ -0,0 +1,92 @@
+# Copyright (c) 2023-present The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or https://opensource.org/license/mit/.
+
+include_guard(GLOBAL)
+
+# Illumos/SmartOS requires linking with -lsocket if
+# using getifaddrs & freeifaddrs.
+# See:
+# - https://github.com/bitcoin/bitcoin/pull/21486
+# - https://smartos.org/man/3socket/getifaddrs
+function(test_append_socket_library target)
+ if (NOT TARGET ${target})
+ message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION}() called with non-existent target \"${target}\".")
+ endif()
+
+ set(check_socket_source "
+ #include <sys/types.h>
+ #include <ifaddrs.h>
+
+ int main() {
+ struct ifaddrs* ifaddr;
+ getifaddrs(&ifaddr);
+ freeifaddrs(ifaddr);
+ }
+ ")
+
+ include(CheckSourceCompilesAndLinks)
+ check_cxx_source_links("${check_socket_source}" IFADDR_LINKS_WITHOUT_LIBSOCKET)
+ if(NOT IFADDR_LINKS_WITHOUT_LIBSOCKET)
+ check_cxx_source_links_with_libs(socket "${check_socket_source}" IFADDR_NEEDS_LINK_TO_LIBSOCKET)
+ if(IFADDR_NEEDS_LINK_TO_LIBSOCKET)
+ target_link_libraries(${target} INTERFACE socket)
+ else()
+ message(FATAL_ERROR "Cannot figure out how to use getifaddrs/freeifaddrs.")
+ endif()
+ endif()
+ set(HAVE_DECL_GETIFADDRS TRUE PARENT_SCOPE)
+ set(HAVE_DECL_FREEIFADDRS TRUE PARENT_SCOPE)
+endfunction()
+
+# Clang, when building for 32-bit,
+# and linking against libstdc++, requires linking with
+# -latomic if using the C++ atomic library.
+# Can be tested with: clang++ -std=c++20 test.cpp -m32
+#
+# Sourced from http://bugs.debian.org/797228
+function(test_append_atomic_library target)
+ if (NOT TARGET ${target})
+ message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION}() called with non-existent target \"${target}\".")
+ endif()
+
+ set(check_atomic_source "
+ #include <atomic>
+ #include <cstdint>
+ #include <chrono>
+
+ using namespace std::chrono_literals;
+
+ int main() {
+ std::atomic<bool> lock{true};
+ lock.exchange(false);
+
+ std::atomic<std::chrono::seconds> t{0s};
+ t.store(2s);
+ auto t1 = t.load();
+ t.compare_exchange_strong(t1, 3s);
+
+ std::atomic<double> d{};
+ d.store(3.14);
+ auto d1 = d.load();
+
+ std::atomic<int64_t> a{};
+ int64_t v = 5;
+ int64_t r = a.fetch_add(v);
+ return static_cast<int>(r);
+ }
+ ")
+
+ include(CheckSourceCompilesAndLinks)
+ check_cxx_source_links("${check_atomic_source}" STD_ATOMIC_LINKS_WITHOUT_LIBATOMIC)
+ if(STD_ATOMIC_LINKS_WITHOUT_LIBATOMIC)
+ return()
+ endif()
+
+ check_cxx_source_links_with_libs(atomic "${check_atomic_source}" STD_ATOMIC_NEEDS_LINK_TO_LIBATOMIC)
+ if(STD_ATOMIC_NEEDS_LINK_TO_LIBATOMIC)
+ target_link_libraries(${target} INTERFACE atomic)
+ else()
+ message(FATAL_ERROR "Cannot figure out how to use std::atomic.")
+ endif()
+endfunction()
diff --git a/cmake/module/TryAppendCXXFlags.cmake b/cmake/module/TryAppendCXXFlags.cmake
new file mode 100644
index 0000000000..c07455e89e
--- /dev/null
+++ b/cmake/module/TryAppendCXXFlags.cmake
@@ -0,0 +1,125 @@
+# Copyright (c) 2023-present The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or https://opensource.org/license/mit/.
+
+include_guard(GLOBAL)
+include(CheckCXXSourceCompiles)
+
+#[=[
+Add language-wide flags, which will be passed to all invocations of the compiler.
+This includes invocations that drive compiling and those that drive linking.
+
+Usage examples:
+
+ try_append_cxx_flags("-Wformat -Wformat-security" VAR warn_cxx_flags)
+
+
+ try_append_cxx_flags("-Wsuggest-override" VAR warn_cxx_flags
+ SOURCE "struct A { virtual void f(); }; struct B : A { void f() final; };"
+ )
+
+
+ try_append_cxx_flags("-fsanitize=${SANITIZERS}" TARGET core_interface
+ RESULT_VAR cxx_supports_sanitizers
+ )
+ if(NOT cxx_supports_sanitizers)
+ message(FATAL_ERROR "Compiler did not accept requested flags.")
+ endif()
+
+
+ try_append_cxx_flags("-Wunused-parameter" TARGET core_interface
+ IF_CHECK_PASSED "-Wno-unused-parameter"
+ )
+
+
+In configuration output, this function prints a string by the following pattern:
+
+ -- Performing Test CXX_SUPPORTS_[flags]
+ -- Performing Test CXX_SUPPORTS_[flags] - Success
+
+]=]
+function(try_append_cxx_flags flags)
+ cmake_parse_arguments(PARSE_ARGV 1
+ TACXXF # prefix
+ "SKIP_LINK" # options
+ "TARGET;VAR;SOURCE;RESULT_VAR" # one_value_keywords
+ "IF_CHECK_PASSED" # multi_value_keywords
+ )
+
+ set(flags_as_string "${flags}")
+ separate_arguments(flags)
+
+ string(MAKE_C_IDENTIFIER "${flags_as_string}" id_string)
+ string(TOUPPER "${id_string}" id_string)
+
+ set(source "int main() { return 0; }")
+ if(DEFINED TACXXF_SOURCE AND NOT TACXXF_SOURCE STREQUAL source)
+ set(source "${TACXXF_SOURCE}")
+ string(SHA256 source_hash "${source}")
+ string(SUBSTRING ${source_hash} 0 4 source_hash_head)
+ string(APPEND id_string _${source_hash_head})
+ endif()
+
+ # This avoids running a linker.
+ set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
+ set(CMAKE_REQUIRED_FLAGS "${flags_as_string} ${working_compiler_werror_flag}")
+ set(compiler_result CXX_SUPPORTS_${id_string})
+ check_cxx_source_compiles("${source}" ${compiler_result})
+
+ if(${compiler_result})
+ if(DEFINED TACXXF_IF_CHECK_PASSED)
+ if(DEFINED TACXXF_TARGET)
+ target_compile_options(${TACXXF_TARGET} INTERFACE ${TACXXF_IF_CHECK_PASSED})
+ endif()
+ if(DEFINED TACXXF_VAR)
+ string(STRIP "${${TACXXF_VAR}} ${TACXXF_IF_CHECK_PASSED}" ${TACXXF_VAR})
+ endif()
+ else()
+ if(DEFINED TACXXF_TARGET)
+ target_compile_options(${TACXXF_TARGET} INTERFACE ${flags})
+ endif()
+ if(DEFINED TACXXF_VAR)
+ string(STRIP "${${TACXXF_VAR}} ${flags_as_string}" ${TACXXF_VAR})
+ endif()
+ endif()
+ endif()
+
+ if(DEFINED TACXXF_VAR)
+ set(${TACXXF_VAR} "${${TACXXF_VAR}}" PARENT_SCOPE)
+ endif()
+
+ if(DEFINED TACXXF_RESULT_VAR)
+ set(${TACXXF_RESULT_VAR} "${${compiler_result}}" PARENT_SCOPE)
+ endif()
+
+ if(NOT ${compiler_result} OR TACXXF_SKIP_LINK)
+ return()
+ endif()
+
+ # This forces running a linker.
+ set(CMAKE_TRY_COMPILE_TARGET_TYPE EXECUTABLE)
+ set(CMAKE_REQUIRED_FLAGS "${flags_as_string}")
+ set(CMAKE_REQUIRED_LINK_OPTIONS ${working_linker_werror_flag})
+ set(linker_result LINKER_SUPPORTS_${id_string})
+ check_cxx_source_compiles("${source}" ${linker_result})
+
+ if(${linker_result})
+ if(DEFINED TACXXF_IF_CHECK_PASSED)
+ if(DEFINED TACXXF_TARGET)
+ target_link_options(${TACXXF_TARGET} INTERFACE ${TACXXF_IF_CHECK_PASSED})
+ endif()
+ else()
+ if(DEFINED TACXXF_TARGET)
+ target_link_options(${TACXXF_TARGET} INTERFACE ${flags})
+ endif()
+ endif()
+ else()
+ message(WARNING "'${flags_as_string}' fail(s) to link.")
+ endif()
+endfunction()
+
+if(MSVC)
+ try_append_cxx_flags("/WX /options:strict" VAR working_compiler_werror_flag SKIP_LINK)
+else()
+ try_append_cxx_flags("-Werror" VAR working_compiler_werror_flag SKIP_LINK)
+endif()
diff --git a/cmake/module/TryAppendLinkerFlag.cmake b/cmake/module/TryAppendLinkerFlag.cmake
new file mode 100644
index 0000000000..8cbd83678d
--- /dev/null
+++ b/cmake/module/TryAppendLinkerFlag.cmake
@@ -0,0 +1,78 @@
+# Copyright (c) 2023-present The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or https://opensource.org/license/mit/.
+
+include_guard(GLOBAL)
+include(CheckCXXSourceCompiles)
+
+#[=[
+Usage example:
+
+ try_append_linker_flag("-Wl,--major-subsystem-version,6" TARGET core_interface)
+
+
+In configuration output, this function prints a string by the following pattern:
+
+ -- Performing Test LINKER_SUPPORTS_[flag]
+ -- Performing Test LINKER_SUPPORTS_[flag] - Success
+
+]=]
+function(try_append_linker_flag flag)
+ cmake_parse_arguments(PARSE_ARGV 1
+ TALF # prefix
+ "" # options
+ "TARGET;VAR;SOURCE;RESULT_VAR" # one_value_keywords
+ "IF_CHECK_PASSED" # multi_value_keywords
+ )
+
+ string(MAKE_C_IDENTIFIER "${flag}" result)
+ string(TOUPPER "${result}" result)
+ string(PREPEND result LINKER_SUPPORTS_)
+
+ set(source "int main() { return 0; }")
+ if(DEFINED TALF_SOURCE AND NOT TALF_SOURCE STREQUAL source)
+ set(source "${TALF_SOURCE}")
+ string(SHA256 source_hash "${source}")
+ string(SUBSTRING ${source_hash} 0 4 source_hash_head)
+ string(APPEND result _${source_hash_head})
+ endif()
+
+ # This forces running a linker.
+ set(CMAKE_TRY_COMPILE_TARGET_TYPE EXECUTABLE)
+ set(CMAKE_REQUIRED_LINK_OPTIONS ${flag} ${working_linker_werror_flag})
+ check_cxx_source_compiles("${source}" ${result})
+
+ if(${result})
+ if(DEFINED TALF_IF_CHECK_PASSED)
+ if(DEFINED TALF_TARGET)
+ target_link_options(${TALF_TARGET} INTERFACE ${TALF_IF_CHECK_PASSED})
+ endif()
+ if(DEFINED TALF_VAR)
+ string(STRIP "${${TALF_VAR}} ${TALF_IF_CHECK_PASSED}" ${TALF_VAR})
+ endif()
+ else()
+ if(DEFINED TALF_TARGET)
+ target_link_options(${TALF_TARGET} INTERFACE ${flag})
+ endif()
+ if(DEFINED TALF_VAR)
+ string(STRIP "${${TALF_VAR}} ${flag}" ${TALF_VAR})
+ endif()
+ endif()
+ endif()
+
+ if(DEFINED TALF_VAR)
+ set(${TALF_VAR} "${${TALF_VAR}}" PARENT_SCOPE)
+ endif()
+
+ if(DEFINED TALF_RESULT_VAR)
+ set(${TALF_RESULT_VAR} "${${result}}" PARENT_SCOPE)
+ endif()
+endfunction()
+
+if(MSVC)
+ try_append_linker_flag("/WX" VAR working_linker_werror_flag)
+elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
+ try_append_linker_flag("-Wl,-fatal_warnings" VAR working_linker_werror_flag)
+else()
+ try_append_linker_flag("-Wl,--fatal-warnings" VAR working_linker_werror_flag)
+endif()
diff --git a/cmake/module/WarnAboutGlobalProperties.cmake b/cmake/module/WarnAboutGlobalProperties.cmake
new file mode 100644
index 0000000000..faa56a2a7f
--- /dev/null
+++ b/cmake/module/WarnAboutGlobalProperties.cmake
@@ -0,0 +1,36 @@
+# Copyright (c) 2023-present The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or https://opensource.org/license/mit/.
+
+include_guard(GLOBAL)
+
+# Avoid the directory-wide add_definitions() and add_compile_definitions() commands.
+# Instead, prefer the target-specific target_compile_definitions() one.
+get_directory_property(global_compile_definitions COMPILE_DEFINITIONS)
+if(global_compile_definitions)
+ message(AUTHOR_WARNING "The directory's COMPILE_DEFINITIONS property is not empty: ${global_compile_definitions}")
+endif()
+
+# Avoid the directory-wide add_compile_options() command.
+# Instead, prefer the target-specific target_compile_options() one.
+get_directory_property(global_compile_options COMPILE_OPTIONS)
+if(global_compile_options)
+ message(AUTHOR_WARNING "The directory's COMPILE_OPTIONS property is not empty: ${global_compile_options}")
+endif()
+
+# Avoid the directory-wide add_link_options() command.
+# Instead, prefer the target-specific target_link_options() one.
+get_directory_property(global_link_options LINK_OPTIONS)
+if(global_link_options)
+ message(AUTHOR_WARNING "The directory's LINK_OPTIONS property is not empty: ${global_link_options}")
+endif()
+
+# Avoid the directory-wide link_libraries() command.
+# Instead, prefer the target-specific target_link_libraries() one.
+file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/dummy_cxx_source.cpp "#error")
+add_library(check_loose_linked_libraries OBJECT EXCLUDE_FROM_ALL ${CMAKE_CURRENT_BINARY_DIR}/dummy_cxx_source.cpp)
+set_target_properties(check_loose_linked_libraries PROPERTIES EXPORT_COMPILE_COMMANDS OFF)
+get_target_property(global_linked_libraries check_loose_linked_libraries LINK_LIBRARIES)
+if(global_linked_libraries)
+ message(AUTHOR_WARNING "There are libraries linked with `link_libraries` commands: ${global_linked_libraries}")
+endif()