diff --git a/.clang-format b/.clang-format index 01d5fac..43e7cbc 100644 --- a/.clang-format +++ b/.clang-format @@ -1,4 +1,7 @@ --- +Language: Json +IndentWidth: 2 +--- Language: Cpp AccessModifierOffset: -2 AlignAfterOpenBracket: Align diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 887526d..58e104e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,14 +13,14 @@ jobs: fail-fast: false matrix: config: - - {name: "Ubuntu Clang 20", os: ubuntu-24.04, toolchain: "clang-20", clang_version: 20, installed_clang_version: 17, cmake_args: "-G \"Ninja Multi-Config\" -DCMAKE_CONFIGURATION_TYPES=\"RelWithDebInfo;Asan\" "} + - {name: "Ubuntu Clang 20", os: ubuntu-24.04, toolchain: "clang-20", clang_version: 20, installed_clang_version: 17, cmake_args: "-G \"Ninja Multi-Config\" -DCMAKE_CONFIGURATION_TYPES=\"RelWithDebInfo;Debug;Asan\" "} # Note: clang-19 + Asan setup causes errors on some platforms. Temporary skip some checks via .asan_options. - {name: "Ubuntu Clang 19", os: ubuntu-24.04, toolchain: "clang-19", clang_version: 19, installed_clang_version: 17, cmake_args: "-G \"Ninja Multi-Config\" -DCMAKE_CONFIGURATION_TYPES=\"RelWithDebInfo;Asan\" ", asan_options: "new_delete_type_mismatch=0"} - {name: "Ubuntu Clang 18", os: ubuntu-24.04, toolchain: "clang-18", clang_version: 18, installed_clang_version: 17, cmake_args: "-G \"Ninja Multi-Config\" -DCMAKE_CONFIGURATION_TYPES=\"RelWithDebInfo;Asan\" "} - {name: "Ubuntu Clang 17", os: ubuntu-24.04, toolchain: "clang-17", clang_version: 17, installed_clang_version: 17, cmake_args: "-G \"Ninja Multi-Config\" -DCMAKE_CONFIGURATION_TYPES=\"RelWithDebInfo;Asan\" "} - {name: "Ubuntu GCC 14", os: ubuntu-24.04, toolchain: "gcc-14", cmake_args: "-G \"Ninja Multi-Config\" -DCMAKE_CONFIGURATION_TYPES=\"RelWithDebInfo;Asan;Gcov\" ", coverage: true} - - {name: "Ubuntu GCC 13", os: ubuntu-24.04, toolchain: "gcc-13", cmake_args: "-G \"Ninja Multi-Config\" -DCMAKE_CONFIGURATION_TYPES=\"RelWithDebInfo;Asan\" "} - - {name: "Ubuntu GCC 12", os: ubuntu-24.04, toolchain: "gcc-12", cmake_args: "-G \"Ninja Multi-Config\" -DCMAKE_CONFIGURATION_TYPES=\"RelWithDebInfo;Asan\" "} + - {name: "Ubuntu GCC 13", os: ubuntu-24.04, toolchain: "gcc-13", cmake_args: "-G \"Ninja Multi-Config\" -DCMAKE_CONFIGURATION_TYPES=\"RelWithDebInfo;Asan\" "} + - {name: "Ubuntu GCC 12", os: ubuntu-24.04, toolchain: "gcc-12", cmake_args: "-G \"Ninja Multi-Config\" -DCMAKE_CONFIGURATION_TYPES=\"RelWithDebInfo;Asan\" "} steps: - uses: actions/checkout@v3 with: @@ -64,6 +64,7 @@ jobs: [[ ${CLANG_VERSION} = 17 ]] && sudo apt-get install libc++-dev libc++1 libc++abi-dev libc++abi1 find /usr/lib/x86_64-linux-gnu/ -name libc++.so* || true clang++-${CLANG_VERSION} --version + type clang++-${CLANG_VERSION} - name: Install GCC if: startsWith(matrix.config.name, 'Ubuntu GCC') run: | @@ -77,6 +78,7 @@ jobs: sudo apt-get install g++-${GCC_VERSION} gcc-${GCC_VERSION} find /usr/lib/x86_64-linux-gnu/ -name libstdc++.so* g++-${GCC_VERSION} --version + type g++-${GCC_VERSION} - name: Install Gcovr if: matrix.config.coverage run: | @@ -88,7 +90,7 @@ jobs: echo ${{ matrix.config.cmake_args }} echo ${{ matrix.config.toolchain }} rm -rf .build - cmake ${{ matrix.config.cmake_args }} -DCMAKE_INSTALL_PREFIX=.install -DCMAKE_TOOLCHAIN_FILE="etc/${{ matrix.config.toolchain }}-toolchain.cmake" -B .build -S . + cmake ${{ matrix.config.cmake_args }} -DCMAKE_INSTALL_PREFIX=.install -DCMAKE_PREFIX_PATH=.install -DCMAKE_TOOLCHAIN_FILE="etc/${{ matrix.config.toolchain }}-toolchain.cmake" -B .build -S . - name: CMake ASAN Build run: | set -x @@ -134,3 +136,7 @@ jobs: with: file: ${{runner.workspace}}/optional26/.build/coverage.json github-token: ${{ secrets.GITHUB_TOKEN }} + - name: CMake Debug Workflow + run: | + set -x + cmake --workflow --preset ${{ matrix.config.toolchain }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 72a4a83..1329d45 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,7 +6,9 @@ repos: hooks: - id: trailing-whitespace - id: end-of-file-fixer + - id: check-json - id: check-yaml + exclude: ^\.clang-format$ - id: check-added-large-files # Clang-format for C++ @@ -16,7 +18,7 @@ repos: rev: v18.1.8 hooks: - id: clang-format - types_or: [c++, c] + types_or: [c++, c, json] # CMake linting and formatting - repo: https://github.com/BlankSpruce/gersemi diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b4897d..e0e1214 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,15 +2,20 @@ # # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -cmake_minimum_required(VERSION 3.27) +set(CMAKE_SKIP_TEST_ALL_DEPENDENCY FALSE) -project(beman_optional26 VERSION 0.0.0 LANGUAGES CXX) +cmake_minimum_required(VERSION 3.29...3.31) + +project(beman_optional26 VERSION 0.0.1 LANGUAGES CXX) # Includes -include(CTest) -include(FetchContent) +include(CPack) +include(GNUInstallDirs) +include(CMakePackageConfigHelpers) -set(TARGETS_EXPORT_NAME ${CMAKE_PROJECT_NAME}Targets) +set(TARGET_PACKAGE_NAME ${PROJECT_NAME}) +set(TARGETS_EXPORT_NAME ${TARGET_PACKAGE_NAME}-targets) +set(INSTALL_CONFIGDIR ${CMAKE_INSTALL_LIBDIR}/cmake/${TARGET_PACKAGE_NAME}) option( OPTIONAL26_ENABLE_TESTING @@ -20,6 +25,8 @@ option( # Build the tests if enabled via the option OPTIONAL26_ENABLE_TESTING if(OPTIONAL26_ENABLE_TESTING) + include(FetchContent) + # Fetch GoogleTest FetchContent_Declare( googletest @@ -29,12 +36,15 @@ if(OPTIONAL26_ENABLE_TESTING) e39786088138f2749d64e9e90e0f9902daa77c40 # release-1.15.0 ) FetchContent_MakeAvailable(googletest) + + enable_testing() endif() set(CMAKE_VERIFY_INTERFACE_HEADER_SETS ON) # Create the library target and named header set for beman_optional26 add_library(beman_optional26 INTERFACE) +add_library(Beman::Optional26::beman_optional26 ALIAS beman_optional26) target_sources( beman_optional26 PUBLIC FILE_SET beman_optional26_headers TYPE HEADERS BASE_DIRS include @@ -59,23 +69,24 @@ add_subdirectory(include/beman/optional26) add_subdirectory(examples) -include(CMakePackageConfigHelpers) +# install +write_basic_package_version_file( + ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_PACKAGE_NAME}-config-version.cmake + VERSION ${PROJECT_VERSION} + COMPATIBILITY AnyNewerVersion +) -# This will be used to replace @PACKAGE_cmakeModulesDir@ -set(cmakeModulesDir cmake/beman) configure_package_config_file( cmake/Config.cmake.in - BemanOptional26Config.cmake - INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/beman/optional26/ - PATH_VARS cmakeModulesDir - NO_SET_AND_CHECK_MACRO - NO_CHECK_REQUIRED_COMPONENTS_MACRO + ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_PACKAGE_NAME}-config.cmake + INSTALL_DESTINATION ${INSTALL_CONFIGDIR} ) install( - FILES ${CMAKE_CURRENT_BINARY_DIR}/BemanOptional26Config.cmake - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/beman/optional26/ - COMPONENT beman_optional26_development + FILES + ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_PACKAGE_NAME}-config.cmake + ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_PACKAGE_NAME}-config-version.cmake + DESTINATION ${INSTALL_CONFIGDIR} ) # Coverage @@ -87,4 +98,5 @@ add_custom_target( COMMENT "Running gcovr to process coverage results" COMMAND mkdir -p coverage COMMAND gcovr --config gcovr.cfg . + DEPENDS test ) diff --git a/CMakePresets.json b/CMakePresets.json index 11abeb1..7e176ad 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -14,7 +14,17 @@ "binaryDir": "${sourceDir}/.build/${presetName}", "installDir": "${sourceDir}/.install/${presetName}", "cacheVariables": { - "CMAKE_CONFIGURATION_TYPES": "RelWithDebInfo;Debug;Tsan;Asan" + "CMAKE_PREFIX_PATH": { + "type": "path", + "value": "${sourceDir}/.install/${presetName}" + }, + "CMAKE_BUILD_TYPE": "Debug", + "CMAKE_CONFIGURATION_TYPES": "RelWithDebInfo;Debug;Tsan;Asan", + "CMAKE_CXX_EXTENSIONS": false, + "CMAKE_CXX_STANDARD": "20", + "CMAKE_CXX_STANDARD_REQUIRED": true, + "CMAKE_EXPORT_COMPILE_COMMANDS": true, + "CMAKE_SKIP_TEST_ALL_DEPENDENCY": false } }, { @@ -85,38 +95,27 @@ { "name": "common", "hidden": true, - "configuration": "Asan", + "configuration": "Debug", "targets": [ "all_verify_interface_header_sets", - "all" + "all", + "install" ] }, { "name": "system", "inherits": "common", - "configurePreset": "system", - "targets": [ - "all_verify_interface_header_sets", - "all" - ] + "configurePreset": "system" }, { "name": "gcc-14", "inherits": "common", - "configurePreset": "gcc-14", - "targets": [ - "all_verify_interface_header_sets", - "all" - ] + "configurePreset": "gcc-14" }, { "name": "gcc-13", "inherits": "common", - "configurePreset": "gcc-13", - "targets": [ - "all_verify_interface_header_sets", - "all" - ] + "configurePreset": "gcc-13" }, { "name": "gcc-12", @@ -131,45 +130,29 @@ { "name": "clang-19", "inherits": "common", - "configurePreset": "clang-19", - "targets": [ - "all_verify_interface_header_sets", - "all" - ] + "configurePreset": "clang-19" }, { "name": "clang-18", "inherits": "common", - "configurePreset": "clang-18", - "targets": [ - "all_verify_interface_header_sets", - "all" - ] + "configurePreset": "clang-18" }, { "name": "clang-17", "inherits": "common", - "configurePreset": "clang-17", - "targets": [ - "all_verify_interface_header_sets", - "all" - ] + "configurePreset": "clang-17" }, { "name": "clang-16", "inherits": "common", - "configurePreset": "clang-16", - "targets": [ - "all_verify_interface_header_sets", - "all" - ] + "configurePreset": "clang-16" } ], "testPresets": [ { "name": "common", "hidden": true, - "configuration": "Asan", + "configuration": "Debug", "output": { "outputOnFailure": true }, diff --git a/README.md b/README.md index 09cc70d..df5e9d4 100644 --- a/README.md +++ b/README.md @@ -141,7 +141,7 @@ apt-get install -y cmake make ninja-build # Example of toolchains: apt-get install \ - g++-14 gcc-14 gcc-13 g++-14 \ + g++-14 gcc-14 gcc-13 g++-13 \ clang-18 clang++-18 clang-17 clang++-17 ``` @@ -162,8 +162,12 @@ Available workflow presets: "system" "gcc-14" "gcc-13" + "gcc-12" + "clang-20" + "clang-19" "clang-18" "clang-17" + "clang-16" # Run examples: $ cmake --workflow --preset gcc-14 diff --git a/etc/clang-flags.cmake b/etc/clang-flags.cmake index 5b23bf7..2f651cf 100644 --- a/etc/clang-flags.cmake +++ b/etc/clang-flags.cmake @@ -1,6 +1,6 @@ include_guard(GLOBAL) -set(CMAKE_CXX_STANDARD 23) +set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_FLAGS "-stdlib=libc++ -Wall -Wextra " diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index b94bbab..a2d10a4 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -3,9 +3,15 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception # cmake-format: on -set(BEMAN_OPTIONAL26_LIBRARY "beman_optional26") +cmake_minimum_required(VERSION 3.29...3.31) -include(GNUInstallDirs) +project(beman_optional26_example VERSION 0.0.1 LANGUAGES CXX) + +set(BEMAN_OPTIONAL26_LIBRARY "Beman::Optional26::beman_optional26") + +if(PROJECT_IS_TOP_LEVEL) + find_package(beman_optional26 0.0.1 EXACT REQUIRED) +endif() # List of all buildable examples. set(EXAMPLES @@ -27,13 +33,15 @@ foreach(example ${EXAMPLES}) # Link example with the library. target_link_libraries(${example} "${BEMAN_OPTIONAL26_LIBRARY}") - # Install . - install( - TARGETS - ${example} - COMPONENT - beman_optional26_examples - DESTINATION - ${CMAKE_INSTALL_BINDIR} - ) + if(NOT PROJECT_IS_TOP_LEVEL) + # Install . + install( + TARGETS + ${example} + COMPONENT + beman_optional26_examples + DESTINATION + ${CMAKE_INSTALL_BINDIR} + ) + endif() endforeach() diff --git a/include/beman/optional26/CMakeLists.txt b/include/beman/optional26/CMakeLists.txt index e43fc93..e4c2028 100644 --- a/include/beman/optional26/CMakeLists.txt +++ b/include/beman/optional26/CMakeLists.txt @@ -33,9 +33,9 @@ install( install( EXPORT beman_optional26_export - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/beman/optional26/ + DESTINATION ${INSTALL_CONFIGDIR} NAMESPACE Beman::Optional26:: - FILE beman_optional26.cmake + FILE beman_optional26-config-targets.cmake EXPORT_LINK_INTERFACE_LIBRARIES COMPONENT beman_optional26_development ) diff --git a/src/beman/optional26/tests/CMakeLists.txt b/src/beman/optional26/tests/CMakeLists.txt index 5a2c1ad..2996dda 100644 --- a/src/beman/optional26/tests/CMakeLists.txt +++ b/src/beman/optional26/tests/CMakeLists.txt @@ -29,7 +29,7 @@ target_sources( target_link_libraries( beman_optional26_test - PRIVATE beman_optional26 GTest::gtest GTest::gtest_main + PRIVATE Beman::Optional26::beman_optional26 GTest::gtest GTest::gtest_main ) # Issue #32: Re-enable ASAN run CI/clang-19. @@ -41,7 +41,10 @@ gtest_add_tests(TARGET beman_optional26_test "" AUTO) add_library(constructor_fails test_constructor_fail.cpp) -target_link_libraries(constructor_fails PRIVATE beman_optional26) +target_link_libraries( + constructor_fails + PRIVATE Beman::Optional26::beman_optional26 +) set_target_properties( constructor_fails @@ -59,3 +62,21 @@ set_tests_properties(constructor_fails PROPERTIES WILL_FAIL true) # Alternatively -- check for a particular regex to pass # set_tests_properties(constructor_fails PROPERTIES PASS_REGULAR_EXPRESSION # "Assert true") + +# test if the targets are findable from the build directory +if(CMAKE_BUILD_TYPE STREQUAL Debug) + add_test( + NAME find-package-test + COMMAND + ${CMAKE_CTEST_COMMAND} + # --verbose + --output-on-failure -C $ --build-and-test + "${PROJECT_SOURCE_DIR}" + "${CMAKE_CURRENT_BINARY_DIR}/find-package-test" --build-generator + ${CMAKE_GENERATOR} --build-makeprogram ${CMAKE_MAKE_PROGRAM} + --build-options "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}" + "-DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}" + "-DCMAKE_BUILD_TYPE=$" + "-DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH}" + ) +endif()