AddBoostIfNeeded.cmake raw

   1  # Copyright (c) 2023-present The Limenka developers
   2  # Distributed under the MIT software license, see the accompanying
   3  # file COPYING or https://opensource.org/license/mit/.
   4  
   5  function(add_boost_if_needed)
   6    if(BUILD_DAEMON)
   7    elseif(BUILD_CLI)
   8    # BUILD_LIMENKACONSENSUS_LIB does NOT require boost
   9    elseif(BUILD_TX)
  10    elseif(BUILD_UTIL)
  11    elseif(BUILD_UTIL_CHAINSTATE)
  12    elseif(BUILD_KERNEL_LIB)
  13    elseif(BUILD_WALLET_TOOL)
  14    elseif(BUILD_GUI)
  15    elseif(BUILD_TESTS)
  16    elseif(BUILD_GUI_TESTS)
  17    elseif(BUILD_BENCH)
  18    elseif(BUILD_FUZZ_BINARY)
  19    else()
  20      # No targets that require boost; but we still define them, so make a dummy "library"
  21      add_library(Boost::headers INTERFACE IMPORTED)
  22      return()
  23    endif()
  24  
  25    #[=[
  26    TODO: Not all targets, which will be added in the future, require
  27          Boost. Therefore, a proper check will be appropriate here.
  28  
  29    Implementation notes:
  30    Although only Boost headers are used to build Limenka,
  31    we still leverage a standard CMake's approach to handle
  32    dependencies, i.e., the Boost::headers "library".
  33    A command target_link_libraries(target PRIVATE Boost::headers)
  34    will propagate Boost::headers usage requirements to the target.
  35    For Boost::headers such usage requirements is an include
  36    directory and other added INTERFACE properties.
  37    ]=]
  38  
  39    if(CMAKE_HOST_APPLE)
  40      find_program(HOMEBREW_EXECUTABLE brew)
  41      if(HOMEBREW_EXECUTABLE)
  42        execute_process(
  43          COMMAND ${HOMEBREW_EXECUTABLE} --prefix boost
  44          OUTPUT_VARIABLE Boost_ROOT
  45          ERROR_QUIET
  46          OUTPUT_STRIP_TRAILING_WHITESPACE
  47        )
  48      endif()
  49    endif()
  50  
  51    # We cannot rely on find_package(Boost ...) to work properly without
  52    # Boost_NO_BOOST_CMAKE set until we require a more recent Boost because
  53    # upstream did not ship proper CMake files until 1.82.0.
  54    # Until then, we rely on CMake's FindBoost module.
  55    # See: https://cmake.org/cmake/help/latest/policy/CMP0167.html
  56    if(POLICY CMP0167)
  57      cmake_policy(SET CMP0167 OLD)
  58    endif()
  59    set(Boost_NO_BOOST_CMAKE ON)
  60    find_package(Boost 1.73.0 REQUIRED)
  61    mark_as_advanced(Boost_INCLUDE_DIR)
  62    set_target_properties(Boost::headers PROPERTIES IMPORTED_GLOBAL TRUE)
  63    target_compile_definitions(Boost::headers INTERFACE
  64      # We don't use multi_index serialization.
  65      BOOST_MULTI_INDEX_DISABLE_SERIALIZATION
  66    )
  67    if(DEFINED VCPKG_TARGET_TRIPLET)
  68      # Workaround for https://github.com/microsoft/vcpkg/issues/36955.
  69      target_compile_definitions(Boost::headers INTERFACE
  70        BOOST_NO_USER_CONFIG
  71      )
  72    endif()
  73  
  74    # Prevent use of std::unary_function, which was removed in C++17,
  75    # and will generate warnings with newer compilers for Boost
  76    # older than 1.80.
  77    # See: https://github.com/boostorg/config/pull/430.
  78    set(CMAKE_REQUIRED_DEFINITIONS -DBOOST_NO_CXX98_FUNCTION_BASE)
  79    set(CMAKE_REQUIRED_INCLUDES ${Boost_INCLUDE_DIR})
  80    include(CMakePushCheckState)
  81    cmake_push_check_state()
  82    include(TryAppendCXXFlags)
  83    set(CMAKE_REQUIRED_FLAGS ${working_compiler_werror_flag})
  84    set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
  85    check_cxx_source_compiles("
  86      #include <boost/config.hpp>
  87      " NO_DIAGNOSTICS_BOOST_NO_CXX98_FUNCTION_BASE
  88    )
  89    cmake_pop_check_state()
  90    if(NO_DIAGNOSTICS_BOOST_NO_CXX98_FUNCTION_BASE)
  91      target_compile_definitions(Boost::headers INTERFACE
  92        BOOST_NO_CXX98_FUNCTION_BASE
  93      )
  94    else()
  95      set(CMAKE_REQUIRED_DEFINITIONS)
  96    endif()
  97  
  98    # Some package managers, such as vcpkg, vendor Boost.Test separately
  99    # from the rest of the headers, so we have to check for it individually.
 100    if(BUILD_TESTS AND DEFINED VCPKG_TARGET_TRIPLET)
 101      list(APPEND CMAKE_REQUIRED_DEFINITIONS -DBOOST_TEST_NO_MAIN)
 102      include(CheckIncludeFileCXX)
 103      check_include_file_cxx(boost/test/included/unit_test.hpp HAVE_BOOST_INCLUDED_UNIT_TEST_H)
 104      if(NOT HAVE_BOOST_INCLUDED_UNIT_TEST_H)
 105        message(FATAL_ERROR "Building test_limenka executable requested but boost/test/included/unit_test.hpp header not available.")
 106      endif()
 107    endif()
 108  
 109  endfunction()
 110