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,45 @@ +include(InstallationHelper) + +# Wrapper for the add_library() function that allow to require more than a +# single library type. The type can be STATIC, SHARED or both. +# LINK_LIBS applies to all the types and follow the syntax of +# target_link_libraries(). +# OBJLIBS can be used to add sources from object targets by using the +# $ generator expression. +function(add_library_with_type NAME) + cmake_parse_arguments(ARG + "SHARED;STATIC" + "" + "LINK_LIBS;OBJLIBS" + ${ARGN} + ) + + if(NOT (ARG_STATIC OR ARG_SHARED)) + message(FATAL_ERROR "Missing library type(s) (STATIC, SHARED or both).") + endif() + + set(_all_files ${ARG_OBJLIBS} ${ARG_UNPARSED_ARGUMENTS}) + + # 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}) + + target_link_libraries(${_obj_name} ${ARG_LINK_LIBS}) + set(_all_files "$") + + add_library_with_type("${NAME}-shared" SHARED + OBJLIBS ${_all_files} + LINK_LIBS ${ARG_LINK_LIBS} + ) + unset(ARG_SHARED) + endif() + + if(ARG_SHARED) + add_library(${NAME} SHARED ${_all_files}) + else() + add_library(${NAME} STATIC ${_all_files}) + endif() + + target_link_libraries(${NAME} ${ARG_LINK_LIBS}) +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 @@ -389,17 +389,67 @@ target_link_libraries(script common) -# libbitcoinconsensus -add_library(bitcoinconsensus +if(NOT BUILD_SHARED_LIBS) + set(BITCOIN_CONSENSUS_ENABLE_STATIC STATIC) +endif() +if(BUILD_SHARED_LIBS OR BUILD_LIBBITCOINCONSENSUS) + set(BITCOIN_CONSENSUS_ENABLE_SHARED SHARED) +endif() + +include(AddLibraryHelper) +add_library_with_type(bitcoinconsensus + ${BITCOIN_CONSENSUS_ENABLE_STATIC} + ${BITCOIN_CONSENSUS_ENABLE_SHARED} + arith_uint256.cpp hash.cpp primitives/transaction.cpp pubkey.cpp uint256.cpp util/strencodings.cpp + + LINK_LIBS script ) -target_link_libraries(bitcoinconsensus script) +if(BUILD_LIBBITCOINCONSENSUS) + if(BUILD_SHARED_LIBS) + set(LIBBITCOINCONSENSUS bitcoinconsensus) + else() + set(LIBBITCOINCONSENSUS bitcoinconsensus-shared) + endif() + + target_sources(${LIBBITCOINCONSENSUS} PRIVATE script/bitcoinconsensus.cpp) + target_compile_definitions(${LIBBITCOINCONSENSUS} PRIVATE BUILD_BITCOIN_INTERNAL) + + # For autotools compatibility, rename the library to libbitcoinconsensus-0.dll + if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") + set(LIBBITCOINCONSENSUS_NAME "bitcoinconsensus-${bitcoin-abc_VERSION_MAJOR}") + else() + set(LIBBITCOINCONSENSUS_NAME "bitcoinconsensus") + endif() + + set(LIBBITCOINCONSENSUS_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 LIBBITCOINCONSENSUS_VERSION "${bitcoin-abc_VERSION_MINOR}.${bitcoin-abc_VERSION_PATCH})" + string(APPEND LIBBITCOINCONSENSUS_VERSION ".0.0") + endif() + + set_target_properties(${LIBBITCOINCONSENSUS} PROPERTIES + OUTPUT_NAME "${LIBBITCOINCONSENSUS_NAME}" + VERSION "${LIBBITCOINCONSENSUS_VERSION}" + SOVERSION "${bitcoin-abc_VERSION_MAJOR}" + PUBLIC_HEADER script/bitcoinconsensus.h + ) + + install_target(${LIBBITCOINCONSENSUS}) +endif() + # 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()