diff --git a/cmake/modules/FindBerkeleyDB.cmake b/cmake/modules/FindBerkeleyDB.cmake --- a/cmake/modules/FindBerkeleyDB.cmake +++ b/cmake/modules/FindBerkeleyDB.cmake @@ -1,41 +1,168 @@ -# Try to find the BerkeleyDB libraries -# BDB_FOUND - system has Berkeley DB lib -# BDB_INCLUDE_DIR - the Berkeley DB include directory -# BDB_LIBRARY - Library needed to use Berkeley DB -# BDBXX_INCLUDE_DIR - the Berkeley DB include directory for C++ -# BDBXX_LIBRARY - Library needed to use Berkeley DB C++ API +# Copyright (c) 2017-2020 The Bitcoin developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#.rst +# FindBerkeleyDB +# ------------- +# +# This is inspired by https://github.com/sum01/FindBerkeleyDB. +# +# Find the Berkeley database (versions >= 5.x) libraries: +# - db (mandatory) +# - db_cxx (optional, part of db on Windows) +# +# This will define the following variables:: +# +# BerkeleyDB_FOUND - system has Berkeley DB lib +# BerkeleyDB_INCLUDE_DIRS - the Berkeley DB include directories +# BerkeleyDB_LIBRARIES - Libraries needed to use Berkeley DB +# BerkeleyDB_VERSION - The library version MAJOR.MINOR.PATCH +# BerkeleyDB_VERSION_MAJOR - Major version number +# BerkeleyDB_VERSION_MINOR - Minor version number +# BerkeleyDB_VERSION_PATCH - Patch version number +# +# And the following imported target:: +# +# Oracle::BerkeleyDB include(BrewHelper) find_brew_prefix(BREW_HINT berkeley-db) -find_path(BDB_INCLUDE_DIR - NAMES db.h - HINTS ${BREW_HINT} - PATH_SUFFIXES db5 -) -find_library(BDB_LIBRARY - NAMES db libdb - HINTS ${BREW_HINT} - PATH_SUFFIXES db5 -) +# Generate a list of all the possible versioned library name variants given a +# list of separators. +function(generate_versions_variants VARIANTS LIB MAJOR MINOR) + set(SEPARATORS + "" "." "-" "_" + ) -find_path(BDBXX_INCLUDE_DIR - NAMES db_cxx.h - HINTS ${BREW_HINT} - PATH_SUFFIXES db5 + set(${VARIANTS} "${LIB}") + foreach(_separator1 IN LISTS SEPARATORS) + list(APPEND ${VARIANTS} "${LIB}${_separator1}${MAJOR}") + foreach(_separator2 IN LISTS SEPARATORS) + list(APPEND ${VARIANTS} "${LIB}${_separator1}${MAJOR}${_separator2}${MINOR}") + endforeach() + endforeach() + + set(${VARIANTS} ${${VARIANTS}} PARENT_SCOPE) +endfunction() + +# Berkeley DB 5 including latest minor release. +generate_versions_variants(_BerkeleyDB_PATH_SUFFIXES_5_3 db 5 3) +# Berkeley DB 6 including latest minor release. +generate_versions_variants(_BerkeleyDB_PATH_SUFFIXES_6_2 db 6 2) +# Berkeley DB 18 including latest minor release (current). +generate_versions_variants(_BerkeleyDB_PATH_SUFFIXES_18_1 db 18 1) + +set(_BerkeleyDB_PATH_SUFFIXES + ${_BerkeleyDB_PATH_SUFFIXES_5_3} + ${_BerkeleyDB_PATH_SUFFIXES_6_2} + ${_BerkeleyDB_PATH_SUFFIXES_18_1} ) -find_library(BDBXX_LIBRARY - NAMES db_cxx libdb_cxx db5_cxx +list(REMOVE_DUPLICATES _BerkeleyDB_PATH_SUFFIXES) + +# Try to find the db.h header. +# If the header is not found the user can supply the correct path by passing the +# `BerkeleyDB_ROOT` variable to cmake. +find_path(BerkeleyDB_INCLUDE_DIR + NAMES db.h HINTS ${BREW_HINT} - PATH_SUFFIXES db5 + PATH_SUFFIXES ${_BerkeleyDB_PATH_SUFFIXES} ) -MESSAGE(STATUS "BerkeleyDB libs: " ${BDB_LIBRARY} " " ${BDBXX_LIBRARY}) +# There is a single common include directory. +# Set the BerkeleyDB_INCLUDE_DIRS variable which is the expected standard output +# variable name for the include directories. +set(BerkeleyDB_INCLUDE_DIRS "${BerkeleyDB_INCLUDE_DIR}") +mark_as_advanced(BerkeleyDB_INCLUDE_DIR) + +# Extract version information from the db.h header. +if(BerkeleyDB_INCLUDE_DIR) + # Read the version from file db.h into a variable. + file(READ "${BerkeleyDB_INCLUDE_DIR}/db.h" _BerkeleyDB_DB_HEADER) + + # Parse the version into variables. + string(REGEX REPLACE + ".*DB_VERSION_MAJOR ([0-9]+).*" "\\1" + BerkeleyDB_VERSION_MAJOR + "${_BerkeleyDB_DB_HEADER}" + ) + string(REGEX REPLACE + ".*DB_VERSION_MINOR ([0-9]+).*" "\\1" + BerkeleyDB_VERSION_MINOR + "${_BerkeleyDB_DB_HEADER}" + ) + # Patch version example on non-crypto installs: x.x.xNC + string(REGEX REPLACE + ".*DB_VERSION_PATCH ([0-9]+(NC)?).*" "\\1" + BerkeleyDB_VERSION_PATCH + "${_BerkeleyDB_DB_HEADER}" + ) +else() + # Set some garbage values to the versions since we didn't find a file to + # read. + set(BerkeleyDB_VERSION_MAJOR "0") + set(BerkeleyDB_VERSION_MINOR "0") + set(BerkeleyDB_VERSION_PATCH "0") +endif() + +# The actual returned/output version variable (the others can be used if needed) +set(BerkeleyDB_VERSION "${BerkeleyDB_VERSION_MAJOR}.${BerkeleyDB_VERSION_MINOR}.${BerkeleyDB_VERSION_PATCH}") + +# Finds the target library for Berkeley DB, since they all follow the same +# naming conventions. +function(findpackage_berkeleydb_get_lib OUTPUT_VARNAME LIB) + # Different systems sometimes have a version in the lib name... + # and some have a dash or underscore before the versions. + # Generate all combinations from the separators "" (none), ".", "-" and "_". + generate_versions_variants( + LIB_VARIANTS + "${LIB}" + "${BerkeleyDB_VERSION_MAJOR}" + "${BerkeleyDB_VERSION_MINOR}" + ) + + find_library(${OUTPUT_VARNAME} + NAMES ${LIB_VARIANTS} + HINTS ${BREW_HINT} + PATH_SUFFIXES ${LIB_VARIANTS} + ) + + mark_as_advanced(${OUTPUT_VARNAME}) + + # If the library was found, add it to our list of libraries. + if(${OUTPUT_VARNAME}) + list(APPEND BerkeleyDB_LIBRARIES "${${OUTPUT_VARNAME}}") + endif() + + set(${OUTPUT_VARNAME} ${${OUTPUT_VARNAME}} PARENT_SCOPE) + set(BerkeleyDB_LIBRARIES ${BerkeleyDB_LIBRARIES} PARENT_SCOPE) +endfunction() + +findpackage_berkeleydb_get_lib(BerkeleyDB_LIBRARY db) +findpackage_berkeleydb_get_lib(BerkeleyDB_CXX_LIBRARY db_cxx) include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(BerkeleyDB DEFAULT_MSG BDB_INCLUDE_DIR BDB_LIBRARY BDBXX_INCLUDE_DIR BDBXX_LIBRARY) +find_package_handle_standard_args(BerkeleyDB + REQUIRED_VARS + BerkeleyDB_INCLUDE_DIR + BerkeleyDB_LIBRARY + VERSION_VAR BerkeleyDB_VERSION +) -mark_as_advanced(BDB_INCLUDE_DIR BDB_LIBRARY BDBXX_INCLUDE_DIR BDBXX_LIBRARY) +if(BerkeleyDB_FOUND) + include(FindPackageMessage) + find_package_message(BerkeleyDB + "Found BerkeleyDB libraries: ${BerkeleyDB_LIBRARIES}" + "[${BerkeleyDB_LIBRARIES}][${BerkeleyDB_INCLUDE_DIRS}]" + ) -set(BerkeleyDB_LIBRARIES ${BDB_LIBRARY} ${BDBXX_LIBRARY}) -set(BerkeleyDB_INCLUDE_DIRS ${BDB_INCLUDE_DIR} ${BDBXX_INCLUDE_DIR}) + if(NOT TARGET Oracle::BerkeleyDB) + add_library(Oracle::BerkeleyDB UNKNOWN IMPORTED) + set_target_properties(Oracle::BerkeleyDB PROPERTIES + IMPORTED_LOCATION "${BerkeleyDB_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${BerkeleyDB_INCLUDE_DIR}" + INTERFACE_LINK_LIBRARIES "${BerkeleyDB_LIBRARIES}" + ) + endif() +endif() diff --git a/src/wallet/CMakeLists.txt b/src/wallet/CMakeLists.txt --- a/src/wallet/CMakeLists.txt +++ b/src/wallet/CMakeLists.txt @@ -3,7 +3,7 @@ project(wallet) # Add Berkeley DB dependency. -find_package(BerkeleyDB REQUIRED) +find_package(BerkeleyDB 5.3 REQUIRED) # Add event dependency. This is only required for evhttp_uridecode # in rpcwallet.cpp so it may be worth considering using an alternative. @@ -25,6 +25,4 @@ walletutil.cpp ) -target_link_libraries(wallet script univalue Event ${BDBXX_LIBRARY}) - -target_include_directories(wallet PUBLIC ${BDBXX_INCLUDE_DIR}) +target_link_libraries(wallet script univalue Event Oracle::BerkeleyDB)