From de93336895496b55a8ca7c61b904f1c5c72f9fae Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Tue, 21 Jan 2020 17:29:38 +0100 Subject: [PATCH 1/3] Simplify CMake Remove LAYOUT and SYSTEM_INCLUDE parameters (handled by superproject if wanted). Remove BoostAddLibrary and add the options in the "classic" way. Refactor BoostInstall into a generic InstallTargets function that wraps all boilerplate code required for almost all libraries. --- CMakeLists.txt | 30 +++++++++------- Config.cmake.in | 4 +-- appveyor.yml | 2 +- cmake/BoostAddLibrary.cmake | 67 ------------------------------------ cmake/BoostAddOptions.cmake | 32 +++++++---------- cmake/BoostInstall.cmake | 57 ------------------------------- cmake/InstallTargets.cmake | 68 +++++++++++++++++++++++++++++++++++++ 7 files changed, 100 insertions(+), 160 deletions(-) delete mode 100644 cmake/BoostAddLibrary.cmake delete mode 100644 cmake/BoostInstall.cmake create mode 100644 cmake/InstallTargets.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 571839b..42e31cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,18 +37,26 @@ if(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY) endif() include(BoostAddOptions) -include(BoostAddLibrary) include(BoostAddWarnings) -boost_add_options(nowide) if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) include(CTest) endif() -if(BOOST_NOWIDE_SYSTEM_INCLUDE) - set(nowideSystem SYSTEM) -else() - set(nowideSystem "") + +# Using glob here is ok as it is only for headers +file(GLOB_RECURSE headers include/*.hpp) +add_library(boost_nowide src/iostream.cpp ${headers}) +add_library(Boost::nowide ALIAS boost_nowide) +set_target_properties(boost_nowide PROPERTIES + CXX_VISIBILITY_PRESET hidden + VISIBILITY_INLINES_HIDDEN ON + VERSION ${PROJECT_VERSION} + EXPORT_NAME nowide +) +if(BUILD_SHARED_LIBS) + target_compile_definitions(boost_nowide PUBLIC BOOST_NOWIDE_DYN_LINK) endif() -boost_add_library(nowide ${nowideSystem} LAYOUT ${BOOST_NOWIDE_LAYOUT}) +target_compile_definitions(boost_nowide PUBLIC BOOST_NOWIDE_NO_LIB) +target_include_directories(boost_nowide PUBLIC include) boost_add_warnings(boost_nowide pedantic ${BOOST_NOWIDE_WERROR}) if(BOOST_NOWIDE_STANDALONE) @@ -67,15 +75,11 @@ else() endif() endif() -# Using glob here is ok as it is only for headers -file(GLOB_RECURSE headers include/*.hpp) -target_sources(boost_nowide PRIVATE src/iostream.cpp ${headers}) - if(BUILD_TESTING) add_subdirectory(test) endif() if(BOOST_NOWIDE_INSTALL) - include(BoostInstall) - boost_install(TARGETS boost_nowide LAYOUT ${BOOST_NOWIDE_LAYOUT}) + include(InstallTargets) + install_targets(TARGETS boost_nowide NAMESPACE Boost CONFIG_FILE ${PROJECT_SOURCE_DIR}/Config.cmake.in) endif() diff --git a/Config.cmake.in b/Config.cmake.in index 016b952..a0787e4 100644 --- a/Config.cmake.in +++ b/Config.cmake.in @@ -1,7 +1,7 @@ @PACKAGE_INIT@ -set(_boost_nowide_standalone @NOWIDE_STANDALONE@) -set(_boost_nowide_superproject @BOOST_SUPERPROJECT_SOURCE_DIR@) +set(_boost_nowide_standalone @BOOST_NOWIDE_STANDALONE@) +set(_boost_nowide_superproject "@BOOST_SUPERPROJECT_SOURCE_DIR@") if(NOT _boost_nowide_standalone) include(CMakeFindDependencyMacro) diff --git a/appveyor.yml b/appveyor.yml index 355627d..48760af 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -114,7 +114,7 @@ for: - if exist %INSTALL_DIR%\ (rmdir /S /Q %INSTALL_DIR%) - mkdir build - cd build - - cmake -G "%GENERATOR%" -DBOOST_NOWIDE_LAYOUT=versioned -DCMAKE_INSTALL_PREFIX=%INSTALL_DIR% .. + - cmake -G "%GENERATOR%" -DCMAKE_INSTALL_PREFIX=%INSTALL_DIR% .. build: project: build/boost_nowide.sln diff --git a/cmake/BoostAddLibrary.cmake b/cmake/BoostAddLibrary.cmake deleted file mode 100644 index 31b58aa..0000000 --- a/cmake/BoostAddLibrary.cmake +++ /dev/null @@ -1,67 +0,0 @@ -# Add boost library X as boost_X with alias target Boost::X and useful properties set -# Arguments: -# SYSTEM: Add include directory as system include -# LAYOUT: system or versioned to append version, compiler, ... -# SOURCES: Source files -function(boost_add_library name) - cmake_parse_arguments(PARSE_ARGV 1 ARG "SYSTEM;INTERFACE" "LAYOUT" "SOURCES") - if(ARG_UNPARSED_ARGUMENTS) - message(FATAL_ERROR "Invalid argument(s): ${ARG_UNPARSED_ARGUMENTS}") - endif() - - set(targetName boost_${name}) - string(TOUPPER "${targetName}" targetNameUpper) - - if(NOT ARG_LAYOUT) - set(ARG_LAYOUT system) - endif() - if(ARG_SYSTEM) - set(system SYSTEM) - else() - set(system "") - endif() - if(ARG_INTERFACE) - if(ARG_SOURCES) - message(FATAL_ERROR "Cannot add sources to an interface library") - endif() - add_library(${targetName} INTERFACE) - set(scope INTERFACE) - else() - add_library(${targetName} ${ARG_SOURCES}) - set(scope PUBLIC) - endif() - - set(libname ${targetName}) - if(ARG_LAYOUT STREQUAL "versioned") - string(APPEND libname -$) - if(CMAKE_CXX_COMPILER_VERSION MATCHES "^([0-9]+)\.") - string(APPEND libname ${CMAKE_MATCH_1}) - endif() - set(abiTag "$<$:-d>") # TODO: add remaining abitags - string(APPEND libname -$,x32,x64>) - string(APPEND libname -${PROJECT_VERSION_MAJOR}_${PROJECT_VERSION_MINOR}) - if(NOT PROJECT_VERSION_PATCH EQUAL "0") - string(APPEND libname _${PROJECT_VERSION_PATCH}) - endif() - string(APPEND libname ) - elseif(NOT ARG_LAYOUT STREQUAL "system") - message(FATAL_ERROR "Unsupported layout: ${ARG_LAYOUT}") - endif() - - set_target_properties(${targetName} PROPERTIES - CXX_VISIBILITY_PRESET hidden - VISIBILITY_INLINES_HIDDEN ON - POSITION_INDEPENDENT_CODE ON - EXPORT_NAME ${name} - OUTPUT_NAME ${libname} - VERSION ${PROJECT_VERSION} - ) - if(BUILD_SHARED_LIBS) - target_compile_definitions(${targetName} ${scope} ${targetNameUpper}_DYN_LINK) - endif() - add_library(Boost::${name} ALIAS ${targetName}) - target_compile_definitions(${targetName} ${scope} ${targetNameUpper}_NO_LIB) - target_include_directories(${targetName} ${system} ${scope} - $ - ) -endfunction() diff --git a/cmake/BoostAddOptions.cmake b/cmake/BoostAddOptions.cmake index 94ad02b..4c95ccb 100644 --- a/cmake/BoostAddOptions.cmake +++ b/cmake/BoostAddOptions.cmake @@ -1,21 +1,13 @@ -# Add common options for the library with the given name -function(boost_add_options name) - if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR OR BOOST_SUPERPROJECT_SOURCE_DIR) - set(def_INSTALL ON) - set(def_SYSTEM_INCLUDE OFF) - set(def_WERROR ON) - set(def_LAYOUT system) - else() - set(def_INSTALL OFF) - set(def_SYSTEM_INCLUDE ON) - set(def_WERROR OFF) - set(def_LAYOUT system) - endif() - - string(TOUPPER ${name} NAME) +# Add common options for the current library project +if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR OR BOOST_SUPERPROJECT_SOURCE_DIR) + set(def_INSTALL ON) + set(def_WERROR ON) +else() + set(def_INSTALL OFF) + set(def_WERROR OFF) +endif() - option(BOOST_${NAME}_INSTALL "Install library" "${def_INSTALL}") - option(BOOST_${NAME}_SYSTEM_INCLUDE "Treat includes as system includes" "${def_SYSTEM_INCLUDE}") - option(BOOST_${NAME}_WERROR "Treat warnings as errors" "${def_WERROR}") - set(BOOST_${NAME}_LAYOUT "${def_LAYOUT}" CACHE STRING "Layout of installed library [system, versioned]") -endfunction() +string(TOUPPER ${PROJECT_NAME} NAME) + +option(${NAME}_INSTALL "Install library" "${def_INSTALL}") +option(${NAME}_WERROR "Treat warnings as errors" "${def_WERROR}") diff --git a/cmake/BoostInstall.cmake b/cmake/BoostInstall.cmake deleted file mode 100644 index 398531a..0000000 --- a/cmake/BoostInstall.cmake +++ /dev/null @@ -1,57 +0,0 @@ -include(GNUInstallDirs) -include(CMakePackageConfigHelpers) - -# Install all passed libraries including *Config.cmake and *ConfigVersion.cmake -# Requires a file Config.cmake.in the projects source dir -# Arguments: -# - TARGETS: List of targets to install -function(boost_install) - cmake_parse_arguments(PARSE_ARGV 0 ARG "" "LAYOUT" "TARGETS") - if(ARG_UNPARSED_ARGUMENTS) - message(FATAL_ERROR "Invalid argument(s): ${ARG_UNPARSED_ARGUMENTS}") - endif() - if(NOT ARG_LAYOUT) - set(ARG_LAYOUT system) - endif() - - if(ARG_LAYOUT STREQUAL "versioned") - set(install_includedir ${CMAKE_INSTALL_INCLUDEDIR}/boost-${PROJECT_VERSION_MAJOR}_${PROJECT_VERSION_MINOR}) - set(configFolder ${PROJECT_NAME}-${PROJECT_VERSION}) - elseif(ARG_LAYOUT STREQUAL "system") - set(install_includedir ${CMAKE_INSTALL_INCLUDEDIR}) - set(configFolder ${PROJECT_NAME}) - endif() - foreach(tgt IN LISTS ARG_TARGETS) - target_include_directories(${tgt} INTERFACE $) - endforeach() - - install(TARGETS ${ARG_TARGETS} - EXPORT ${PROJECT_NAME}Targets - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - ) - install(DIRECTORY include/ DESTINATION ${install_includedir}) - - set(configFile ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake) - set(versionFile ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake) - set(configInstallDestination lib/cmake/${configFolder}) - - configure_package_config_file( - ${PROJECT_SOURCE_DIR}/Config.cmake.in - ${configFile} - INSTALL_DESTINATION ${configInstallDestination} - ) - write_basic_package_version_file( - ${versionFile} - COMPATIBILITY SameMajorVersion - ) - - install(FILES ${configFile} ${versionFile} DESTINATION ${configInstallDestination}) - - install( - EXPORT ${PROJECT_NAME}Targets - NAMESPACE "Boost::" - DESTINATION ${configInstallDestination} - ) -endfunction() diff --git a/cmake/InstallTargets.cmake b/cmake/InstallTargets.cmake new file mode 100644 index 0000000..ecd7b14 --- /dev/null +++ b/cmake/InstallTargets.cmake @@ -0,0 +1,68 @@ +include(GNUInstallDirs) +include(CMakePackageConfigHelpers) + +# Install all passed libraries including Config.cmake and ConfigVersion.cmake +# Assumes that your headers are in 'include/' +# Uses GNUInstallDirs to determine install locations +# Note: Use of BUILD_INTERFACE for headers is not required as it will be fixed up +# Arguments: +# - TARGETS: List of targets to install +# - NAMESPACE: Namespace to use (Installed libraries will be available as "Namespace::Name") +# - CONFIG_FILE: If passed, this will be used to configure the *Config.cmake, +# else a reasonable default will be used which is enough if there are no dependencies +function(install_targets) + cmake_parse_arguments(PARSE_ARGV 0 ARG "" "NAMESPACE;CONFIG_FILE" "TARGETS") + if(ARG_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "Invalid argument(s): ${ARG_UNPARSED_ARGUMENTS}") + endif() + if(ARG_NAMESPACE) + string(APPEND ARG_NAMESPACE "::") + endif() + if(NOT ARG_CONFIG_FILE) + set(ARG_CONFIG_FILE "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake.in") + file(WRITE ${ARG_CONFIG_FILE} + "@PACKAGE_INIT@\n" + "include(\"${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake\")\n" + "check_required_components(\"@PROJECT_NAME@\")\n" + ) + endif() + + # Fixup INTERFACE_INCLUDE_DIRECTORIES: + # Wrap source includes into BUILD_INTERFACE and add INSTALL_INTERFACE + foreach(tgt IN LISTS ARG_TARGETS) + get_target_property(old_inc_dirs ${tgt} INTERFACE_INCLUDE_DIRECTORIES) + set(inc_dirs "$") + foreach(dir IN LISTS old_inc_dirs) + string(FIND "${dir}" "${PROJECT_SOURCE_DIR}" pos) + string(FIND "${dir}" "${PROJECT_BINARY_DIR}" pos2) + if(pos EQUAL 0 OR pos2 EQUAL 0) + set(dir "$") + endif() + list(APPEND inc_dirs "${dir}") + endforeach() + set_target_properties(${tgt} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${inc_dirs}") + endforeach() + + install(TARGETS ${ARG_TARGETS} + EXPORT ${PROJECT_NAME}Targets + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + ) + install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + + set(configFile ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake) + set(versionFile ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake) + set(configInstallDestination lib/cmake/${PROJECT_NAME}) + + configure_package_config_file(${ARG_CONFIG_FILE} ${configFile} INSTALL_DESTINATION ${configInstallDestination}) + write_basic_package_version_file(${versionFile} COMPATIBILITY SameMajorVersion) + + install(FILES ${configFile} ${versionFile} DESTINATION ${configInstallDestination}) + + install( + EXPORT ${PROJECT_NAME}Targets + NAMESPACE ${ARG_NAMESPACE} + DESTINATION ${configInstallDestination} + ) +endfunction() From 20b04415f05ac1831fb236917e0fb9c2462cfc91 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Fri, 24 Jan 2020 10:21:41 +0100 Subject: [PATCH 2/3] Remove usage of BOOST_GCC_VERSION We only check for the major version which is simpler this way --- include/boost/nowide/config.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/nowide/config.hpp b/include/boost/nowide/config.hpp index db49fb0..bdf7953 100644 --- a/include/boost/nowide/config.hpp +++ b/include/boost/nowide/config.hpp @@ -64,7 +64,7 @@ #define BOOST_NOWIDE_USE_FSTREAM_REPLACEMENTS 0 #endif -#if BOOST_VERSION < 106500 && defined(BOOST_GCC) && BOOST_GCC_VERSION >= 70000 +#if BOOST_VERSION < 106500 && defined(BOOST_GCC) && __GNUC__ >= 7 #define BOOST_NOWIDE_FALLTHROUGH __attribute__((fallthrough)) #else #define BOOST_NOWIDE_FALLTHROUGH BOOST_FALLTHROUGH From 22d0d00f70b568e369942fdc44336731cba0ab3f Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Fri, 24 Jan 2020 10:20:39 +0100 Subject: [PATCH 3/3] Build Boost on Github CI Avoid dependency on some unknown version --- .github/workflows/ci_tests.yml | 39 +++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci_tests.yml b/.github/workflows/ci_tests.yml index 58e5dd8..3d17f5c 100644 --- a/.github/workflows/ci_tests.yml +++ b/.github/workflows/ci_tests.yml @@ -22,22 +22,45 @@ jobs: - os: windows-latest generator: Unix Makefiles runs-on: ${{matrix.os}} + env: + DEP_DIR: ${{github.workspace}}/dependencies + BOOST_VERSION: 1.56.0 steps: - uses: actions/checkout@v2 + - uses: actions/cache@v1 + with: + path: ${{env.DEP_DIR}} + key: ${{matrix.os}}-${{matrix.generator}}-${{env.BOOST_VERSION}} # Install newer CMake to be able to find Boost - name: Install CMake if: runner.os == 'Linux' && ! matrix.standalone - run: wget -O- https://cmake.org/files/v3.14/cmake-3.14.0-Linux-x86_64.tar.gz | sudo tar --strip-components=1 -xzC /usr/local - - name: Build Boost - if: matrix.generator == 'MinGW Makefiles' - shell: bash + run: wget -qO- https://cmake.org/files/v3.14/cmake-3.14.0-Linux-x86_64.tar.gz | sudo tar --strip-components=1 -xzC /usr/local + # Install Boost, no wget on Windows -.- + - name: Download Boost + shell: cmake -P {0} run: | - cd "${BOOST_ROOT}" - ./bootstrap.sh --with-libraries=system,filesystem,chrono threading=multi - ./b2 link=static variant=release -j$(nproc) + string(REPLACE "." "_" filename boost_$ENV{BOOST_VERSION}) + set(BOOST_ROOT $ENV{DEP_DIR}/${filename}) + set(boost_url https://sourceforge.net/projects/boost/files/boost/$ENV{BOOST_VERSION}/${filename}.7z/download) + set(DEP_BUILD_DIR $ENV{DEP_DIR}/build) + file(MAKE_DIRECTORY ${DEP_BUILD_DIR}) + file(DOWNLOAD "${boost_url}" ${DEP_BUILD_DIR}/boost.7z SHOW_PROGRESS) + message("::set-env name=BOOST_ROOT::${BOOST_ROOT}") + - name: Build Boost + shell: bash + working-directory: ${{env.DEP_DIR}}/build + run: | + 7z x boost.7z > /dev/null + cd $(basename "$BOOST_ROOT") + [[ "${{matrix.generator}}" =~ "Unix" ]] && toolset=gcc || toolset=mingw + ./bootstrap.sh --with-toolset="$toolset" --with-libraries=system,filesystem,chrono threading=multi || (cat bootstrap.log && false) + sed -i 's/mingw/gcc/' project-config.jam + [[ "${{matrix.generator}}" =~ "Visual Studio" ]] && toolset=msvc-14.0 || toolset=gcc + ./b2 link=static toolset=$toolset address-model=64 -j$(nproc) --prefix="$BOOST_ROOT" install + cd "$DEP_DIR" && rm -r build - name: Configure working-directory: build - run: cmake .. -DBoost_ARCHITECTURE=-x64 -DCMAKE_BUILD_TYPE=${{matrix.buildType}} -DBUILD_SHARED_LIBS=${{matrix.shared_lib}} -DCMAKE_INSTALL_PREFIX=${{runner.workspace}}/../install -G "${{matrix.generator}}" -DCMAKE_SH="CMAKE_SH-NOTFOUND" + run: cmake .. -DBoost_DEBUG=ON -DCMAKE_BUILD_TYPE=${{matrix.buildType}} -DBUILD_SHARED_LIBS=${{matrix.shared_lib}} -DCMAKE_INSTALL_PREFIX=${{runner.workspace}}/../install -G "${{matrix.generator}}" -DCMAKE_SH="CMAKE_SH-NOTFOUND" - name: Build & Install run: cmake --build build --config ${{matrix.buildType}} --target install # Run test with both bash and powershell and watch for "Using std::cin" on bash but not on powershell