diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 016f8dd..f538265 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -243,8 +243,8 @@ jobs: needs: posix runs-on: ubuntu-latest steps: - - name: Coveralls Finished - uses: coverallsapp/github-action@master - with: - github-token: ${{ secrets.github_token }} - parallel-finished: true + - name: Coveralls Finished + uses: coverallsapp/github-action@master + with: + github-token: ${{ secrets.github_token }} + parallel-finished: true diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6654b8d --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +build/ +compile_commands.json diff --git a/CMakeLists.txt b/CMakeLists.txt index 8fd8717..48dcb5e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,46 +1,120 @@ +# ----------------------------------------------------------------------------- +# Boost.Any CMake +# Handles: no modules, modules, modules + import std; +# ----------------------------------------------------------------------------- # Copyright 2019 Mike Dev # Distributed under the Boost Software License, Version 1.0. -# See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt +# ----------------------------------------------------------------------------- -cmake_minimum_required( VERSION 3.8...3.31 ) -project( boost_any VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX ) +cmake_minimum_required(VERSION 3.21...4.2) + +project(boost_any VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX) + +if(PROJECT_IS_TOP_LEVEL) + find_package(Boost 1.90.0 CONFIG) +endif() + +# ----------------------------------------------------------------------------- +# User option: enable C++ modules +# ----------------------------------------------------------------------------- +option(BOOST_USE_MODULES "Build Boost using C++ modules" OFF) + +# ----------------------------------------------------------------------------- +# Determine target type and sources +# ----------------------------------------------------------------------------- +if(BOOST_USE_MODULES) + + # Ensure CMAKE_CXX_STANDARD is set for module detection + if(NOT DEFINED CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 20) + endif() -if (BOOST_USE_MODULES) add_library(boost_any) - target_sources(boost_any PUBLIC - FILE_SET modules_public - TYPE CXX_MODULES - FILES modules/boost_any.cppm + + target_sources( + boost_any + PUBLIC + FILE_SET modules_public + TYPE CXX_MODULES + FILES modules/boost_any.cppm ) - target_compile_features(boost_any PUBLIC cxx_std_20) + # Require C++20 for modules + target_compile_features(boost_any PUBLIC cxx_std_${CMAKE_CXX_STANDARD}) + + # Define macro indicating modules usage target_compile_definitions(boost_any PUBLIC BOOST_USE_MODULES) - set(__boost_cxx_standard ${CMAKE_CXX_STANDARD}) - if (NOT __boost_cxx_standard) - set(__boost_cxx_standard 20) - endif() - if (CMAKE_CXX_COMPILER_IMPORT_STD AND ${__boost_cxx_standard} IN_LIST CMAKE_CXX_COMPILER_IMPORT_STD) - target_compile_definitions(boost_any PRIVATE BOOST_ANY_USE_STD_MODULE) - message(STATUS "Using `import std;`") + + # Check if import std; is available for the current standard + if(${CMAKE_CXX_STANDARD} IN_LIST CMAKE_CXX_COMPILER_IMPORT_STD) + target_compile_definitions(boost_any PUBLIC BOOST_ANY_USE_STD_MODULE) + set_property(TARGET boost_any CXX_MODULE_STD ON) + message(STATUS "Boost.Any: Using `import std;`") else() - message(STATUS "`import std;` is not available") + message(WARNING "Boost.Any: `import std;` is not available for C++${CMAKE_CXX_STANDARD}") endif() + set(__scope PUBLIC) + else() + + # Modules disabled -> INTERFACE library add_library(boost_any INTERFACE) + + # If modules are disabled, require C++17 for headers + target_compile_features(boost_any INTERFACE cxx_std_17) + + # Verify interface headers only at top level + if(PROJECT_IS_TOP_LEVEL) + set(CMAKE_VERIFY_INTERFACE_HEADER_SETS ON) + endif() + set(__scope INTERFACE) + endif() -target_include_directories(boost_any ${__scope} include) -target_link_libraries( boost_any - ${__scope} +# ----------------------------------------------------------------------------- +# Include headers +# ----------------------------------------------------------------------------- +if(BOOST_USE_MODULES) + target_sources( + boost_any + PUBLIC + FILE_SET headers_public + TYPE HEADERS + BASE_DIRS include + FILES + include/boost/any/bad_any_cast.hpp + include/boost/any/basic_any.hpp + include/boost/any/fwd.hpp + include/boost/any/unique_any.hpp + include/boost/any/detail/config.hpp + include/boost/any/detail/placeholder.hpp + ) +else() + target_include_directories(boost_any ${__scope} include) +endif() + +# ----------------------------------------------------------------------------- +# Link dependencies +# ----------------------------------------------------------------------------- +if(PROJECT_IS_TOP_LEVEL) + target_link_libraries(boost_any ${__scope} Boost::headers) +else() + target_link_libraries(boost_any + ${__scope} Boost::config Boost::throw_exception Boost::type_index -) + ) +endif() -add_library( Boost::any ALIAS boost_any ) +# Alias for convenient import +add_library(Boost::any ALIAS boost_any) +# ----------------------------------------------------------------------------- +# Testing +# ----------------------------------------------------------------------------- if(BUILD_TESTING) add_subdirectory(test) endif() diff --git a/include/boost/any/fwd.hpp b/include/boost/any/fwd.hpp index 0f6c6f4..b147bbd 100644 --- a/include/boost/any/fwd.hpp +++ b/include/boost/any/fwd.hpp @@ -17,6 +17,9 @@ #ifdef BOOST_HAS_PRAGMA_ONCE # pragma once #endif + +#include + #endif // #ifndef BOOST_ANY_INTERFACE_UNIT /// \file boost/any/fwd.hpp diff --git a/modules/boost_any.cppm b/modules/boost_any.cppm index de7430c..413ef1b 100644 --- a/modules/boost_any.cppm +++ b/modules/boost_any.cppm @@ -11,12 +11,14 @@ module; #include #include #include -#include + +#include // for std::addressof + +import boost.type_index; #ifdef BOOST_ANY_USE_STD_MODULE import std; #else -#include #include #include #include diff --git a/modules/usage_sample.cpp b/modules/usage_sample.cpp index f82308c..4e492bc 100644 --- a/modules/usage_sample.cpp +++ b/modules/usage_sample.cpp @@ -7,10 +7,50 @@ // clang++ -std=c++20 -fmodule-file=type_index.pcm type_index.pcm usage_sample.cpp //[any_module_example + +#ifdef BOOST_ANY_USE_STD_MODULE +import std; +#else +# include +# include +# include +#endif + import boost.any; -int main() { - boost::any a = 42; +namespace { + + template auto any_to_string(const boost::any& a) -> std::string { + std::ostringstream oss; + + auto try_cast = [&](auto* dummy) -> bool { + using T = std::decay_t; + if (a.type() == typeid(T)) { + oss << boost::any_cast(a); + return true; + } + return false; + }; + + // Expand over Ts... + bool const success = (try_cast((Ts*)nullptr) || ...); + + if (!success) { + oss << ""; + } + return oss.str(); + } + +} // namespace + +// Usage: +auto main() -> int { + boost::any const a = 42; +#ifdef BOOST_ANY_USE_STD_MODULE + std::println("{}", any_to_string(a)); +#else + std::cout << any_to_string(a) << '\n'; +#endif } //] diff --git a/test/cmake_subdir_test/CMakeLists.txt b/test/cmake_subdir_test/CMakeLists.txt index cae23df..537a3f5 100644 --- a/test/cmake_subdir_test/CMakeLists.txt +++ b/test/cmake_subdir_test/CMakeLists.txt @@ -2,9 +2,9 @@ # Distributed under the Boost Software License, Version 1.0. # See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt -cmake_minimum_required(VERSION 3.5...4.0) +cmake_minimum_required(VERSION 3.21...4.2) -project(any_subdir_test LANGUAGES CXX) +project(boost_any LANGUAGES CXX VERSION 1.90.0) add_subdirectory(../../../assert boostorg/assert) add_subdirectory(../../../core boostorg/core) @@ -19,35 +19,49 @@ add_subdirectory(../../../throw_exception boostorg/throw_exception) add_subdirectory(../../../type_index boostorg/type_index) add_subdirectory(../../../type_traits boostorg/type_traits) +# ../../CMakeLists.txt add_subdirectory(../../ boostorg/any) +include(cmake/boost-install-library.cmake) +boost_install_library(boost_config TARGETS boost_config) +boost_install_library(boost_assert TARGETS boost_assert) +boost_install_library(boost_mp11 TARGETS boost_mp11 DEPENDENCIES Boost::core) +boost_install_library(boost_describe TARGETS boost_describe DEPENDENCIES Boost::mp11) +boost_install_library(boost_container_hash TARGETS boost_container_hash DEPENDENCIES Boost::describe) +boost_install_library(boost_throw_exception TARGETS boost_throw_exception DEPENDENCIES Boost::assert) +boost_install_library(boost_type_index TARGETS boost_type_index DEPENDENCIES Boost::boost_container_hash) +boost_install_library(boost_any TARGETS boost_any DEPENDENCIES Boost::type_index Boost::config Boost::throw_exception) + enable_testing() -if (BOOST_USE_MODULES) +if(BOOST_USE_MODULES) add_executable(boost_any_module_usage ../../modules/usage_sample.cpp) target_link_libraries(boost_any_module_usage PRIVATE Boost::any) add_test(NAME boost_any_module_usage COMMAND boost_any_module_usage) +else() + set(RUN_TESTS_SOURCES + any_test_mplif.cpp + any_test_rv.cpp + basic_any_test.cpp + basic_any_test_large_object.cpp + basic_any_test_mplif.cpp + basic_any_test_rv.cpp + basic_any_test_small_object.cpp + unique_any/base.cpp + unique_any/emplace.cpp + unique_any/from_any.cpp + unique_any/move.cpp + # any_test.cpp # Ambiguous with modules, because all the anys now available + ) endif() -list(APPEND RUN_TESTS_SOURCES - any_test_mplif.cpp - basic_any_test_small_object.cpp - any_test_rv.cpp - basic_any_test.cpp - - unique_any/from_any.cpp - unique_any/move.cpp - unique_any/emplace.cpp - unique_any/base.cpp - - basic_any_test_mplif.cpp - basic_any_test_rv.cpp - basic_any_test_large_object.cpp - # any_test.cpp # Ambiguous with modules, because all the anys now available -) - -foreach (testsourcefile ${RUN_TESTS_SOURCES}) - get_filename_component(testname ${testsourcefile} NAME_WLE) +foreach(testsourcefile ${RUN_TESTS_SOURCES}) + if(NOT EXISTS ../${testsourcefile}) + message(WARNING "Missing ../${testsourcefile}") + continue() + endif() + + get_filename_component(testname ../${testsourcefile} NAME_WLE) add_executable(${PROJECT_NAME}_${testname} ../${testsourcefile}) target_link_libraries(${PROJECT_NAME}_${testname} Boost::any Boost::core) add_test(NAME ${PROJECT_NAME}_${testname} COMMAND ${PROJECT_NAME}_${testname}) diff --git a/test/cmake_subdir_test/GNUmakefile b/test/cmake_subdir_test/GNUmakefile new file mode 100644 index 0000000..6d37ba3 --- /dev/null +++ b/test/cmake_subdir_test/GNUmakefile @@ -0,0 +1,98 @@ +# Copyright Claus Klein, 2025-2026 +# Distributed under the Boost Software License, Version 1.0. +# See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt + +# Standard stuff + +.SUFFIXES: + +MAKEFLAGS+= --no-builtin-rules # Disable the built-in implicit rules. +# MAKEFLAGS+= --warn-undefined-variables # Warn when an undefined variable is referenced. +# MAKEFLAGS+= --include-dir=$(CURDIR)/conan # Search DIRECTORY for included makefiles (*.mk). + +export hostSystemName=$(shell uname) + +ifeq (${hostSystemName},Darwin) + export LLVM_PREFIX:=$(shell brew --prefix llvm) + export LLVM_DIR:=$(shell realpath ${LLVM_PREFIX}) + export PATH:=${LLVM_DIR}/bin:${PATH} + + export CMAKE_CXX_STDLIB_MODULES_JSON=${LLVM_DIR}/lib/c++/libc++.modules.json + export CXXFLAGS:=-stdlib=libc++ + export LDFLAGS=-L$(LLVM_DIR)/lib/c++ # XXX -lc++abi + export CXX=clang++ + # FIXME: export GCOV="llvm-cov gcov" + + ### TODO: to test g++-15: + export GCC_PREFIX:=$(shell brew --prefix gcc) + export GCC_DIR:=$(shell realpath ${GCC_PREFIX}) + + # export CMAKE_CXX_STDLIB_MODULES_JSON=${GCC_DIR}/lib/gcc/current/libstdc++.modules.json + # export CXXFLAGS:=-stdlib=libstdc++ + # export CXX:=g++-15 + # export GCOV="gcov" +else ifeq (${hostSystemName},Linux) + export LLVM_DIR=/usr/lib/llvm-20 + export PATH:=${LLVM_DIR}/bin:${PATH} + export CXX=clang++-20 +endif + +.PHONY: all install coverage gclean distclean format demo + +all: build/compile_commands.json + ln -sf $< . + ninja -C build + +build/compile_commands.json: CMakeLists.txt GNUmakefile + cmake -S . -B build -G Ninja \ + -D CMAKE_EXPERIMENTAL_CXX_IMPORT_STD="d0edc3af-4c50-42ea-a356-e2862fe7a444" \ + -D CMAKE_CXX_STDLIB_MODULES_JSON=${CMAKE_CXX_STDLIB_MODULES_JSON} \ + -D CMAKE_CXX_STANDARD=20 -D CMAKE_CXX_EXTENSIONS=YES -D CMAKE_CXX_STANDARD_REQUIRED=YES \ + -D CMAKE_CXX_MODULE_STD=NO \ + -D BOOST_USE_MODULES=YES \ + -D BUILD_TESTING=NO \ + -D CMAKE_BUILD_TYPE=Release \ + -D CMAKE_INSTALL_MESSAGE=LAZY \ + -D CMAKE_SKIP_INSTALL_RULES=NO \ + --log-level=VERBOSE --fresh \ + # -D CMAKE_CXX_FLAGS='-fno-inline --coverage' \ + # --trace-expand --trace-source=use-fetch-content.cmake \ + # --debug-find-pkg=GTest + +install: build/cmake_install.cmake + cmake --install build + +distclean: # XXX clean + rm -rf build stagedir compile_commands.json + find . -name '*~' -delete + +gclean: clean + find build -name '*.gc..' -delete + +build/coverage: test + mkdir -p $@ + +coverage: build/coverage + gcovr --merge-mode-functions separate + +format: distclean + pre-commit run --all + +demo: distclean + -rm -rf /opt/local/*/* + cmake --preset appleclang-release --fresh --log-level=VERBOSE + cmake --workflow appleclang-release + cmake --preset gcc-release --fresh --log-level=VERBOSE + cmake --workflow gcc-release + cmake --preset llvm-release --fresh --log-level=VERBOSE + cmake --workflow llvm-release + cmake --preset llvm-debug --fresh --log-level=VERBOSE + cmake --workflow llvm-debug + cmake --install build/llvm-debug --prefix=/opt/local + cmake --install build/llvm-release --prefix=/opt/local + tree /opt/local + + +# Anything we don't know how to build will use this rule. +% :: + ninja -C build $(@) diff --git a/test/cmake_subdir_test/cmake/Config.cmake.in b/test/cmake_subdir_test/cmake/Config.cmake.in new file mode 100644 index 0000000..07222f3 --- /dev/null +++ b/test/cmake_subdir_test/cmake/Config.cmake.in @@ -0,0 +1,13 @@ +# Copyright Claus Klein, 2025-2026 +# Distributed under the Boost Software License, Version 1.0. +# See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt + +include(CMakeFindDependencyMacro) + +@BOOST_FIND_DEPENDENCIES@ + +@PACKAGE_INIT@ + +include(${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@-targets.cmake) + +check_required_components(@PROJECT_NAME@) diff --git a/test/cmake_subdir_test/cmake/boost-install-library.cmake b/test/cmake_subdir_test/cmake/boost-install-library.cmake new file mode 100644 index 0000000..ae51b3f --- /dev/null +++ b/test/cmake_subdir_test/cmake/boost-install-library.cmake @@ -0,0 +1,353 @@ +# Copyright Claus Klein, 2025-2026 +# Distributed under the Boost Software License, Version 1.0. +# See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt + +cmake_minimum_required(VERSION 3.30) + +include_guard(GLOBAL) + +include(CMakePackageConfigHelpers) +include(GNUInstallDirs) + +# boost_install_library +# ===================== +# +# Installs a library (or set of targets) along with headers, C++ modules, +# and optional CMake package configuration files. +# +# Usage: +# ------ +# boost_install_library( +# TARGETS [ ...] +# [DEPENDENCIES [ ...]] +# [NAMESPACE ] +# [EXPORT_NAME ] +# [DESTINATION ] +# [NO_VERSION_SUFFIX] +# ) +# +# Arguments: +# ---------- +# +# name +# Logical package name (e.g. "boost_any"). +# Used to derive config file names and cache variable prefixes. +# +# TARGETS (required) +# List of CMake targets to install. +# +# DEPENDENCIES (optional) +# Semicolon-separated list, one dependency per entry. +# Each entry is a valid find_dependency() argument list. +# NOTE: you must use the bracket form for quoting if not only a package name is used! CK +# "[===[Boost::type_traits 1.0.0]===] [===[Boost::scope 0.0.1 EXACT]===] fmt" +# +# NAMESPACE (optional) +# Namespace for exported targets. +# Defaults to "Boost::". +# +# EXPORT_NAME (optional) +# Name of the CMake export set. +# Defaults to "-targets". +# +# DESTINATION (optional) +# The install destination for CXX_MODULES. +# Defaults to ${CMAKE_INSTALL_LIBDIR}/cmake/${name}/modules. +# +# NO_VERSION_SUFFIX (optional) +# option to disable the versioning of install destinations +# +# Brief +# ----- +# +# This function installs the specified project TARGETS and its FILE_SET +# HEADERS to the default CMAKE install destination. +# +# It also handles the installation of the CMake config package files if +# needed. If the given targets has FILE_SET CXX_MODULE, it will also +# installed to the given DESTINATION +# +# Cache variables: +# ---------------- +# +# BOOST_INSTALL_CONFIG_FILE_PACKAGES +# List of package names for which config files should be installed. +# +# _INSTALL_CONFIG_FILE_PACKAGE +# Per-package override to enable/disable config file installation. +# is the uppercased package name with dots replaced by underscores. +# +# Caveats +# ------- +# +# **Only one `FILE_SET CXX_MODULES` is yet supported to install with this +# function!** +# +# **Only header files contained in a `PUBLIC FILE_SET TYPE HEADERS` will be +# install with this function!** + +function(boost_install_library name) + # ---------------------------- + # Argument parsing + # ---------------------------- + set(options NO_VERSION_SUFFIX) + set(oneValueArgs NAMESPACE EXPORT_NAME DESTINATION) + set(multiValueArgs TARGETS DEPENDENCIES) + + cmake_parse_arguments( + BOOST + "${options}" + "${oneValueArgs}" + "${multiValueArgs}" + ${ARGN} + ) + + if(NOT BOOST_TARGETS) + message( + FATAL_ERROR + "boost_install_library(${name}): TARGETS must be specified" + ) + endif() + + if(CMAKE_SKIP_INSTALL_RULES) + message( + WARNING + "boost_install_library(${name}): not installing targets '${BOOST_TARGETS}' due to CMAKE_SKIP_INSTALL_RULES" + ) + return() + endif() + + # gersemi: off + # NOTE: If one of this variables is not set, the default DESTINATION is used! CK + if(NOT BOOST_NO_VERSION_SUFFIX) + set(_version_suffix "-${PROJECT_VERSION}") + set(_include_install_dir DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/boost${_version_suffix}) + # set(_lib_install_dir DESTINATION ${CMAKE_INSTALL_LIBDIR}/boost${_version_suffix}) + # set(_bin_install_dir DESTINATION ${CMAKE_INSTALL_BINDIR}/boost${_version_suffix}) + endif() + set(_config_install_dir "${CMAKE_INSTALL_LIBDIR}/cmake/${name}${_version_suffix}") + # gersemi: on + + # ---------------------------- + # Defaults + # ---------------------------- + if(NOT BOOST_NAMESPACE) + set(BOOST_NAMESPACE "Boost::") + endif() + + if(NOT BOOST_EXPORT_NAME) + set(BOOST_EXPORT_NAME "${name}-targets") + endif() + + if(NOT BOOST_DESTINATION) + set(BOOST_DESTINATION "${_config_install_dir}/modules") + endif() + + # XXX string(REPLACE "boost_" "" install_component_name "${name}") + set(install_component_name "boost") + message( + VERBOSE + "boost-install-library(${name}): COMPONENT '${install_component_name}'" + ) + + # -------------------------------------------------- + # Install each target with all of its file sets + # -------------------------------------------------- + foreach(_tgt IN LISTS BOOST_TARGETS) + if(NOT TARGET "${_tgt}") + message( + WARNING + "boost_install_library(${name}): '${_tgt}' is not a target" + ) + continue() + endif() + + # Given boost_any, the component_name is any + string(REPLACE "_" ";" name_parts "${_tgt}") + # fail if the name doesn't look like boost_any + list(LENGTH name_parts name_parts_length) + if(NOT name_parts_length GREATER_EQUAL 2) + message( + FATAL_ERROR + "boost_install_library(${name}): expects a name of the form 'boost_', got '${_tgt}'" + ) + endif() + # XXX list(GET name_parts -1 component_name) + + set(component_name "${_tgt}") + set_target_properties( + "${_tgt}" + PROPERTIES EXPORT_NAME "${component_name}" + ) + message( + VERBOSE + "boost_install_library(${name}): EXPORT_NAME ${component_name} for TARGET '${_tgt}'" + ) + + # Get the list of interface header sets, exact one expected! + set(_install_header_set_args) + get_target_property( + _available_header_sets + ${_tgt} + INTERFACE_HEADER_SETS + ) + if(_available_header_sets) + message( + VERBOSE + "boost-install-library(${name}): '${_tgt}' has INTERFACE_HEADER_SETS=${_available_header_sets}" + ) + foreach(_install_header_set IN LISTS _available_header_sets) + list( + APPEND _install_header_set_args + FILE_SET + "${_install_header_set}" + ${_include_install_dir} + COMPONENT + "${install_component_name}_Development" + ) + endforeach() + else() + set(_install_header_set_args FILE_SET HEADERS) # NOTE: empty FILE_SET in this case! CK + endif() + + # Detect presence of C++ module file sets, exact one expected! + get_target_property(_module_sets "${_tgt}" CXX_MODULE_SETS) + if(_module_sets) + message( + VERBOSE + "boost-install-library(${name}): '${_tgt}' has CXX_MODULE_SETS=${_module_sets}" + ) + install( + TARGETS "${_tgt}" + EXPORT ${BOOST_EXPORT_NAME} + ARCHIVE + ${_lib_install_dir} + COMPONENT "${install_component_name}_Development" + LIBRARY + ${_lib_install_dir} + COMPONENT "${install_component_name}_Runtime" + NAMELINK_COMPONENT "${install_component_name}_Development" + RUNTIME + ${_bin_install_dir} + COMPONENT "${install_component_name}_Runtime" + ${_install_header_set_args} + FILE_SET ${_module_sets} + DESTINATION "${BOOST_DESTINATION}" + COMPONENT "${install_component_name}_Development" + # NOTE: There's currently no convention for this location! CK + CXX_MODULES_BMI + # TODO(CK): DESTINATION ${_config_install_dir}/bmi-${CMAKE_CXX_COMPILER_ID}_$ + COMPONENT "${install_component_name}_Development" + ) + else() + install( + TARGETS "${_tgt}" + EXPORT ${BOOST_EXPORT_NAME} + ARCHIVE + ${_lib_install_dir} + COMPONENT "${install_component_name}_Development" + LIBRARY + ${_lib_install_dir} + COMPONENT "${install_component_name}_Runtime" + NAMELINK_COMPONENT "${install_component_name}_Development" + RUNTIME + ${_bin_install_dir} + COMPONENT "${install_component_name}_Runtime" + ${_install_header_set_args} + ) + endif() + endforeach() + + # -------------------------------------------------- + # Export targets + # -------------------------------------------------- + # gersemi: off + install( + EXPORT ${BOOST_EXPORT_NAME} + NAMESPACE ${BOOST_NAMESPACE} + CXX_MODULES_DIRECTORY cxx-modules + DESTINATION ${_config_install_dir} + COMPONENT "${install_component_name}_Development" + ) + # gersemi: on + + # ---------------------------------------- + # Config file installation logic + # ---------------------------------------- + string(TOUPPER "${name}" _pkg_upper) + string(REPLACE "." "_" _pkg_prefix "${_pkg_upper}") + + option( + ${_pkg_prefix}_INSTALL_CONFIG_FILE_PACKAGE + "Enable creating and installing a CMake config-file package. Default: ON. Values: { ON, OFF }." + ON + ) + + set(_pkg_var "${_pkg_prefix}_INSTALL_CONFIG_FILE_PACKAGE") + + if(NOT DEFINED ${_pkg_var}) + set(${_pkg_var} + OFF + CACHE BOOL + "Install CMake package config files for ${name}" + ) + endif() + + set(_install_config OFF) + + if(${_pkg_var}) + set(_install_config ON) + elseif(BOOST_INSTALL_CONFIG_FILE_PACKAGES) + list(FIND BOOST_INSTALL_CONFIG_FILE_PACKAGES "${name}" _idx) + if(NOT _idx EQUAL -1) + set(_install_config ON) + endif() + endif() + + # ---------------------------------------- + # expand dependencies + # ---------------------------------------- + set(_boost_find_deps "") + foreach(dep IN ITEMS ${BOOST_DEPENDENCIES}) + message( + VERBOSE + "boost-install-library(${name}): Add find_dependency(${dep})" + ) + string(APPEND _boost_find_deps "find_dependency(${dep})\n") + endforeach() + set(BOOST_FIND_DEPENDENCIES "${_boost_find_deps}") + + # ---------------------------------------- + # Generate + install config files + # ---------------------------------------- + if(_install_config) + configure_package_config_file( + "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/Config.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/${name}-config.cmake" + INSTALL_DESTINATION ${_config_install_dir} + ) + + write_basic_package_version_file( + "${CMAKE_CURRENT_BINARY_DIR}/${name}-config-version.cmake" + VERSION ${PROJECT_VERSION} + COMPATIBILITY SameMajorVersion + ) + + install( + FILES + "${CMAKE_CURRENT_BINARY_DIR}/${name}-config.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/${name}-config-version.cmake" + DESTINATION ${_config_install_dir} + COMPONENT "${install_component_name}_Development" + ) + else() + message( + WARNING + "boost-install-library(${name}): Not installing a config package for '${name}'" + ) + endif() +endfunction() + +set(CPACK_GENERATOR TGZ) +include(CPack) +