From 8b27041fbe717b45d29cb18441df719e290663ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Mon, 15 Feb 2021 23:56:56 +0100 Subject: [PATCH 1/3] Add CMake option to generate surrogate TUs in development build A surrogate TU is TU that includes 1 specific header, and does nothing else. This is useful to verify that the header is self-sufficient and does not require other headers to be included for compilation to succeed. Closes #2106 Closes #2166 (this is a better solution) --- CMakeLists.txt | 2 ++ tests/CMakeLists.txt | 61 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 90d5806b..c0e13d44 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,8 @@ cmake_dependent_option(CATCH_BUILD_EXTRA_TESTS "Build extra tests" OFF "CATCH_DE cmake_dependent_option(CATCH_BUILD_FUZZERS "Build fuzzers" OFF "CATCH_DEVELOPMENT_BUILD" OFF) cmake_dependent_option(CATCH_ENABLE_COVERAGE "Generate coverage for codecov.io" OFF "CATCH_DEVELOPMENT_BUILD" OFF) cmake_dependent_option(CATCH_ENABLE_WERROR "Enables Werror during build" ON "CATCH_DEVELOPMENT_BUILD" OFF) +cmake_dependent_option(CATCH_BUILD_SURROGATES "Enable generating and building surrogate TUs for the main headers" OFF "CATCH_DEVELOPMENT_BUILD" OFF) + # Catch2's build breaks if done in-tree. You probably should not build # things in tree anyway, but we can allow projects that include Catch2 diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index f8bdb3b4..1a490398 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,5 +1,66 @@ include(MiscFunctions) +if (CATCH_BUILD_SURROGATES) + message(STATUS "Configuring targets for surrogate TUs") + + # If the folder does not exist before we ask for output redirect to + # a file, it won't work. + file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/surrogates) + + # Creates target to generate the surrogate TU for provided header. + # Returns the path to the generated file. + function(createSurrogateFileTarget sourceHeader pathToFile) + set(pathPrefix ${PROJECT_SOURCE_DIR}/src) + + file(RELATIVE_PATH includePath ${pathPrefix} ${sourceHeader}) + + get_filename_component(basicFileName "${sourceHeader}" NAME_WE) + + set(surrogateFilePath ${CMAKE_CURRENT_BINARY_DIR}/surrogates/surrogate_${basicFileName}.cpp) + + add_custom_command( + OUTPUT ${surrogateFilePath} + COMMAND cmake -E echo "\#include <${includePath}>" > "${surrogateFilePath}" + VERBATIM + ) + + set(${pathToFile} ${surrogateFilePath} PARENT_SCOPE) + endfunction() + + # Extracts all non-helper (e.g. catch_all.hpp) headers from the + # Catch2 target, and returns them through the argument. + function(ExtractCatch2Headers OutArg) + get_target_property(targetSources Catch2 SOURCES) + foreach(Source ${targetSources}) + string(REGEX MATCH "^.*\\.hpp$" isHeader ${Source}) + string(REGEX MATCH "_all.hpp" isAllHeader ${Source}) + if(isHeader AND NOT isAllHeader) + list(APPEND AllHeaders ${Source}) + endif() + endforeach() + set(${OutArg} ${AllHeaders} PARENT_SCOPE) + endfunction() + + + ExtractCatch2Headers(mainHeaders) + + if (NOT mainHeaders) + message(FATAL_ERROR "No headers in the main target were detected. Something is broken.") + endif() + + foreach(header ${mainHeaders}) + createSurrogateFileTarget(${header} pathToGeneratedFile) + list(APPEND surrogateFiles ${pathToGeneratedFile}) + endforeach() + + + add_executable(Catch2SurrogateTarget + ${surrogateFiles} + ) + target_link_libraries(Catch2SurrogateTarget PRIVATE Catch2WithMain) + +endif(CATCH_BUILD_SURROGATES) + #### # Temporary workaround for VS toolset changes in 2017 # We need to disable property, but CMake doesn't support it From e5e9afad167be344939a24337322f5652ab3e7ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 16 Feb 2021 14:28:12 +0100 Subject: [PATCH 2/3] Fix headers whose surrogate TUs did not compile --- src/catch2/benchmark/catch_constructor.hpp | 1 + src/catch2/benchmark/detail/catch_analyse.hpp | 2 ++ src/catch2/catch_reporter_registrars.hpp | 4 ++++ .../interfaces/catch_interfaces_reporter_factory.hpp | 7 +++++++ src/catch2/internal/catch_container_nonmembers.hpp | 2 ++ 5 files changed, 16 insertions(+) diff --git a/src/catch2/benchmark/catch_constructor.hpp b/src/catch2/benchmark/catch_constructor.hpp index 59600f21..fe651f1c 100644 --- a/src/catch2/benchmark/catch_constructor.hpp +++ b/src/catch2/benchmark/catch_constructor.hpp @@ -11,6 +11,7 @@ #define CATCH_CONSTRUCTOR_HPP_INCLUDED #include +#include namespace Catch { namespace Benchmark { diff --git a/src/catch2/benchmark/detail/catch_analyse.hpp b/src/catch2/benchmark/detail/catch_analyse.hpp index 0a52a845..46382c62 100644 --- a/src/catch2/benchmark/detail/catch_analyse.hpp +++ b/src/catch2/benchmark/detail/catch_analyse.hpp @@ -11,8 +11,10 @@ #define CATCH_ANALYSE_HPP_INCLUDED #include +#include #include #include +#include #include #include diff --git a/src/catch2/catch_reporter_registrars.hpp b/src/catch2/catch_reporter_registrars.hpp index e7375aa7..978d2925 100644 --- a/src/catch2/catch_reporter_registrars.hpp +++ b/src/catch2/catch_reporter_registrars.hpp @@ -9,11 +9,15 @@ #define CATCH_REPORTER_REGISTRARS_HPP_INCLUDED #include +#include #include #include namespace Catch { + struct IStreamingReporter; + using IStreamingReporterPtr = Detail::unique_ptr; + template class ReporterFactory : public IReporterFactory { diff --git a/src/catch2/interfaces/catch_interfaces_reporter_factory.hpp b/src/catch2/interfaces/catch_interfaces_reporter_factory.hpp index 9bcf94f0..5a40d1bd 100644 --- a/src/catch2/interfaces/catch_interfaces_reporter_factory.hpp +++ b/src/catch2/interfaces/catch_interfaces_reporter_factory.hpp @@ -8,9 +8,16 @@ #ifndef CATCH_INTERFACES_REPORTER_FACTORY_HPP_INCLUDED #define CATCH_INTERFACES_REPORTER_FACTORY_HPP_INCLUDED +#include + +#include + namespace Catch { struct ReporterConfig; + struct IStreamingReporter; + using IStreamingReporterPtr = Detail::unique_ptr; + struct IReporterFactory { virtual ~IReporterFactory(); // = default diff --git a/src/catch2/internal/catch_container_nonmembers.hpp b/src/catch2/internal/catch_container_nonmembers.hpp index f1dedeb6..d6f10eb5 100644 --- a/src/catch2/internal/catch_container_nonmembers.hpp +++ b/src/catch2/internal/catch_container_nonmembers.hpp @@ -10,6 +10,8 @@ #include +#include +#include // We want a simple polyfill over `std::empty`, `std::size` and so on // for C++14 or C++ libraries with incomplete support. From 29050daec0fc1a1b092ac2dc711bfc40648b8976 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 16 Feb 2021 16:05:23 +0100 Subject: [PATCH 3/3] Add Linux and Windows CI builds with surrogate TUs --- .github/workflows/linux-builds.yml | 10 +++++++++- appveyor.yml | 3 ++- tools/misc/appveyorBuildConfigurationScript.bat | 2 +- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/.github/workflows/linux-builds.yml b/.github/workflows/linux-builds.yml index 93ae21e6..eae7e003 100644 --- a/.github/workflows/linux-builds.yml +++ b/.github/workflows/linux-builds.yml @@ -20,6 +20,7 @@ jobs: - clang++-10 build_type: [Debug, Release] std: [14] + surrogates: [OFF] include: # cannot be installed on ubuntu-20.04 be default? # - cxx: g++-6 @@ -30,6 +31,13 @@ jobs: other_pkgs: clang-7 - cxx: clang++-10 other_pkgs: clang-10 + # We want one build to build surrogates -- but not more, to + # avoid trouble with long compilation/CI times. + - cxx: clang++-10 + build_type: Debug + std: 14 + other_pkgs: clang-10 + surrogates: ON steps: - uses: actions/checkout@v2 @@ -47,7 +55,7 @@ jobs: run: | cmake -Bbuild -H$GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=${{matrix.build_type}} \ -DCMAKE_CXX_STANDARD=${{matrix.std}} -DCATCH_DEVELOPMENT_BUILD=ON \ - -G Ninja + -DCATCH_BUILD_SURROGATES=${{matrix.surrogates}} -G Ninja - name: Build tests + lib working-directory: ${{runner.workspace}}/build diff --git a/appveyor.yml b/appveyor.yml index 86a1df18..d84d775c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -51,8 +51,9 @@ test_script: # build explicitly. environment: matrix: - - FLAVOR: VS 2019 x64 Debug + - FLAVOR: VS 2019 x64 Debug Surrogates APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 + surrogates: 1 platform: x64 configuration: Debug diff --git a/tools/misc/appveyorBuildConfigurationScript.bat b/tools/misc/appveyorBuildConfigurationScript.bat index 9ebd6ae0..d9be52eb 100644 --- a/tools/misc/appveyorBuildConfigurationScript.bat +++ b/tools/misc/appveyorBuildConfigurationScript.bat @@ -13,7 +13,7 @@ if "%CONFIGURATION%"=="Debug" ( cmake -H. -BBuild -A%PLATFORM% -DCATCH_TEST_USE_WMAIN=%wmain% -DMEMORYCHECK_COMMAND=build-misc\Debug\CoverageHelper.exe -DMEMORYCHECK_COMMAND_OPTIONS=--sep-- -DMEMORYCHECK_TYPE=Valgrind -DCATCH_BUILD_EXAMPLES=%examples% -DCATCH_BUILD_EXTRA_TESTS=%examples% -DCATCH_DEVELOPMENT_BUILD=ON || exit /b !ERRORLEVEL! ) else ( @REM # We know that coverage is 0 - cmake -H. -BBuild -A%PLATFORM% -DCATCH_TEST_USE_WMAIN=%wmain% -DCATCH_BUILD_EXAMPLES=%examples% -DCATCH_BUILD_EXTRA_TESTS=%examples% -DCATCH_DEVELOPMENT_BUILD=ON || exit /b !ERRORLEVEL! + cmake -H. -BBuild -A%PLATFORM% -DCATCH_TEST_USE_WMAIN=%wmain% -DCATCH_BUILD_EXAMPLES=%examples% -DCATCH_BUILD_EXTRA_TESTS=%examples% -DCATCH_BUILD_SURROGATES=%surrogates% -DCATCH_DEVELOPMENT_BUILD=ON || exit /b !ERRORLEVEL! ) ) if "%CONFIGURATION%"=="Release" (