diff --git a/cmake/modules/AddLibraryHelper.cmake b/cmake/modules/AddLibraryHelper.cmake new file mode 100644 --- /dev/null +++ b/cmake/modules/AddLibraryHelper.cmake @@ -0,0 +1,113 @@ +include(InstallationHelper) + +# Wrapper for the add_library() function. +function(add_and_configure_library NAME) + cmake_parse_arguments(ARG + "INSTALL;SHARED;STATIC" + "OUTPUT_NAME" + "DEFINITIONS;DEPENDS;LINK_LIBS;OBJLIBS;PRIVATE_HEADERS;PUBLIC_HEADERS" + ${ARGN} + ) + + if(ARG_OBJLIBS) + set(_all_files ${ARG_OBJLIBS}) + else() + set(_all_files + ${ARG_UNPARSED_ARGUMENTS} + ${ARG_PRIVATE_HEADERS} + ${ARG_PUBLIC_HEADERS} + ) + endif() + + # If none of STATIC or SHARED is explicitly set, determine the library type + # from BUILD_SHARED_LIBS. + if(BUILD_SHARED_LIBS AND NOT ARG_STATIC) + set(ARG_SHARED TRUE) + endif() + if(NOT ARG_SHARED) + set(ARG_STATIC TRUE) + endif() + + # If both static and shared are requested, use an object library. + if(ARG_SHARED AND ARG_STATIC) + set(_obj_name "${NAME}-object") + add_library(${_obj_name} OBJECT EXCLUDE_FROM_ALL ${_all_files}) + + if(ARG_DEPENDS) + add_dependencies(${_obj_name} ${ARG_DEPENDS}) + unset(ARG_DEPENDS) + endif() + + target_link_libraries(${_obj_name} ${ARG_LINK_LIBS}) + target_compile_definitions(${_obj_name} PRIVATE ${ARG_DEFINITIONS}) + unset(ARG_DEFINITIONS) + + set(_all_files "$") + + if(ARG_OUTPUT_NAME) + set(_output_name OUTPUT_NAME "${ARG_OUTPUT_NAME}") + endif() + if(ARG_INSTALL) + set(_install INSTALL) + endif() + + add_and_configure_library("${NAME}-shared" SHARED + ${_install} + OBJLIBS ${_all_files} + LINK_LIBS ${ARG_LINK_LIBS} + PRIVATE_HEADERS ${ARG_PRIVATE_HEADERS} + PUBLIC_HEADERS ${ARG_PUBLIC_HEADERS} + ${_output_name} + ) + + unset(ARG_SHARED) + endif() + + if(ARG_SHARED) + add_library(${NAME} SHARED ${_all_files}) + else() + add_library(${NAME} STATIC ${_all_files}) + endif() + + if(ARG_DEPENDS) + add_dependencies(${NAME} ${ARG_DEPENDS}) + endif() + + target_link_libraries(${NAME} ${ARG_LINK_LIBS}) + target_compile_definitions(${NAME} PRIVATE ${ARG_DEFINITIONS}) + + set(_version "${bitcoin-abc_VERSION_MAJOR}") + if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") + # FIXME For compatibility reason with autotools, the version is set + # to 0.0.0 (major being actually 0). This is obviously wrong and the + # version of the library should reflect the version of the release. + # On platforms other than linux, only the major version (0) is used. + # Replace the VERSION line with the statement below to set the + # correct version: + # string(APPEND "${bitcoin-abc_VERSION_MINOR}.${bitcoin-abc_VERSION_PATCH})" + string(APPEND _version ".0.0") + endif() + + set(_properties VERSION ${_version}) + + if(ARG_OUTPUT_NAME) + list(APPEND _properties OUTPUT_NAME "${ARG_OUTPUT_NAME}") + endif() + + if(ARG_SHARED) + list(APPEND _properties SOVERSION "${bitcoin-abc_VERSION_MAJOR}") + + if(ARG_PRIVATE_HEADERS) + list(APPEND _properties PRIVATE_HEADER "${ARG_PRIVATE_HEADERS}") + endif() + if(ARG_PUBLIC_HEADERS) + list(APPEND _properties PUBLIC_HEADER "${ARG_PUBLIC_HEADERS}") + endif() + endif() + + set_target_properties(${NAME} PROPERTIES ${_properties}) + + if(ARG_INSTALL) + install_target(${NAME}) + endif() +endfunction() diff --git a/cmake/modules/InstallationHelper.cmake b/cmake/modules/InstallationHelper.cmake --- a/cmake/modules/InstallationHelper.cmake +++ b/cmake/modules/InstallationHelper.cmake @@ -2,11 +2,21 @@ include(GNUInstallDirs) -macro(install_target _target) +function(install_target _target) + set(RUNTIME_DESTINATION "${CMAKE_INSTALL_BINDIR}") + # CMake installs Windows shared libraries to the RUNTIME destination folder, + # but autotools install them into the LIBRARY destination folder. + # This special case only purpose is to provide identical installation trees + # between CMake and autotools. + get_target_property(_target_type ${_target} TYPE) + if(${CMAKE_SYSTEM_NAME} MATCHES "Windows" AND _target_type STREQUAL "SHARED_LIBRARY") + set(RUNTIME_DESTINATION "${CMAKE_INSTALL_LIBDIR}") + endif() + install( TARGETS ${_target} - RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" + RUNTIME DESTINATION "${RUNTIME_DESTINATION}" LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" ) -endmacro() +endfunction() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2017 The Bitcoin developers -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.12) project(bitcoind) set(CMAKE_CXX_STANDARD 14) @@ -15,6 +15,7 @@ option(BUILD_BITCOIN_CLI "Build bitcoin-cli" ON) option(BUILD_BITCOIN_TX "Build bitcoin-tx" ON) option(BUILD_BITCOIN_QT "Build bitcoin-qt" ON) +option(BUILD_LIBBITCOINCONSENSUS "Build the bitcoinconsenus shared library" ON) option(ENABLE_HARDENING "Harden the executables" ON) option(ENABLE_REDUCE_EXPORTS "Reduce the amount of exported symbols" OFF) option(ENABLE_STATIC_LIBSTDCXX "Statically link libstdc++" OFF) @@ -376,7 +377,6 @@ # script library add_library(script - script/bitcoinconsensus.cpp script/bitfield.cpp script/interpreter.cpp script/ismine.cpp @@ -390,7 +390,7 @@ target_link_libraries(script common) # libbitcoinconsensus -add_library(bitcoinconsensus +set(BITCOINCONSENSUS_SOURCES arith_uint256.cpp hash.cpp primitives/transaction.cpp @@ -399,7 +399,47 @@ util/strencodings.cpp ) -target_link_libraries(bitcoinconsensus script) +if(BUILD_LIBBITCOINCONSENSUS) + list(APPEND BITCOINCONSENSUS_SOURCES + script/bitcoinconsensus.cpp + ) + set(BITCOINCONSENSUS_PUBLIC_HEADERS + PUBLIC_HEADERS script/bitcoinconsensus.h + ) + + # Export the symbols from script/bitcoinconsensus.h. + set(BITCOINCONSENSUS_DEFINITIONS + DEFINITIONS BUILD_BITCOIN_INTERNAL + ) + + # If BUILD_LIBBITCOINCONSENSUS is set, build both static and shared. + # Otherwise don't set the type explicitly so it is set according to the + # BUILD_SHARED_LIBS switch. + # Also install the library only in this case. It is pointless to install the + # library if there is no exported symbol. + set(BITCOINCONSENSUS_FEATURES + STATIC + SHARED + INSTALL + ) +endif() + +# For autotools compatibility, rename the library to libbitcoinconsensus-0.dll +if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") + set(BITCOINCONSENSUS_NAME "bitcoinconsensus-${bitcoin-abc_VERSION_MAJOR}") +else() + set(BITCOINCONSENSUS_NAME "bitcoinconsensus") +endif() + +include(AddLibraryHelper) +add_and_configure_library(bitcoinconsensus + ${BITCOINCONSENSUS_FEATURES} + ${BITCOINCONSENSUS_SOURCES} + ${BITCOINCONSENSUS_PUBLIC_HEADERS} + ${BITCOINCONSENSUS_DEFINITIONS} + OUTPUT_NAME ${BITCOINCONSENSUS_NAME} + LINK_LIBS script +) # Bitcoin server facilities add_library(server diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -178,3 +178,7 @@ ../wallet/test/coinselector_tests.cpp ) endif() + +if(BUILD_LIBBITCOINCONSENSUS) + target_compile_definitions(test_bitcoin PRIVATE HAVE_CONSENSUS_LIB) +endif()