diff --git a/.github/workflows/ci_coverage.yml b/.github/workflows/ci_coverage.yml index d0a3b6a9..e2cb481f 100644 --- a/.github/workflows/ci_coverage.yml +++ b/.github/workflows/ci_coverage.yml @@ -43,16 +43,9 @@ jobs: uses: actions/checkout@v4 with: fetch-depth: 0 - submodules: true - - name: Load ccache - uses: actions/cache@v4 - with: - path: /home/runner/.ccache - key: ccache-${{ runner.os }}-${{ github.workflow }}-${{ matrix.compiler }}-${{ github.ref }}-${{ github.run_id }} - restore-keys: | - ccache-${{ runner.os }}-${{ github.workflow }}-${{ matrix.compiler }}-${{ github.ref }} - ccache-${{ runner.os }}-${{ github.workflow }}-${{ matrix.compiler }} + - name: Setup cache + uses: seqan/actions/setup-actions-cache@main - name: Increase ccache size run: echo "CCACHE_MAXSIZE=300M" >> "${GITHUB_ENV}" diff --git a/.github/workflows/ci_linux.yml b/.github/workflows/ci_linux.yml index 582e038b..7c61bcd2 100644 --- a/.github/workflows/ci_linux.yml +++ b/.github/workflows/ci_linux.yml @@ -44,17 +44,9 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - with: - submodules: true - - name: Load ccache - uses: actions/cache@v4 - with: - path: /home/runner/.ccache - key: ccache-${{ runner.os }}-${{ github.workflow }}-${{ matrix.compiler }}-${{ github.ref }}-${{ github.run_id }} - restore-keys: | - ccache-${{ runner.os }}-${{ github.workflow }}-${{ matrix.compiler }}-${{ github.ref }} - ccache-${{ runner.os }}-${{ github.workflow }}-${{ matrix.compiler }} + - name: Setup cache + uses: seqan/actions/setup-actions-cache@main - name: Configure tests run: | diff --git a/.github/workflows/ci_macos.yml b/.github/workflows/ci_macos.yml index 0fcac0ab..397aba5d 100644 --- a/.github/workflows/ci_macos.yml +++ b/.github/workflows/ci_macos.yml @@ -37,8 +37,6 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - with: - submodules: true - name: Setup toolchain uses: seqan/actions/setup-toolchain@main diff --git a/.github/workflows/ci_misc.yml b/.github/workflows/ci_misc.yml index ee046c8f..b0fc35ae 100644 --- a/.github/workflows/ci_misc.yml +++ b/.github/workflows/ci_misc.yml @@ -45,17 +45,9 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - with: - submodules: true - - name: Load ccache - uses: actions/cache@v4 - with: - path: /home/runner/.ccache - key: ccache-${{ runner.os }}-${{ github.workflow }}-${{ matrix.build }}-${{ matrix.compiler }}-${{ github.ref }}-${{ github.run_id }} - restore-keys: | - ccache-${{ runner.os }}-${{ github.workflow }}-${{ matrix.build }}-${{ matrix.compiler }}-${{ github.ref }} - ccache-${{ runner.os }}-${{ github.workflow }}-${{ matrix.build }}-${{ matrix.compiler }} + - name: Setup cache + uses: seqan/actions/setup-actions-cache@main - name: Configure tests run: | diff --git a/README.md b/README.md index e7f0f149..f5bc4598 100644 --- a/README.md +++ b/README.md @@ -163,7 +163,7 @@ VERSION | | requirement | version | comment | |-------------------|-----------------------------------------------------------|----------|---------------------------------------------| -|**compiler** | [GCC](https://gcc.gnu.org) | ≥ 11 | | +|**compiler** | [GCC](https://gcc.gnu.org) | ≥ 12 | | |**compiler** | [Clang](https://clang.llvm.org/) | ≥ 17 | | |**build system** | [CMake](https://cmake.org) | ≥ 3.16 | optional, but recommended | |**optional libs** | [TDL](https://github.com/deNBI-cibi/tool_description_lib) | ≥ 1.0.0 | required for CWL and CTD export | diff --git a/cmake/sharg-config.cmake b/cmake/sharg-config.cmake index 42e0ab41..e26ee7e3 100644 --- a/cmake/sharg-config.cmake +++ b/cmake/sharg-config.cmake @@ -40,7 +40,6 @@ # SHARG_INCLUDE_DIRS -- to be passed to include_directories () # SHARG_LIBRARIES -- to be passed to target_link_libraries () # SHARG_DEFINITIONS -- to be passed to add_definitions () -# SHARG_CXX_FLAGS -- to be added to CMAKE_CXX_FLAGS # # Additionally, the following [IMPORTED][IMPORTED] targets are defined: # @@ -50,7 +49,6 @@ # target_include_directories(target $SHARG_INCLUDE_DIRS), # target_link_libraries(target $SHARG_LIBRARIES), # target_compile_definitions(target $SHARG_DEFINITIONS) and -# target_compile_options(target $SHARG_CXX_FLAGS) # for a target. # # [IMPORTED]: https://cmake.org/cmake/help/v3.10/prop_tgt/IMPORTED.html#prop_tgt:IMPORTED @@ -154,46 +152,25 @@ set (CMAKE_REQUIRED_FLAGS ${CMAKE_CXX_FLAGS}) option (SHARG_NO_TDL "Do not use TDL, even if present." OFF) # ---------------------------------------------------------------------------- -# Require C++20 +# Check supported compilers # ---------------------------------------------------------------------------- -set (SHARG_CXX_FLAGS "") - -set (CMAKE_REQUIRED_FLAGS_SAVE ${CMAKE_REQUIRED_FLAGS}) - -set (CXXSTD_TEST_SOURCE - "#if !defined (__cplusplus) || (__cplusplus < 202002) - #error NOCXX20 - #endif - int main() {}") - -check_cxx_source_compiles ("${CXXSTD_TEST_SOURCE}" CXX20_BUILTIN) - -if (CXX20_BUILTIN) - sharg_config_print ("C++ Standard-20 support: builtin") -else () - set (CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS_SAVE} -std=c++20") - - check_cxx_source_compiles ("${CXXSTD_TEST_SOURCE}" CXX20_FLAG) - - if (CXX20_FLAG) - sharg_config_print ("C++ Standard-20 support: via -std=c++20") - else () - sharg_config_error ("SHARG requires C++20, but your compiler does not support it.") - endif () +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12) + message (FATAL_ERROR "GCC < 12 is not supported. The detected compiler version is ${CMAKE_CXX_COMPILER_VERSION}.") +endif () - list (APPEND SHARG_CXX_FLAGS "-std=c++20") +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 17) + message (FATAL_ERROR "Clang < 17 is not supported. The detected compiler version is ${CMAKE_CXX_COMPILER_VERSION}.") endif () # ---------------------------------------------------------------------------- # thread support (pthread, windows threads) # ---------------------------------------------------------------------------- -set (SHARG_LIBRARIES "") set (THREADS_PREFER_PTHREAD_FLAG TRUE) find_package (Threads QUIET) -if (Threads_FOUND) +if (TARGET Threads::Threads) list (APPEND SHARG_LIBRARIES Threads::Threads) if ("${CMAKE_THREAD_LIBS_INIT}" STREQUAL "") sharg_config_print ("Thread support: builtin.") @@ -207,7 +184,6 @@ endif () # ---------------------------------------------------------------------------- # tool description lib (tdl) dependency # ---------------------------------------------------------------------------- -set (SHARG_USE_TDL FALSE) if (NOT SHARG_NO_TDL) if (NOT SHARG_HAS_CPM) @@ -216,21 +192,17 @@ if (NOT SHARG_NO_TDL) CPMGetPackage (tdl) endif () - if (TDL_FOUND OR tdl_ADDED) + if (TARGET tdl::tdl) sharg_config_print ("Optional dependency: TDL found.") - set (SHARG_USE_TDL TRUE) + list (APPEND SHARG_DEFINITIONS "-DSHARG_HAS_TDL=1") list (APPEND SHARG_LIBRARIES tdl::tdl) else () sharg_config_print ("Optional dependency: TDL not found.") + list (APPEND SHARG_DEFINITIONS "-DSHARG_HAS_TDL=0") endif () else () sharg_config_print ("Optional dependency: TDL deactivated.") -endif () - -if (SHARG_USE_TDL) - set (SHARG_DEFINITIONS ${SHARG_DEFINITIONS} "-DSHARG_HAS_TDL=1") -else () - set (SHARG_DEFINITIONS ${SHARG_DEFINITIONS} "-DSHARG_HAS_TDL=0") + list (APPEND SHARG_DEFINITIONS "-DSHARG_HAS_TDL=0") endif () # ---------------------------------------------------------------------------- @@ -238,20 +210,16 @@ endif () # ---------------------------------------------------------------------------- # librt -if ((${CMAKE_SYSTEM_NAME} STREQUAL "Linux") - OR (${CMAKE_SYSTEM_NAME} STREQUAL "kFreeBSD") - OR (${CMAKE_SYSTEM_NAME} STREQUAL "GNU")) - list (APPEND SHARG_LIBRARIES rt) +find_library (SHARG_RT_LIB rt) +if (SHARG_RT_LIB) + list (APPEND SHARG_LIBRARIES ${SHARG_RT_LIB}) endif () # libexecinfo -- implicit -check_include_file_cxx (execinfo.h _SHARG_HAVE_EXECINFO) -mark_as_advanced (_SHARG_HAVE_EXECINFO) -if (_SHARG_HAVE_EXECINFO) +find_package (Backtrace QUIET) +if (TARGET Backtrace::Backtrace) + list (APPEND SHARG_LIBRARIES Backtrace::Backtrace) sharg_config_print ("Optional dependency: libexecinfo found.") - if ((${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD") OR (${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD")) - list (APPEND SHARG_LIBRARIES execinfo elf) - endif () else () sharg_config_print ("Optional dependency: libexecinfo not found.") endif () @@ -260,22 +228,22 @@ endif () # Perform compilability test of platform.hpp (tests some requirements) # ---------------------------------------------------------------------------- -set (CXXSTD_TEST_SOURCE "#include - int main() {}") +# cmake-format: off +# Note: With CMake >= 3.25, the file WRITE can be removed, the second and third line in try_compile can be replaced by +# SOURCE_FROM_CONTENT "platform_test.cpp" "#include \nint main() {}" +file (WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/platform_test.cpp" + "#include \nint main() {}") -# using try_compile instead of check_cxx_source_compiles to capture output in case of failure -file (WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.cxx" "${CXXSTD_TEST_SOURCE}\n") - -# Can't find tdl::tdl in try_compile, so we need to remove it from SHARG_LIBRARIES -set (SHARG_TRY_COMPILE_LIBRARIES ${SHARG_LIBRARIES}) -list (REMOVE_ITEM SHARG_TRY_COMPILE_LIBRARIES tdl::tdl) -try_compile (SHARG_PLATFORM_TEST ${CMAKE_BINARY_DIR} - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.cxx - CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${CMAKE_CXX_FLAGS} ${SHARG_CXX_FLAGS}" - "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_INCLUDE_PATH};${SHARG_INCLUDE_DIR}" +try_compile (SHARG_PLATFORM_TEST + ${CMAKE_BINARY_DIR} + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/platform_test.cpp + CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${SHARG_INCLUDE_DIR}" COMPILE_DEFINITIONS ${SHARG_DEFINITIONS} - LINK_LIBRARIES ${SHARG_TRY_COMPILE_LIBRARIES} + CXX_STANDARD 23 + CXX_STANDARD_REQUIRED ON + CXX_EXTENSIONS OFF OUTPUT_VARIABLE SHARG_PLATFORM_TEST_OUTPUT) +# cmake-format: on if (SHARG_PLATFORM_TEST) sharg_config_print ("SHARG platform.hpp build: passed.") @@ -310,6 +278,7 @@ if (CMAKE_FIND_PACKAGE_NAME) else () set (SHARG_VERSION "${PACKAGE_VERSION}") endif () + # ---------------------------------------------------------------------------- # Export targets # ---------------------------------------------------------------------------- @@ -317,7 +286,7 @@ endif () if (NOT TARGET sharg::sharg) add_library (sharg_sharg INTERFACE) target_compile_definitions (sharg_sharg INTERFACE ${SHARG_DEFINITIONS}) - target_compile_options (sharg_sharg INTERFACE ${SHARG_CXX_FLAGS}) + target_compile_features (sharg_sharg INTERFACE cxx_std_23) target_link_libraries (sharg_sharg INTERFACE ${SHARG_LIBRARIES}) target_include_directories (sharg_sharg INTERFACE "${SHARG_INCLUDE_DIR}") add_library (sharg::sharg ALIAS sharg_sharg) @@ -338,7 +307,6 @@ if (SHARG_FIND_DEBUG) message (" SHARG_INCLUDE_DIR ${SHARG_INCLUDE_DIR}") message (" SHARG_LIBRARIES ${SHARG_LIBRARIES}") message (" SHARG_DEFINITIONS ${SHARG_DEFINITIONS}") - message (" SHARG_CXX_FLAGS ${SHARG_CXX_FLAGS}") message ("") message (" SHARG_VERSION ${SHARG_VERSION}") message (" SHARG_VERSION_MAJOR ${SHARG_VERSION_MAJOR}") diff --git a/include/sharg/detail/type_name_as_string.hpp b/include/sharg/detail/type_name_as_string.hpp index 38e16153..b736e548 100644 --- a/include/sharg/detail/type_name_as_string.hpp +++ b/include/sharg/detail/type_name_as_string.hpp @@ -54,14 +54,16 @@ inline std::string const type_name_as_string = []() // We exclude status != 0, because this code can't be reached normally, only if there is a defect in the compiler // itself, since the type is directly given by the compiler. See https://github.com/seqan/seqan3/pull/2311. // LCOV_EXCL_START - // clang-format off if (status != 0) - return std::string{typeid(type).name()} + - " (abi::__cxa_demangle error status (" + std::to_string(status) + "): " + - (status == -1 ? "A memory allocation failure occurred." : - (status == -2 ? "mangled_name is not a valid name under the C++ ABI mangling rules." : - (status == -3 ? "One of the arguments is invalid." : "Unknown Error"))) + ")"; - // clang-format on + { + demangled_name = + std::string{typeid(type).name()} + " (abi::__cxa_demangle error status (" + std::to_string(status) + "): " + + (status == -1 ? "A memory allocation failure occurred." + : (status == -2 ? "mangled_name is not a valid name under the C++ ABI mangling rules." + : (status == -3 ? "One of the arguments is invalid." : "Unknown Error"))) + + ")"; + return demangled_name; + } // LCOV_EXCL_STOP demangled_name = std::string{std::addressof(*demangled_name_ptr)}; diff --git a/test/header/generate_header_source.cmake b/test/header/generate_header_source.cmake index a1f742c5..76fe3582 100644 --- a/test/header/generate_header_source.cmake +++ b/test/header/generate_header_source.cmake @@ -13,26 +13,33 @@ option (HEADER_SUB_TEST "") file (WRITE "${HEADER_TARGET_SOURCE}" "") # write empty file +# cmake-format: off + if (HEADER_SUB_TEST STREQUAL "no-self-include") # this test ensures that a header will not be included by itself later file (READ "${HEADER_FILE_ABSOLUTE}" header_content) string (REPLACE "#pragma once" "" header_content "${header_content}") - file (APPEND "${HEADER_TARGET_SOURCE}" "${header_content}") + file (APPEND "${HEADER_TARGET_SOURCE}" + "// sharg-header-test-no-self-include-start\n" + "${header_content}\n" + "// sharg-header-test-no-self-include-end\n\n") else () # this test ensures that a header guard is in place file (APPEND "${HEADER_TARGET_SOURCE}" - " -#include <${HEADER_FILE_INCLUDE}> -#include <${HEADER_FILE_INCLUDE}>") + "// sharg-header-test-header-guard-start\n" + "#include <${HEADER_FILE_INCLUDE}>\n" + "#include <${HEADER_FILE_INCLUDE}>\n" + "// sharg-header-test-header-guard-end\n\n") endif () # these includes are required by some headers (note that they follow) file (APPEND "${HEADER_TARGET_SOURCE}" - " -#include -TEST(${HEADER_TEST_NAME_SAFE}) {}") + "// sharg-header-test-dependencies-start\n" + "#include \n" + "TEST(${HEADER_TEST_NAME_SAFE}) {}\n" + "// sharg-header-test-dependencies-end\n\n") # test that sharg headers include platform.hpp if ("${HEADER_COMPONENT}" MATCHES "sharg") @@ -40,34 +47,23 @@ if ("${HEADER_COMPONENT}" MATCHES "sharg") # exclude sharg/std/* and sharg/version.hpp from platform test if (NOT HEADER_FILE_INCLUDE MATCHES "sharg/(std/|version.hpp)") file (APPEND "${HEADER_TARGET_SOURCE}" - " -#ifndef SHARG_DOXYGEN_ONLY -#error \"Your header '${HEADER_FILE_INCLUDE}' file is missing #include \" -#endif") + "// sharg-header-test-platform-start\n" + "#ifndef SHARG_DOXYGEN_ONLY\n" + "#error \"Your header '${HEADER_FILE_INCLUDE}' file is missing #include \"\n" + "#endif\n" + "// sharg-header-test-platform-end\n\n") endif () # sharg/std/* must not include platform.hpp (and therefore any other sharg header) # See https://github.com/seqan/product_backlog/issues/135 if (HEADER_FILE_INCLUDE MATCHES "sharg/std/") file (APPEND "${HEADER_TARGET_SOURCE}" - " -#ifdef SHARG_DOXYGEN_ONLY -#error \"The standard header '${HEADER_FILE_INCLUDE}' file MUST NOT include any other sharg header\" -#endif") + "// sharg-header-test-no-platform-start\n" + "#ifdef SHARG_DOXYGEN_ONLY\n" + "#error \"The standard header '${HEADER_FILE_INCLUDE}' file MUST NOT include any other sharg header\"\n" + "#endif\n" + "// sharg-header-test-no-platform-end\n\n") endif () - - # test whether sharg has the visibility bug on lower gcc versions - # https://github.com/seqan/seqan3/issues/1317 - if (NOT HEADER_FILE_INCLUDE MATCHES "sharg/version.hpp") - file (APPEND "${HEADER_TARGET_SOURCE}" - " -#include -class A{ int i{5}; }; - -template -concept private_bug = requires(t a){a.i;}; - -static_assert(!private_bug, \"See https://github.com/seqan/seqan3/issues/1317\");") - endif () - endif () + +# cmake-format: on diff --git a/test/sharg-test.cmake b/test/sharg-test.cmake index 57551e57..ed14dc01 100644 --- a/test/sharg-test.cmake +++ b/test/sharg-test.cmake @@ -8,6 +8,18 @@ cmake_minimum_required (VERSION 3.12) +if (NOT DEFINED CMAKE_CXX_STANDARD) + set (CMAKE_CXX_STANDARD 23) +endif () + +if (NOT DEFINED CMAKE_CXX_STANDARD_REQUIRED) + set (CMAKE_CXX_STANDARD_REQUIRED ON) +endif () + +if (NOT DEFINED CMAKE_CXX_EXTENSIONS) + set (CMAKE_CXX_EXTENSIONS OFF) +endif () + # require Sharg package find_package (Sharg REQUIRED HINTS ${CMAKE_CURRENT_LIST_DIR}/../cmake) @@ -22,6 +34,8 @@ include (FindPackageMessage) option (SHARG_TEST_BUILD_OFFLINE "Skip the update step of external projects." OFF) +option (SHARG_WITH_WERROR "Report compiler warnings as errors." ON) + # ---------------------------------------------------------------------------- # Paths to folders. # ---------------------------------------------------------------------------- @@ -42,13 +56,23 @@ list (APPEND CMAKE_MODULE_PATH "${SHARG_TEST_CMAKE_MODULE_DIR}") # libraries which are in common for **all** seqan3 tests if (NOT TARGET sharg::test) add_library (sharg_test INTERFACE) - target_compile_options (sharg_test INTERFACE "-pedantic" "-Wall" "-Wextra" "-Werror") + target_compile_options (sharg_test INTERFACE "-pedantic" "-Wall" "-Wextra") + + if (SHARG_WITH_WERROR) + target_compile_options (sharg_test INTERFACE "-Werror") + message (STATUS "Building tests with -Werror.") + endif () - # GCC12 and above: Disable warning about std::hardware_destructive_interference_size not being ABI-stable. if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + # GCC12 and above: Disable warning about std::hardware_destructive_interference_size not being ABI-stable. if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 12) target_compile_options (sharg_test INTERFACE "-Wno-interference-size") endif () + + # Warn about failed return value optimization. + if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 14) + target_compile_options (sharg_test INTERFACE "-Wnrvo") + endif () endif () target_link_libraries (sharg_test INTERFACE "sharg::sharg" "pthread") @@ -64,24 +88,6 @@ if (NOT TARGET sharg::test::unit) add_library (sharg::test::unit ALIAS sharg_test_unit) endif () -# sharg::test::coverage specifies required flags, includes and libraries -# needed for coverage test cases in sharg/test/coverage -if (NOT TARGET sharg::test::coverage) - add_library (sharg_test_coverage INTERFACE) - target_compile_options (sharg_test_coverage INTERFACE "--coverage" "-fprofile-arcs" "-ftest-coverage") - # -fprofile-abs-path requires at least gcc8, it forces gcov to report absolute instead of relative paths. - # gcovr has trouble detecting the headers otherwise. - # ccache is not aware of this option, so it needs to be skipped with `--ccache-skip`. - find_program (CCACHE_PROGRAM ccache) - if (CCACHE_PROGRAM) - target_compile_options (sharg_test_coverage INTERFACE "--ccache-skip" "-fprofile-abs-path") - else () - target_compile_options (sharg_test_coverage INTERFACE "-fprofile-abs-path") - endif () - target_link_libraries (sharg_test_coverage INTERFACE "sharg::test::unit" "gcov") - add_library (sharg::test::coverage ALIAS sharg_test_coverage) -endif () - # sharg::test::header specifies required flags, includes and libraries # needed for header test cases in sharg/test/header if (NOT TARGET sharg::test::header)