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,97 @@ +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(). +# OUTPUT_NAME allow to redefine the library output name. If not set the target +# name is used. +# OBJLIBS can be used to add sources from object targets by using the +# $ generator expression. +# +# This function makes 2 variables available to the caller space, named after the +# supplied name suffixed by _static_lib and _shared_lib. These variables contain +# the actual target name respectively for the static library and the shared +# library. If both are not build, the corresponding variable is not set. The +# value of these variables can be tested with `if(TARGET ${foo_static_lib}` to +# determine if the desired version has been defined and what is the target name. +function(add_library_with_type NAME) + cmake_parse_arguments(ARG + "SHARED;STATIC" + "OUTPUT_NAME" + "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 ${_all_files}) + + target_link_libraries(${_obj_name} ${ARG_LINK_LIBS}) + set(_all_files "$") + + if(ARG_OUTPUT_NAME) + set(_output_name OUTPUT_NAME ${ARG_OUTPUT_NAME}) + else() + set(_output_name OUTPUT_NAME ${NAME}) + endif() + + set(_shared_lib_name "${NAME}-shared") + set(${NAME}_shared_target "${_shared_lib_name}" PARENT_SCOPE) + + add_library_with_type(${_shared_lib_name} SHARED + OBJLIBS ${_all_files} + LINK_LIBS ${ARG_LINK_LIBS} + ${_output_name} + ${_shared_lib_target} + ) + unset(ARG_SHARED) + endif() + + if(ARG_SHARED) + add_library(${NAME} SHARED ${_all_files}) + set(${NAME}_shared_target "${NAME}" PARENT_SCOPE) + else() + add_library(${NAME} STATIC ${_all_files}) + set(${NAME}_static_target "${NAME}" PARENT_SCOPE) + endif() + + target_link_libraries(${NAME} ${ARG_LINK_LIBS}) + + 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: + # set(_properties VERSION "${bitcoin-abc_VERSION}") + set(_properties VERSION "${bitcoin-abc_VERSION_MAJOR}.0.0") + else() + set(_properties VERSION "${bitcoin-abc_VERSION_MAJOR}") + endif() + + if(ARG_OUTPUT_NAME) + # For autotools compatibility, rename the library to ${OUTPUT_NAME}-0.dll + if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") + list(APPEND _properties OUTPUT_NAME "${ARG_OUTPUT_NAME}-${bitcoin-abc_VERSION_MAJOR}") + else() + list(APPEND _properties OUTPUT_NAME "${ARG_OUTPUT_NAME}") + endif() + endif() + + if(ARG_SHARED) + list(APPEND _properties SOVERSION "${bitcoin-abc_VERSION_MAJOR}") + endif() + + set_target_properties(${NAME} PROPERTIES ${_properties}) + +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 @@ -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) @@ -374,7 +375,6 @@ # script library add_library(script - script/bitcoinconsensus.cpp script/bitfield.cpp script/interpreter.cpp script/ismine.cpp @@ -387,17 +387,50 @@ 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) + set(LIBBITCOINCONSENSUS_SOURCES + script/bitcoinconsensus.cpp + ) + if(TARGET ${bitcoinconsensus_static_target}) + target_sources(${bitcoinconsensus_static_target} PRIVATE + ${LIBBITCOINCONSENSUS_SOURCES} + ) + endif() + target_sources(${bitcoinconsensus_shared_target} PRIVATE + ${LIBBITCOINCONSENSUS_SOURCES} + ) + + target_compile_definitions(${bitcoinconsensus_shared_target} PRIVATE + BUILD_BITCOIN_INTERNAL + ) + set_target_properties(${bitcoinconsensus_shared_target} PROPERTIES + PUBLIC_HEADER script/bitcoinconsensus.h + ) + + install_target(${bitcoinconsensus_shared_target}) +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()