From 4edbe91c54955db8aa4b03ac39b637b4293e4fde Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Wed, 1 May 2024 14:50:23 -0700 Subject: [PATCH 01/59] Check against the right C++ standard We should only be checking against C++11. --- .github/workflows/cmake-static-analysis-dbg.yml | 2 +- .github/workflows/cmake-static-analysis-rls.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cmake-static-analysis-dbg.yml b/.github/workflows/cmake-static-analysis-dbg.yml index d84a1df..a5748e6 100644 --- a/.github/workflows/cmake-static-analysis-dbg.yml +++ b/.github/workflows/cmake-static-analysis-dbg.yml @@ -30,4 +30,4 @@ jobs: use_cmake: true cmake_args: -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -Wno-dev - cppcheck_args: --enable=all --suppress=missingIncludeSystem + cppcheck_args: --enable=all --suppress=missingIncludeSystem --std=c++11 diff --git a/.github/workflows/cmake-static-analysis-rls.yml b/.github/workflows/cmake-static-analysis-rls.yml index b763d06..163a824 100644 --- a/.github/workflows/cmake-static-analysis-rls.yml +++ b/.github/workflows/cmake-static-analysis-rls.yml @@ -30,4 +30,4 @@ jobs: use_cmake: true cmake_args: -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -Wno-dev - cppcheck_args: --enable=all --suppress=missingIncludeSystem + cppcheck_args: --enable=all --suppress=missingIncludeSystem --std=c++11 From 69b384fadddc29fde05345dae93e41a3d6e94804 Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Wed, 1 May 2024 16:18:09 -0700 Subject: [PATCH 02/59] Fix static analysis workflow, add cppcheck + info to readme Also clean up clang-tidy configuration, stop including the deprecated and removed AnalyzeTemporaryDtors option as the option no longer is used or even exists in versions of clang-tidy after version 6. Merge static analysis workflows to use only the debug workflow. It's not necessary to run the analysis on both release and debug build configurations, from what I can see. This is reflected in the README. Added information to the README on running cppcheck from CodeLite. Added information to the README on running cppcheck on the project from the command line/terminal. Added clang-tidy information to the README. Added custom build action to the CodeLite project to run cppcheck. --- .clang-tidy | 1 - .../workflows/cmake-static-analysis-rls.yml | 33 ---------------- ...ysis-dbg.yml => cmake-static-analysis.yml} | 4 +- README.md | 38 +++++++++++++++++-- TestFramework.project | 5 ++- 5 files changed, 39 insertions(+), 42 deletions(-) delete mode 100644 .github/workflows/cmake-static-analysis-rls.yml rename .github/workflows/{cmake-static-analysis-dbg.yml => cmake-static-analysis.yml} (89%) diff --git a/.clang-tidy b/.clang-tidy index e925d82..a98339f 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,3 +1,2 @@ Checks: '-*,bugprone-*,cert-*,clang-analyzer-*,cppcoreguidelines-*,hicpp-*,misc-*,modernize-*,performance-*,portability-*,readability-*' -AnalyzeTemporaryDtors: false FormatStyle: "file" diff --git a/.github/workflows/cmake-static-analysis-rls.yml b/.github/workflows/cmake-static-analysis-rls.yml deleted file mode 100644 index 163a824..0000000 --- a/.github/workflows/cmake-static-analysis-rls.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: TestCPP Static analysis - Release - -on: - # Will run on push when merging to 'branches'. The output will be shown in the console - push: - branches: - - main - - # 'pull_request_target' allows this Action to also run on forked repositories - # The output will be shown in PR comments (unless the 'force_console_print' flag is used) - pull_request_target: - branches: - - "*" - -jobs: - static_analysis: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: Run static analysis - uses: JacobDomagala/StaticAnalysis@master - with: - language: c++ - - # Exclude any issues found in ${Project_root_dir}/lib - exclude_dir: lib - - use_cmake: true - cmake_args: -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -Wno-dev - - cppcheck_args: --enable=all --suppress=missingIncludeSystem --std=c++11 diff --git a/.github/workflows/cmake-static-analysis-dbg.yml b/.github/workflows/cmake-static-analysis.yml similarity index 89% rename from .github/workflows/cmake-static-analysis-dbg.yml rename to .github/workflows/cmake-static-analysis.yml index a5748e6..8f6768b 100644 --- a/.github/workflows/cmake-static-analysis-dbg.yml +++ b/.github/workflows/cmake-static-analysis.yml @@ -1,4 +1,4 @@ -name: TestCPP Static analysis - Debug +name: TestCPP Static analysis - cppcheck/clang-tidy on: # Will run on push when merging to 'branches'. The output will be shown in the console @@ -30,4 +30,4 @@ jobs: use_cmake: true cmake_args: -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -Wno-dev - cppcheck_args: --enable=all --suppress=missingIncludeSystem --std=c++11 + cppcheck_args: --enable=all --suppress=missingIncludeSystem --suppress=unusedFunction --std=c++11 diff --git a/README.md b/README.md index 85c6f53..72bd8dc 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,7 @@ [![RPM_DEB-Packaging-NoStacktraces](https://github.com/eljonny/TestCPP/actions/workflows/cmake-linux-pack-nost.yml/badge.svg?event=push)](https://github.com/eljonny/TestCPP/actions/workflows/cmake-linux-pack-nost.yml) [![Coverage](https://github.com/eljonny/TestCPP/actions/workflows/cmake-build-cov-st.yml/badge.svg?event=push)](https://github.com/eljonny/TestCPP/actions/workflows/cmake-build-cov-st.yml) [![Security](https://github.com/eljonny/TestCPP/actions/workflows/codeql.yml/badge.svg?event=push)](https://github.com/eljonny/TestCPP/actions/workflows/codeql.yml) -[![StaticAnalysis-Debug](https://github.com/eljonny/TestCPP/actions/workflows/cmake-static-analysis-dbg.yml/badge.svg?event=push)](https://github.com/eljonny/TestCPP/actions/workflows/cmake-static-analysis-dbg.yml) -[![StaticAnalysis-Release](https://github.com/eljonny/TestCPP/actions/workflows/cmake-static-analysis-rls.yml/badge.svg?event=push)](https://github.com/eljonny/TestCPP/actions/workflows/cmake-static-analysis-rls.yml) +[![StaticAnalysis](https://github.com/eljonny/TestCPP/actions/workflows/cmake-static-analysis-dbg.yml/badge.svg?event=push)](https://github.com/eljonny/TestCPP/actions/workflows/cmake-static-analysis.yml) [![codecov](https://codecov.io/gh/eljonny/TestCPP/graph/badge.svg?token=WFG41QY4BB)](https://codecov.io/gh/eljonny/TestCPP) # Introduction @@ -181,13 +180,18 @@ To build within the CodeLite IDE: deploy the library, cmake-rls or cmake-nost-rls) In the Custom Targets... context menu option there are also, depending - on the build configuration chose, ctest, cpack, clean, clang-tidy, - cmake-nost-rls, and cmake-rls targets, which will, respectively: + on the build configuration chose, ctest, cpack, cppcheck, clean, + clang-tidy, cmake-nost-rls, and cmake-rls targets, which will, + respectively: - Run the test suite for the library and, if the Debug configuration is selected, generate code coverage reports for the library code. - Create binary and/or source packages (depending on the build configuration selected), and if you're on a Linux distro that supports building RPM and/or DEB packages, will build those too. + - Runs CMake without actually running the build so the build system + is generated with compile_commands.json, then runs cppcheck against + what is defined in compile_commands.json. In this case, this is + only the core library header and source files. - Runs the CMake clean command and completely removes the build directory, based on the selected configuration. - Runs the build with the TESTCPP_ANALYSIS_ENABLED build variable @@ -313,6 +317,32 @@ Both Release and Debug configurations support building with stack trace functionality with the folloeing flag: - `-DTESTCPP_STACKTRACE_ENABLED` +You can run cppcheck and clang-tidy on the generated + compile_commands.json. +For clang-tidy, you can also use the CMake flag to have CMake run + clang-tidy during the build. + +My suggested options for cppcheck are: + - --project=compile_commands.json + - Uses the generated CMake output to define a check project + - -itest + - Ignores tests, in case building with tests enabled + - -idemo + - Ignores demo code, in case building with demo enabled + - --enable=all + - Enables all CPPCheck checks + - --suppress=missingIncludeSystem + - Then suppress missing system includes, there are no <>-enclosed + includes that need to be checked for this project. + - --suppress=unusedFunction + - Then suppress checking for unused functions. Most API functions + are not used within the library itself, and CPPCheck will generate + numerous errors saying the functions are unused. + +clang-tidy uses the .clang-tidy configuration file so you don't need to + specify any options unless you want to run it with different checks/ + behavior from what I usually run for this project. + # Testing and Code Coverage The library is tested using itself. diff --git a/TestFramework.project b/TestFramework.project index b21de56..d6badc7 100644 --- a/TestFramework.project +++ b/TestFramework.project @@ -71,8 +71,7 @@ - - + @@ -573,6 +572,8 @@ mkdir -p coverage && cd coverage find .. -name '*.gcda' | xargs gcov -abcfmu find . -type f -not -name 'Test*.gcov' | xargs rm + cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -Wno-dev +cppcheck --project=compile_commands.json -itest -idemo --enable=all --suppress=missingIncludeSystem --suppress=unusedFunction cpack --config CPackConfig.cmake cpack --config CPackSourceConfig.cmake cpack -G DEB From ac71f6903345f9e67baabcacdaebce2e6ba8d905 Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Thu, 2 May 2024 13:56:53 -0700 Subject: [PATCH 03/59] Fix catching the object by value. --- src/TestCPP.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TestCPP.cpp b/src/TestCPP.cpp index aa287e5..8be0714 100644 --- a/src/TestCPP.cpp +++ b/src/TestCPP.cpp @@ -259,7 +259,7 @@ namespace TestCPP { this->pass = false; logTestFailure(errorMessage); } - catch(string errorMessage) { + catch(string& errorMessage) { this->pass = false; logTestFailure(errorMessage); } From 6e44859372e7eba3368d9a9f0b10235ba89c0374 Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Thu, 2 May 2024 14:22:42 -0700 Subject: [PATCH 04/59] Hopefully this will fix the permissions issue. --- .github/workflows/cmake-static-analysis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/cmake-static-analysis.yml b/.github/workflows/cmake-static-analysis.yml index 8f6768b..b6b3da0 100644 --- a/.github/workflows/cmake-static-analysis.yml +++ b/.github/workflows/cmake-static-analysis.yml @@ -22,6 +22,8 @@ jobs: - name: Run static analysis uses: JacobDomagala/StaticAnalysis@master with: + github_token: ${{ secrets.GITHUB_TOKEN }} + language: c++ # Exclude any issues found in ${Project_root_dir}/lib From f95f242eb75f44ed82d9349ae6bb43775e1a5d54 Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Thu, 2 May 2024 14:45:50 -0700 Subject: [PATCH 05/59] Reverting the previous change, there was just a permission issue in the repo settings in GH. --- .github/workflows/cmake-static-analysis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/cmake-static-analysis.yml b/.github/workflows/cmake-static-analysis.yml index b6b3da0..8f6768b 100644 --- a/.github/workflows/cmake-static-analysis.yml +++ b/.github/workflows/cmake-static-analysis.yml @@ -22,8 +22,6 @@ jobs: - name: Run static analysis uses: JacobDomagala/StaticAnalysis@master with: - github_token: ${{ secrets.GITHUB_TOKEN }} - language: c++ # Exclude any issues found in ${Project_root_dir}/lib From 7a4e082798b45d235f806bff2bee934560af924e Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Fri, 3 May 2024 12:35:50 -0700 Subject: [PATCH 06/59] Change TestCaseName to TestObjName, extract strings Use the TestCaseName class (now named TestObjName) also for TestSuite to protect against null char * in string construction, which also simplifies the setSuiteName logic. Change the setSuiteName signature appropriately for the new type. Change private suiteName member type from string to TestObjName. Change constructor parameter for suite name from string to TestObjName, and ensure it's moved properly when storing it. Coincidentally, fixes GH issue #7. Extract strings into structs per-class so strings that are used more than once only need to be changed once, and can be referenced by tests for log verification when appropriate. Also if something will then be used again, just reference it. --- include/TestCPP.h | 48 +++++++++++++++++++++++++++++++++++------------ src/TestCPP.cpp | 47 +++++++++++++++++++++------------------------- 2 files changed, 57 insertions(+), 38 deletions(-) diff --git a/include/TestCPP.h b/include/TestCPP.h index 0567063..1e17348 100644 --- a/include/TestCPP.h +++ b/include/TestCPP.h @@ -69,16 +69,16 @@ namespace TestCPP { TestFailedException (string&& msg); }; - class TestCaseName { + class TestObjName { public: - TestCaseName () = default; - TestCaseName (const char* name); + TestObjName () = default; + TestObjName (const char* name); const string& getTestName (); friend std::ostream& operator<< ( std::ostream& s, - TestCaseName& tcName + TestObjName& tcName ) { s << tcName.getTestName(); @@ -88,6 +88,10 @@ namespace TestCPP { private: string testCaseName; + struct TCNStr { + static constexpr const char * NVTN = + "Not a valid test name!"; + }; }; class TestCase { @@ -99,7 +103,7 @@ namespace TestCPP { }; TestCase ( - TestCaseName&& testName, + TestObjName&& testName, function test, bool testPassedMessage = true, bool captureOut = false, @@ -132,7 +136,7 @@ namespace TestCPP { bool pass; long long lastRunTime; - TestCaseName testName; + TestObjName testName; function test; TestCaseOutCompareOptions option; @@ -168,24 +172,44 @@ namespace TestCPP { system_clock::now() - start ); } + + struct TCStr { + static constexpr const char * APOS = "'"; + static constexpr const char * FAIL = " failed! ("; + static constexpr const char * NCONTAIN = + " does not contain "; + static constexpr const char * NEQUIV = + " is not equivalent to "; + static constexpr const char * PASS = " passed! ("; + static constexpr const char * REASON = "Reason: "; + static constexpr const char * SEC = "s)"; + static constexpr const char * START_RUN = + "Starting run of test "; + static constexpr const char * TEST_ = "Test "; + static constexpr const char * UNK_CMP_OPT = + "Unknown comparison option! "; + static constexpr const char * UNK_EXC = + "Unknown error occurred in test!"; + static constexpr const char * UNK_OPT = "Unknown option "; + }; }; class TestSuite { public: template - TestSuite (string suiteName, + TestSuite (TestObjName&& suiteName, typename enable_if::type) { this->testPassedMessage = true; - this->setSuiteName(suiteName); + this->setSuiteName(move(suiteName)); this->tests = vector(); } template - TestSuite (string suiteName, TestType ...tests) { + TestSuite (TestObjName&& suiteName, TestType ...tests) { this->testPassedMessage = true; - this->setSuiteName(suiteName); + this->setSuiteName(move(suiteName)); this->tests = vector(); this->addTests(tests...); @@ -215,7 +239,7 @@ namespace TestCPP { return T(args...); } - void setSuiteName (string testSuiteName); + void setSuiteName (TestObjName&& testSuiteName); template static void assertEquals ( @@ -329,7 +353,7 @@ namespace TestCPP { unsigned lastRunFailCount; unsigned long long totalRuntime; - string suiteName; + TestObjName suiteName; vector tests; }; } diff --git a/src/TestCPP.cpp b/src/TestCPP.cpp index 8be0714..6e9d9bf 100644 --- a/src/TestCPP.cpp +++ b/src/TestCPP.cpp @@ -88,16 +88,16 @@ namespace TestCPP { #endif } - TestCaseName::TestCaseName (const char* name) { + TestObjName::TestObjName (const char* name) { if (name) { this->testCaseName = name; } else { - throw TestCPPException("Not a valid test name!"); + throw TestCPPException(TCNStr::NVTN); } } - const string& TestCaseName::getTestName () { + const string& TestObjName::getTestName () { return this->testCaseName; } @@ -115,7 +115,7 @@ namespace TestCPP { unique_ptr TestCase::clogOriginal = nullptr; unique_ptr TestCase::stderrOriginal = nullptr; - TestCase::TestCase (TestCaseName&& name, + TestCase::TestCase (TestObjName&& name, function test, bool msg, bool captureOut, bool captureLog, @@ -231,21 +231,21 @@ namespace TestCPP { void TestCase::logTestFailure (string reason) { clog << fixed; clog << setprecision(4); - clog << "Test " << this->testName << " failed! (" + clog << TCStr::TEST_ << this->testName << TCStr::FAIL << static_cast(this->lastRunTime) - /1000000000.0 << "s)" << endl; - clog << "Reason: " << reason << endl; + /1000000000.0 << TCStr::SEC << endl; + clog << TCStr::REASON << reason << endl; } void TestCase::runTest () { - clog << "Starting run of test " << this->testName << endl; + clog << TCStr::START_RUN << this->testName << endl; this->lastRunTime = duration(this->test).count(); if (this->notifyTestPassed) { clog << fixed; clog << setprecision(4); - clog << "Test " << this->testName << " passed! (" + clog << TCStr::TEST_ << this->testName << TCStr::PASS << static_cast(this->lastRunTime) - /1000000000.0 << "s)" << endl; + /1000000000.0 << TCStr::SEC << endl; } this->pass = true; } @@ -269,7 +269,7 @@ namespace TestCPP { } catch (...) { this->pass = false; - logTestFailure("Unknown error occurred in test!"); + logTestFailure(TCStr::UNK_EXC); } return false; @@ -342,7 +342,7 @@ namespace TestCPP { default: stringstream error; - error << "Unknown option " << opt; + error << TCStr::UNK_OPT << opt; throw TestCPPException(error.str()); } } @@ -390,8 +390,9 @@ namespace TestCPP { } else { stringstream nomatch; - nomatch << "'" << source << "' is not equivalent to '"; - nomatch << against << "'"; + nomatch << TCStr::APOS << source << TCStr::APOS; + nomatch << TCStr::NEQUIV << TCStr::APOS; + nomatch << against << TCStr::APOS; if (this->clogOriginal != nullptr) { ostream tmp(this->clogOriginal.get()); @@ -411,8 +412,9 @@ namespace TestCPP { } else { stringstream nomatch; - nomatch << "'" << source << "' does not contain '"; - nomatch << against << "'"; + nomatch << TCStr::APOS << source << TCStr::APOS; + nomatch << TCStr::NCONTAIN << TCStr::APOS; + nomatch << against << TCStr::APOS; if (this->clogOriginal != nullptr) { ostream tmp(this->clogOriginal.get()); @@ -428,7 +430,7 @@ namespace TestCPP { default: stringstream re; - re << "Unknown comparison option! " << opt; + re << TCStr::UNK_CMP_OPT << opt; throw TestCPPException(re.str()); } } @@ -446,15 +448,8 @@ namespace TestCPP { } } - void TestSuite::setSuiteName (string testSuiteName) { - if (testSuiteName.data()) { - this->suiteName = testSuiteName; - } - else { - stringstream e; - e << "An invalid string was passed as the Test Suite Name!"; - throw TestCPPException(e.str()); - } + void TestSuite::setSuiteName (TestObjName&& testSuiteName) { + this->suiteName = move(testSuiteName); } unsigned TestSuite::getLastRunFailCount () { From 38600d28d9c21edfe6f5d6e5a3f3ddc8c12caa37 Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Fri, 3 May 2024 12:37:32 -0700 Subject: [PATCH 07/59] TestObjName does not allow construction with std::string In order to protect against null char *, we don't know how a string is constructed before it's passed to TestObjName. --- demo/src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demo/src/main.cpp b/demo/src/main.cpp index eb65b50..a06e0d5 100644 --- a/demo/src/main.cpp +++ b/demo/src/main.cpp @@ -12,7 +12,7 @@ int main(void) { try { TestSuite suite( - string("Demo Test Suite"), + "Demo Test Suite", make_tuple( "simpleTest", From fb0d5caad642269ba2b9d43dd7f2fe2bab586a8e Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Mon, 13 May 2024 08:06:03 -0700 Subject: [PATCH 08/59] Major refactor and API change I broke up TestCPP.h and the corresponding .cpp file into many pieces. It just started to get too big, and I wanted more focused TUs. So this is the first commit for that, where I split them out into different header files, put them in an 'internal' subdirectory, and turned TestCPP.h into an aggregate include for including the types and definitions needed by the library. So the common definitions are now split out into their own header-only definition in internal/TestCPPCommon.h. The exception types are now in their own internal/TestCPPExceptions.h header with corresponding .cpp. TestCase and TestSuite now have their own headers, internal/TestCPPTestCase.h and internal/TestCPPTestSuite.h, with corresponding .cpps. And finally TestCPPUtil.h is moved into internal and the TestObjName type has been moved into the Util header and definition .cpp, but is still in the base namespace TestCPP, not in TestCPP::Util. The biggest functional change is splitting the assertions out of TestSuite and into their own Assertions class, in their own TU. So from now on, the TestCPP assertions should be referenced through the Assertions class, not the TestSuite class, which makes a lot more sense. I added a couple new assertions a few weeks back, and I can see adding more, so they really need their own type to encapsulate that functionality. There's some significant cleanup to do, but that will probably be in a separate PR. --- include/TestCPP.h | 341 +----------------- include/internal/TestCPPAssertions.h | 251 +++++++++++++ include/internal/TestCPPCommon.h | 106 ++++++ include/internal/TestCPPExceptions.h | 102 ++++++ include/internal/TestCPPTestCase.h | 276 ++++++++++++++ include/internal/TestCPPTestSuite.h | 190 ++++++++++ include/internal/TestCPPUtil.h | 137 +++++++ src/TestCPPAssertions.cpp | 125 +++++++ .../TestCPPExceptions.cpp | 47 ++- src/{TestCPP.cpp => TestCPPTestCase.cpp} | 268 ++------------ src/TestCPPTestSuite.cpp | 150 ++++++++ src/TestCPPUtil.cpp | 21 +- 12 files changed, 1436 insertions(+), 578 deletions(-) create mode 100644 include/internal/TestCPPAssertions.h create mode 100644 include/internal/TestCPPCommon.h create mode 100644 include/internal/TestCPPExceptions.h create mode 100644 include/internal/TestCPPTestCase.h create mode 100644 include/internal/TestCPPTestSuite.h create mode 100644 include/internal/TestCPPUtil.h create mode 100644 src/TestCPPAssertions.cpp rename include/TestCPPUtil.h => src/TestCPPExceptions.cpp (56%) rename src/{TestCPP.cpp => TestCPPTestCase.cpp} (61%) create mode 100644 src/TestCPPTestSuite.cpp diff --git a/include/TestCPP.h b/include/TestCPP.h index 1e17348..74f6ad2 100644 --- a/include/TestCPP.h +++ b/include/TestCPP.h @@ -25,337 +25,14 @@ OTHER DEALINGS IN THE SOFTWARE. For more information, please refer to */ -//Original author: Jonathan Hyry CSU-Fullerton SECS 6896-02 Fall 2014/15 - -#ifndef TESTCPP_CLASSES_ -#define TESTCPP_CLASSES_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using std::atomic_int; -using std::chrono::nanoseconds; -using std::chrono::system_clock; -using std::chrono::duration_cast; -using std::enable_if; -using std::endl; -using std::forward; -using std::function; -using std::move; -using std::runtime_error; -using std::string; -using std::streambuf; -using std::stringstream; -using std::unique_ptr; -using std::vector; - -namespace TestCPP { - class TestCPPException : public runtime_error { - public: - TestCPPException (const char * msg); - TestCPPException (string&& msg); - }; - - class TestFailedException : public TestCPPException { - public: - TestFailedException (const char * msg); - TestFailedException (string&& msg); - }; - - class TestObjName { - public: - TestObjName () = default; - TestObjName (const char* name); - - const string& getTestName (); - - friend std::ostream& operator<< ( - std::ostream& s, - TestObjName& tcName - ) - { - s << tcName.getTestName(); - return s; - } - - private: - string testCaseName; - - struct TCNStr { - static constexpr const char * NVTN = - "Not a valid test name!"; - }; - }; - - class TestCase { - - public: - enum TestCaseOutCompareOptions { - CONTAINS, - EXACT - }; - - TestCase ( - TestObjName&& testName, - function test, - bool testPassedMessage = true, - bool captureOut = false, - bool captureLog = false, - bool captureErr = false, - TestCaseOutCompareOptions opt = CONTAINS - ); - - TestCase (TestCase& o); - TestCase (TestCase&& o); - - TestCase& operator= (TestCase& rhs); - TestCase& operator= (TestCase&& rhs); - - ~TestCase (); - - void setNotifyPassed (bool); - void outCompareOption (TestCaseOutCompareOptions opt); - void clearStdoutCapture (); - void clearLogCapture (); - void clearStderrCapture (); - bool checkStdout (string against); - bool checkLog (string against); - bool checkStderr (string against); - bool go (); - long long getLastRuntime (); - - private: - bool notifyTestPassed; - bool pass; - long long lastRunTime; - - TestObjName testName; - function test; - - TestCaseOutCompareOptions option; - - void captureStdout (); - void captureClog (); - void captureStdErr (); - void logTestFailure (string); - void runTest (); - bool checkOutput (TestCaseOutCompareOptions opt, string source, - string against); - - static atomic_int stdoutCaptureCasesConstructed; - static atomic_int logCaptureCasesConstructed; - static atomic_int stderrCaptureCasesConstructed; - static atomic_int stdoutCaptureCasesDestroyed; - static atomic_int logCaptureCasesDestroyed; - static atomic_int stderrCaptureCasesDestroyed; - - static unique_ptr stdoutBuffer; - static unique_ptr clogBuffer; - static unique_ptr stderrBuffer; - static unique_ptr stdoutOriginal; - static unique_ptr clogOriginal; - static unique_ptr stderrOriginal; - - template - static nanoseconds duration (F func, Args&&... args) - { - auto start = system_clock::now(); - func(forward(args)...); - return duration_cast( - system_clock::now() - start - ); - } - - struct TCStr { - static constexpr const char * APOS = "'"; - static constexpr const char * FAIL = " failed! ("; - static constexpr const char * NCONTAIN = - " does not contain "; - static constexpr const char * NEQUIV = - " is not equivalent to "; - static constexpr const char * PASS = " passed! ("; - static constexpr const char * REASON = "Reason: "; - static constexpr const char * SEC = "s)"; - static constexpr const char * START_RUN = - "Starting run of test "; - static constexpr const char * TEST_ = "Test "; - static constexpr const char * UNK_CMP_OPT = - "Unknown comparison option! "; - static constexpr const char * UNK_EXC = - "Unknown error occurred in test!"; - static constexpr const char * UNK_OPT = "Unknown option "; - }; - }; - - class TestSuite { - - public: - template - TestSuite (TestObjName&& suiteName, - typename enable_if::type) - { - this->testPassedMessage = true; - this->setSuiteName(move(suiteName)); - this->tests = vector(); - } - - template - TestSuite (TestObjName&& suiteName, TestType ...tests) { - this->testPassedMessage = true; - this->setSuiteName(move(suiteName)); - this->tests = vector(); - - this->addTests(tests...); - } - - template - void addTest (T&& test) { - this->tests.emplace_back( - std::get<0>(test), - std::get<1>(test), - this->testPassedMessage - ); - } - - template - typename enable_if::type - inline addTests () { } - - template - void addTests (Test test, OtherTests ...tests) { - addTest(move(test)); - addTests(tests...); - } - - template - static T getTestObject (ConstructionArgs ...args) { - return T(args...); - } - - void setSuiteName (TestObjName&& testSuiteName); - - template - static void assertEquals ( - T1 expected, T2 actual, - string failureMessage = "Arguments are not equivalent!" - ) - { - if (expected != actual) { - stringstream err; - - err << "Equivalence assertion failed!" << endl; - err << failureMessage << endl; - err << "Expected: <" << expected << ">" << endl; - err << "Actual: <" << actual << ">" << endl; - - throw TestFailedException(err.str()); - } - } - - template - static void assertNotEquals ( - T1 expected, T2 actual, - string failureMessage = "Arguments are equivalent!" - ) - { - if (expected == actual) { - stringstream err; - - err << "Non-Equivalence assertion failed!" << endl; - err << failureMessage << endl; - err << "Expected: <" << expected << ">" << endl; - err << "Actual: <" << actual << ">" << endl; - - throw TestFailedException(err.str()); - } - } - - template - static void assertNull ( - T ptr, - string failureMessage = "Object is not null!" - ) - { - bool null = ptr == nullptr; - - if (!null) { - stringstream err; - - err << "Null assertion failed!" << endl; - err << failureMessage << endl; - - throw TestFailedException(err.str()); - } - } - - template - static void assertNotNull ( - T ptr, - string failureMessage = "Object is null!" - ) - { - bool notNull = ptr != nullptr; - - if (!notNull) { - stringstream err; - - err << "Not Null assertion failed!" << endl; - err << failureMessage << endl; - - throw TestFailedException(err.str()); - } - } - - static void assertThrows ( - function shouldThrow, - string failureMessage = - "Should have thrown something!" - ); - - static void assertNoThrows ( - function shouldNotThrow, - string failureMessage = - "Should not have thrown anything!" - ); - - static void assertTrue ( - bool condition, - string failureMessage = "Condition is false!" - ); - - static void assertFalse ( - bool condition, - string failureMessage = "Condition is true!" - ); - - static void fail ( - string failureMessage = "Forced test failure!" - ); - - void enableTestPassedMessage (); - void disableTestPassedMessage (); - - unsigned getLastRunFailCount (); - - void run (); - - private: - bool testPassedMessage; - bool lastRunSucceeded; - unsigned lastRunSuccessCount; - unsigned lastRunFailCount; - unsigned long long totalRuntime; - - TestObjName suiteName; - vector tests; - }; -} +#ifndef TESTCPP_AGGREGATE_ +#define TESTCPP_AGGREGATE_ + +#include "internal/TestCPPAssertions.h" +#include "internal/TestCPPCommon.h" +#include "internal/TestCPPExceptions.h" +#include "internal/TestCPPTestCase.h" +#include "internal/TestCPPTestSuite.h" +#include "internal/TestCPPUtil.h" #endif diff --git a/include/internal/TestCPPAssertions.h b/include/internal/TestCPPAssertions.h new file mode 100644 index 0000000..517f013 --- /dev/null +++ b/include/internal/TestCPPAssertions.h @@ -0,0 +1,251 @@ +/* +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to + */ + +#ifndef TESTCPP_ASSERTIONS_ +#define TESTCPP_ASSERTIONS_ + +#include "TestCPPExceptions.h" +#include "TestCPPTestCase.h" + +/** + * The base namespace for all TestCPP library code. + */ +namespace TestCPP { + + /** + * @class Assertions + * @author Jonathan Hyry + * @date 11/05/24 + * @file TestCPPAssertions.h + * @brief Contains the TestCPP library's assertions. + * + * Defines some assertions here, where they are templated. + * Declares the rest. + * + * This is the place where the TestCPP Assertions API is defined. + */ + class Assertions { + public: + /** + * @brief Check that something equals something else using the + * built-in operator== for each type. + * @param expected The value that the actual value should be + * equivalent to. + * @param actual The actual value that will be checked against + * the expected value. + * @param failureMessage Failure message that should be logged + * if the assertion fails. This + * defaults to a generic failure + * message related to the assertion + * type. + */ + template + static void assertEquals ( + T1 expected, T2 actual, + string failureMessage = "Arguments are not equivalent!" + ) + { + if (expected != actual) { + stringstream err; + + err << "Equivalence assertion failed!" << endl; + err << failureMessage << endl; + err << "Expected: <" << expected << ">" << endl; + err << "Actual: <" << actual << ">" << endl; + + throw TestFailedException(err.str()); + } + } + + /** + * @brief Check that something is not equivalent to something + * else using the built-in operator== for each type. + * @param expected The value that the actual value should not be + * equivalent to. + * @param actual The actual value that will be checked against + * the expected value. + * @param failureMessage Failure message that should be logged + * if the assertion fails. This + * defaults to a generic failure + * message related to the assertion + * type. + */ + template + static void assertNotEquals ( + T1 expected, T2 actual, + string failureMessage = "Arguments are equivalent!" + ) + { + if (expected == actual) { + stringstream err; + + err << "Non-Equivalence assertion failed!" << endl; + err << failureMessage << endl; + err << "Expected: <" << expected << ">" << endl; + err << "Actual: <" << actual << ">" << endl; + + throw TestFailedException(err.str()); + } + } + + /** + * @brief Check that a pointer is null. + * @param ptr The pointer to check. + * @param failureMessage Failure message that should be logged + * if the assertion fails. This + * defaults to a generic failure + * message related to the assertion + * type. + */ + template + static void assertNull ( + T ptr, + string failureMessage = "Object is not null!" + ) + { + bool null = ptr == nullptr; + + if (!null) { + stringstream err; + + err << "Null assertion failed!" << endl; + err << failureMessage << endl; + + throw TestFailedException(err.str()); + } + } + + /** + * @brief Check that a pointer is non-null. + * @param ptr The pointer to check. + * @param failureMessage Failure message that should be logged + * if the assertion fails. This + * defaults to a generic failure + * message related to the assertion + * type. + */ + template + static void assertNotNull ( + T ptr, + string failureMessage = "Object is null!" + ) + { + bool notNull = ptr != nullptr; + + if (!notNull) { + stringstream err; + + err << "Not Null assertion failed!" << endl; + err << failureMessage << endl; + + throw TestFailedException(err.str()); + } + } + + /** + * @brief Verify that a function throws something. + * @param shouldThrow The function to check, to ensure that it + * throws something. + * @param failureMessage Failure message that should be logged + * if the assertion fails. This + * defaults to a generic failure + * message related to the assertion + * type. + */ + static void assertThrows ( + function shouldThrow, + string failureMessage = + "Should have thrown something!" + ); + + /** + * @brief Verify that a function does not throw something. + * @param shouldThrow The function to check, to ensure that it + * does not throw something. + * @param failureMessage Failure message that should be logged + * if the assertion fails. This + * defaults to a generic failure + * message related to the assertion + * type. + */ + static void assertNoThrows ( + function shouldNotThrow, + string failureMessage = + "Should not have thrown anything!" + ); + + /** + * @brief Verify that a logical condition is true. + * @param condition The result of the logical condition to + * check. + * @param failureMessage Failure message that should be logged + * if the assertion fails. This + * defaults to a generic failure + * message related to the assertion + * type. + */ + static void assertTrue ( + bool condition, + string failureMessage = "Condition is false!" + ); + + /** + * @brief Verify that a logical condition is not true. + * @param condition The result of the logical condition to + * check. + * @param failureMessage Failure message that should be logged + * if the assertion fails. This + * defaults to a generic failure + * message related to the assertion + * type. + */ + static void assertFalse ( + bool condition, + string failureMessage = "Condition is true!" + ); + + /** + * @brief Force a test to fail. + * @param failureMessage Failure message that should be logged + * if the assertion fails. This + * defaults to a generic failure + * message related to the assertion + * type. + * + * Useful in certain situations when: + * - Generating code for test cases, to ensure that skeletons + * fail by default. + * - Forcing test failure in certain circumstances where there + * is nothing to assert but a certain code path is taken. + */ + static void fail ( + string failureMessage = "Forced test failure!" + ); + }; +} + +#endif diff --git a/include/internal/TestCPPCommon.h b/include/internal/TestCPPCommon.h new file mode 100644 index 0000000..5747719 --- /dev/null +++ b/include/internal/TestCPPCommon.h @@ -0,0 +1,106 @@ +/* +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to + */ + +#ifndef TESTCPP_COMMON_ +#define TESTCPP_COMMON_ + +/** + * The base namespace for all TestCPP library code. + */ +namespace TestCPP { + + /** + * @class TestCPPCommon + * @author Jonathan Hyry + * @date 03/05/24 + * @file TestCPP.h + * @brief Categories of common objects that are used. + */ + class TestCPPCommon { + public: + /** + * @class Nums + * @author Jonathan Hyry + * @date 03/05/24 + * @file TestCPP.h + * @brief Common magic numbers used by the library. + */ + struct Nums { + static constexpr const int TIME_PRECISION = 4; + static constexpr const double NANOS_IN_SEC = 1000000000.0; + }; + + /** + * @class Strings + * @author Jonathan Hyry + * @date 03/05/24 + * @file TestCPP.h + * @brief Common literal strings used by the library. + * + * As struct member name prefixes and postfixes, underscores + * denote leading and trailing spaces, respectively. + */ + struct Strings { + static constexpr const char * ALL_ = "All "; + static constexpr const char * APOS = "'"; + static constexpr const char * _FAIL_ = " failed! "; + static constexpr const char * FINISHED_SUITE_ = + "Finished running test suite "; + static constexpr const char * FWSL = "/"; + static constexpr const char * _IN_ABOUT_ = " in about "; + static constexpr const char * _NCONTAIN_ = + " does not contain "; + static constexpr const char * _NEQUIV_ = + " is not equivalent to "; + static constexpr const char * NTR = "No tests to run!"; + static constexpr const char * NVTN = + "Not a valid test name!"; + static constexpr const char * PARENL = "("; + static constexpr const char * PARENR = ")"; + static constexpr const char * _PASS_ = " passed! "; + static constexpr const char * _PASSED = " passed"; + static constexpr const char * REASON_ = "Reason: "; + static constexpr const char * SEC = "s"; + static constexpr const char * SP = " "; + static constexpr const char * START_RUN = + "Starting run of test "; + static constexpr const char * SUITE_ = "Suite "; + static constexpr const char * _SUITE_TESTS_PASSED = + " suite tests passed!"; + static constexpr const char * TEST_ = "Test "; + static constexpr const char * TEST_EXC_ = + "Exception occurred during test run: "; + static constexpr const char * UNK_CMP_OPT_ = + "Unknown comparison option! "; + static constexpr const char * UNK_EXC = + "Unknown error occurred in test!"; + static constexpr const char * UNK_OPT_ = "Unknown option "; + }; + }; +} + +#endif \ No newline at end of file diff --git a/include/internal/TestCPPExceptions.h b/include/internal/TestCPPExceptions.h new file mode 100644 index 0000000..ec4bb64 --- /dev/null +++ b/include/internal/TestCPPExceptions.h @@ -0,0 +1,102 @@ +/* +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to + */ + +#ifndef TESTCPP_EXCEPTIONS_ +#define TESTCPP_EXCEPTIONS_ + +#include +#include + +using std::runtime_error; +using std::string; + +/** + * The base namespace for all TestCPP library code. + */ +namespace TestCPP { + + /** + * @class TestCPPException + * @author Jonathan Hyry + * @date 03/05/24 + * @file TestCPP.h + * @brief Provides a custom base exception for failure conditions. + * + * There are two types of failures in the library: + * - Errors caused by bugs, system problems, etc. + * - Test failures + * + * This type, when used directly, is for representing the first type + * of failure: errors in the library caused by bugs or other + * problems. + */ + class TestCPPException : public runtime_error { + public: + /** + * Construct an exception of this type with a string literal for + * its failure message. + */ + TestCPPException (const char * msg); + + /** + * Construct an exception of this type with a string object for + * its failure message. + */ + TestCPPException (string&& msg); + }; + + /** + * @class TestFailedException + * @author Jonathan Hyry + * @date 03/05/24 + * @file TestCPP.h + * @brief Provides an exception type specifically for test failures. + * + * There are two types of failures in the library: + * - Errors caused by bugs, system problems, etc. + * - Test failures + * + * This type is for representing the second type of failure: test + * failures. + */ + class TestFailedException : public TestCPPException { + public: + /** + * Construct an exception of this type with a string literal for + * its failure message. + */ + TestFailedException (const char * msg); + + /** + * Construct an exception of this type with a string literal for + * its failure message. + */ + TestFailedException (string&& msg); + }; +} + +#endif diff --git a/include/internal/TestCPPTestCase.h b/include/internal/TestCPPTestCase.h new file mode 100644 index 0000000..cc2c3f5 --- /dev/null +++ b/include/internal/TestCPPTestCase.h @@ -0,0 +1,276 @@ +/* +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to + */ + +//Original author: Jonathan Hyry CSU-Fullerton SECS 6896-02 Fall 2014/15 + +#ifndef TESTCPP_TESTCASE_TYPE_ +#define TESTCPP_TESTCASE_TYPE_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "TestCPPUtil.h" + +using std::atomic_int; +using std::chrono::nanoseconds; +using std::chrono::system_clock; +using std::chrono::duration_cast; +using std::enable_if; +using std::endl; +using std::forward; +using std::function; +using std::move; +using std::runtime_error; +using std::string; +using std::streambuf; +using std::stringstream; +using std::unique_ptr; +using std::vector; + +/** + * The base namespace for all TestCPP library code. + */ +namespace TestCPP { + + /** + * @class TestCase + * @author Jonathan Hyry + * @date 03/05/24 + * @file TestCPP.h + * @brief Provides an interface for implementing tests. + * + * TestCase is one of three core types that define the TestCPP API. + * TestCase provides faculties for defining and controlling tests + * and the stdout/stderr/clog environment. + * TestCase objects are defined by the following elements: + * - their name + * - the code that will be run that defines what the test does + * and how it does it + * - whether to log test passage + * - output capturing flags + * - how captured output is analyzed (exact or contains) + */ + class TestCase { + + public: + /** + * Provides a specification for how to analyze captured stdout, + * stderr, and clog data. + */ + enum TestCaseOutCompareOptions { + CONTAINS, + EXACT + }; + + /** + * Instantiate and define a test case. + * All parameters are optional other than the test name and the + * test function. + * Optional parameters have the following default values: + * - testPassedMessage defaults to true, so by default test + * cases will emit a message when the pass. + * - captureOut defaults to false, the test case by default + * does not capture stdout data. + * - captureLog defaults to false, the test case by default + * does not capture data streamed to clog. + * - captureErr defaults to false, the test case by default + * does not capture stderr data. + * - opt defaults to CONTAINS, so when output is captured and + * checked for something, the default technique is to check + * that the output of a given stream contains a given + * string. + */ + TestCase ( + TestObjName&& testName, + function test, + bool testPassedMessage = true, + bool captureOut = false, + bool captureLog = false, + bool captureErr = false, + TestCaseOutCompareOptions opt = CONTAINS + ); + + /** + * Construct a TestCase by copying it from another TestCase. + */ + TestCase (TestCase& o); + + /** + * Construct a TestCase by moving all data from another + * TestCase. + */ + TestCase (TestCase&& o); + + /** + * @brief Copy a TestCase into another TestCase. + * @param rhs The test case to copy from. + */ + TestCase& operator= (TestCase& rhs); + + /** + * @brief Move a TestCase into another TestCase. + */ + TestCase& operator= (TestCase&& rhs); + + /** + * @brief Destroy a TestCase object. + */ + ~TestCase (); + + /** + * @brief Set whether to notify in std::clog when a test passes. + * @param shouldNotify Will notify on test passed if true. + */ + void setNotifyPassed (bool shouldNotify); + + /** + * @brief Set the output comparison mode. + * @param opt Accepts specified mode from the referenced enum. + * + * If this is called with an option specified that is different + * from what is set for this test case already, subsequent + * calls to any of the output check functions will use the + * updated mode that is specified in the call to this function. + */ + void outCompareOption (TestCaseOutCompareOptions opt); + + /** + * @brief Clears the captured output from stdout. + * + * This can be used for checking sections of output based on + * test configuration. + */ + void clearStdoutCapture (); + + /** + * @brief Clears the captured output from std::clog. + * + * This can be used for checking sections of output based on + * test configuration. + */ + void clearLogCapture (); + + /** + * @brief Clears the captured output from stderr. + * + * This can be used for checking sections of output based on + * test configuration. + */ + void clearStderrCapture (); + + /** + * @brief Check the argument against what is captured from + * stdout using the configured comparison mode. + * @param against The value to check the captured output against + * @return True if the argument results in a successful check + * using the configured comparison mode. + */ + bool checkStdout (string against); + + /** + * @brief Check the argument against what is captured from + * std::clog using the configured comparison mode. + * @param against The value to check the captured output against + * @return True if the argument results in a successful check + * using the configured comparison mode. + */ + bool checkLog (string against); + + /** + * @brief Check the argument against what is captured from + * stderr using the configured comparison mode. + * @param against The value to check the captured output against + * @return True if the argument results in a successful check + * using the configured comparison mode, false + * otherwise. + */ + bool checkStderr (string against); + + /** + * @brief Run the test case. + * @return True if the test ran successfully, false otherwise. + */ + bool go (); + + /** + * @brief Returns the duration of the last run in nanoseconds. + * @return The duration of the last run in nanoseconds. + */ + long long getLastRuntime (); + + private: + bool notifyTestPassed; + bool pass; + long long lastRunTime; + + TestObjName testName; + function test; + + TestCaseOutCompareOptions option; + + void captureStdout (); + void captureClog (); + void captureStdErr (); + void logTestFailure (string); + void runTest (); + bool checkOutput (TestCaseOutCompareOptions opt, string source, + string against); + + static atomic_int stdoutCaptureCasesConstructed; + static atomic_int logCaptureCasesConstructed; + static atomic_int stderrCaptureCasesConstructed; + static atomic_int stdoutCaptureCasesDestroyed; + static atomic_int logCaptureCasesDestroyed; + static atomic_int stderrCaptureCasesDestroyed; + + static unique_ptr stdoutBuffer; + static unique_ptr clogBuffer; + static unique_ptr stderrBuffer; + static unique_ptr stdoutOriginal; + static unique_ptr clogOriginal; + static unique_ptr stderrOriginal; + + template + static nanoseconds duration (F func, Args&&... args) + { + auto start = system_clock::now(); + func(forward(args)...); + return duration_cast( + system_clock::now() - start + ); + } + }; +} + +#endif diff --git a/include/internal/TestCPPTestSuite.h b/include/internal/TestCPPTestSuite.h new file mode 100644 index 0000000..9945227 --- /dev/null +++ b/include/internal/TestCPPTestSuite.h @@ -0,0 +1,190 @@ +/* +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to + */ + +//Original author: Jonathan Hyry CSU-Fullerton SECS 6896-02 Fall 2014/15 + +#ifndef TESTCPP_TESTSUITE_TYPE_ +#define TESTCPP_TESTSUITE_TYPE_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using std::atomic_int; +using std::chrono::nanoseconds; +using std::chrono::system_clock; +using std::chrono::duration_cast; +using std::enable_if; +using std::endl; +using std::forward; +using std::function; +using std::move; +using std::runtime_error; +using std::string; +using std::streambuf; +using std::stringstream; +using std::unique_ptr; +using std::vector; + +/** + * The base namespace for all TestCPP library code. + */ +namespace TestCPP { + + /** + * @class TestSuite + * @author Jonathan Hyry + * @date 05/05/24 + * @file TestCPP.h + * @brief Defines a container for a collection of TestCase objects. + * + * + */ + class TestSuite { + + public: + /** + * @brief Specialization for constructing a test suite with no + * tests. + */ + template + TestSuite (TestObjName&& suiteName, + typename enable_if::type) + { + this->testPassedMessage = true; + this->setSuiteName(move(suiteName)); + this->tests = vector(); + } + + /** + * @brief The general case for constructing a test suite with + * tests. + */ + template + TestSuite (TestObjName&& suiteName, TestType ...tests) { + this->testPassedMessage = true; + this->setSuiteName(move(suiteName)); + this->tests = vector(); + + this->addTests(tests...); + } + + /** + * @brief Add a test to this test suite. + * + * The test should be defined as a tuple with 2 elements to use + * this. The first element is the test name, and the second + * element is the test function that defines the test. + */ + template + void addTest (T&& test) { + this->tests.emplace_back( + std::get<0>(test), + std::get<1>(test), + this->testPassedMessage + ); + } + + /** + * @brief Specialization to handle when someone tries to call + * the template function with no tests. + * + * This is a noop. + */ + template + typename enable_if::type + inline addTests () { } + + /** + * @brief Add one or more tests at once to the test suite. + * @param test The first test to add. + */ + template + void addTests (Test test, OtherTests ...tests) { + addTest(move(test)); + addTests(tests...); + } + + /** + * @brief Get the TestCase object that is associated with the + * given test case construction arguments. + * @return The TestCase with the given construction arguments. + */ + template + static T getTestObject (ConstructionArgs ...args) { + return T(args...); + } + + /** + * @brief Sets the name of this test suite. + */ + void setSuiteName (TestObjName&& testSuiteName); + + /** + * @brief After called, all tests in the suite will emit a + * message if they pass. + */ + void enableTestPassedMessage (); + + /** + * @brief After called, all tests in the suite will not emit a + * message if they pass. + */ + void disableTestPassedMessage (); + + /** + * @brief Calculate the total number of tests in the suite that + * failed after the last suite run. + * @return The total number of tests that failed in the last + * suite run. + */ + unsigned getLastRunFailCount (); + + /** + * @brief Run all tests in the test suite. + */ + void run (); + + private: + bool testPassedMessage; + bool lastRunSucceeded; + unsigned lastRunSuccessCount; + unsigned lastRunFailCount; + unsigned long long totalRuntime; + + TestObjName suiteName; + vector tests; + }; +} + +#endif diff --git a/include/internal/TestCPPUtil.h b/include/internal/TestCPPUtil.h new file mode 100644 index 0000000..839625a --- /dev/null +++ b/include/internal/TestCPPUtil.h @@ -0,0 +1,137 @@ +/* +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to + */ + +#ifndef TESTCPP_UTIL_ +#define TESTCPP_UTIL_ + +#include + +using std::string; + +/** + * The base namespace for all TestCPP library code. + */ +namespace TestCPP { + + /** + * @class TestObjName + * @author Jonathan Hyry + * @date 03/05/24 + * @file TestCPP.h + * @brief Provides a null-safe name for test objects. + * + * Both TestCase and TestSuite objects use this for their name to + * protect against nullptr/NULL being used to create a std::string + * and name the test with that non-null-char-*-based std::string. + */ + class TestObjName { + public: + /** + * @brief Construct an empty Test Object Name object. + * @return The empty TestObjName. + * + * This should never be called by user code but is required for + * the code to compile. + */ + TestObjName () = default; + + /** + * @brief Construct a Test Object Name object with a string + * literal or existing const char *. + * @return The TestObjName, where it is verified that the name + * used to construct it was not null. + */ + TestObjName (const char* name); + + /** + * @brief Get the encapsulated name for the TestCPP object that + * holds this object. + * @return The name of the TestCPP object that this object + * names. + */ + const string& getName (); + + /** + * @brief Output the test object name to the specified stream. + * @param s The stream to output to. + * @param tcName The test object name object. + * @return The stream for chaining. + */ + friend std::ostream& operator<< ( + std::ostream& s, + TestObjName& tcName + ) + { + s << tcName.getName(); + return s; + } + + private: + string testCaseName; + }; + + /** + * The namespace for general TestCPP utility code. + */ + namespace Util { + + /** + * @brief Log a message that will only be output when debug + * logging is enabled. + * + * @param message The debug message to log. + * @param omitNewline Whether or not to end the log with a + * newline character. + * Defaults to false. + */ + void debugLog (const string& message, bool omitNewline = false); + + /** + * @brief Check if a std::string is contained within another + * std::string; this exists since we're not using C++26 + * here. + * + * @param source The base std::string to check within. + * @param contains Checks the base std::string to see if it + * contains this std::string. + * + * @return True if source includes contains in whole, false + * otherwise. + */ + bool stringContains (const string& source, + const string& contains); + + /** + * @brief Safely converts unsigned integer values to signed. + * @param toCast The unsigned value to convert. + * @return The signed value equivalent to the unsigned value. + */ + int unsignedToSigned(unsigned toCast); + } +} + +#endif diff --git a/src/TestCPPAssertions.cpp b/src/TestCPPAssertions.cpp new file mode 100644 index 0000000..57344f9 --- /dev/null +++ b/src/TestCPPAssertions.cpp @@ -0,0 +1,125 @@ +/* +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to + */ + +#include "internal/TestCPPAssertions.h" +#include "internal/TestCPPTestCase.h" + +using std::clog; +using std::current_exception; +using std::endl; +using std::exception; +using std::exception_ptr; +using std::function; +using std::move; +using std::rethrow_exception; +using std::string; +using std::stringstream; + +namespace TestCPP { + + void Assertions::assertThrows ( + function shouldThrow, + string failureMessage + ) + { + try { + shouldThrow(); + } + catch (...) { + exception_ptr eptr = current_exception(); + + if (eptr) { + try { + rethrow_exception(eptr); + } + catch (const exception& e) { + clog << "assertThrows caught exception: " + << TestFailedException(e.what()).what() + << endl; + } + } + else { + clog << "Something was thrown, not sure what." << endl + << "This satisfies the assertion, so no failure is" + << " present. " + << TestFailedException("Unknown thrown object"). + what(); + } + + return; + } + + throw TestFailedException(move(failureMessage)); + } + + void Assertions::assertNoThrows ( + function shouldNotThrow, + string failureMessage + ) + { + try { + shouldNotThrow(); + } + catch (...) { + throw TestFailedException(move(failureMessage)); + } + } + + void Assertions::assertTrue ( + bool condition, + string failureMessage + ) + { + if (!condition) { + stringstream err; + + err << "Boolean Truth assertion failed!" << endl; + err << failureMessage << endl; + + throw TestFailedException(err.str()); + } + } + + void Assertions::assertFalse ( + bool condition, + string failureMessage + ) + { + if (condition) { + stringstream err; + + err << "Boolean False assertion failed!" << endl; + err << failureMessage << endl; + + throw TestFailedException(err.str()); + } + } + + void Assertions::fail(string failureMessage) { + throw TestFailedException(move(failureMessage)); + } +} \ No newline at end of file diff --git a/include/TestCPPUtil.h b/src/TestCPPExceptions.cpp similarity index 56% rename from include/TestCPPUtil.h rename to src/TestCPPExceptions.cpp index cae25cf..78d6ae0 100644 --- a/include/TestCPPUtil.h +++ b/src/TestCPPExceptions.cpp @@ -25,20 +25,49 @@ OTHER DEALINGS IN THE SOFTWARE. For more information, please refer to */ -#ifndef TESTCPP_UTIL_ -#define TESTCPP_UTIL_ +#include -#include +#include "internal/TestCPPExceptions.h" +#ifdef TESTCPP_STACKTRACE_ENABLED +#include +#endif + +using std::clog; +using std::move; using std::string; +using std::runtime_error; namespace TestCPP { - namespace Util { - void debugLog (const string& message, bool omitNewline = false); - bool stringContains (const string& source, - const string& contains); - int unsignedToSigned(unsigned toCast); + + TestCPPException::TestCPPException (const char * msg) : + runtime_error(msg) + { +#ifdef TESTCPP_STACKTRACE_ENABLED + clog << boost::stacktrace::stacktrace(); +#endif + } + TestCPPException::TestCPPException (string&& msg) : + runtime_error(move(msg)) + { +#ifdef TESTCPP_STACKTRACE_ENABLED + clog << boost::stacktrace::stacktrace(); +#endif } -} + TestFailedException::TestFailedException (const char * msg) : + TestCPPException(msg) + { +#ifdef TESTCPP_STACKTRACE_ENABLED + clog << boost::stacktrace::stacktrace(); #endif + } + + TestFailedException::TestFailedException (string&& msg) : + TestCPPException(move(msg)) + { +#ifdef TESTCPP_STACKTRACE_ENABLED + clog << boost::stacktrace::stacktrace(); +#endif + } +} diff --git a/src/TestCPP.cpp b/src/TestCPPTestCase.cpp similarity index 61% rename from src/TestCPP.cpp rename to src/TestCPPTestCase.cpp index 6e9d9bf..95ca948 100644 --- a/src/TestCPP.cpp +++ b/src/TestCPPTestCase.cpp @@ -27,7 +27,9 @@ For more information, please refer to //Original author: Jonathan Hyry CSU-Fullerton SECS 6896-02 Fall 2014/15 -#include "TestCPP.h" +#include "internal/TestCPPCommon.h" +#include "internal/TestCPPExceptions.h" +#include "internal/TestCPPTestCase.h" #ifdef TESTCPP_STACKTRACE_ENABLED #include @@ -35,16 +37,14 @@ For more information, please refer to #include -#include "TestCPPUtil.h" +#include "internal/TestCPPUtil.h" using TestCPP::Util::debugLog; using std::cerr; using std::clog; using std::cout; -using std::current_exception; using std::endl; using std::exception; -using std::exception_ptr; using std::fixed; using std::function; using std::invalid_argument; @@ -56,50 +56,10 @@ using std::setprecision; using std::string; using std::tuple; -namespace TestCPP { - TestCPPException::TestCPPException (const char * msg) : - runtime_error(msg) - { -#ifdef TESTCPP_STACKTRACE_ENABLED - clog << boost::stacktrace::stacktrace(); -#endif - } - TestCPPException::TestCPPException (string&& msg) : - runtime_error(move(msg)) - { -#ifdef TESTCPP_STACKTRACE_ENABLED - clog << boost::stacktrace::stacktrace(); -#endif - } - - TestFailedException::TestFailedException (const char * msg) : - TestCPPException(msg) - { -#ifdef TESTCPP_STACKTRACE_ENABLED - clog << boost::stacktrace::stacktrace(); -#endif - } - - TestFailedException::TestFailedException (string&& msg) : - TestCPPException(move(msg)) - { -#ifdef TESTCPP_STACKTRACE_ENABLED - clog << boost::stacktrace::stacktrace(); -#endif - } - - TestObjName::TestObjName (const char* name) { - if (name) { - this->testCaseName = name; - } - else { - throw TestCPPException(TCNStr::NVTN); - } - } +using TCPPNum = TestCPP::TestCPPCommon::Nums; +using TCPPStr = TestCPP::TestCPPCommon::Strings; - const string& TestObjName::getTestName () { - return this->testCaseName; - } +namespace TestCPP { atomic_int TestCase::stdoutCaptureCasesConstructed; atomic_int TestCase::logCaptureCasesConstructed; @@ -230,22 +190,28 @@ namespace TestCPP { void TestCase::logTestFailure (string reason) { clog << fixed; - clog << setprecision(4); - clog << TCStr::TEST_ << this->testName << TCStr::FAIL - << static_cast(this->lastRunTime) - /1000000000.0 << TCStr::SEC << endl; - clog << TCStr::REASON << reason << endl; + clog << setprecision(TCPPNum::TIME_PRECISION); + clog << TCPPStr::TEST_ << this->testName << TCPPStr::_FAIL_ + << TCPPStr::PARENL + << static_cast(this->lastRunTime)/ + TCPPNum::NANOS_IN_SEC + << TCPPStr::SEC << TCPPStr::PARENR + << endl; + clog << TCPPStr::REASON_ << reason << endl; } void TestCase::runTest () { - clog << TCStr::START_RUN << this->testName << endl; + clog << TCPPStr::START_RUN << this->testName << endl; this->lastRunTime = duration(this->test).count(); if (this->notifyTestPassed) { clog << fixed; - clog << setprecision(4); - clog << TCStr::TEST_ << this->testName << TCStr::PASS - << static_cast(this->lastRunTime) - /1000000000.0 << TCStr::SEC << endl; + clog << setprecision(TCPPNum::TIME_PRECISION); + clog << TCPPStr::TEST_ << this->testName << TCPPStr::_PASS_ + << TCPPStr::PARENL + << static_cast(this->lastRunTime)/ + TCPPNum::NANOS_IN_SEC + << TCPPStr::SEC << TCPPStr::PARENR + << endl; } this->pass = true; } @@ -269,7 +235,7 @@ namespace TestCPP { } catch (...) { this->pass = false; - logTestFailure(TCStr::UNK_EXC); + logTestFailure(TCPPStr::UNK_EXC); } return false; @@ -342,7 +308,7 @@ namespace TestCPP { default: stringstream error; - error << TCStr::UNK_OPT << opt; + error << TCPPStr::UNK_OPT_ << opt; throw TestCPPException(error.str()); } } @@ -390,9 +356,9 @@ namespace TestCPP { } else { stringstream nomatch; - nomatch << TCStr::APOS << source << TCStr::APOS; - nomatch << TCStr::NEQUIV << TCStr::APOS; - nomatch << against << TCStr::APOS; + nomatch << TCPPStr::APOS << source << TCPPStr::APOS; + nomatch << TCPPStr::_NEQUIV_ << TCPPStr::APOS; + nomatch << against << TCPPStr::APOS; if (this->clogOriginal != nullptr) { ostream tmp(this->clogOriginal.get()); @@ -412,9 +378,9 @@ namespace TestCPP { } else { stringstream nomatch; - nomatch << TCStr::APOS << source << TCStr::APOS; - nomatch << TCStr::NCONTAIN << TCStr::APOS; - nomatch << against << TCStr::APOS; + nomatch << TCPPStr::APOS << source << TCPPStr::APOS; + nomatch << TCPPStr::_NCONTAIN_ << TCPPStr::APOS; + nomatch << against << TCPPStr::APOS; if (this->clogOriginal != nullptr) { ostream tmp(this->clogOriginal.get()); @@ -430,178 +396,8 @@ namespace TestCPP { default: stringstream re; - re << TCStr::UNK_CMP_OPT << opt; + re << TCPPStr::UNK_CMP_OPT_ << opt; throw TestCPPException(re.str()); } } - - void TestSuite::enableTestPassedMessage () { - this->testPassedMessage = true; - for (TestCase test : this->tests) { - test.setNotifyPassed(true); - } - } - void TestSuite::disableTestPassedMessage () { - this->testPassedMessage = false; - for (TestCase test : this->tests) { - test.setNotifyPassed(false); - } - } - - void TestSuite::setSuiteName (TestObjName&& testSuiteName) { - this->suiteName = move(testSuiteName); - } - - unsigned TestSuite::getLastRunFailCount () { - return this->lastRunFailCount; - } - - void TestSuite::run () { - if (this->tests.size() == 0) { - clog << "No tests to run!" << endl; - return; - } - - this->lastRunSucceeded = true; - this->lastRunFailCount = 0; - this->lastRunSuccessCount = 0; - this->totalRuntime = 0; - - clog << endl - << "Starting to run test suite '" << this->suiteName << "'" - << endl << endl; - - for (TestCase test : this->tests) { - bool testPassed = false; - try { - testPassed = test.go(); - } - catch (exception& e) { - clog << "Exception occurred during test run: " - << e.what() << endl; - } - catch (...) { - cerr << "An unknown error occurred during test run." - << endl; - } - - if (!testPassed && this->lastRunSucceeded) { - this->lastRunFailCount++; - this->lastRunSucceeded = false; - } - else if (!testPassed) { - this->lastRunFailCount++; - } - else { - this->lastRunSuccessCount++; - } - - this->totalRuntime += test.getLastRuntime(); - } - - clog << endl; - - if (this->testPassedMessage && - this->lastRunFailCount == 0) { - clog << "All '" << this->suiteName - << "' suite tests passed!" << endl; - } - - double suiteRuntimeElapsed = static_cast( - this->totalRuntime)/1000000000.0; - - clog << fixed; - clog << setprecision(0); - clog << "Finished running suite '" << this->suiteName << "' in " - << suiteRuntimeElapsed << "s ("<< this->lastRunSuccessCount - << "/" << this->tests.size() << " passed)" << endl; - clog << endl; - } - - template<> - void TestSuite::addTest (TestCase&& test) { - this->tests.emplace_back(test); - } - - void TestSuite::assertThrows ( - function shouldThrow, - string failureMessage - ) - { - try { - shouldThrow(); - } - catch (...) { - exception_ptr eptr = current_exception(); - - if (eptr) { - try { - rethrow_exception(eptr); - } - catch (const exception& e) { - clog << "assertThrows caught exception: " - << TestFailedException(e.what()).what() - << endl; - } - } - else { - clog << "Something was thrown, not sure what." << endl - << "This satisfies the assertion, so no failure is" - << " present. " - << TestFailedException("Unknown thrown object"). - what(); - } - - return; - } - - throw TestFailedException(move(failureMessage)); - } - - void TestSuite::assertNoThrows ( - function shouldNotThrow, - string failureMessage - ) - { - try { - shouldNotThrow(); - } - catch (...) { - throw TestFailedException(move(failureMessage)); - } - } - - void TestSuite::assertTrue ( - bool condition, - string failureMessage - ) - { - if (!condition) { - stringstream err; - - err << "Boolean Truth assertion failed!" << std::endl; - err << failureMessage << std::endl; - - throw TestFailedException(err.str()); - } - } - - void TestSuite::assertFalse ( - bool condition, - string failureMessage - ) - { - if (condition) { - stringstream err; - - err << "Boolean False assertion failed!" << std::endl; - err << failureMessage << std::endl; - - throw TestFailedException(err.str()); - } - } - - void TestSuite::fail(string failureMessage) { - throw TestFailedException(move(failureMessage)); - } } diff --git a/src/TestCPPTestSuite.cpp b/src/TestCPPTestSuite.cpp new file mode 100644 index 0000000..ca68aa2 --- /dev/null +++ b/src/TestCPPTestSuite.cpp @@ -0,0 +1,150 @@ +/* +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to + */ + +//Original author: Jonathan Hyry CSU-Fullerton SECS 6896-02 Fall 2014/15 + +#include + +#include "internal/TestCPPCommon.h" +#include "internal/TestCPPTestCase.h" +#include "internal/TestCPPTestSuite.h" + +using std::cerr; +using std::clog; +using std::cout; +using std::endl; +using std::exception; +using std::fixed; +using std::function; +using std::invalid_argument; +using std::move; +using std::ostream; +using std::rethrow_exception; +using std::runtime_error; +using std::setprecision; +using std::string; +using std::tuple; + +using TCPPNum = TestCPP::TestCPPCommon::Nums; +using TCPPStr = TestCPP::TestCPPCommon::Strings; + +namespace TestCPP { + + void TestSuite::enableTestPassedMessage () { + this->testPassedMessage = true; + for (TestCase test : this->tests) { + test.setNotifyPassed(true); + } + } + void TestSuite::disableTestPassedMessage () { + this->testPassedMessage = false; + for (TestCase test : this->tests) { + test.setNotifyPassed(false); + } + } + + void TestSuite::setSuiteName (TestObjName&& testSuiteName) { + this->suiteName = move(testSuiteName); + } + + unsigned TestSuite::getLastRunFailCount () { + return this->lastRunFailCount; + } + + void TestSuite::run () { + if (this->tests.size() == 0) { + clog << TCPPStr::NTR << endl; + return; + } + + this->lastRunSucceeded = true; + this->lastRunFailCount = 0; + this->lastRunSuccessCount = 0; + this->totalRuntime = 0; + + clog << endl + << TCPPStr::START_RUN << TCPPStr::SUITE_ + << TCPPStr::APOS << this->suiteName << TCPPStr::APOS + << endl + << endl; + + for (TestCase test : this->tests) { + bool testPassed = false; + try { + testPassed = test.go(); + } + catch (exception& e) { + clog << TCPPStr::TEST_EXC_ << e.what() + << endl; + } + catch (...) { + cerr << TCPPStr::UNK_EXC + << endl; + } + + if (!testPassed && this->lastRunSucceeded) { + this->lastRunFailCount++; + this->lastRunSucceeded = false; + } + else if (!testPassed) { + this->lastRunFailCount++; + } + else { + this->lastRunSuccessCount++; + } + + this->totalRuntime += test.getLastRuntime(); + } + + clog << endl; + + if (this->testPassedMessage && + this->lastRunFailCount == 0) { + clog << TCPPStr::ALL_ << TCPPStr::APOS << this->suiteName + << TCPPStr::APOS << TCPPStr::_SUITE_TESTS_PASSED + << endl; + } + + double suiteRuntimeElapsed = static_cast( + this->totalRuntime)/TCPPNum::NANOS_IN_SEC; + + clog << fixed; + clog << setprecision(0); + clog << TCPPStr::FINISHED_SUITE_ << TCPPStr::APOS + << this->suiteName << TCPPStr::APOS << TCPPStr::_IN_ABOUT_ + << suiteRuntimeElapsed << TCPPStr::SEC << TCPPStr::SP + << TCPPStr::PARENL << this->lastRunSuccessCount + << TCPPStr::FWSL << this->tests.size() << TCPPStr::_PASSED + << TCPPStr::PARENR + << endl; + } + + template<> + void TestSuite::addTest (TestCase&& test) { + this->tests.emplace_back(test); + } +} diff --git a/src/TestCPPUtil.cpp b/src/TestCPPUtil.cpp index b48693e..6215740 100644 --- a/src/TestCPPUtil.cpp +++ b/src/TestCPPUtil.cpp @@ -28,7 +28,9 @@ For more information, please refer to #include #include -#include "TestCPPUtil.h" +#include "internal/TestCPPCommon.h" +#include "internal/TestCPPExceptions.h" +#include "internal/TestCPPUtil.h" #ifdef DEBUG_LOG #include @@ -39,8 +41,25 @@ using std::clog; using std::endl; #endif +using TCPPStr = TestCPP::TestCPPCommon::Strings; + namespace TestCPP { + + TestObjName::TestObjName (const char* name) { + if (name) { + this->testCaseName = name; + } + else { + throw TestCPPException(TCPPStr::NVTN); + } + } + + const string& TestObjName::getName () { + return this->testCaseName; + } + namespace Util { + void debugLog(const string& message, bool omitNewline) { #ifdef DEBUG_LOG clog << message; From 9277978fcbeaad4ad319b424bef10d216010392c Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Mon, 13 May 2024 08:12:38 -0700 Subject: [PATCH 09/59] Refactoring, new Assertions-specific test suite Since Assertions are now in their own TU, they now have their own test module. Assertion tests are removed from TestSuite tests. Removed now-unnecessary TestCPPUtil.h #include. Refactored assertion calls. Formatting. --- demo/src/main.cpp | 1 - demo/src/tests.cpp | 7 +++- test/include/Assertions/AssertionsSuite.h | 33 ++++++++++++++++ test/include/Assertions/AssertionsTests.h | 15 +++++++ test/include/TestSuite/TestSuiteSuite.h | 16 -------- test/include/TestSuite/TestSuiteTests.h | 4 -- test/src/Assertions/AssertionsTests.cpp | 48 +++++++++++++++++++++++ test/src/TestCPPAssertionsMain.cpp | 25 ++++++++++++ test/src/TestCPPTestCaseMain.cpp | 1 - test/src/TestCPPTestSuiteMain.cpp | 1 - test/src/TestCase/TestCaseTestChunks.cpp | 1 - test/src/TestSuite/TestSuiteTests.cpp | 40 ------------------- 12 files changed, 126 insertions(+), 66 deletions(-) create mode 100644 test/include/Assertions/AssertionsSuite.h create mode 100644 test/include/Assertions/AssertionsTests.h create mode 100644 test/src/Assertions/AssertionsTests.cpp create mode 100644 test/src/TestCPPAssertionsMain.cpp diff --git a/demo/src/main.cpp b/demo/src/main.cpp index a06e0d5..dd0cd66 100644 --- a/demo/src/main.cpp +++ b/demo/src/main.cpp @@ -1,5 +1,4 @@ #include "TestCPP.h" -#include "TestCPPUtil.h" using TestCPP::TestSuite; using std::string; diff --git a/demo/src/tests.cpp b/demo/src/tests.cpp index 7660d8a..77f6042 100644 --- a/demo/src/tests.cpp +++ b/demo/src/tests.cpp @@ -6,13 +6,16 @@ namespace TestCPP { void simpleTest () { int lower = 5; int higher = 9; - TestSuite::assertTrue(higher > lower, "Something is seriously wrong."); + Assertions::assertTrue( + higher > lower, + "Something is seriously wrong." + ); } void otherSimpleTest () { string s1 = string("A string"); string s2 = string("another string"); - TestSuite::assertNotEquals(s1, s2); + Assertions::assertNotEquals(s1, s2); } } } diff --git a/test/include/Assertions/AssertionsSuite.h b/test/include/Assertions/AssertionsSuite.h new file mode 100644 index 0000000..68596b1 --- /dev/null +++ b/test/include/Assertions/AssertionsSuite.h @@ -0,0 +1,33 @@ +#ifndef TESTCPP_ASSERTIONS_SUITE_ +#define TESTCPP_ASSERTIONS_SUITE_ + +#include "AssertionsTests.h" + +namespace TestCPP { + namespace Testing { + namespace AssertionsSuite { + TestSuite suite( + "TestCPP Assertions Tests", + + make_tuple( + "assertNull Test", + function(AssertionsTests::TestAssertNull) + ), + make_tuple( + "assertNotNull Test", + function(AssertionsTests::TestAssertNotNull) + ), + make_tuple( + "assertTrue Test", + function(AssertionsTests::TestAssertTrue) + ), + make_tuple( + "assertFalse Test", + function(AssertionsTests::TestAssertFalse) + ) + ); + } + } +} + +#endif diff --git a/test/include/Assertions/AssertionsTests.h b/test/include/Assertions/AssertionsTests.h new file mode 100644 index 0000000..9a69fb7 --- /dev/null +++ b/test/include/Assertions/AssertionsTests.h @@ -0,0 +1,15 @@ +#ifndef TESTCPP_ASSERTIONS_TESTS_ +#define TESTCPP_ASSERTIONS_TESTS_ + +namespace TestCPP { + namespace Testing { + namespace AssertionsTests { + void TestAssertTrue (); + void TestAssertFalse (); + void TestAssertNull (); + void TestAssertNotNull (); + } + } +} + +#endif diff --git a/test/include/TestSuite/TestSuiteSuite.h b/test/include/TestSuite/TestSuiteSuite.h index ca195ec..4aa4194 100644 --- a/test/include/TestSuite/TestSuiteSuite.h +++ b/test/include/TestSuite/TestSuiteSuite.h @@ -12,22 +12,6 @@ namespace TestCPP { make_tuple( "Suite construction Test", function(TestSuiteTests::TestConstructSuite) - ), - make_tuple( - "assertNull Test", - function(TestSuiteTests::TestAssertNull) - ), - make_tuple( - "assertNotNull Test", - function(TestSuiteTests::TestAssertNotNull) - ), - make_tuple( - "assertTrue Test", - function(TestSuiteTests::TestAssertTrue) - ), - make_tuple( - "assertFalse Test", - function(TestSuiteTests::TestAssertFalse) ) ); } diff --git a/test/include/TestSuite/TestSuiteTests.h b/test/include/TestSuite/TestSuiteTests.h index 22aeb86..6fa855b 100644 --- a/test/include/TestSuite/TestSuiteTests.h +++ b/test/include/TestSuite/TestSuiteTests.h @@ -5,10 +5,6 @@ namespace TestCPP { namespace Testing { namespace TestSuiteTests { void TestConstructSuite (); - void TestAssertTrue (); - void TestAssertFalse (); - void TestAssertNull (); - void TestAssertNotNull (); } } } diff --git a/test/src/Assertions/AssertionsTests.cpp b/test/src/Assertions/AssertionsTests.cpp new file mode 100644 index 0000000..10f4634 --- /dev/null +++ b/test/src/Assertions/AssertionsTests.cpp @@ -0,0 +1,48 @@ +#include "TestCPP.h" +#include "Assertions/AssertionsTests.h" + +namespace TestCPP { + namespace Testing { + namespace AssertionsTests { + void TestAssertTrue () { + int lower = 5; + int higher = 9; + + Assertions::assertTrue(higher > lower, + "Negated condtion!"); + } + + void TestAssertFalse () { + int lower = 5; + int higher = 9; + + Assertions::assertFalse(higher < lower, + "Negated condtion!"); + } + + void TestAssertNull () { + string * nullString = nullptr; + + Assertions::assertNull(nullString, "nullptr is null!"); + } + + void TestAssertNotNull () { + string notNull("non-null"); + + Assertions::assertNotNull( + ¬Null, + "A constructed std::string is not null!" + ); + Assertions::assertNotNull( + "non-null", + "A const char * is not null!" + ); + + int testInt = 5; + + Assertions::assertNotNull(&testInt, + "An int pointer is not null!"); + } + } + } +} \ No newline at end of file diff --git a/test/src/TestCPPAssertionsMain.cpp b/test/src/TestCPPAssertionsMain.cpp new file mode 100644 index 0000000..b0e5374 --- /dev/null +++ b/test/src/TestCPPAssertionsMain.cpp @@ -0,0 +1,25 @@ +#include "TestCPP.h" + +using TestCPP::TestCase; +using TestCPP::TestSuite; +using std::string; +using std::make_tuple; +using std::function; + +#include "Assertions/AssertionsSuite.h" + +int main(void) +{ + try { + TestCPP::Testing::AssertionsSuite::suite.run(); + return TestCPP::Util::unsignedToSigned( + TestCPP::Testing::AssertionsSuite::suite. + getLastRunFailCount() + ); + } + catch (std::exception& e) { + std::cerr << "Test suite run failed with an exception: " + << e.what() << std::endl; + return -1; + } +} diff --git a/test/src/TestCPPTestCaseMain.cpp b/test/src/TestCPPTestCaseMain.cpp index 89287f2..3db3ee6 100644 --- a/test/src/TestCPPTestCaseMain.cpp +++ b/test/src/TestCPPTestCaseMain.cpp @@ -1,5 +1,4 @@ #include "TestCPP.h" -#include "TestCPPUtil.h" using TestCPP::TestCase; using TestCPP::TestSuite; diff --git a/test/src/TestCPPTestSuiteMain.cpp b/test/src/TestCPPTestSuiteMain.cpp index 61f8968..8cb0f8a 100644 --- a/test/src/TestCPPTestSuiteMain.cpp +++ b/test/src/TestCPPTestSuiteMain.cpp @@ -1,5 +1,4 @@ #include "TestCPP.h" -#include "TestCPPUtil.h" using TestCPP::TestCase; using TestCPP::TestSuite; diff --git a/test/src/TestCase/TestCaseTestChunks.cpp b/test/src/TestCase/TestCaseTestChunks.cpp index 7d6d4fe..661cd48 100644 --- a/test/src/TestCase/TestCaseTestChunks.cpp +++ b/test/src/TestCase/TestCaseTestChunks.cpp @@ -1,7 +1,6 @@ #include #include "TestCPP.h" -#include "TestCPPUtil.h" #include "TestCase/TestCaseTestChunks.h" using TestCPP::TestCase; diff --git a/test/src/TestSuite/TestSuiteTests.cpp b/test/src/TestSuite/TestSuiteTests.cpp index 6ee58d7..e4f070f 100644 --- a/test/src/TestSuite/TestSuiteTests.cpp +++ b/test/src/TestSuite/TestSuiteTests.cpp @@ -9,46 +9,6 @@ namespace TestCPP { "Suite construction" )); } - - void TestAssertTrue () { - int lower = 5; - int higher = 9; - - TestSuite::assertTrue(higher > lower, - "Negated condtion!"); - } - - void TestAssertFalse () { - int lower = 5; - int higher = 9; - - TestSuite::assertFalse(higher < lower, - "Negated condtion!"); - } - - void TestAssertNull () { - string * nullString = nullptr; - - TestSuite::assertNull(nullString, "nullptr is null!"); - } - - void TestAssertNotNull () { - string notNull("non-null"); - - TestSuite::assertNotNull( - ¬Null, - "A constructed std::string is not null!" - ); - TestSuite::assertNotNull( - "non-null", - "A const char * is not null!" - ); - - int testInt = 5; - - TestSuite::assertNotNull(&testInt, - "An int pointer is not null!"); - } } } } From 83594f9c28744fbf5518d1954378c6cc091af3a6 Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Mon, 13 May 2024 08:18:58 -0700 Subject: [PATCH 10/59] Test coverage to get patch coverage up for the PR. Refactoring. Cover the patched line to get the CodeCov patch coverage to an acceptable level, plus a little. Added 3 new tests for this. Refactoring for API changes. Use TestCPPCommon to check output is as expected. Remove now-unnecessary TestCPPUtil.h #include. --- test/include/TestCase/TestCaseSuite.h | 12 ++++ test/include/TestCase/TestCaseTests.h | 3 + test/src/TestCase/TestCaseTests.cpp | 95 +++++++++++++++++++++++---- 3 files changed, 98 insertions(+), 12 deletions(-) diff --git a/test/include/TestCase/TestCaseSuite.h b/test/include/TestCase/TestCaseSuite.h index ba3115b..68b7bc2 100644 --- a/test/include/TestCase/TestCaseSuite.h +++ b/test/include/TestCase/TestCaseSuite.h @@ -17,6 +17,18 @@ namespace TestCPP { "Case runner Test", function(TestCaseTests::TestTestCaseGo) ), + make_tuple( + "Case runner Test - string thrown", + function(TestCaseTests::TestTestCaseGoThrowStr) + ), + make_tuple( + "Case runner Test - char thrown", + function(TestCaseTests::TestTestCaseGoThrowChr) + ), + make_tuple( + "Case runner Test - test catchall", + function(TestCaseTests::TestTestCaseGoThrowInt) + ), make_tuple( "Case setNotifyPassed Test", function( diff --git a/test/include/TestCase/TestCaseTests.h b/test/include/TestCase/TestCaseTests.h index d1569f8..90b526c 100644 --- a/test/include/TestCase/TestCaseTests.h +++ b/test/include/TestCase/TestCaseTests.h @@ -6,6 +6,9 @@ namespace TestCPP { namespace TestCaseTests { void TestConstructCase (); void TestTestCaseGo (); + void TestTestCaseGoThrowStr (); + void TestTestCaseGoThrowChr (); + void TestTestCaseGoThrowInt (); void TestTestCaseSetNotifyPassed (); } } diff --git a/test/src/TestCase/TestCaseTests.cpp b/test/src/TestCase/TestCaseTests.cpp index 530a68d..8fef9ec 100644 --- a/test/src/TestCase/TestCaseTests.cpp +++ b/test/src/TestCase/TestCaseTests.cpp @@ -1,9 +1,10 @@ #include "TestCPP.h" -#include "TestCPPUtil.h" #include "TestCase/TestCaseTestChunks.h" using TestCPP::Util::debugLog; +using TCPPStr = TestCPP::TestCPPCommon::Strings; + namespace TestCPP { namespace Testing { namespace TestCaseTests { @@ -15,7 +16,7 @@ namespace TestCPP { )); debugLog("Construct with nullptr string"); - TestSuite::assertThrows( + Assertions::assertThrows( []() { debugLog("Construct with nullptr string", true); debugLog(" - assertThrows lambda"); @@ -41,12 +42,82 @@ namespace TestCPP { true )); - TestSuite::assertTrue( + Assertions::assertTrue( test->go(), "Should have succeeded basic no-op test!" ); } + void TestTestCaseGoThrowStr () { + const string throwStr = "Test throw string!"; + + auto test = unique_ptr(new TestCase( + "SUB-TEST TestCaseGo case Test - throws str", + function([&throwStr](){ + throw throwStr; + }), + true, false, true, false, + TestCase::TestCaseOutCompareOptions::CONTAINS + )); + + Assertions::assertFalse( + test->go(), + "Should have succeeded str throws test!" + ); + + Assertions::assertTrue( + test->checkLog(throwStr), + "Something is off, expected output does not exist!" + ); + } + + void TestTestCaseGoThrowChr () { + constexpr const char * throwChr = + "Test throw const char *!"; + + auto test = unique_ptr(new TestCase( + "SUB-TEST TestCaseGo case Test - throws chr", + function([&throwChr](){ + throw throwChr; + }), + true, false, true, false, + TestCase::TestCaseOutCompareOptions::CONTAINS + )); + + Assertions::assertFalse( + test->go(), + "Should have succeeded chr throws test!" + ); + + string tcLog(throwChr); + + Assertions::assertTrue( + test->checkLog(tcLog), + "Something is off, expected output does not exist!" + ); + } + + void TestTestCaseGoThrowInt () { + auto test = unique_ptr(new TestCase( + "SUB-TEST TestCaseGo case Test - throws int", + function([](){ + throw -1; + }), + true, false, true, false, + TestCase::TestCaseOutCompareOptions::CONTAINS + )); + + Assertions::assertFalse( + test->go(), + "Should have succeeded catchall throws test!" + ); + + Assertions::assertTrue( + test->checkLog(TCPPStr::UNK_EXC), + "Something is off, expected output does not exist!" + ); + } + void TestTestCaseSetNotifyPassed () { auto test = unique_ptr(new TestCase( "TestCaseSetNotifyPassed case Test", @@ -55,7 +126,7 @@ namespace TestCPP { TestCase::TestCaseOutCompareOptions::CONTAINS )); - TestSuite::assertTrue( + Assertions::assertTrue( test->go(), "TestSetNotifyPassed go() 1" ); @@ -64,26 +135,26 @@ namespace TestCPP { tcLog << "Test "; tcLog << "TestCaseSetNotifyPassed case Test passed! ("; - TestSuite::assertTrue( + Assertions::assertTrue( !test->checkLog(tcLog.str()), "TestSetNotifyPassed checkLog() 1" ); - TestSuite::assertTrue( + Assertions::assertTrue( !test->checkLog(string("s)")), "TestSetNotifyPassed checkLog() 2" ); test->setNotifyPassed(true); - TestSuite::assertTrue( + Assertions::assertTrue( test->go(), "TestSetNotifyPassed go() 2" ); - TestSuite::assertTrue( + Assertions::assertTrue( test->checkLog(tcLog.str()), "TestSetNotifyPassed checkLog() 3" ); - TestSuite::assertTrue( + Assertions::assertTrue( test->checkLog(string("s)")), "TestSetNotifyPassed checkLog() 4" ); @@ -91,16 +162,16 @@ namespace TestCPP { test->clearLogCapture(); test->setNotifyPassed(false); - TestSuite::assertTrue( + Assertions::assertTrue( test->go(), "TestSetNotifyPassed go() 3" ); - TestSuite::assertTrue( + Assertions::assertTrue( !test->checkLog(tcLog.str()), "TestSetNotifyPassed checkLog() 5" ); - TestSuite::assertTrue( + Assertions::assertTrue( !test->checkLog(string("s)")), "TestSetNotifyPassed checkLog() 6" ); From 63e49cd333836c85bd7ef6739b0f2786489929de Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Mon, 13 May 2024 08:28:30 -0700 Subject: [PATCH 11/59] Version bump to 1.0.0. New test target. Install new internal headers. Bump the major version because of the API change. This is still considered a beta-project, regardless. Work on the build takes the refactorings into account. This includes ensuring the new header structure is properly accounted for in packages and installation. --- CMakeLists.txt | 2 +- cmake/BuildTypeHandling.cmake | 29 +++++++++++++++++++++++++++++ cmake/Includes.cmake | 6 ++++++ cmake/Installing.cmake | 13 +++++++++++++ cmake/Linking.cmake | 33 +++++++++++++++++++++++++++++++++ cmake/Targets.cmake | 11 ++++++++++- cmake/Testing.cmake | 5 +++++ 7 files changed, 97 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 04f62a9..ce2e566 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required (VERSION 3.16) set (PROJECT_NAME "TestCPP") set (PROJECT_GROUP_NAME "cpptesting") -project (${PROJECT_NAME} VERSION 0.2.1 LANGUAGES CXX) +project (${PROJECT_NAME} VERSION 1.0.0 LANGUAGES CXX) set (CMAKE_CXX_STANDARD 11) set (CMAKE_CXX_STANDARD_REQUIRED ON) diff --git a/cmake/BuildTypeHandling.cmake b/cmake/BuildTypeHandling.cmake index eba34cd..37d1387 100644 --- a/cmake/BuildTypeHandling.cmake +++ b/cmake/BuildTypeHandling.cmake @@ -135,6 +135,12 @@ if (${CMAKE_BUILD_TYPE} STREQUAL "Release") PUBLIC ${MSVC_RELEASE_BUILD_OPTS} ) + + target_compile_options ( + ${PROJECT_NAME}_Assertions_test + PUBLIC + ${MSVC_RELEASE_BUILD_OPTS} + ) endif () else () @@ -164,6 +170,12 @@ if (${CMAKE_BUILD_TYPE} STREQUAL "Release") PUBLIC ${GCC_CLANG_RELEASE_BUILD_OPTS} ) + + target_compile_options ( + ${PROJECT_NAME}_Assertions_test + PUBLIC + ${GCC_CLANG_RELEASE_BUILD_OPTS} + ) endif () endif () @@ -195,6 +207,11 @@ else () PUBLIC DEBUG_LOG ) + target_compile_definitions ( + ${PROJECT_NAME}_Assertions_test + PUBLIC + DEBUG_LOG + ) endif () if (MSVC) @@ -224,6 +241,12 @@ else () PUBLIC ${MSVC_DEBUG_BUILD_OPTS} ) + + target_compile_options ( + ${PROJECT_NAME}_Assertions_test + PUBLIC + ${MSVC_DEBUG_BUILD_OPTS} + ) endif () else () @@ -256,6 +279,12 @@ else () ${COVERAGE_BUILD_OPTS} ) + target_compile_options ( + ${PROJECT_NAME}_Assertions_test + PUBLIC + ${COVERAGE_BUILD_OPTS} + ) + else () target_compile_options ( ${PROJECT_NAME} diff --git a/cmake/Includes.cmake b/cmake/Includes.cmake index 200a7ae..a34ba82 100644 --- a/cmake/Includes.cmake +++ b/cmake/Includes.cmake @@ -32,4 +32,10 @@ if (BUILD_TESTING) test/include include ) + + target_include_directories ( + ${PROJECT_NAME}_Assertions_test PRIVATE + test/include + include + ) endif () diff --git a/cmake/Installing.cmake b/cmake/Installing.cmake index 39ac2b2..f8ac878 100644 --- a/cmake/Installing.cmake +++ b/cmake/Installing.cmake @@ -4,12 +4,25 @@ set_target_properties ( PUBLIC_HEADER include/TestCPP.h ) +set_target_properties ( + ${PROJECT_NAME} + PROPERTIES + PRIVATE_HEADER + include/internal/TestCPPAssertions.h + include/internal/TestCPPCommon.h + include/internal/TestCPPExceptions.h + include/internal/TestCPPTestCase.h + include/internal/TestCPPTestSuite.h + include/internal/TestCPPUtil.h +) include (GNUInstallDirs) install ( TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME}Targets PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} + PRIVATE_HEADER + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}/internal ) export ( EXPORT ${PROJECT_NAME}Targets diff --git a/cmake/Linking.cmake b/cmake/Linking.cmake index f6c6cb0..f585edf 100644 --- a/cmake/Linking.cmake +++ b/cmake/Linking.cmake @@ -46,6 +46,13 @@ if (BUILD_TESTING) ole32 dbgeng ) + target_link_libraries ( + ${PROJECT_NAME}_Assertions_test + ${PROJECT_NAME} + gcov + ole32 + dbgeng + ) elseif (${TESTCPP_STACKTRACE_ENABLED}) target_link_libraries ( @@ -60,6 +67,12 @@ if (BUILD_TESTING) gcov dl ) + target_link_libraries ( + ${PROJECT_NAME}_Assertions_test + ${PROJECT_NAME} + gcov + dl + ) else () target_link_libraries ( @@ -72,6 +85,11 @@ if (BUILD_TESTING) ${PROJECT_NAME} gcov ) + target_link_libraries ( + ${PROJECT_NAME}_Assertions_test + ${PROJECT_NAME} + gcov + ) endif () else () @@ -88,6 +106,12 @@ if (BUILD_TESTING) ole32 dbgeng ) + target_link_libraries ( + ${PROJECT_NAME}_Assertions_test + ${PROJECT_NAME} + ole32 + dbgeng + ) elseif (${TESTCPP_STACKTRACE_ENABLED}) target_link_libraries ( @@ -100,6 +124,11 @@ if (BUILD_TESTING) ${PROJECT_NAME} dl ) + target_link_libraries ( + ${PROJECT_NAME}_Assertions_test + ${PROJECT_NAME} + dl + ) else () target_link_libraries ( @@ -110,6 +139,10 @@ if (BUILD_TESTING) ${PROJECT_NAME}_TestSuite_test ${PROJECT_NAME} ) + target_link_libraries ( + ${PROJECT_NAME}_Assertions_test + ${PROJECT_NAME} + ) endif () endif () endif () diff --git a/cmake/Targets.cmake b/cmake/Targets.cmake index 49fa350..66b198e 100644 --- a/cmake/Targets.cmake +++ b/cmake/Targets.cmake @@ -1,7 +1,10 @@ add_library ( ${PROJECT_NAME} + src/TestCPPAssertions.cpp + src/TestCPPExceptions.cpp + src/TestCPPTestCase.cpp + src/TestCPPTestSuite.cpp src/TestCPPUtil.cpp - src/TestCPP.cpp ) add_library ( ${PROJECT_GROUP_NAME}::${PROJECT_NAME} @@ -30,4 +33,10 @@ if (BUILD_TESTING) test/src/TestSuite/TestSuiteTests.cpp test/src/TestCPPTestSuiteMain.cpp ) + + add_executable ( + ${PROJECT_NAME}_Assertions_test + test/src/Assertions/AssertionsTests.cpp + test/src/TestCPPAssertionsMain.cpp + ) endif () diff --git a/cmake/Testing.cmake b/cmake/Testing.cmake index e454ef8..b7c4c1b 100644 --- a/cmake/Testing.cmake +++ b/cmake/Testing.cmake @@ -8,4 +8,9 @@ if (BUILD_TESTING) NAME ${PROJECT_NAME}TestSuiteTests COMMAND ${PROJECT_NAME}_TestSuite_test ) + + add_test ( + NAME ${PROJECT_NAME}AssertionsTests + COMMAND ${PROJECT_NAME}_Assertions_test + ) endif () From dadf9198e2ea7c92f158cba3c1797649375b5511 Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Mon, 13 May 2024 08:29:10 -0700 Subject: [PATCH 12/59] Restructure and add to the CodeLite project. --- TestFramework.project | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/TestFramework.project b/TestFramework.project index d6badc7..31c2d53 100644 --- a/TestFramework.project +++ b/TestFramework.project @@ -3,12 +3,23 @@ - + + + + - + + + + + + + + + @@ -43,11 +54,14 @@ - + + + + @@ -59,6 +73,10 @@ + + + + From dfdad56c15ccf860c7f6e38dd7fb1d2349655b43 Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Mon, 13 May 2024 08:59:32 -0700 Subject: [PATCH 13/59] Fix PRIVATE_HEADER property There are now multiple private headers, needed to encapsulate them into a list in order to have them properly applied to packing/installing build steps. --- cmake/Installing.cmake | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/cmake/Installing.cmake b/cmake/Installing.cmake index f8ac878..7606865 100644 --- a/cmake/Installing.cmake +++ b/cmake/Installing.cmake @@ -1,19 +1,31 @@ +list ( + APPEND + TESTCPP_PUBLIC_HEADERS + include/TestCPP.h +) + +list ( + APPEND + TESTCPP_PRIVATE_HEADERS + include/internal/TestCPPAssertions.h + include/internal/TestCPPCommon.h + include/internal/TestCPPExceptions.h + include/internal/TestCPPTestCase.h + include/internal/TestCPPTestSuite.h + include/internal/TestCPPUtil.h +) + set_target_properties ( ${PROJECT_NAME} PROPERTIES PUBLIC_HEADER - include/TestCPP.h + "${TESTCPP_PUBLIC_HEADERS}" ) set_target_properties ( ${PROJECT_NAME} PROPERTIES PRIVATE_HEADER - include/internal/TestCPPAssertions.h - include/internal/TestCPPCommon.h - include/internal/TestCPPExceptions.h - include/internal/TestCPPTestCase.h - include/internal/TestCPPTestSuite.h - include/internal/TestCPPUtil.h + "${TESTCPP_PRIVATE_HEADERS}" ) include (GNUInstallDirs) install ( From 92997ea88f45ed0f80df5c6549b64d076460c305 Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Mon, 13 May 2024 09:17:32 -0700 Subject: [PATCH 14/59] Remove unnecessary include. Add necessary include. --- src/TestCPPAssertions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TestCPPAssertions.cpp b/src/TestCPPAssertions.cpp index 57344f9..25dc566 100644 --- a/src/TestCPPAssertions.cpp +++ b/src/TestCPPAssertions.cpp @@ -26,7 +26,7 @@ For more information, please refer to */ #include "internal/TestCPPAssertions.h" -#include "internal/TestCPPTestCase.h" +#include "internal/TestCPPExceptions.h" using std::clog; using std::current_exception; From 109ab7387f1241c3a5177db3c2dbdc02fb00b777 Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Mon, 13 May 2024 09:23:18 -0700 Subject: [PATCH 15/59] Accidentally moved TestCaseTests.cpp to the wrong virtual directory This fixes that. --- TestFramework.project | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TestFramework.project b/TestFramework.project index 31c2d53..bab697a 100644 --- a/TestFramework.project +++ b/TestFramework.project @@ -18,7 +18,6 @@ - @@ -54,6 +53,7 @@ + From 4f0e898f4091db64b6135518f5cb197ad57c9f4b Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Mon, 13 May 2024 09:31:11 -0700 Subject: [PATCH 16/59] Let's try this again. Fix Assertions includes and add std usings. --- include/internal/TestCPPAssertions.h | 11 ++++++++++- src/TestCPPAssertions.cpp | 1 - 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/include/internal/TestCPPAssertions.h b/include/internal/TestCPPAssertions.h index 517f013..8032643 100644 --- a/include/internal/TestCPPAssertions.h +++ b/include/internal/TestCPPAssertions.h @@ -28,8 +28,17 @@ For more information, please refer to #ifndef TESTCPP_ASSERTIONS_ #define TESTCPP_ASSERTIONS_ +#include +#include +#include +#include + #include "TestCPPExceptions.h" -#include "TestCPPTestCase.h" + +using std::endl; +using std::function; +using std::string; +using std::stringstream; /** * The base namespace for all TestCPP library code. diff --git a/src/TestCPPAssertions.cpp b/src/TestCPPAssertions.cpp index 25dc566..f689234 100644 --- a/src/TestCPPAssertions.cpp +++ b/src/TestCPPAssertions.cpp @@ -26,7 +26,6 @@ For more information, please refer to */ #include "internal/TestCPPAssertions.h" -#include "internal/TestCPPExceptions.h" using std::clog; using std::current_exception; From 7ece33448f3f94137a09b765cde2ae1b49fac6eb Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Mon, 13 May 2024 09:44:56 -0700 Subject: [PATCH 17/59] Move the operator<< definition to the source file. --- include/internal/TestCPPUtil.h | 6 +----- src/TestCPPUtil.cpp | 9 +++++++++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/include/internal/TestCPPUtil.h b/include/internal/TestCPPUtil.h index 839625a..045def4 100644 --- a/include/internal/TestCPPUtil.h +++ b/include/internal/TestCPPUtil.h @@ -84,11 +84,7 @@ namespace TestCPP { friend std::ostream& operator<< ( std::ostream& s, TestObjName& tcName - ) - { - s << tcName.getName(); - return s; - } + ); private: string testCaseName; diff --git a/src/TestCPPUtil.cpp b/src/TestCPPUtil.cpp index 6215740..424cf85 100644 --- a/src/TestCPPUtil.cpp +++ b/src/TestCPPUtil.cpp @@ -58,6 +58,15 @@ namespace TestCPP { return this->testCaseName; } + std::ostream& operator<< ( + std::ostream& s, + TestObjName& tcName + ) + { + s << tcName.getName(); + return s; + } + namespace Util { void debugLog(const string& message, bool omitNewline) { From 7014e8903508f188cb95268ab61fac5730a712cc Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Mon, 13 May 2024 09:59:52 -0700 Subject: [PATCH 18/59] Forgot to include ostream. --- src/TestCPPUtil.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/TestCPPUtil.cpp b/src/TestCPPUtil.cpp index 424cf85..37a8662 100644 --- a/src/TestCPPUtil.cpp +++ b/src/TestCPPUtil.cpp @@ -26,6 +26,7 @@ For more information, please refer to */ #include +#include #include #include "internal/TestCPPCommon.h" From 19970c0c06b38a3916ba6ca226b5b86dc2a74f9b Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Mon, 13 May 2024 10:05:01 -0700 Subject: [PATCH 19/59] This include should have been conditional. Now it is, if it doesn't need iostream for debug logging then just include ostream for the friend operator<< overload. --- src/TestCPPUtil.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/TestCPPUtil.cpp b/src/TestCPPUtil.cpp index 37a8662..671d8ea 100644 --- a/src/TestCPPUtil.cpp +++ b/src/TestCPPUtil.cpp @@ -26,7 +26,6 @@ For more information, please refer to */ #include -#include #include #include "internal/TestCPPCommon.h" @@ -35,6 +34,8 @@ For more information, please refer to #ifdef DEBUG_LOG #include +#else +#include #endif #ifdef DEBUG_LOG From 039bf5d540ea0e2ab396ee4a5c6c3a2ab254a0ff Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Mon, 13 May 2024 10:10:39 -0700 Subject: [PATCH 20/59] Fix clang error -wunused-lambda-capture I think this is not required for capture because it's constexpr. --- test/src/TestCase/TestCaseTests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/src/TestCase/TestCaseTests.cpp b/test/src/TestCase/TestCaseTests.cpp index 8fef9ec..0db1108 100644 --- a/test/src/TestCase/TestCaseTests.cpp +++ b/test/src/TestCase/TestCaseTests.cpp @@ -77,7 +77,7 @@ namespace TestCPP { auto test = unique_ptr(new TestCase( "SUB-TEST TestCaseGo case Test - throws chr", - function([&throwChr](){ + function([](){ throw throwChr; }), true, false, true, false, From 606be6ec0a73fa60ec2e0c192e23991d86c2ae09 Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Mon, 13 May 2024 10:59:00 -0700 Subject: [PATCH 21/59] Workaround for MSVC error C3493 I have to ignore the clang warning to work around the MSVC issue since the library is for C++11 not >=C++14, where there is an available workaround that doesn't involve ignoring a warning. --- cmake/BuildTypeHandling.cmake | 26 ++++++++++++++++++-------- test/src/TestCase/TestCaseTests.cpp | 2 +- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/cmake/BuildTypeHandling.cmake b/cmake/BuildTypeHandling.cmake index 37d1387..67543b7 100644 --- a/cmake/BuildTypeHandling.cmake +++ b/cmake/BuildTypeHandling.cmake @@ -80,13 +80,23 @@ endif () list ( APPEND GCC_CLANG_RELEASE_BUILD_OPTS - -O3 # Optimize the Release build - -Wall # Enable most warnings - -Wextra # Enable even more warnings - -Wpedantic # Enable most of the rest of the warnings - -Werror # Treat all warnings as errors - -Wno-unused-parameter # Unused parameters occur in the Release - # build in debugLog + -O3 # Optimize the Release build + -Wall # Enable most warnings + -Wextra # Enable even more warnings + -Wpedantic # Enable most of the rest of the warnings + -Werror # Treat all warnings as errors + -Wno-unused-parameter # Unused parameters occur in the Release + # build in debugLog + -Wno-unused-lambda-capture # Avoid MSVC error C3493 - There is + # implementation divergence here and + # since we're not using >=C++14 there + # is no workaround other than to ignore + # this warning (the MSVC issue is an + # error). A workaround for >=C++14 is to + # use an explicit capture - if ever I + # change the library to use >=C++14 I + # can remove this and use an explicit + # capture. ) list ( APPEND @@ -94,7 +104,7 @@ list ( -g # Enable all debugging information -Og # Ensure the compiler doesn't use optimizations that would harm # debuggability of the resulting code - -Wall -Wextra -Wpedantic -Werror + -Wall -Wextra -Wpedantic -Werror -Wno-unused-lambda-capture ) list ( APPEND diff --git a/test/src/TestCase/TestCaseTests.cpp b/test/src/TestCase/TestCaseTests.cpp index 0db1108..8fef9ec 100644 --- a/test/src/TestCase/TestCaseTests.cpp +++ b/test/src/TestCase/TestCaseTests.cpp @@ -77,7 +77,7 @@ namespace TestCPP { auto test = unique_ptr(new TestCase( "SUB-TEST TestCaseGo case Test - throws chr", - function([](){ + function([&throwChr](){ throw throwChr; }), true, false, true, false, From 7801478b42dc94ca96a29f7cdb77bb48b49c04cb Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Sat, 22 Jun 2024 09:14:17 -0700 Subject: [PATCH 22/59] Cleanup, TC member initialization, TC capture bools, fix message bug Initialize everything in TestCase with sane defaults. Name the parameter in the logTestFailure function prototype. Add boolean members that indicate whether for the given TestCase the output should be captured. Add implementation details for capture bools. This ensures all are counted properly. Rename the testPassedMessage TestSuite member to testSuitePassedMessage. This properly differentiates it from the similar member of TestCase. No addTest specializations in header file, only the template. Moved the specialization from the header file that was there to the source file. This fixed an issue when testing where the compiler could not find the proper specialization. Flesh out/add/fix docs. Fixed a huge bug in how the test passage message is enabled/disabled en- mass through a TestSuite. Previously the vector was iterated over with the newer style, but this causes a copy to be made on every iteration of every TestCase, which is completely not what we want to do here. Fall back to index-based vector iteration so we're properly modifying each original TestCase and not making copies thinking we're modifying the actual TestCases. --- include/internal/TestCPPTestCase.h | 14 ++++--- include/internal/TestCPPTestSuite.h | 19 +++------ src/TestCPPTestCase.cpp | 60 +++++++++++++++++++++++++++++ src/TestCPPTestSuite.cpp | 36 +++++++++++++---- 4 files changed, 104 insertions(+), 25 deletions(-) diff --git a/include/internal/TestCPPTestCase.h b/include/internal/TestCPPTestCase.h index cc2c3f5..721062a 100644 --- a/include/internal/TestCPPTestCase.h +++ b/include/internal/TestCPPTestCase.h @@ -230,19 +230,23 @@ namespace TestCPP { long long getLastRuntime (); private: - bool notifyTestPassed; - bool pass; - long long lastRunTime; + bool notifyTestPassed = false; + bool pass = false; + bool stdoutCaptured = false; + bool clogCaptured = false; + bool stderrCaptured = false; + long long lastRunTime = -1; TestObjName testName; function test; - TestCaseOutCompareOptions option; + TestCaseOutCompareOptions option = + TestCaseOutCompareOptions::CONTAINS; void captureStdout (); void captureClog (); void captureStdErr (); - void logTestFailure (string); + void logTestFailure (string failureMessage); void runTest (); bool checkOutput (TestCaseOutCompareOptions opt, string source, string against); diff --git a/include/internal/TestCPPTestSuite.h b/include/internal/TestCPPTestSuite.h index 9945227..4277174 100644 --- a/include/internal/TestCPPTestSuite.h +++ b/include/internal/TestCPPTestSuite.h @@ -81,7 +81,7 @@ namespace TestCPP { TestSuite (TestObjName&& suiteName, typename enable_if::type) { - this->testPassedMessage = true; + this->testSuitePassedMessage = true; this->setSuiteName(move(suiteName)); this->tests = vector(); } @@ -92,7 +92,7 @@ namespace TestCPP { */ template TestSuite (TestObjName&& suiteName, TestType ...tests) { - this->testPassedMessage = true; + this->testSuitePassedMessage = true; this->setSuiteName(move(suiteName)); this->tests = vector(); @@ -102,18 +102,10 @@ namespace TestCPP { /** * @brief Add a test to this test suite. * - * The test should be defined as a tuple with 2 elements to use - * this. The first element is the test name, and the second - * element is the test function that defines the test. + * Appropriate specializations defined in the source file. */ template - void addTest (T&& test) { - this->tests.emplace_back( - std::get<0>(test), - std::get<1>(test), - this->testPassedMessage - ); - } + void addTest (T&& test); /** * @brief Specialization to handle when someone tries to call @@ -128,6 +120,7 @@ namespace TestCPP { /** * @brief Add one or more tests at once to the test suite. * @param test The first test to add. + * @param tests The rest of the tests to add. */ template void addTests (Test test, OtherTests ...tests) { @@ -176,7 +169,7 @@ namespace TestCPP { void run (); private: - bool testPassedMessage; + bool testSuitePassedMessage; bool lastRunSucceeded; unsigned lastRunSuccessCount; unsigned lastRunFailCount; diff --git a/src/TestCPPTestCase.cpp b/src/TestCPPTestCase.cpp index 95ca948..a76f091 100644 --- a/src/TestCPPTestCase.cpp +++ b/src/TestCPPTestCase.cpp @@ -97,6 +97,10 @@ namespace TestCPP { captureStdErr(); } + this->stdoutCaptured = captureOut; + this->clogCaptured = captureLog; + this->stderrCaptured = captureErr; + this->option = opt; } @@ -107,6 +111,20 @@ namespace TestCPP { this->pass = o.pass; this->lastRunTime = o.lastRunTime; + this->stdoutCaptured = o.stdoutCaptured; + this->clogCaptured = o.clogCaptured; + this->stderrCaptured = o.stderrCaptured; + + if (this->stdoutCaptured) { + captureStdout(); + } + if (this->clogCaptured) { + captureClog(); + } + if (this->stderrCaptured) { + captureStdErr(); + } + this->testName = o.testName; this->test = o.test; } @@ -118,6 +136,20 @@ namespace TestCPP { this->pass = move(o.pass); this->lastRunTime = move(o.lastRunTime); + this->stdoutCaptured = move(o.stdoutCaptured); + this->clogCaptured = move(o.clogCaptured); + this->stderrCaptured = move(o.stderrCaptured); + + if (this->stdoutCaptured) { + captureStdout(); + } + if (this->clogCaptured) { + captureClog(); + } + if (this->stderrCaptured) { + captureStdErr(); + } + this->testName = move(o.testName); this->test = move(o.test); } @@ -165,6 +197,20 @@ namespace TestCPP { this->pass = rhs.pass; this->lastRunTime = rhs.lastRunTime; + this->stdoutCaptured = rhs.stdoutCaptured; + this->clogCaptured = rhs.clogCaptured; + this->stderrCaptured = rhs.stderrCaptured; + + if (this->stdoutCaptured) { + captureStdout(); + } + if (this->clogCaptured) { + captureClog(); + } + if (this->stderrCaptured) { + captureStdErr(); + } + this->testName = rhs.testName; this->test = rhs.test; @@ -178,6 +224,20 @@ namespace TestCPP { this->pass = move(rhs.pass); this->lastRunTime = move(rhs.lastRunTime); + this->stdoutCaptured = move(rhs.stdoutCaptured); + this->clogCaptured = move(rhs.clogCaptured); + this->stderrCaptured = move(rhs.stderrCaptured); + + if (this->stdoutCaptured) { + captureStdout(); + } + if (this->clogCaptured) { + captureClog(); + } + if (this->stderrCaptured) { + captureStdErr(); + } + this->testName = move(rhs.testName); this->test = move(rhs.test); diff --git a/src/TestCPPTestSuite.cpp b/src/TestCPPTestSuite.cpp index ca68aa2..89736a7 100644 --- a/src/TestCPPTestSuite.cpp +++ b/src/TestCPPTestSuite.cpp @@ -55,15 +55,15 @@ using TCPPStr = TestCPP::TestCPPCommon::Strings; namespace TestCPP { void TestSuite::enableTestPassedMessage () { - this->testPassedMessage = true; - for (TestCase test : this->tests) { - test.setNotifyPassed(true); + this->testSuitePassedMessage = true; + for (unsigned i = 0; i < this->tests.size(); i += 1) { + this->tests[i].setNotifyPassed(true); } } void TestSuite::disableTestPassedMessage () { - this->testPassedMessage = false; - for (TestCase test : this->tests) { - test.setNotifyPassed(false); + this->testSuitePassedMessage = false; + for (unsigned i = 0; i < this->tests.size(); i += 1) { + this->tests[i].setNotifyPassed(false); } } @@ -122,7 +122,7 @@ namespace TestCPP { clog << endl; - if (this->testPassedMessage && + if (this->testSuitePassedMessage && this->lastRunFailCount == 0) { clog << TCPPStr::ALL_ << TCPPStr::APOS << this->suiteName << TCPPStr::APOS << TCPPStr::_SUITE_TESTS_PASSED @@ -143,8 +143,30 @@ namespace TestCPP { << endl; } + /** + * @brief Add a test to this test suite. + * + * The test should be a TestCase object. + */ template<> void TestSuite::addTest (TestCase&& test) { this->tests.emplace_back(test); } + + /** + * @brief Add a test to this test suite. + * + * The test should be defined as a tuple with 2 elements to use + * this. The first element is the test name, and the second + * element is the test function that defines the test. + */ + template<> + void TestSuite::addTest (tuple>&& test) { + this->tests.emplace_back( + std::get<0>(test), + std::get<1>(test), + this->testSuitePassedMessage + ); + } } From ed52762402de9694a484014efb5aedb2b5830216 Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Sat, 22 Jun 2024 09:19:55 -0700 Subject: [PATCH 23/59] Expand TestSuite test suite The following is what was previously tested in TestSuite: - Bare construction, no tests, only suite name The following is now tested, in addition to what was previously tested: - All possible construction parameters > Suite construction with TestCase objects > Suite construction with tuples > Suite construction with various mixes of TestCases and tuples - TestSuite::enableTestPassedMessage with various mixes of numbers of tests. - TestSuite::disableTestPassedMessage with various mixes of numbers of tests. --- test/include/TestSuite/TestSuiteSuite.h | 60 ++- test/include/TestSuite/TestSuiteTests.h | 11 +- test/src/TestSuite/TestSuiteTests.cpp | 525 +++++++++++++++++++++++- 3 files changed, 590 insertions(+), 6 deletions(-) diff --git a/test/include/TestSuite/TestSuiteSuite.h b/test/include/TestSuite/TestSuiteSuite.h index 4aa4194..68cef2c 100644 --- a/test/include/TestSuite/TestSuiteSuite.h +++ b/test/include/TestSuite/TestSuiteSuite.h @@ -10,8 +10,64 @@ namespace TestCPP { "TestCPP TestSuite Tests", make_tuple( - "Suite construction Test", - function(TestSuiteTests::TestConstructSuite) + "Suite construction Test - no tests", + function( + TestSuiteTests::TestConstructSuiteBare + ) + ), + make_tuple( + "Suite construction Test - TestCases", + function( + TestSuiteTests::TestConstructSuiteTestCases + ) + ), + make_tuple( + "Suite construction Test - tuples", + function( + TestSuiteTests::TestConstructSuiteTuples + ) + ), + make_tuple( + "Suite construction Test - mixed", + function( + TestSuiteTests::TestConstructSuiteMixed + ) + ), + make_tuple( + "Suite enable test passed message - no tests", + function( + TestSuiteTests::TestEnableTestPassedMessageNoTests + ) + ), + make_tuple( + "Suite enable test passed message - one test", + function( + TestSuiteTests::TestEnableTestPassedMessageOneTest + ) + ), + make_tuple( + "Suite enable test passed message - many tests", + function( + TestSuiteTests::TestEnableTestPassedMessageManyTests + ) + ), + make_tuple( + "Suite disable test passed message - no tests", + function( + TestSuiteTests::TestDisableTestPassedMessageNoTests + ) + ), + make_tuple( + "Suite disable test passed message - one test", + function( + TestSuiteTests::TestDisableTestPassedMessageOneTest + ) + ), + make_tuple( + "Suite disable test passed message - many tests", + function( + TestSuiteTests::TestDisableTestPassedMessageManyTests + ) ) ); } diff --git a/test/include/TestSuite/TestSuiteTests.h b/test/include/TestSuite/TestSuiteTests.h index 6fa855b..878c6a6 100644 --- a/test/include/TestSuite/TestSuiteTests.h +++ b/test/include/TestSuite/TestSuiteTests.h @@ -4,7 +4,16 @@ namespace TestCPP { namespace Testing { namespace TestSuiteTests { - void TestConstructSuite (); + void TestConstructSuiteBare (); + void TestConstructSuiteTestCases (); + void TestConstructSuiteTuples (); + void TestConstructSuiteMixed (); + void TestEnableTestPassedMessageNoTests (); + void TestEnableTestPassedMessageOneTest (); + void TestEnableTestPassedMessageManyTests (); + void TestDisableTestPassedMessageNoTests (); + void TestDisableTestPassedMessageOneTest (); + void TestDisableTestPassedMessageManyTests (); } } } diff --git a/test/src/TestSuite/TestSuiteTests.cpp b/test/src/TestSuite/TestSuiteTests.cpp index e4f070f..19dc164 100644 --- a/test/src/TestSuite/TestSuiteTests.cpp +++ b/test/src/TestSuite/TestSuiteTests.cpp @@ -4,11 +4,530 @@ namespace TestCPP { namespace Testing { namespace TestSuiteTests { - void TestConstructSuite () { - auto test = unique_ptr(new TestSuite( - "Suite construction" + void TestConstructSuiteBare () { + auto testSuite = unique_ptr(new TestSuite( + "Suite construction - bare" )); } + void TestConstructSuiteTestCases () { + TestCase test1("dummy 1", [](){}), + test2("dummy 2", [](){}); + + auto testSuite = unique_ptr(new TestSuite( + "Suite construction - TestCases", + test1 + )); + testSuite = unique_ptr(new TestSuite( + "Suite construction - TestCases", + test1, test2 + )); + } + void TestConstructSuiteTuples () { + auto testSuite = unique_ptr(new TestSuite( + "Suite construction - tuples", + make_tuple("dummy 1", function([](){})) + )); + testSuite = unique_ptr(new TestSuite( + "Suite construction - tuples", + make_tuple("dummy 1", function([](){})), + make_tuple("dummy 2", function([](){})) + )); + } + void TestConstructSuiteMixed () { + TestCase test1("dummy 1", [](){}), + test2("dummy 2", [](){}); + auto testSuite = unique_ptr(new TestSuite( + "Suite construction - mixed", + test1, + make_tuple("dummy 1", function([](){})) + )); + testSuite = unique_ptr(new TestSuite( + "Suite construction - mixed", + test1, test2, + make_tuple("dummy 1", function([](){})) + )); + testSuite = unique_ptr(new TestSuite( + "Suite construction - mixed", + test1, + make_tuple("dummy 1", function([](){})), + make_tuple("dummy 2", function([](){})) + )); + testSuite = unique_ptr(new TestSuite( + "Suite construction - mixed", + test1, test2, + make_tuple("dummy 1", function([](){})), + make_tuple("dummy 2", function([](){})) + )); + testSuite = unique_ptr(new TestSuite( + "Suite construction - mixed", + test1, + make_tuple("dummy 1", function([](){})), + make_tuple("dummy 2", function([](){})), + test2 + )); + testSuite = unique_ptr(new TestSuite( + "Suite construction - mixed", + make_tuple("dummy 1", function([](){})), + test1, test2, + make_tuple("dummy 2", function([](){})) + )); + testSuite = unique_ptr(new TestSuite( + "Suite construction - mixed", + test1, + make_tuple("dummy 1", function([](){})), + test2, + make_tuple("dummy 2", function([](){})) + )); + testSuite = unique_ptr(new TestSuite( + "Suite construction - mixed", + make_tuple("dummy 1", function([](){})), + test2, + make_tuple("dummy 2", function([](){})), + test1 + )); + } + + void TestEnableTestPassedMessageNoTests() { + auto testSuite = unique_ptr(new TestSuite( + "SUBSUITE - Test Passed Message Enabled - no tests" + )); + testSuite->enableTestPassedMessage(); + testSuite->run(); + } + void TestEnableTestPassedMessageOneTest() { + const char * suiteName = + "SUBSUITE - Test Passed Message Enabled - one test"; + const char * testName = + "SUBTEST - enable test passed message dummy 1"; + + TestCase test( + testName, + [](){}, + false, + false, + true, + false + ); + + auto testSuite = unique_ptr(new TestSuite( + suiteName, test + )); + + testSuite->enableTestPassedMessage(); + testSuite->run(); + + stringstream tsLog; + tsLog << "All '"; + tsLog << suiteName; + tsLog << "' suite tests passed!"; + + stringstream tcLog; + tcLog << "Test "; + tcLog << testName; + tcLog << " passed! ("; + + string secondsParen = "s)"; + + Assertions::assertTrue( + test.checkLog(tcLog.str()), + "Should have notified on test passage! 1" + ); + Assertions::assertTrue( + test.checkLog(secondsParen), + "Should have notified on test passage! 2" + ); + Assertions::assertTrue( + test.checkLog(tsLog.str()), + "Should have notified on suite passage! 1" + ); + + test.clearLogCapture(); + + test = TestCase( + testName, + [](){}, + true, + false, + true, + false + ); + + testSuite = unique_ptr(new TestSuite( + suiteName, test + )); + + testSuite->enableTestPassedMessage(); + testSuite->run(); + + Assertions::assertTrue( + test.checkLog(tcLog.str()), + "Should have notified on test passage! 3" + ); + Assertions::assertTrue( + test.checkLog(secondsParen), + "Should have notified on test passage! 4" + ); + Assertions::assertTrue( + test.checkLog(tsLog.str()), + "Should have notified on suite passage! 2" + ); + } + void TestEnableTestPassedMessageManyTests() { + const char * suiteName = + "SUBSUITE - Test Passed Message Enabled - many tests"; + const char * test1Name = + "SUBTEST - enable test passed message dummy 1"; + const char * test2Name = + "SUBTEST - enable test passed message dummy 2"; + const char * test3Name = + "SUBTEST - enable test passed message dummy 3"; + + TestCase test1( + test1Name, + [](){}, + false, + false, + true, + false + ); + TestCase test2( + test2Name, + [](){}, + false, + false, + true, + false + ); + TestCase test3( + test3Name, + [](){}, + false, + false, + true, + false + ); + + auto testSuite = unique_ptr(new TestSuite( + suiteName, test1, test2, test3 + )); + testSuite->enableTestPassedMessage(); + testSuite->run(); + + stringstream tsLog; + tsLog << "All '"; + tsLog << suiteName; + tsLog << "' suite tests passed!"; + + stringstream tc1Log; + tc1Log << "Test "; + tc1Log << test1Name; + tc1Log << " passed! ("; + stringstream tc2Log; + tc2Log << "Test "; + tc2Log << test2Name; + tc2Log << " passed! ("; + stringstream tc3Log; + tc3Log << "Test "; + tc3Log << test3Name; + tc3Log << " passed! ("; + + string secondsParen = "s)"; + + Assertions::assertTrue( + test1.checkLog(tc1Log.str()), + "Should have notified on test passage! 1" + ); + Assertions::assertTrue( + test1.checkLog(tc2Log.str()), + "Should have notified on test passage! 2" + ); + Assertions::assertTrue( + test1.checkLog(tc3Log.str()), + "Should have notified on test passage! 3" + ); + Assertions::assertTrue( + test1.checkLog(secondsParen), + "Should have notified on test passage! 4" + ); + Assertions::assertTrue( + test1.checkLog(tsLog.str()), + "Should have notified on suite passage! 1" + ); + + test1.clearLogCapture(); + + test1 = TestCase( + test1Name, + [](){}, + true, + false, + true, + false + ); + test2 = TestCase( + test2Name, + [](){}, + true, + false, + true, + false + ); + test3 = TestCase( + test3Name, + [](){}, + true, + false, + true, + false + ); + + testSuite = unique_ptr(new TestSuite( + suiteName, test1, test2, test3 + )); + + testSuite->enableTestPassedMessage(); + testSuite->run(); + + Assertions::assertTrue( + test1.checkLog(tc1Log.str()), + "Should have notified on test passage! 5" + ); + Assertions::assertTrue( + test1.checkLog(tc2Log.str()), + "Should have notified on test passage! 6" + ); + Assertions::assertTrue( + test1.checkLog(tc3Log.str()), + "Should have notified on test passage! 7" + ); + Assertions::assertTrue( + test1.checkLog(secondsParen), + "Should have notified on test passage! 8" + ); + Assertions::assertTrue( + test1.checkLog(tsLog.str()), + "Should have notified on suite passage! 2" + ); + } + + void TestDisableTestPassedMessageNoTests() { + auto testSuite = unique_ptr(new TestSuite( + "Test Passed Message Disabled - no tests" + )); + testSuite->disableTestPassedMessage(); + testSuite->run(); + } + void TestDisableTestPassedMessageOneTest() { + const char * suiteName = + "SUBSUITE - Test Passed Message Disabled - one test"; + const char * testName = + "SUBTEST - disable test passed message dummy 1"; + + TestCase test( + testName, + [](){}, + false, + false, + true, + false + ); + + auto testSuite = unique_ptr(new TestSuite( + suiteName, test + )); + + testSuite->disableTestPassedMessage(); + testSuite->run(); + + stringstream tsLog; + tsLog << "All '"; + tsLog << suiteName; + tsLog << "' suite tests passed!"; + + stringstream tcLog; + tcLog << "Test "; + tcLog << testName; + tcLog << " passed! ("; + + string secondsParen = "s)"; + + Assertions::assertFalse( + test.checkLog(tcLog.str()), + "Should not have notified on test passage! 1" + ); + Assertions::assertFalse( + test.checkLog(secondsParen), + "Should not have notified on test passage! 2" + ); + Assertions::assertFalse( + test.checkLog(tsLog.str()), + "Should not have notified on suite passage! 1" + ); + + test = TestCase( + testName, + [](){}, + true, + false, + true, + false + ); + + testSuite = unique_ptr(new TestSuite( + suiteName, test + )); + + testSuite->disableTestPassedMessage(); + testSuite->run(); + + Assertions::assertFalse( + test.checkLog(tcLog.str()), + "Should not have notified on test passage! 3" + ); + Assertions::assertFalse( + test.checkLog(secondsParen), + "Should not have notified on test passage! 4" + ); + Assertions::assertFalse( + test.checkLog(tsLog.str()), + "Should not have notified on suite passage! 2" + ); + } + void TestDisableTestPassedMessageManyTests() { + const char * suiteName = + "SUBSUITE - Test Passed Message Disabled - many tests"; + const char * test1Name = + "SUBTEST - disable test passed message dummy 1"; + const char * test2Name = + "SUBTEST - disable test passed message dummy 2"; + const char * test3Name = + "SUBTEST - disable test passed message dummy 3"; + + TestCase test1( + test1Name, + [](){}, + false, + false, + true, + false + ); + TestCase test2( + test2Name, + [](){}, + false, + false, + true, + false + ); + TestCase test3( + test3Name, + [](){}, + false, + false, + true, + false + ); + + auto testSuite = unique_ptr(new TestSuite( + suiteName, test1, test2, test3 + )); + testSuite->disableTestPassedMessage(); + testSuite->run(); + + stringstream tsLog; + tsLog << "All '"; + tsLog << suiteName; + tsLog << "' suite tests passed!"; + + stringstream tc1Log; + tc1Log << "Test "; + tc1Log << test1Name; + tc1Log << " passed! ("; + stringstream tc2Log; + tc2Log << "Test "; + tc2Log << test2Name; + tc2Log << " passed! ("; + stringstream tc3Log; + tc3Log << "Test "; + tc3Log << test3Name; + tc3Log << " passed! ("; + + string secondsParen = "s)"; + + Assertions::assertFalse( + test1.checkLog(tc1Log.str()), + "Should not have notified on test passage! 1" + ); + Assertions::assertFalse( + test1.checkLog(tc2Log.str()), + "Should not have notified on test passage! 2" + ); + Assertions::assertFalse( + test1.checkLog(tc3Log.str()), + "Should not have notified on test passage! 3" + ); + Assertions::assertFalse( + test1.checkLog(secondsParen), + "Should not have notified on test passage! 4" + ); + Assertions::assertFalse( + test1.checkLog(tsLog.str()), + "Should not have notified on suite passage! 1" + ); + + test1 = TestCase( + test1Name, + [](){}, + true, + false, + true, + false + ); + test2 = TestCase( + test2Name, + [](){}, + true, + false, + true, + false + ); + test3 = TestCase( + test3Name, + [](){}, + true, + false, + true, + false + ); + + testSuite = unique_ptr(new TestSuite( + suiteName, test1, test2, test3 + )); + + testSuite->disableTestPassedMessage(); + testSuite->run(); + + Assertions::assertFalse( + test1.checkLog(tc1Log.str()), + "Should not have notified on test passage! 5" + ); + Assertions::assertFalse( + test1.checkLog(tc2Log.str()), + "Should not have notified on test passage! 6" + ); + Assertions::assertFalse( + test1.checkLog(tc3Log.str()), + "Should not have notified on test passage! 7" + ); + Assertions::assertFalse( + test1.checkLog(secondsParen), + "Should not have notified on test passage! 8" + ); + Assertions::assertFalse( + test1.checkLog(tsLog.str()), + "Should not have notified on suite passage! 2" + ); + } } } } From a7cf79cadaea6c2587ef23a913cc3082baf5ac72 Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Sun, 23 Jun 2024 11:40:22 -0700 Subject: [PATCH 24/59] Remove excess whitespace, add/fix/flesh-out docs, fix private API. Excess whitespace in doc comments has been removed. Docs have been expanded/fixed. Removed unnecessary parameter from internal private API and adjust implementation to fix unnecessary reliance on the removed parameter. --- include/internal/TestCPPTestCase.h | 85 ++++++++++++++++++++++++++---- src/TestCPPTestCase.cpp | 11 ++-- 2 files changed, 79 insertions(+), 17 deletions(-) diff --git a/include/internal/TestCPPTestCase.h b/include/internal/TestCPPTestCase.h index 721062a..41ff892 100644 --- a/include/internal/TestCPPTestCase.h +++ b/include/internal/TestCPPTestCase.h @@ -69,7 +69,7 @@ namespace TestCPP { * @date 03/05/24 * @file TestCPP.h * @brief Provides an interface for implementing tests. - * + * * TestCase is one of three core types that define the TestCPP API. * TestCase provides faculties for defining and controlling tests * and the stdout/stderr/clog environment. @@ -94,6 +94,22 @@ namespace TestCPP { }; /** + * @brief Construct a test case with possibility to use all + * options. + * + * @param testName The name of the test as a TestObjName. + * @param test The implementation or pointer to the test. + * @param testPassedMessage Whether to omit a message indicating + * test passage. + * @param captureOut Whether to capture stdout output for + * analysis after the test run. + * @param captureLog Whether to capture clog output for + * analysis after the test run. + * @param captureErr Whether to capture stderr output for + * analysis after the test run. + * @param opt Technique for comparing actual output with + * expected output after the test run. + * * Instantiate and define a test case. * All parameters are optional other than the test name and the * test function. @@ -122,24 +138,32 @@ namespace TestCPP { ); /** - * Construct a TestCase by copying it from another TestCase. + * @brief Construct a TestCase by copying it from another + * TestCase. + * @param o The test case from which to make a copy. */ TestCase (TestCase& o); /** - * Construct a TestCase by moving all data from another - * TestCase. + * @brief Construct a TestCase by moving all data from another + * TestCase. + * @param o Move everything from this TestCase into the new one. */ TestCase (TestCase&& o); /** * @brief Copy a TestCase into another TestCase. * @param rhs The test case to copy from. + * @return A reference to the new TestCase copy. */ TestCase& operator= (TestCase& rhs); /** * @brief Move a TestCase into another TestCase. + * @param rhs Move everything from this TestCase into the new + * one. + * @return A reference to the TestCase that everything from the + * old TestCase was moved into. */ TestCase& operator= (TestCase&& rhs); @@ -157,7 +181,7 @@ namespace TestCPP { /** * @brief Set the output comparison mode. * @param opt Accepts specified mode from the referenced enum. - * + * * If this is called with an option specified that is different * from what is set for this test case already, subsequent * calls to any of the output check functions will use the @@ -167,7 +191,7 @@ namespace TestCPP { /** * @brief Clears the captured output from stdout. - * + * * This can be used for checking sections of output based on * test configuration. */ @@ -175,7 +199,7 @@ namespace TestCPP { /** * @brief Clears the captured output from std::clog. - * + * * This can be used for checking sections of output based on * test configuration. */ @@ -183,7 +207,7 @@ namespace TestCPP { /** * @brief Clears the captured output from stderr. - * + * * This can be used for checking sections of output based on * test configuration. */ @@ -225,7 +249,8 @@ namespace TestCPP { /** * @brief Returns the duration of the last run in nanoseconds. - * @return The duration of the last run in nanoseconds. + * @return The duration of the last run of this TestCase in + * nanoseconds. */ long long getLastRuntime (); @@ -243,13 +268,44 @@ namespace TestCPP { TestCaseOutCompareOptions option = TestCaseOutCompareOptions::CONTAINS; + /** + * @brief If instructed, capture stdout while this test is + * active. + */ void captureStdout (); + /** + * @brief If instructed, capture clog while this test is + * active. + */ void captureClog (); + /** + * @brief If instructed, capture stderr while this test is + * active. + */ void captureStdErr (); + /** + * @brief If a test encounters an error while running, this + * function will be called to log the test error. + * @param failureMessage The error message from the test that + * should be logged. + */ void logTestFailure (string failureMessage); + /** + * @brief Internal test run controller. + */ void runTest (); - bool checkOutput (TestCaseOutCompareOptions opt, string source, - string against); + /** + * @brief Handles the internal logic for calls to checkStdout, + * checkLog, and checkStderr based on the selected + * comparison technique for this test. + * @param source The actual output + * @param against The expected output, or a portion of the + * expected output. + * @return True if the argument results in a successful check + * using the configured comparison mode, false + * otherwise. + */ + bool checkOutput (string source, string against); static atomic_int stdoutCaptureCasesConstructed; static atomic_int logCaptureCasesConstructed; @@ -265,6 +321,13 @@ namespace TestCPP { static unique_ptr clogOriginal; static unique_ptr stderrOriginal; + /** + * @brief Measure the duration of a function when run. + * @param func Measure the duration of this function when run. + * @param args A template pack of arguments to apply to the + * given function of which to measure the duration. + * @return The duration of the function run, in nanoseconds. + */ template static nanoseconds duration (F func, Args&&... args) { diff --git a/src/TestCPPTestCase.cpp b/src/TestCPPTestCase.cpp index a76f091..c0bbb96 100644 --- a/src/TestCPPTestCase.cpp +++ b/src/TestCPPTestCase.cpp @@ -392,24 +392,23 @@ namespace TestCPP { } bool TestCase::checkStdout (string against) { - return checkOutput(this->option, TestCase::stdoutBuffer->str(), + return checkOutput(TestCase::stdoutBuffer->str(), against); } bool TestCase::checkLog (string against) { - return checkOutput(this->option, TestCase::clogBuffer->str(), + return checkOutput(TestCase::clogBuffer->str(), against); } bool TestCase::checkStderr (string against) { - return checkOutput(this->option, TestCase::stderrBuffer->str(), + return checkOutput(TestCase::stderrBuffer->str(), against); } - bool TestCase::checkOutput (TestCase::TestCaseOutCompareOptions opt, - string source, string against) + bool TestCase::checkOutput (string source, string against) { - switch (opt) { + switch (this->option) { case EXACT: if (source == against) { return true; From c71d69d25ed6aa2fef237b4d7bfd330750693f08 Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Sun, 23 Jun 2024 11:45:07 -0700 Subject: [PATCH 25/59] Finish removing reliance on the parameter Whoopsies --- src/TestCPPTestCase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TestCPPTestCase.cpp b/src/TestCPPTestCase.cpp index c0bbb96..4e4a607 100644 --- a/src/TestCPPTestCase.cpp +++ b/src/TestCPPTestCase.cpp @@ -455,7 +455,7 @@ namespace TestCPP { default: stringstream re; - re << TCPPStr::UNK_CMP_OPT_ << opt; + re << TCPPStr::UNK_CMP_OPT_ << this->option; throw TestCPPException(re.str()); } } From cf18cf3a0e01611fcd44194c74c3e238a9d6a6ab Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Sun, 23 Jun 2024 12:12:09 -0700 Subject: [PATCH 26/59] Remove unused function I don't know why I put this in there in the first place. It has been unused ever since I can remember. I think I was just messing with templates back in 2014 and this seemed like a cool function to implement. --- include/internal/TestCPPTestSuite.h | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/include/internal/TestCPPTestSuite.h b/include/internal/TestCPPTestSuite.h index 4277174..e47717b 100644 --- a/include/internal/TestCPPTestSuite.h +++ b/include/internal/TestCPPTestSuite.h @@ -128,16 +128,6 @@ namespace TestCPP { addTests(tests...); } - /** - * @brief Get the TestCase object that is associated with the - * given test case construction arguments. - * @return The TestCase with the given construction arguments. - */ - template - static T getTestObject (ConstructionArgs ...args) { - return T(args...); - } - /** * @brief Sets the name of this test suite. */ From 782e4fda1201f9d59f98d53723cf4d65c4b81d96 Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Thu, 27 Jun 2024 16:11:29 -0700 Subject: [PATCH 27/59] Fix multiple frees on streams, make sure test failures aren't silenced Make sure stream capture does not affect logging of test failures. ----------------------------------------------------------------------- Created a subroutine for logging test failures where the output stream is injected instead of just using std::clog. This allows the TestCase::logTestFailure function to log to the real clog stream and the captured (if captured) clog stream to ensure any expected output is present for analysis. This ensures test failures are logged even if the stream being logged to is captured for analysis for the given test. This was an oversight on my part, and there are more than likely other instances where this will need to be corrected. Fix multiple frees on streams (stringstreams and streambufs) ----------------------------------------------------------------------- I've been working on this periodically since last month to figure out what is happening. It turns out, std::unique_ptr seems to add an exit handler to the program (this is a possibility, I haven't looked at the STL implementation code to confirm) that calls the deleter when it is a static object. The default deleter just calls delete on the pointed-to object without checking that and with no context around the object. The solution ended up being constructing each std::unique_ptr with a custom no-op deleter to allow the TestCase destructor to properly handle desctruction, since proper functionality of the TestCase code depends on the semaphore behavior defined in the construction and destruction of TestCases depending on the stream capture arguments, so it knows when to free the buffers: only when nothing is using them. The std::unique_ptr template arguments are adjusted accordingly, and the buffers are now freed at the proper time and place. The streambufs are also left alone with custom no-op deleters, as we have no business freeing streambufs that are not ours to delete (the underlying streams for std::cout, std::clog, and std::cerr). --- include/internal/TestCPPTestCase.h | 25 ++++-- src/TestCPPTestCase.cpp | 126 +++++++++++++++++++++-------- 2 files changed, 111 insertions(+), 40 deletions(-) diff --git a/include/internal/TestCPPTestCase.h b/include/internal/TestCPPTestCase.h index 41ff892..0d39113 100644 --- a/include/internal/TestCPPTestCase.h +++ b/include/internal/TestCPPTestCase.h @@ -51,6 +51,7 @@ using std::endl; using std::forward; using std::function; using std::move; +using std::ostream; using std::runtime_error; using std::string; using std::streambuf; @@ -283,6 +284,12 @@ namespace TestCPP { * active. */ void captureStdErr (); + /** + * @brief Write a test failure reason to the specified stream. + * @param out The stream to write the test failure reason to. + * @param reason The test failure reason to write. + */ + void logFailure (ostream& out, string& reason); /** * @brief If a test encounters an error while running, this * function will be called to log the test error. @@ -314,12 +321,18 @@ namespace TestCPP { static atomic_int logCaptureCasesDestroyed; static atomic_int stderrCaptureCasesDestroyed; - static unique_ptr stdoutBuffer; - static unique_ptr clogBuffer; - static unique_ptr stderrBuffer; - static unique_ptr stdoutOriginal; - static unique_ptr clogOriginal; - static unique_ptr stderrOriginal; + static unique_ptr + stdoutBuffer; + static unique_ptr + clogBuffer; + static unique_ptr + stderrBuffer; + static unique_ptr + stdoutOriginal; + static unique_ptr + clogOriginal; + static unique_ptr + stderrOriginal; /** * @brief Measure the duration of a function when run. diff --git a/src/TestCPPTestCase.cpp b/src/TestCPPTestCase.cpp index 4e4a607..16c4072 100644 --- a/src/TestCPPTestCase.cpp +++ b/src/TestCPPTestCase.cpp @@ -49,7 +49,6 @@ using std::fixed; using std::function; using std::invalid_argument; using std::move; -using std::ostream; using std::rethrow_exception; using std::runtime_error; using std::setprecision; @@ -68,12 +67,36 @@ namespace TestCPP { atomic_int TestCase::logCaptureCasesDestroyed; atomic_int TestCase::stderrCaptureCasesDestroyed; - unique_ptr TestCase::stdoutBuffer = nullptr; - unique_ptr TestCase::clogBuffer = nullptr; - unique_ptr TestCase::stderrBuffer = nullptr; - unique_ptr TestCase::stdoutOriginal = nullptr; - unique_ptr TestCase::clogOriginal = nullptr; - unique_ptr TestCase::stderrOriginal = nullptr; + unique_ptr + TestCase::stdoutBuffer = + unique_ptr( + nullptr, [](stringstream*){} + ); + unique_ptr + TestCase::clogBuffer = + unique_ptr( + nullptr, [](stringstream*){} + ); + unique_ptr + TestCase::stderrBuffer = + unique_ptr( + nullptr, [](stringstream*){} + ); + unique_ptr + TestCase::stdoutOriginal = + unique_ptr( + nullptr, [](streambuf*){} + ); + unique_ptr + TestCase::clogOriginal = + unique_ptr( + nullptr, [](streambuf*){} + ); + unique_ptr + TestCase::stderrOriginal = + unique_ptr( + nullptr, [](streambuf*){} + ); TestCase::TestCase (TestObjName&& name, function test, @@ -161,6 +184,7 @@ namespace TestCPP { TestCase::stdoutCaptureCasesConstructed - 1) { cout.rdbuf(TestCase::stdoutOriginal.release()); + delete TestCase::stdoutBuffer.get(); TestCase::stdoutBuffer = nullptr; } @@ -172,6 +196,7 @@ namespace TestCPP { TestCase::logCaptureCasesConstructed - 1) { clog.rdbuf(TestCase::clogOriginal.release()); + delete TestCase::clogBuffer.get(); TestCase::clogBuffer = nullptr; } @@ -183,6 +208,7 @@ namespace TestCPP { TestCase::stderrCaptureCasesConstructed - 1) { cerr.rdbuf(TestCase::stderrOriginal.release()); + delete TestCase::stderrBuffer.get(); TestCase::stderrBuffer = nullptr; } @@ -248,16 +274,42 @@ namespace TestCPP { return this->lastRunTime; } + void TestCase::logFailure(ostream& out, string& reason) { + out << fixed; + out << setprecision(TCPPNum::TIME_PRECISION); + out << TCPPStr::TEST_ << this->testName << TCPPStr::_FAIL_ + << TCPPStr::PARENL + << static_cast(this->lastRunTime)/ + TCPPNum::NANOS_IN_SEC + << TCPPStr::SEC << TCPPStr::PARENR + << endl; + out << TCPPStr::REASON_ << reason << endl; + } + void TestCase::logTestFailure (string reason) { - clog << fixed; - clog << setprecision(TCPPNum::TIME_PRECISION); - clog << TCPPStr::TEST_ << this->testName << TCPPStr::_FAIL_ - << TCPPStr::PARENL - << static_cast(this->lastRunTime)/ - TCPPNum::NANOS_IN_SEC - << TCPPStr::SEC << TCPPStr::PARENR - << endl; - clog << TCPPStr::REASON_ << reason << endl; + unique_ptr logStream = nullptr; + + if (this->clogOriginal != nullptr) { + logStream = unique_ptr( + new ostream(this->clogOriginal.get()) + ); + } + else { + logStream = unique_ptr(&clog); + } + + logFailure(*logStream, reason); + + if (this->clogOriginal != nullptr) { + logStream->flush(); + + // If someone is looking for something in the message, + // and it's captured, make sure it's there. + logFailure(clog, reason); + } + + logStream.release(); + logStream.reset(); } void TestCase::runTest () { @@ -310,12 +362,14 @@ namespace TestCPP { TestCase::stdoutCaptureCasesDestroyed) { TestCase::stdoutCaptureCasesConstructed += 1; - TestCase::stdoutBuffer = unique_ptr( - new stringstream() - ); - TestCase::stdoutOriginal = unique_ptr( - cout.rdbuf() - ); + TestCase::stdoutBuffer = + unique_ptr( + new stringstream(), [](stringstream *) {} + ); + TestCase::stdoutOriginal = + unique_ptr( + cout.rdbuf(), [](streambuf *) {} + ); cout.rdbuf(TestCase::stdoutBuffer->rdbuf()); } else { @@ -328,12 +382,14 @@ namespace TestCPP { TestCase::logCaptureCasesDestroyed) { TestCase::logCaptureCasesConstructed += 1; - TestCase::clogBuffer = unique_ptr( - new stringstream() - ); - TestCase::clogOriginal = unique_ptr( - clog.rdbuf() - ); + TestCase::clogBuffer = + unique_ptr( + new stringstream(), [](stringstream *) {} + ); + TestCase::clogOriginal = + unique_ptr( + cout.rdbuf(), [](streambuf *) {} + ); clog.rdbuf(TestCase::clogBuffer->rdbuf()); } else { @@ -346,12 +402,14 @@ namespace TestCPP { TestCase::stderrCaptureCasesDestroyed) { TestCase::stderrCaptureCasesConstructed += 1; - TestCase::stderrBuffer = unique_ptr( - new stringstream() - ); - TestCase::stderrOriginal = unique_ptr( - cerr.rdbuf() - ); + TestCase::stderrBuffer = + unique_ptr( + new stringstream(), [](stringstream *) {} + ); + TestCase::stderrOriginal = + unique_ptr( + cout.rdbuf(), [](streambuf *) {} + ); cerr.rdbuf(TestCase::stderrBuffer->rdbuf()); } else { From 424779fded191f9980c25ad6d1c9969bb28f0b49 Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Thu, 27 Jun 2024 16:17:58 -0700 Subject: [PATCH 28/59] Clean up how test failures in a suite are recorded; Fixed failing tests There is now only one place for incrementing, and the conditions are now logically split and actions clearer. Tests in TestSuiteTests are no longer failing. The output buffer was not being cleared and there was lingering buffer content from previous tests. The tests were checking that nothing was logged related to test passage, so the checks for lack of output were failing. All tests pass! :) --- src/TestCPPTestSuite.cpp | 10 +++++----- test/src/TestSuite/TestSuiteTests.cpp | 9 +++++++++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/TestCPPTestSuite.cpp b/src/TestCPPTestSuite.cpp index 89736a7..c5b04fa 100644 --- a/src/TestCPPTestSuite.cpp +++ b/src/TestCPPTestSuite.cpp @@ -106,12 +106,12 @@ namespace TestCPP { << endl; } - if (!testPassed && this->lastRunSucceeded) { - this->lastRunFailCount++; - this->lastRunSucceeded = false; - } - else if (!testPassed) { + if (!testPassed) { this->lastRunFailCount++; + + if (this->lastRunSucceeded) { + this->lastRunSucceeded = false; + } } else { this->lastRunSuccessCount++; diff --git a/test/src/TestSuite/TestSuiteTests.cpp b/test/src/TestSuite/TestSuiteTests.cpp index 19dc164..52189a1 100644 --- a/test/src/TestSuite/TestSuiteTests.cpp +++ b/test/src/TestSuite/TestSuiteTests.cpp @@ -336,6 +336,8 @@ namespace TestCPP { suiteName, test )); + test.clearLogCapture(); + testSuite->disableTestPassedMessage(); testSuite->run(); @@ -377,6 +379,8 @@ namespace TestCPP { suiteName, test )); + test.clearLogCapture(); + testSuite->disableTestPassedMessage(); testSuite->run(); @@ -431,6 +435,9 @@ namespace TestCPP { auto testSuite = unique_ptr(new TestSuite( suiteName, test1, test2, test3 )); + + test1.clearLogCapture(); + testSuite->disableTestPassedMessage(); testSuite->run(); @@ -504,6 +511,8 @@ namespace TestCPP { suiteName, test1, test2, test3 )); + test1.clearLogCapture(); + testSuite->disableTestPassedMessage(); testSuite->run(); From 817c33bab5dc66b021977a69024bda148c17ee68 Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Thu, 27 Jun 2024 16:39:38 -0700 Subject: [PATCH 29/59] Another windows-only segfault Try to figure out where this is happening since I have no windows box to test this on. --- test/src/TestCase/TestCaseTestChunks.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/src/TestCase/TestCaseTestChunks.cpp b/test/src/TestCase/TestCaseTestChunks.cpp index 661cd48..f6854f9 100644 --- a/test/src/TestCase/TestCaseTestChunks.cpp +++ b/test/src/TestCase/TestCaseTestChunks.cpp @@ -71,48 +71,56 @@ namespace TestCPP { } void varyingCaptureLog () { + debugLog("CaptureLog param ctor test chunk FFF"); auto test = unique_ptr(new TestCase( "ConstructCase Test - w/NF,COF,CLF", function([](){}), false, false, false )); + debugLog("CaptureLog param ctor test chunk FFT"); test = unique_ptr(new TestCase( "ConstructCase Test - w/NF,COF,CLT", function([](){}), false, false, true )); + debugLog("CaptureLog param ctor test chunk FTF"); test = unique_ptr(new TestCase( "ConstructCase Test - w/NF,COT,CLF", function([](){}), false, true, false )); + debugLog("CaptureLog param ctor test chunk FTT"); test = unique_ptr(new TestCase( "ConstructCase Test - w/NF,COT,CLT", function([](){}), false, true, true )); + debugLog("CaptureLog param ctor test chunk TFF"); test = unique_ptr(new TestCase( "ConstructCase Test - w/NT,COF,CLF", function([](){}), true, false, false )); + debugLog("CaptureLog param ctor test chunk TFT"); test = unique_ptr(new TestCase( "ConstructCase Test - w/NT,COF,CLT", function([](){}), true, false, true )); + debugLog("CaptureLog param ctor test chunk TTF"); test = unique_ptr(new TestCase( "ConstructCase Test - w/NT,COT,CLF", function([](){}), true, true, false )); + debugLog("CaptureLog param ctor test chunk TTT"); test = unique_ptr(new TestCase( "ConstructCase Test - w/NT,COT,CLT", function([](){}), From 3428c7e03712f30ced06d939dc30b6749e8b5e63 Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Thu, 27 Jun 2024 16:49:08 -0700 Subject: [PATCH 30/59] Windows segfault - deeper debug logging more debug logging --- src/TestCPPTestCase.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/TestCPPTestCase.cpp b/src/TestCPPTestCase.cpp index 16c4072..30205f1 100644 --- a/src/TestCPPTestCase.cpp +++ b/src/TestCPPTestCase.cpp @@ -105,26 +105,40 @@ namespace TestCPP { bool captureErr, TestCase::TestCaseOutCompareOptions opt) { + debugLog("CaptureLog windows segfault check - open"); this->notifyTestPassed = msg; + debugLog("CaptureLog windows segfault check - ntp bool"); this->test = test; + debugLog("CaptureLog windows segfault check - test fn"); this->testName = name; + debugLog("CaptureLog windows segfault check - test name"); if (captureOut) { + debugLog("CaptureLog windows segfault check - stdout cap"); captureStdout(); + debugLog("CaptureLog windows segfault check - stdout end"); } if (captureLog) { + debugLog("CaptureLog windows segfault check - clog cap"); captureClog(); + debugLog("CaptureLog windows segfault check - clog end"); } if (captureErr) { + debugLog("CaptureLog windows segfault check - stderr cap"); captureStdErr(); + debugLog("CaptureLog windows segfault check - stderr end"); } this->stdoutCaptured = captureOut; + debugLog("CaptureLog windows segfault check - stdout bool"); this->clogCaptured = captureLog; + debugLog("CaptureLog windows segfault check - clog bool"); this->stderrCaptured = captureErr; + debugLog("CaptureLog windows segfault check - stderr bool"); this->option = opt; + debugLog("CaptureLog windows segfault check - cmp opt"); } TestCase::TestCase (TestCase& o) { From a5e049f3c79b9c38d1c3b758cea4428142c74d00 Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Thu, 27 Jun 2024 17:02:56 -0700 Subject: [PATCH 31/59] Windows segfault debugging - remove some dbg logging, add deeper logging debug logging for windows segfault issue --- src/TestCPPTestCase.cpp | 21 +++++++++------------ test/src/TestCase/TestCaseTestChunks.cpp | 4 ---- 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/src/TestCPPTestCase.cpp b/src/TestCPPTestCase.cpp index 30205f1..96ed883 100644 --- a/src/TestCPPTestCase.cpp +++ b/src/TestCPPTestCase.cpp @@ -105,19 +105,13 @@ namespace TestCPP { bool captureErr, TestCase::TestCaseOutCompareOptions opt) { - debugLog("CaptureLog windows segfault check - open"); this->notifyTestPassed = msg; - debugLog("CaptureLog windows segfault check - ntp bool"); this->test = test; - debugLog("CaptureLog windows segfault check - test fn"); this->testName = name; - debugLog("CaptureLog windows segfault check - test name"); if (captureOut) { - debugLog("CaptureLog windows segfault check - stdout cap"); captureStdout(); - debugLog("CaptureLog windows segfault check - stdout end"); } if (captureLog) { debugLog("CaptureLog windows segfault check - clog cap"); @@ -125,20 +119,14 @@ namespace TestCPP { debugLog("CaptureLog windows segfault check - clog end"); } if (captureErr) { - debugLog("CaptureLog windows segfault check - stderr cap"); captureStdErr(); - debugLog("CaptureLog windows segfault check - stderr end"); } this->stdoutCaptured = captureOut; - debugLog("CaptureLog windows segfault check - stdout bool"); this->clogCaptured = captureLog; - debugLog("CaptureLog windows segfault check - clog bool"); this->stderrCaptured = captureErr; - debugLog("CaptureLog windows segfault check - stderr bool"); this->option = opt; - debugLog("CaptureLog windows segfault check - cmp opt"); } TestCase::TestCase (TestCase& o) { @@ -392,23 +380,32 @@ namespace TestCPP { } void TestCase::captureClog () { + debugLog("captureClog winseg check - open"); if (TestCase::logCaptureCasesConstructed == TestCase::logCaptureCasesDestroyed) { + debugLog("captureClog winseg check - clogConstruct"); TestCase::logCaptureCasesConstructed += 1; + debugLog("captureClog winseg check - atomic++"); TestCase::clogBuffer = unique_ptr( new stringstream(), [](stringstream *) {} ); + debugLog("captureClog winseg check - clogBuffer"); TestCase::clogOriginal = unique_ptr( cout.rdbuf(), [](streambuf *) {} ); + debugLog("captureClog winseg check - clogStream"); clog.rdbuf(TestCase::clogBuffer->rdbuf()); + debugLog("captureClog winseg check - clogSet"); } else { + debugLog("captureClog winseg check - clogNoConstruct"); TestCase::logCaptureCasesConstructed += 1; + debugLog("captureClog winseg check - atomic++"); } + debugLog("captureClog winseg check - close"); } void TestCase::captureStdErr () { diff --git a/test/src/TestCase/TestCaseTestChunks.cpp b/test/src/TestCase/TestCaseTestChunks.cpp index f6854f9..6fa4776 100644 --- a/test/src/TestCase/TestCaseTestChunks.cpp +++ b/test/src/TestCase/TestCaseTestChunks.cpp @@ -71,21 +71,17 @@ namespace TestCPP { } void varyingCaptureLog () { - debugLog("CaptureLog param ctor test chunk FFF"); auto test = unique_ptr(new TestCase( "ConstructCase Test - w/NF,COF,CLF", function([](){}), false, false, false )); - debugLog("CaptureLog param ctor test chunk FFT"); test = unique_ptr(new TestCase( "ConstructCase Test - w/NF,COF,CLT", function([](){}), false, false, true )); - - debugLog("CaptureLog param ctor test chunk FTF"); test = unique_ptr(new TestCase( "ConstructCase Test - w/NF,COT,CLF", function([](){}), From 2d1566303a801b455f148456ebf460dcf776d4f1 Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Thu, 27 Jun 2024 17:16:16 -0700 Subject: [PATCH 32/59] Fixed a bug where cout buffer was being used instead of clog and cerr --- src/TestCPPTestCase.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/TestCPPTestCase.cpp b/src/TestCPPTestCase.cpp index 96ed883..7b5588d 100644 --- a/src/TestCPPTestCase.cpp +++ b/src/TestCPPTestCase.cpp @@ -394,7 +394,7 @@ namespace TestCPP { debugLog("captureClog winseg check - clogBuffer"); TestCase::clogOriginal = unique_ptr( - cout.rdbuf(), [](streambuf *) {} + clog.rdbuf(), [](streambuf *) {} ); debugLog("captureClog winseg check - clogStream"); clog.rdbuf(TestCase::clogBuffer->rdbuf()); @@ -419,7 +419,7 @@ namespace TestCPP { ); TestCase::stderrOriginal = unique_ptr( - cout.rdbuf(), [](streambuf *) {} + cerr.rdbuf(), [](streambuf *) {} ); cerr.rdbuf(TestCase::stderrBuffer->rdbuf()); } From 9a33b0ff7ac2b5006123de419fe2ade118783f2a Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Thu, 27 Jun 2024 17:59:34 -0700 Subject: [PATCH 33/59] It looks like that bug fix fixed the windows segfault in the TC tests Removing the debug logs. Since the std::streambuf pointer returned by cout.rdbuf() result was already assigned to a std::unique_ptr, it must have been what was causing the segfault (really an Access Violation, this is Windows not *nix/BSD). The weird thing is that the same code was not causing the issue on any other platform with any other compiler. The only time the issue popped up was on Windows with the MSVC++ cl compiler, compiling with debug options, where there were no compile warnings or errors! Very strange, but the good news is it pointed out 2 really severe but subtle bugs of the same kind in 2 different places, where the wrong std::streambuf was being stored for output capturing, which would have caused an inability to revert the capture for tests that don't capture output after the capturing test(s) have finished running. All because of a copy-paste error 2 times over. Yeesh. --- src/TestCPPTestCase.cpp | 9 --------- test/src/TestCase/TestCaseTestChunks.cpp | 5 ----- 2 files changed, 14 deletions(-) diff --git a/src/TestCPPTestCase.cpp b/src/TestCPPTestCase.cpp index 7b5588d..475aae4 100644 --- a/src/TestCPPTestCase.cpp +++ b/src/TestCPPTestCase.cpp @@ -380,32 +380,23 @@ namespace TestCPP { } void TestCase::captureClog () { - debugLog("captureClog winseg check - open"); if (TestCase::logCaptureCasesConstructed == TestCase::logCaptureCasesDestroyed) { - debugLog("captureClog winseg check - clogConstruct"); TestCase::logCaptureCasesConstructed += 1; - debugLog("captureClog winseg check - atomic++"); TestCase::clogBuffer = unique_ptr( new stringstream(), [](stringstream *) {} ); - debugLog("captureClog winseg check - clogBuffer"); TestCase::clogOriginal = unique_ptr( clog.rdbuf(), [](streambuf *) {} ); - debugLog("captureClog winseg check - clogStream"); clog.rdbuf(TestCase::clogBuffer->rdbuf()); - debugLog("captureClog winseg check - clogSet"); } else { - debugLog("captureClog winseg check - clogNoConstruct"); TestCase::logCaptureCasesConstructed += 1; - debugLog("captureClog winseg check - atomic++"); } - debugLog("captureClog winseg check - close"); } void TestCase::captureStdErr () { diff --git a/test/src/TestCase/TestCaseTestChunks.cpp b/test/src/TestCase/TestCaseTestChunks.cpp index 6fa4776..a022227 100644 --- a/test/src/TestCase/TestCaseTestChunks.cpp +++ b/test/src/TestCase/TestCaseTestChunks.cpp @@ -88,35 +88,30 @@ namespace TestCPP { false, true, false )); - debugLog("CaptureLog param ctor test chunk FTT"); test = unique_ptr(new TestCase( "ConstructCase Test - w/NF,COT,CLT", function([](){}), false, true, true )); - debugLog("CaptureLog param ctor test chunk TFF"); test = unique_ptr(new TestCase( "ConstructCase Test - w/NT,COF,CLF", function([](){}), true, false, false )); - debugLog("CaptureLog param ctor test chunk TFT"); test = unique_ptr(new TestCase( "ConstructCase Test - w/NT,COF,CLT", function([](){}), true, false, true )); - debugLog("CaptureLog param ctor test chunk TTF"); test = unique_ptr(new TestCase( "ConstructCase Test - w/NT,COT,CLF", function([](){}), true, true, false )); - debugLog("CaptureLog param ctor test chunk TTT"); test = unique_ptr(new TestCase( "ConstructCase Test - w/NT,COT,CLT", function([](){}), From 78d198e72d997cea8896cfa32be04f06de39044b Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Thu, 27 Jun 2024 18:31:33 -0700 Subject: [PATCH 34/59] Fix Static Analysis build badge Was pointing to a previous file name where the link had been already corrected, but not the badge. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 72bd8dc..fcb2e5b 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ [![RPM_DEB-Packaging-NoStacktraces](https://github.com/eljonny/TestCPP/actions/workflows/cmake-linux-pack-nost.yml/badge.svg?event=push)](https://github.com/eljonny/TestCPP/actions/workflows/cmake-linux-pack-nost.yml) [![Coverage](https://github.com/eljonny/TestCPP/actions/workflows/cmake-build-cov-st.yml/badge.svg?event=push)](https://github.com/eljonny/TestCPP/actions/workflows/cmake-build-cov-st.yml) [![Security](https://github.com/eljonny/TestCPP/actions/workflows/codeql.yml/badge.svg?event=push)](https://github.com/eljonny/TestCPP/actions/workflows/codeql.yml) -[![StaticAnalysis](https://github.com/eljonny/TestCPP/actions/workflows/cmake-static-analysis-dbg.yml/badge.svg?event=push)](https://github.com/eljonny/TestCPP/actions/workflows/cmake-static-analysis.yml) +[![StaticAnalysis](https://github.com/eljonny/TestCPP/actions/workflows/cmake-static-analysis.yml/badge.svg?event=push)](https://github.com/eljonny/TestCPP/actions/workflows/cmake-static-analysis.yml) [![codecov](https://codecov.io/gh/eljonny/TestCPP/graph/badge.svg?token=WFG41QY4BB)](https://codecov.io/gh/eljonny/TestCPP) # Introduction From 13202bd517e456926ba2b1a832b38b78ca8ee21c Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Thu, 27 Jun 2024 19:03:34 -0700 Subject: [PATCH 35/59] Clarify that the lib cannot be installed with vcpkg or conan yet With a little extra line in the README under the respective sections. --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index fcb2e5b..4c2acd3 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ The library is most useful for educational projects or small For testing more complex projects I would recommend using [GoogleTest](https://github.com/google/googletest). -The code is <1k lines. +The code is ~2k lines. The Release builds are optimized for speed over size, so the build could probably be tweaked to get a smaller binary if desired. @@ -72,6 +72,8 @@ Then add it to your test executable target through ### vcpkg +*In process, not working yet* + As of 0.1.0-beta.1, you might soon be able to also include it in your `vcpkg` project by running the following in the root of your project (pending vcpkg PR approval that I have in right @@ -82,6 +84,8 @@ As of 0.1.0-beta.1, you might soon be able to also include it ### Conan +*In process, not working yet* + As of 0.1.1-beta.2, you might soon be able to also include it in your `conan` project (pending approval from the Conan community). From 4802c28b4ff001a2ab83020ee3cd472039a557ef Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Mon, 1 Jul 2024 19:47:57 -0700 Subject: [PATCH 36/59] This needed to be committed to main Does not seem to apply to the PR run of the workflow when the change is applied to the PR fix branch. --- .github/workflows/cmake-static-analysis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cmake-static-analysis.yml b/.github/workflows/cmake-static-analysis.yml index 8f6768b..5df1015 100644 --- a/.github/workflows/cmake-static-analysis.yml +++ b/.github/workflows/cmake-static-analysis.yml @@ -30,4 +30,4 @@ jobs: use_cmake: true cmake_args: -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -Wno-dev - cppcheck_args: --enable=all --suppress=missingIncludeSystem --suppress=unusedFunction --std=c++11 + cppcheck_args: --enable=all --suppress=missingIncludeSystem --suppress=unusedFunction --std=c++11 --inline-suppr From 246a6cef35a13efe073b3f074c9e69e225db87da Mon Sep 17 00:00:00 2001 From: Jonathan Hyry <3676933+eljonny@users.noreply.github.com> Date: Mon, 1 Jul 2024 20:03:58 -0700 Subject: [PATCH 37/59] Mark constructors as explicit to conform to the C++ standard (#15) * Mark constructors as explicit to conform to the C++ standard These constructors fall into the guideline of constructors that should be marked explicit. They are converting constructors that are not intended to be used for implicit conversions and copy-initialization. See https://en.cppreference.com/w/cpp/language/explicit From that site: Specifies that a constructor [or conversion function (since C++11)] [or deduction guide (since C++17)] is explicit, that is, it cannot be used for implicit conversions and copy-initialization. See https://en.cppreference.com/w/cpp/language/converting_constructor also. Enable inline CPPCheck suppressions in the GitHub static analysis workflow and the local CPPCheck command in the CodeLite project for suppressing one instance of noExplicitConstructor where it is intended to be used for implicit conversions and copy-initialization. Add inline suppression to TestCPPUtil.h for noExplicitConstructor. Add --std=c++11 parameter argument to local CPPCheck check in project. Removed unnecessary ignores from the CPPCheck command arguments where it just needs a clean prior to running the cppcheck custom target because the build system it generated probably includes more than what should be analyzed by CPPCheck. * Moved this change to main --- TestFramework.project | 2 +- include/internal/TestCPPExceptions.h | 8 ++++---- include/internal/TestCPPUtil.h | 5 +++++ 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/TestFramework.project b/TestFramework.project index bab697a..879283e 100644 --- a/TestFramework.project +++ b/TestFramework.project @@ -591,7 +591,7 @@ mkdir -p coverage && cd coverage find .. -name '*.gcda' | xargs gcov -abcfmu find . -type f -not -name 'Test*.gcov' | xargs rm cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -Wno-dev -cppcheck --project=compile_commands.json -itest -idemo --enable=all --suppress=missingIncludeSystem --suppress=unusedFunction +cppcheck --project=compile_commands.json --enable=all --suppress=missingIncludeSystem --suppress=unusedFunction --std=c++11 --inline-suppr cpack --config CPackConfig.cmake cpack --config CPackSourceConfig.cmake cpack -G DEB diff --git a/include/internal/TestCPPExceptions.h b/include/internal/TestCPPExceptions.h index ec4bb64..4337f25 100644 --- a/include/internal/TestCPPExceptions.h +++ b/include/internal/TestCPPExceptions.h @@ -60,13 +60,13 @@ namespace TestCPP { * Construct an exception of this type with a string literal for * its failure message. */ - TestCPPException (const char * msg); + explicit TestCPPException (const char * msg); /** * Construct an exception of this type with a string object for * its failure message. */ - TestCPPException (string&& msg); + explicit TestCPPException (string&& msg); }; /** @@ -89,13 +89,13 @@ namespace TestCPP { * Construct an exception of this type with a string literal for * its failure message. */ - TestFailedException (const char * msg); + explicit TestFailedException (const char * msg); /** * Construct an exception of this type with a string literal for * its failure message. */ - TestFailedException (string&& msg); + explicit TestFailedException (string&& msg); }; } diff --git a/include/internal/TestCPPUtil.h b/include/internal/TestCPPUtil.h index 045def4..1c97f34 100644 --- a/include/internal/TestCPPUtil.h +++ b/include/internal/TestCPPUtil.h @@ -65,6 +65,11 @@ namespace TestCPP { * @return The TestObjName, where it is verified that the name * used to construct it was not null. */ + // + // This is intended to be used for implicit conversions and copy + // initialization. + // + // cppcheck-suppress noExplicitConstructor TestObjName (const char* name); /** From 1cc7a804f4531fd65be94ed4e4a9c07b7996d262 Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Sat, 3 Aug 2024 13:07:58 -0700 Subject: [PATCH 38/59] Ignore .vs directory, should not be in version control --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index a6880ae..abf526b 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ build-debug build-release _packages test_package/build +CMakeUserPresets.json +/.vs From 0505733ff348389cfb24701a4d1cddbef88f1ac6 Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Sun, 11 Aug 2024 20:32:42 -0700 Subject: [PATCH 39/59] Ignore new build output structure. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index abf526b..0cc0e73 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ _packages test_package/build CMakeUserPresets.json /.vs +out/ From c0e22114d0dd359b85605d4c21d322e6a46c42f8 Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Mon, 12 Aug 2024 11:13:25 -0700 Subject: [PATCH 40/59] Sometimes it appears CMAKE_CONFIGURATION_TYPES is used instead of CMAKE_BUILD_TYPE. This takes that into account. --- cmake/BuildTypeHandling.cmake | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cmake/BuildTypeHandling.cmake b/cmake/BuildTypeHandling.cmake index 67543b7..4e20229 100644 --- a/cmake/BuildTypeHandling.cmake +++ b/cmake/BuildTypeHandling.cmake @@ -115,6 +115,10 @@ list ( -ftest-coverage # Enable core code coverage compilation ) +if (NOT CMAKE_BUILD_TYPE) + set (CMAKE_BUILD_TYPE ${CMAKE_CONFIGURATION_TYPES}) +endif () + if (${CMAKE_BUILD_TYPE} STREQUAL "Release") message (STATUS "Release build compilation options enabled") From 81d44c89f745a5a571312088314f85db5b7c3b0c Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Sun, 22 Sep 2024 12:06:13 -0700 Subject: [PATCH 41/59] Work in the build. Break down build arguments into groups into their own CMake files. Same with linking arguments. Start building out CMakePresets. Remove CMakeSettings. --- CMakePresets.json | 14 ++ cmake/BuildTypeHandling.cmake | 302 +-------------------------- cmake/Linking.cmake | 143 +------------ cmake/VarChecks.cmake | 12 +- cmake/build/CompileDefs.cmake | 7 + cmake/build/DebugCompileDefs.cmake | 31 +++ cmake/build/GCCClangDebug.cmake | 65 ++++++ cmake/build/GCCClangRelease.cmake | 57 +++++ cmake/build/GCCCoverage.cmake | 39 ++++ cmake/build/MSVCDebug.cmake | 100 +++++++++ cmake/build/MSVCRelease.cmake | 102 +++++++++ cmake/link/Demo.cmake | 21 ++ cmake/link/TestCPPWithCoverage.cmake | 4 + cmake/link/Tests.cmake | 51 +++++ cmake/link/TestsWithCoverage.cmake | 60 ++++++ cmake/presets/building.json | 81 +++++++ cmake/presets/configuring.json | 282 +++++++++++++++++++++++++ cmake/presets/packaging.json | 43 ++++ cmake/presets/testing.json | 47 +++++ 19 files changed, 1024 insertions(+), 437 deletions(-) create mode 100644 CMakePresets.json create mode 100644 cmake/build/CompileDefs.cmake create mode 100644 cmake/build/DebugCompileDefs.cmake create mode 100644 cmake/build/GCCClangDebug.cmake create mode 100644 cmake/build/GCCClangRelease.cmake create mode 100644 cmake/build/GCCCoverage.cmake create mode 100644 cmake/build/MSVCDebug.cmake create mode 100644 cmake/build/MSVCRelease.cmake create mode 100644 cmake/link/Demo.cmake create mode 100644 cmake/link/TestCPPWithCoverage.cmake create mode 100644 cmake/link/Tests.cmake create mode 100644 cmake/link/TestsWithCoverage.cmake create mode 100644 cmake/presets/building.json create mode 100644 cmake/presets/configuring.json create mode 100644 cmake/presets/packaging.json create mode 100644 cmake/presets/testing.json diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 0000000..0ebdf77 --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,14 @@ +{ + "version": 6, + "cmakeMinimumRequired": { + "major": 3, + "minor": 25, + "patch": 0 + }, + "include": [ + "cmake/presets/configuring.json", + "cmake/presets/building.json", + "cmake/presets/packaging.json", + "cmake/presets/testing.json" + ] +} \ No newline at end of file diff --git a/cmake/BuildTypeHandling.cmake b/cmake/BuildTypeHandling.cmake index 4e20229..403a5da 100644 --- a/cmake/BuildTypeHandling.cmake +++ b/cmake/BuildTypeHandling.cmake @@ -1,119 +1,4 @@ -list ( - APPEND - MSVC_RELEASE_BUILD_OPTS - /Wall # Enable all warnings and treat them as errors - /WX # Treat linker warnings as errors also - /O2 # Do optimizations for the Release build - /wd4668 # There are undefined preprocessor macros in the Windows - # SDK in internal headers. This is a workaround until - # these issues are fixed by Microsoft. - /wd4710 # It's ok if functions are not inlined - /wd4711 # It's also ok if functions are inlined - /wd4820 # Struct/class data member padding is ok, we're concerned - # about speed, not space, and the natural alignment - # is generally fastest. Let the compiler add the padding. - /wd4100 # Unused parameters occur in the Release build in debugLog - /wd5045 # Warns about code that can cause the Spectre - # vulnerability to become exploitable, does not - # go away when /Qspectre is specified. Applied this - # warning suppression since /Qspectre is specified. - /Qspectre # Instructs the compiler to apply Spectre - # vulnerability mitigations. -) -list ( - APPEND - MSVC_DEBUG_BUILD_OPTS - /Wall /WX /Od - /wd4820 /wd4668 /wd5045 - /Qspectre -) - -if (${TESTCPP_STACKTRACE_ENABLED}) - list ( - APPEND - MSVC_RELEASE_BUILD_OPTS - /wd5039 # There's a function or two in the Windows SDK that are - # passed to extern 'C' APIs that are not marked as - # noexcept which causes this warning, which is treated - # as an error. There's nothing we can do about this so - # this is added as a workaround. - /wd4625 # In the Boost.StackTrace code, there are copy - # constructors that are implicitly deleted. Since this - # is in an external library, suppress the warning to - # work around this to ensure clean compilation. - /wd4626 # In the Boost.StackTrace code, there are copy - # assignment operators that are implicitly deleted. - # Since this is in an external library, suppress the - # warning to work around this to ensure clean - # compilation. - /wd5026 # In the Boost.StackTrace code, there are move - # constructors that are implicitly deleted. Since this - # is in an external library, suppress the warning to - # work around this to ensure clean compilation. - /wd5027 # In the Boost.StackTrace code, there are move - # assignment operators that are implicitly deleted. - # Since this is in an external library, suppress the - # warning to work around this to ensure clean - # compilation. - ) - list ( - APPEND - MSVC_DEBUG_BUILD_OPTS - /wd5039 /wd4625 /wd4626 /wd5026 /wd5027 - ) -endif () - -if (BUILD_TESTING) - list ( - APPEND - MSVC_RELEASE_BUILD_OPTS - /wd4514 # It's ok if the compiler removes unreferenced inline - # functions. - ) - list ( - APPEND - MSVC_DEBUG_BUILD_OPTS - /wd4514 - ) -endif () - -list ( - APPEND - GCC_CLANG_RELEASE_BUILD_OPTS - -O3 # Optimize the Release build - -Wall # Enable most warnings - -Wextra # Enable even more warnings - -Wpedantic # Enable most of the rest of the warnings - -Werror # Treat all warnings as errors - -Wno-unused-parameter # Unused parameters occur in the Release - # build in debugLog - -Wno-unused-lambda-capture # Avoid MSVC error C3493 - There is - # implementation divergence here and - # since we're not using >=C++14 there - # is no workaround other than to ignore - # this warning (the MSVC issue is an - # error). A workaround for >=C++14 is to - # use an explicit capture - if ever I - # change the library to use >=C++14 I - # can remove this and use an explicit - # capture. -) -list ( - APPEND - GCC_CLANG_DEBUG_BUILD_OPTS - -g # Enable all debugging information - -Og # Ensure the compiler doesn't use optimizations that would harm - # debuggability of the resulting code - -Wall -Wextra -Wpedantic -Werror -Wno-unused-lambda-capture -) -list ( - APPEND - COVERAGE_BUILD_OPTS - -g -Og -Wall -Wextra -Wpedantic -Werror - -fprofile-arcs # Enable profile points that help with code - # coverage - -ftest-coverage # Enable core code coverage compilation -) +list (APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/build") if (NOT CMAKE_BUILD_TYPE) set (CMAKE_BUILD_TYPE ${CMAKE_CONFIGURATION_TYPES}) @@ -123,196 +8,23 @@ if (${CMAKE_BUILD_TYPE} STREQUAL "Release") message (STATUS "Release build compilation options enabled") if (MSVC) - target_compile_options ( - ${PROJECT_NAME} - PUBLIC - ${MSVC_RELEASE_BUILD_OPTS} - ) - - if (${TESTCPP_DEMO_ENABLED}) - target_compile_options ( - ${PROJECT_NAME}_run - PUBLIC - ${MSVC_RELEASE_BUILD_OPTS} - ) - endif () - - if (BUILD_TESTING) - target_compile_options ( - ${PROJECT_NAME}_TestCase_test - PUBLIC - ${MSVC_RELEASE_BUILD_OPTS} - ) - - target_compile_options ( - ${PROJECT_NAME}_TestSuite_test - PUBLIC - ${MSVC_RELEASE_BUILD_OPTS} - ) - - target_compile_options ( - ${PROJECT_NAME}_Assertions_test - PUBLIC - ${MSVC_RELEASE_BUILD_OPTS} - ) - endif () + include (MSVCRelease) else () - target_compile_options ( - ${PROJECT_NAME} - PUBLIC - ${GCC_CLANG_RELEASE_BUILD_OPTS} - ) - - if (${TESTCPP_DEMO_ENABLED}) - target_compile_options ( - ${PROJECT_NAME}_run - PUBLIC - ${GCC_CLANG_RELEASE_BUILD_OPTS} - ) - endif () - - if (BUILD_TESTING) - target_compile_options ( - ${PROJECT_NAME}_TestCase_test - PUBLIC - ${GCC_CLANG_RELEASE_BUILD_OPTS} - ) - - target_compile_options ( - ${PROJECT_NAME}_TestSuite_test - PUBLIC - ${GCC_CLANG_RELEASE_BUILD_OPTS} - ) - - target_compile_options ( - ${PROJECT_NAME}_Assertions_test - PUBLIC - ${GCC_CLANG_RELEASE_BUILD_OPTS} - ) - endif () + include (GCCClangRelease) endif () else () message (STATUS "Debug build compilation options enabled") - target_compile_definitions ( - ${PROJECT_NAME} - PUBLIC - DEBUG_LOG - ) - - if (${TESTCPP_DEMO_ENABLED}) - target_compile_definitions ( - ${PROJECT_NAME}_run - PUBLIC - DEBUG_LOG - ) - endif () - - if (BUILD_TESTING) - target_compile_definitions ( - ${PROJECT_NAME}_TestCase_test - PUBLIC - DEBUG_LOG - ) - target_compile_definitions ( - ${PROJECT_NAME}_TestSuite_test - PUBLIC - DEBUG_LOG - ) - target_compile_definitions ( - ${PROJECT_NAME}_Assertions_test - PUBLIC - DEBUG_LOG - ) - endif () + include (DebugCompileDefs) if (MSVC) - target_compile_options ( - ${PROJECT_NAME} - PUBLIC - ${MSVC_DEBUG_BUILD_OPTS} - ) - - if (${TESTCPP_DEMO_ENABLED}) - target_compile_options ( - ${PROJECT_NAME}_run - PUBLIC - ${MSVC_DEBUG_BUILD_OPTS} - ) - endif () - - if (BUILD_TESTING) - target_compile_options ( - ${PROJECT_NAME}_TestCase_test - PUBLIC - ${MSVC_DEBUG_BUILD_OPTS} - ) - - target_compile_options ( - ${PROJECT_NAME}_TestSuite_test - PUBLIC - ${MSVC_DEBUG_BUILD_OPTS} - ) - - target_compile_options ( - ${PROJECT_NAME}_Assertions_test - PUBLIC - ${MSVC_DEBUG_BUILD_OPTS} - ) - endif () + include (MSVCDebug) else () - if (${TESTCPP_DEMO_ENABLED}) - target_compile_options ( - ${PROJECT_NAME}_run - PUBLIC - ${GCC_CLANG_DEBUG_BUILD_OPTS} - ) - endif () - - if (BUILD_TESTING AND ${TESTCPP_COVERAGE_ENABLED}) - message (STATUS "Coverage compilation options enabled") - - target_compile_options ( - ${PROJECT_NAME} - PUBLIC - ${COVERAGE_BUILD_OPTS} - ) - - target_compile_options ( - ${PROJECT_NAME}_TestCase_test - PUBLIC - ${COVERAGE_BUILD_OPTS} - ) - - target_compile_options ( - ${PROJECT_NAME}_TestSuite_test - PUBLIC - ${COVERAGE_BUILD_OPTS} - ) - - target_compile_options ( - ${PROJECT_NAME}_Assertions_test - PUBLIC - ${COVERAGE_BUILD_OPTS} - ) - - else () - target_compile_options ( - ${PROJECT_NAME} - PUBLIC - ${GCC_CLANG_DEBUG_BUILD_OPTS} - ) - endif () + include (GCCClangDebug) endif () endif () -if (${TESTCPP_STACKTRACE_ENABLED}) - target_compile_definitions ( - ${PROJECT_NAME} - PUBLIC - TESTCPP_STACKTRACE_ENABLED - ) -endif () +include (CompileDefs) diff --git a/cmake/Linking.cmake b/cmake/Linking.cmake index f585edf..34d743c 100644 --- a/cmake/Linking.cmake +++ b/cmake/Linking.cmake @@ -1,148 +1,17 @@ -if (${TESTCPP_DEMO_ENABLED}) - if (${TESTCPP_STACKTRACE_ENABLED} AND MSVC) - target_link_libraries ( - ${PROJECT_NAME}_run - ${PROJECT_NAME} - ole32 - dbgeng - ) - - elseif (${TESTCPP_STACKTRACE_ENABLED}) - target_link_libraries ( - ${PROJECT_NAME}_run - ${PROJECT_NAME} - dl - ) +list (APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/link") - else () - target_link_libraries ( - ${PROJECT_NAME}_run - ${PROJECT_NAME} - ) - endif () +if (${TESTCPP_DEMO_ENABLED}) + include (Demo) endif () if (BUILD_TESTING) if (${TESTCPP_COVERAGE_ENABLED}) message (STATUS "Linking in gcov") - target_link_libraries ( - ${PROJECT_NAME} - gcov - ) - - if (${TESTCPP_STACKTRACE_ENABLED} AND MSVC) - target_link_libraries ( - ${PROJECT_NAME}_TestCase_test - ${PROJECT_NAME} - gcov - ole32 - dbgeng - ) - target_link_libraries ( - ${PROJECT_NAME}_TestSuite_test - ${PROJECT_NAME} - gcov - ole32 - dbgeng - ) - target_link_libraries ( - ${PROJECT_NAME}_Assertions_test - ${PROJECT_NAME} - gcov - ole32 - dbgeng - ) - - elseif (${TESTCPP_STACKTRACE_ENABLED}) - target_link_libraries ( - ${PROJECT_NAME}_TestCase_test - ${PROJECT_NAME} - gcov - dl - ) - target_link_libraries ( - ${PROJECT_NAME}_TestSuite_test - ${PROJECT_NAME} - gcov - dl - ) - target_link_libraries ( - ${PROJECT_NAME}_Assertions_test - ${PROJECT_NAME} - gcov - dl - ) - - else () - target_link_libraries ( - ${PROJECT_NAME}_TestCase_test - ${PROJECT_NAME} - gcov - ) - target_link_libraries ( - ${PROJECT_NAME}_TestSuite_test - ${PROJECT_NAME} - gcov - ) - target_link_libraries ( - ${PROJECT_NAME}_Assertions_test - ${PROJECT_NAME} - gcov - ) - endif () + include (TestCPPWithCoverage) + include (TestsWithCoverage) else () - if (${TESTCPP_STACKTRACE_ENABLED} AND MSVC) - target_link_libraries ( - ${PROJECT_NAME}_TestCase_test - ${PROJECT_NAME} - ole32 - dbgeng - ) - target_link_libraries ( - ${PROJECT_NAME}_TestSuite_test - ${PROJECT_NAME} - ole32 - dbgeng - ) - target_link_libraries ( - ${PROJECT_NAME}_Assertions_test - ${PROJECT_NAME} - ole32 - dbgeng - ) - - elseif (${TESTCPP_STACKTRACE_ENABLED}) - target_link_libraries ( - ${PROJECT_NAME}_TestCase_test - ${PROJECT_NAME} - dl - ) - target_link_libraries ( - ${PROJECT_NAME}_TestSuite_test - ${PROJECT_NAME} - dl - ) - target_link_libraries ( - ${PROJECT_NAME}_Assertions_test - ${PROJECT_NAME} - dl - ) - - else () - target_link_libraries ( - ${PROJECT_NAME}_TestCase_test - ${PROJECT_NAME} - ) - target_link_libraries ( - ${PROJECT_NAME}_TestSuite_test - ${PROJECT_NAME} - ) - target_link_libraries ( - ${PROJECT_NAME}_Assertions_test - ${PROJECT_NAME} - ) - endif () + include (Tests) endif () endif () diff --git a/cmake/VarChecks.cmake b/cmake/VarChecks.cmake index 9d448db..c19c896 100644 --- a/cmake/VarChecks.cmake +++ b/cmake/VarChecks.cmake @@ -4,7 +4,7 @@ if (NOT DEFINED TESTCPP_COVERAGE_ENABLED) else () message (STATUS - "Defd TESTCPP_COVERAGE_ENABLED ${TESTCPP_COVERAGE_ENABLED}") + "Defd TESTCPP_COVERAGE_ENABLED ${TESTCPP_COVERAGE_ENABLED}") endif () if (NOT DEFINED TESTCPP_DEMO_ENABLED) @@ -12,7 +12,8 @@ if (NOT DEFINED TESTCPP_DEMO_ENABLED) set (TESTCPP_DEMO_ENABLED 0) else () - message (STATUS "Defd TESTCPP_DEMO_ENABLED ${TESTCPP_DEMO_ENABLED}") + message (STATUS + "Defd TESTCPP_DEMO_ENABLED ${TESTCPP_DEMO_ENABLED}") endif () if (NOT DEFINED TESTCPP_TEST_ENABLED) @@ -20,7 +21,8 @@ if (NOT DEFINED TESTCPP_TEST_ENABLED) set (TESTCPP_TEST_ENABLED 0) else () - message (STATUS "Defd TESTCPP_TEST_ENABLED ${TESTCPP_TEST_ENABLED}") + message (STATUS + "Defd TESTCPP_TEST_ENABLED ${TESTCPP_TEST_ENABLED}") endif () if (NOT DEFINED TESTCPP_ANALYSIS_ENABLED) @@ -29,7 +31,7 @@ if (NOT DEFINED TESTCPP_ANALYSIS_ENABLED) else () message (STATUS - "Defd TESTCPP_ANALYSIS_ENABLED ${TESTCPP_ANALYSIS_ENABLED}") + "Defd TESTCPP_ANALYSIS_ENABLED ${TESTCPP_ANALYSIS_ENABLED}") endif () if (NOT DEFINED TESTCPP_STACKTRACE_ENABLED) @@ -38,7 +40,7 @@ if (NOT DEFINED TESTCPP_STACKTRACE_ENABLED) else () message (STATUS - "Defd TESTCPP_STACKTRACE_ENABLED ${TESTCPP_STACKTRACE_ENABLED}") + "Defd TESTCPP_STACKTRACE_ENABLED ${TESTCPP_STACKTRACE_ENABLED}") endif () if (${TESTCPP_TEST_ENABLED}) diff --git a/cmake/build/CompileDefs.cmake b/cmake/build/CompileDefs.cmake new file mode 100644 index 0000000..acf4d94 --- /dev/null +++ b/cmake/build/CompileDefs.cmake @@ -0,0 +1,7 @@ +if (${TESTCPP_STACKTRACE_ENABLED}) + target_compile_definitions ( + ${PROJECT_NAME} + PUBLIC + TESTCPP_STACKTRACE_ENABLED + ) +endif () diff --git a/cmake/build/DebugCompileDefs.cmake b/cmake/build/DebugCompileDefs.cmake new file mode 100644 index 0000000..024799d --- /dev/null +++ b/cmake/build/DebugCompileDefs.cmake @@ -0,0 +1,31 @@ +target_compile_definitions ( + ${PROJECT_NAME} + PUBLIC + DEBUG_LOG +) + +if (${TESTCPP_DEMO_ENABLED}) + target_compile_definitions ( + ${PROJECT_NAME}_run + PUBLIC + DEBUG_LOG + ) +endif () + +if (BUILD_TESTING) + target_compile_definitions ( + ${PROJECT_NAME}_TestCase_test + PUBLIC + DEBUG_LOG + ) + target_compile_definitions ( + ${PROJECT_NAME}_TestSuite_test + PUBLIC + DEBUG_LOG + ) + target_compile_definitions ( + ${PROJECT_NAME}_Assertions_test + PUBLIC + DEBUG_LOG + ) +endif () diff --git a/cmake/build/GCCClangDebug.cmake b/cmake/build/GCCClangDebug.cmake new file mode 100644 index 0000000..a27dcda --- /dev/null +++ b/cmake/build/GCCClangDebug.cmake @@ -0,0 +1,65 @@ +list ( + APPEND + GCC_CLANG_DEBUG_BUILD_OPTS + -g # Enable all debugging information. + -Og # Ensure the compiler doesn't use + # optimizations that would harm + # debuggability of the resulting code. + -Wall # Enable most warnings. + -Wextra # Enable even more warnings. + -Wpedantic # Enable most of the rest of the + # warnings. + -Werror # Treat all warnings as errors. + -Wno-unused-lambda-capture # Avoid MSVC error C3493 - There is + # implementation divergence here and + # since we're not using >=C++14 there + # is no workaround other than to ignore + # this warning (the MSVC issue is an + # error). + # A workaround for >=C++14 is to use an + # explicit capture - if ever I change + # the library to use >=C++14 I can + # remove this and use an explicit + # capture. +) + +if (${TESTCPP_DEMO_ENABLED}) + target_compile_options ( + ${PROJECT_NAME}_run + PUBLIC + ${GCC_CLANG_DEBUG_BUILD_OPTS} + ) +endif () + +if (BUILD_TESTING AND ${TESTCPP_COVERAGE_ENABLED}) + message (STATUS "Coverage compilation options enabled") + + include (GCCCoverage) + +else () + target_compile_options ( + ${PROJECT_NAME} + PUBLIC + ${GCC_CLANG_DEBUG_BUILD_OPTS} + ) + + if (BUILD_TESTING) + target_compile_options ( + ${PROJECT_NAME}_TestCase_test + PUBLIC + ${GCC_CLANG_DEBUG_BUILD_OPTS} + ) + + target_compile_options ( + ${PROJECT_NAME}_TestSuite_test + PUBLIC + ${GCC_CLANG_DEBUG_BUILD_OPTS} + ) + + target_compile_options ( + ${PROJECT_NAME}_Assertions_test + PUBLIC + ${GCC_CLANG_DEBUG_BUILD_OPTS} + ) + endif () +endif () diff --git a/cmake/build/GCCClangRelease.cmake b/cmake/build/GCCClangRelease.cmake new file mode 100644 index 0000000..73e6c2b --- /dev/null +++ b/cmake/build/GCCClangRelease.cmake @@ -0,0 +1,57 @@ +list ( + APPEND + GCC_CLANG_RELEASE_BUILD_OPTS + -O3 # Optimize the Release build. + -Wall # Enable most warnings. + -Wextra # Enable even more warnings. + -Wpedantic # Enable most of the rest of the + # warnings. + -Werror # Treat all warnings as errors. + -Wno-unused-parameter # Unused parameters occur in the Release + # build in debugLog. + -Wno-unused-lambda-capture # Avoid MSVC error C3493 - There is + # implementation divergence here and + # since we're not using >=C++14 there + # is no workaround other than to ignore + # this warning (the MSVC issue is an + # error). + # A workaround for >=C++14 is to use an + # explicit capture - if ever I change + # the library to use >=C++14 I can + # remove this and use an explicit + # capture. +) + +target_compile_options ( + ${PROJECT_NAME} + PUBLIC + ${GCC_CLANG_RELEASE_BUILD_OPTS} +) + +if (${TESTCPP_DEMO_ENABLED}) + target_compile_options ( + ${PROJECT_NAME}_run + PUBLIC + ${GCC_CLANG_RELEASE_BUILD_OPTS} + ) +endif () + +if (BUILD_TESTING) + target_compile_options ( + ${PROJECT_NAME}_TestCase_test + PUBLIC + ${GCC_CLANG_RELEASE_BUILD_OPTS} + ) + + target_compile_options ( + ${PROJECT_NAME}_TestSuite_test + PUBLIC + ${GCC_CLANG_RELEASE_BUILD_OPTS} + ) + + target_compile_options ( + ${PROJECT_NAME}_Assertions_test + PUBLIC + ${GCC_CLANG_RELEASE_BUILD_OPTS} + ) +endif () diff --git a/cmake/build/GCCCoverage.cmake b/cmake/build/GCCCoverage.cmake new file mode 100644 index 0000000..a6b69ab --- /dev/null +++ b/cmake/build/GCCCoverage.cmake @@ -0,0 +1,39 @@ +list ( + APPEND + COVERAGE_BUILD_OPTS + -g # Enable all debugging information. + -Og # Ensure the compiler doesn't use optimizations + # that would harm debuggability of the resulting + # code. + -Wall # Enable most warnings. + -Wextra # Enable even more warnings. + -Wpedantic # Enable most of the rest of the warnings. + -Werror # Treat all warnings as errors. + -fprofile-arcs # Enable profile points that help with code + # coverage. + -ftest-coverage # Enable core code coverage compilation. +) + +target_compile_options ( + ${PROJECT_NAME} + PUBLIC + ${COVERAGE_BUILD_OPTS} +) + +target_compile_options ( + ${PROJECT_NAME}_TestCase_test + PUBLIC + ${COVERAGE_BUILD_OPTS} +) + +target_compile_options ( + ${PROJECT_NAME}_TestSuite_test + PUBLIC + ${COVERAGE_BUILD_OPTS} +) + +target_compile_options ( + ${PROJECT_NAME}_Assertions_test + PUBLIC + ${COVERAGE_BUILD_OPTS} +) diff --git a/cmake/build/MSVCDebug.cmake b/cmake/build/MSVCDebug.cmake new file mode 100644 index 0000000..908486a --- /dev/null +++ b/cmake/build/MSVCDebug.cmake @@ -0,0 +1,100 @@ + +list ( + APPEND + MSVC_DEBUG_BUILD_OPTS + /Wall # Enable all warnings and treat them as errors. + /WX # Treat linker warnings as errors also. + /Od # Perform no optimization; the resulting code is optimized + # for debugging and debuggability. + /wd4820 # Struct/class data member padding is ok, we're concerned + # about speed, not space, and the natural alignment is + # generally fastest. + # Let the compiler add the padding. + /wd4668 # There are undefined preprocessor macros in the Windows + # SDK in internal headers. + # This is a workaround until these issues are fixed by + # Microsoft. + /wd5045 # Warns about code that can cause the Spectre + # vulnerability to become exploitable, does not go away + # when /Qspectre is specified. + # Applied this warning suppression since /Qspectre is + # specified. + /Qspectre # Instructs the compiler to apply Spectre vulnerability + # mitigations. +) + +if (${TESTCPP_STACKTRACE_ENABLED}) + list ( + APPEND + MSVC_DEBUG_BUILD_OPTS + /wd5039 # There's a function or two in the Windows SDK that is/ + # are passed to extern 'C' APIs that are not marked as + # noexcept which causes this warning, which is treated + # as an error. + # There's nothing we can do about this so this is added + # as a workaround. + /wd4625 # In the Boost.StackTrace code, there are copy + # constructors that are implicitly deleted. + # Since this is in an external library, suppress the + # warning to work around this to ensure clean + # compilation. + /wd4626 # In the Boost.StackTrace code, there are copy + # assignment operators that are implicitly deleted. + # Since this is in an external library, suppress the + # warning to work around this to ensure clean + # compilation. + /wd5026 # In the Boost.StackTrace code, there are move + # constructors that are implicitly deleted. + # Since this is in an external library, suppress the + # warning to work around this to ensure clean + # compilation. + /wd5027 # In the Boost.StackTrace code, there are move + # assignment operators that are implicitly deleted. + # Since this is in an external library, suppress the + # warning to work around this to ensure clean + # compilation. + ) +endif () + +if (BUILD_TESTING) + list ( + APPEND + MSVC_DEBUG_BUILD_OPTS + /wd4514 # It's ok if the compiler removes unreferenced inline + # functions. + ) +endif () + +target_compile_options ( + ${PROJECT_NAME} + PUBLIC + ${MSVC_DEBUG_BUILD_OPTS} +) + +if (${TESTCPP_DEMO_ENABLED}) + target_compile_options ( + ${PROJECT_NAME}_run + PUBLIC + ${MSVC_DEBUG_BUILD_OPTS} + ) +endif () + +if (BUILD_TESTING) + target_compile_options ( + ${PROJECT_NAME}_TestCase_test + PUBLIC + ${MSVC_DEBUG_BUILD_OPTS} + ) + + target_compile_options ( + ${PROJECT_NAME}_TestSuite_test + PUBLIC + ${MSVC_DEBUG_BUILD_OPTS} + ) + + target_compile_options ( + ${PROJECT_NAME}_Assertions_test + PUBLIC + ${MSVC_DEBUG_BUILD_OPTS} + ) +endif () diff --git a/cmake/build/MSVCRelease.cmake b/cmake/build/MSVCRelease.cmake new file mode 100644 index 0000000..a0be314 --- /dev/null +++ b/cmake/build/MSVCRelease.cmake @@ -0,0 +1,102 @@ +list ( + APPEND + MSVC_RELEASE_BUILD_OPTS + /Wall # Enable all warnings and treat them as errors. + /WX # Treat linker warnings as errors also. + /O2 # Do optimizations for the Release build. + /wd4668 # There are undefined preprocessor macros in the Windows + # SDK in internal headers. + # This is a workaround until these issues are fixed by + # Microsoft. + /wd4710 # It's ok if functions are not inlined. + /wd4711 # It's also ok if functions are inlined. + /wd4820 # Struct/class data member padding is ok, we're concerned + # about speed, not space, and the natural alignment is + # generally fastest. + # Let the compiler add the padding. + /wd4100 # Unused parameters occur in the Release build in + # debugLog. + /wd5045 # Warns about code that can cause the Spectre + # vulnerability to become exploitable, does not go away + # when /Qspectre is specified. + # Applied this warning suppression since /Qspectre is + # specified. + /Qspectre # Instructs the compiler to apply Spectre vulnerability + # mitigations. +) + +if (${TESTCPP_STACKTRACE_ENABLED}) + list ( + APPEND + MSVC_RELEASE_BUILD_OPTS + /wd5039 # There's a function or two in the Windows SDK that is/ + # are passed to extern 'C' APIs that are not marked as + # noexcept which causes this warning, which is treated + # as an error. + # There's nothing we can do about this so this is added + # as a workaround. + /wd4625 # In the Boost.StackTrace code, there are copy + # constructors that are implicitly deleted. + # Since this is in an external library, suppress the + # warning to work around this to ensure clean + # compilation. + /wd4626 # In the Boost.StackTrace code, there are copy + # assignment operators that are implicitly deleted. + # Since this is in an external library, suppress the + # warning to work around this to ensure clean + # compilation. + /wd5026 # In the Boost.StackTrace code, there are move + # constructors that are implicitly deleted. + # Since this is in an external library, suppress the + # warning to work around this to ensure clean + # compilation. + /wd5027 # In the Boost.StackTrace code, there are move + # assignment operators that are implicitly deleted. + # Since this is in an external library, suppress the + # warning to work around this to ensure clean + # compilation. + ) +endif () + +if (BUILD_TESTING) + list ( + APPEND + MSVC_RELEASE_BUILD_OPTS + /wd4514 # It's ok if the compiler removes unreferenced inline + # functions. + ) +endif () + +target_compile_options ( + ${PROJECT_NAME} + PUBLIC + ${MSVC_RELEASE_BUILD_OPTS} +) + +if (${TESTCPP_DEMO_ENABLED}) + target_compile_options ( + ${PROJECT_NAME}_run + PUBLIC + ${MSVC_RELEASE_BUILD_OPTS} + ) +endif () + +if (BUILD_TESTING) + target_compile_options ( + ${PROJECT_NAME}_TestCase_test + PUBLIC + ${MSVC_RELEASE_BUILD_OPTS} + ) + + target_compile_options ( + ${PROJECT_NAME}_TestSuite_test + PUBLIC + ${MSVC_RELEASE_BUILD_OPTS} + ) + + target_compile_options ( + ${PROJECT_NAME}_Assertions_test + PUBLIC + ${MSVC_RELEASE_BUILD_OPTS} + ) +endif () diff --git a/cmake/link/Demo.cmake b/cmake/link/Demo.cmake new file mode 100644 index 0000000..0588e4b --- /dev/null +++ b/cmake/link/Demo.cmake @@ -0,0 +1,21 @@ +if (${TESTCPP_STACKTRACE_ENABLED} AND MSVC) + target_link_libraries ( + ${PROJECT_NAME}_run + ${PROJECT_NAME} + ole32 + dbgeng + ) + +elseif (${TESTCPP_STACKTRACE_ENABLED}) + target_link_libraries ( + ${PROJECT_NAME}_run + ${PROJECT_NAME} + dl + ) + +else () + target_link_libraries ( + ${PROJECT_NAME}_run + ${PROJECT_NAME} + ) +endif () diff --git a/cmake/link/TestCPPWithCoverage.cmake b/cmake/link/TestCPPWithCoverage.cmake new file mode 100644 index 0000000..f2f2058 --- /dev/null +++ b/cmake/link/TestCPPWithCoverage.cmake @@ -0,0 +1,4 @@ +target_link_libraries ( + ${PROJECT_NAME} + gcov +) diff --git a/cmake/link/Tests.cmake b/cmake/link/Tests.cmake new file mode 100644 index 0000000..f823620 --- /dev/null +++ b/cmake/link/Tests.cmake @@ -0,0 +1,51 @@ +if (${TESTCPP_STACKTRACE_ENABLED} AND MSVC) + target_link_libraries ( + ${PROJECT_NAME}_TestCase_test + ${PROJECT_NAME} + ole32 + dbgeng + ) + target_link_libraries ( + ${PROJECT_NAME}_TestSuite_test + ${PROJECT_NAME} + ole32 + dbgeng + ) + target_link_libraries ( + ${PROJECT_NAME}_Assertions_test + ${PROJECT_NAME} + ole32 + dbgeng + ) + +elseif (${TESTCPP_STACKTRACE_ENABLED}) + target_link_libraries ( + ${PROJECT_NAME}_TestCase_test + ${PROJECT_NAME} + dl + ) + target_link_libraries ( + ${PROJECT_NAME}_TestSuite_test + ${PROJECT_NAME} + dl + ) + target_link_libraries ( + ${PROJECT_NAME}_Assertions_test + ${PROJECT_NAME} + dl + ) + +else () + target_link_libraries ( + ${PROJECT_NAME}_TestCase_test + ${PROJECT_NAME} + ) + target_link_libraries ( + ${PROJECT_NAME}_TestSuite_test + ${PROJECT_NAME} + ) + target_link_libraries ( + ${PROJECT_NAME}_Assertions_test + ${PROJECT_NAME} + ) +endif () diff --git a/cmake/link/TestsWithCoverage.cmake b/cmake/link/TestsWithCoverage.cmake new file mode 100644 index 0000000..ae6e6d1 --- /dev/null +++ b/cmake/link/TestsWithCoverage.cmake @@ -0,0 +1,60 @@ +if (${TESTCPP_STACKTRACE_ENABLED} AND MSVC) + target_link_libraries ( + ${PROJECT_NAME}_TestCase_test + ${PROJECT_NAME} + gcov + ole32 + dbgeng + ) + target_link_libraries ( + ${PROJECT_NAME}_TestSuite_test + ${PROJECT_NAME} + gcov + ole32 + dbgeng + ) + target_link_libraries ( + ${PROJECT_NAME}_Assertions_test + ${PROJECT_NAME} + gcov + ole32 + dbgeng + ) + +elseif (${TESTCPP_STACKTRACE_ENABLED}) + target_link_libraries ( + ${PROJECT_NAME}_TestCase_test + ${PROJECT_NAME} + gcov + dl + ) + target_link_libraries ( + ${PROJECT_NAME}_TestSuite_test + ${PROJECT_NAME} + gcov + dl + ) + target_link_libraries ( + ${PROJECT_NAME}_Assertions_test + ${PROJECT_NAME} + gcov + dl + ) + +else () + target_link_libraries ( + ${PROJECT_NAME}_TestCase_test + ${PROJECT_NAME} + gcov + ) + target_link_libraries ( + ${PROJECT_NAME}_TestSuite_test + ${PROJECT_NAME} + gcov + ) + target_link_libraries ( + ${PROJECT_NAME}_Assertions_test + ${PROJECT_NAME} + gcov + ) +endif () diff --git a/cmake/presets/building.json b/cmake/presets/building.json new file mode 100644 index 0000000..999c7a5 --- /dev/null +++ b/cmake/presets/building.json @@ -0,0 +1,81 @@ +{ + "buildPresets": [ + { + "name": "vs-base-build", + "configurePreset": "vs-base", + "resolvePackageReferences": "on", + "nativeToolOptions": [ + "/ds", + "/m:4", + "/nologo", + "/warnAsError" + ], + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Windows" + } + }, + { + "name": "vs-base-clean-build", + "inherits": "vs-base-build", + "cleanFirst": true + }, + { + "name": "vs-msanalysis", + "inherits": "vs-base-clean-build", + "configurePreset": "vs-nost-base", + "nativeToolOptions": [ + "/external:anglebrackets", + "/external:I${sourceDir}/3rdparty", + "/analyze", + "/analyze:external-", + "/analyze:autolog", + "/analyze:ruleset NativeRecommendedRules.ruleset" + ] + }, + { + "name": "vs-msanalysis-xml", + "inherits": "vs-msanalysis", + "nativeToolOptions": [ + "/analyze:log:format:xml" + ] + }, + { + "name": "vs-msanalysis-sarif", + "inherits": "vs-msanalysis", + "nativeToolOptions": [ + "/analyze:log:format:sarif" + ] + }, + { + "name": "vs64-base-build", + "configurePreset": "vs64-base", + "inherits": "vs-base-build" + }, + { + "name": "vs64-base-clean-build", + "configurePreset": "vs64-base", + "inherits": "vs-base-clean-build" + }, + { + "name": "vs64-msanalysis", + "inherits": "vs-msanalysis", + "configurePreset": "vs64-nost-base" + }, + { + "name": "vs64-msanalysis-xml", + "inherits": "vs64-msanalysis", + "nativeToolOptions": [ + "/analyze:log:format:xml" + ] + }, + { + "name": "vs64-msanalysis-sarif", + "inherits": "vs64-msanalysis", + "nativeToolOptions": [ + "/analyze:log:format:sarif" + ] + } + ] +} \ No newline at end of file diff --git a/cmake/presets/configuring.json b/cmake/presets/configuring.json new file mode 100644 index 0000000..1a70764 --- /dev/null +++ b/cmake/presets/configuring.json @@ -0,0 +1,282 @@ +{ + "configurePresets": [ + { + "name": "base", + "cacheVariables": { + "CMAKE_EXPORT_COMPILE_COMMANDS": "0", + "TESTCPP_STACKTRACE_ENABLED": "0", + "TESTCPP_ANALYSIS_ENABLED": "0", + "TESTCPP_TEST_ENABLED": "0", + "TESTCPP_DEMO_ENABLED": "0", + "TESTCPP_COVERAGE_ENABLED": "0" + }, + "warnings": { + "dev": false, + "deprecated": false, + "uninitialized": true, + "unusedCli": false, + "systemVars": false + } + }, + { + "name": "base-dev-checks", + "description": "Base config preset with dev checks enabled.", + "inherits": "base", + "warnings": { + "dev": true, + "deprecated": true, + "uninitialized": true, + "unusedCli": true, + "systemVars": true + } + }, + { + "name": "export-cc-st-base", + "inherits": "base", + "cacheVariables": { + "CMAKE_EXPORT_COMPILE_COMMANDS": "1", + "TESTCPP_STACKTRACE_ENABLED": "1" + } + }, + { + "name": "export-cc-nost-base", + "inherits": "base", + "cacheVariables": { + "CMAKE_EXPORT_COMPILE_COMMANDS": "1" + } + }, + { + "name": "vs-dev-checks", + "inherits": "base-dev-checks", + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Windows" + } + }, + { + "name": "vs-base", + "inherits": "export-cc-st-base", + "binaryDir": "${sourceDir}/out/build/vs-base", + "installDir": "${sourceDir}/out/install/vs-base", + "displayName": "Windows - Visual Studio - Base (Minimal, Core Lib only) (32-bit)", + "description": "Configure the base Visual Studio Minimal build with the Win32 toolchain architecture.", + "generator": "Visual Studio 17 2022", + "architecture": "Win32", + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Windows" + } + }, + { + "name": "vs-nost-base", + "inherits": "export-cc-nost-base", + "binaryDir": "${sourceDir}/out/build/vs-nost-base", + "installDir": "${sourceDir}/out/install/vs-nost-base", + "displayName": "Windows - Visual Studio - Base (Minimal, Core Lib only) - No Stacktraces (32-bit)", + "description": "Configure the base Visual Studio Minimal build with the Win32 toolchain architecture, but with no stacktraces (strict C++11).", + "cacheVariables": { + "TESTCPP_STACKTRACE_ENABLED": "0" + } + }, + { + "name": "vs-msanalysis", + "inherits": "vs-nost-base", + "binaryDir": "${sourceDir}/out/build/vs-msanalysis", + "installDir": "${sourceDir}/out/install/vs-msanalysis", + "displayName": "Windows - Visual Studio - Base (Minimal, Core Lib only) - MSVC++ Analysis (32-bit)", + "description": "Configure the base Visual Studio Minimal build with the Win32 toolchain architecture, then run the MSVC++ analyzer.", + "generator": "Visual Studio 17 2022", + "architecture": "Win32" + }, + { + "name": "vs-all", + "inherits": "vs-base", + "binaryDir": "${sourceDir}/out/build/vs-all", + "installDir": "${sourceDir}/out/install/vs-all", + "displayName": "Windows - Visual Studio - All Lib Components - Core, Tests, and Demo (32-bit)", + "description": "Configure the Visual Studio build with all Library options set and the Win32 toolchain architecture.", + "cacheVariables": { + "TESTCPP_TEST_ENABLED": "1", + "TESTCPP_DEMO_ENABLED": "1" + } + }, + { + "name": "vs-nost-all", + "inherits": "vs-nost-base", + "binaryDir": "${sourceDir}/out/build/vs-nost-all", + "installDir": "${sourceDir}/out/install/vs-nost-all", + "displayName": "Windows - Visual Studio - All Lib Components - Core, Tests, and Demo - No Stacktraces (32-bit)", + "description": "Configure the Visual Studio build with all Library options set and the Win32 toolchain architecture, but with no stacktraces (strict C++11).", + "cacheVariables": { + "TESTCPP_TEST_ENABLED": "1", + "TESTCPP_DEMO_ENABLED": "1" + } + }, + { + "name": "vs-with-test", + "inherits": "vs-base", + "binaryDir": "${sourceDir}/out/build/vs-withtest", + "installDir": "${sourceDir}/out/install/vs-withtest", + "displayName": "Windows - Visual Studio - Core Lib With Tests (32-bit)", + "description": "Configure the Visual Studio build with Core and Test Library build set and the Win32 toolchain architecture.", + "cacheVariables": { + "TESTCPP_TEST_ENABLED": "1" + } + }, + { + "name": "vs-nost-with-test", + "inherits": "vs-nost-base", + "binaryDir": "${sourceDir}/out/build/vs-nost-withtest", + "installDir": "${sourceDir}/out/install/vs-nost-withtest", + "displayName": "Windows - Visual Studio - Core Lib With Tests - No Stacktraces (32-bit)", + "description": "Configure the Visual Studio build with Core and Test Library build set and the Win32 toolchain architecture, but with no stacktraces (strict C++11).", + "cacheVariables": { + "TESTCPP_TEST_ENABLED": "1" + } + }, + { + "name": "vs-with-demo", + "inherits": "vs-base", + "binaryDir": "${sourceDir}/out/build/vs-withdemo", + "installDir": "${sourceDir}/out/install/vs-withdemo", + "displayName": "Windows - Visual Studio - Core Lib With Demo (32-bit)", + "description": "Configure the Visual Studio build with Core and Demo set and the Win32 toolchain architecture.", + "cacheVariables": { + "TESTCPP_DEMO_ENABLED": "1" + } + }, + { + "name": "vs-nost-with-demo", + "inherits": "vs-nost-base", + "binaryDir": "${sourceDir}/out/build/vs-nost-withdemo", + "installDir": "${sourceDir}/out/install/vs-nost-withdemo", + "displayName": "Windows - Visual Studio - Lib With Demo - No Stacktraces (32-bit)", + "description": "Configure the Visual Studio build with Core and Demo library build set and the Win32 toolchain architecture, but with no stacktraces (strict C++11).", + "cacheVariables": { + "TESTCPP_DEMO_ENABLED": "1" + } + }, + { + "name": "vs-ct", + "inherits": "vs-nost-base", + "binaryDir": "${sourceDir}/out/build/vs-ct", + "installDir": "${sourceDir}/out/install/vs-ct", + "displayName": "Windows - Visual Studio - Clang Tidy analysis (32-bit)", + "description": "Configure the Visual Studio build with clang-tidy analysis and the Win32 toolchain architecture.", + "cacheVariables": { + "TESTCPP_ANALYSIS_ENABLED": "1" + } + }, + { + "name": "vs64-base", + "inherits": "vs-base", + "binaryDir": "${sourceDir}/out/build/vs64-base", + "installDir": "${sourceDir}/out/install/vs64-base", + "displayName": "Windows - Visual Studio - Base (64-bit)", + "description": "Configure the base Visual Studio build with the Win64 toolchain architecture.", + "architecture": "Win64" + }, + { + "name": "vs64-nost-base", + "inherits": "vs64-base", + "binaryDir": "${sourceDir}/out/build/vs64-nost-base", + "installDir": "${sourceDir}/out/install/vs64-nost-base", + "displayName": "Windows - Visual Studio - Base - No Stacktraces (64-bit)", + "description": "Configure the base Visual Studio build with the Win64 toolchain architecture, but with no stacktraces (strict C++11).", + "cacheVariables": { + "TESTCPP_STACKTRACE_ENABLED": "0" + } + }, + { + "name": "vs64-msanalysis", + "inherits": "vs64-nost-base", + "binaryDir": "${sourceDir}/out/build/vs64-msanalysis", + "installDir": "${sourceDir}/out/install/vs64-msanalysis", + "displayName": "Windows - Visual Studio - Base (Minimal, Core Lib only) - MSVC++ Analysis (64-bit)", + "description": "Configure the base Visual Studio Minimal build with the Win64 toolchain architecture, then run the MSVC++ analyzer.", + "generator": "Visual Studio 17 2022", + "architecture": "Win64" + }, + { + "name": "vs64-all", + "inherits": "vs64-base", + "binaryDir": "${sourceDir}/out/build/vs64-all", + "installDir": "${sourceDir}/out/install/vs64-all", + "displayName": "Windows - Visual Studio - All Lib Components - Core, Tests, and Demo (64-bit)", + "description": "Configure the Visual Studio build with all Library options set and the Win64 toolchain architecture.", + "cacheVariables": { + "TESTCPP_TEST_ENABLED": "1", + "TESTCPP_DEMO_ENABLED": "1" + } + }, + { + "name": "vs64-nost-all", + "inherits": "vs64-nost-base", + "binaryDir": "${sourceDir}/out/build/vs64-nost-all", + "installDir": "${sourceDir}/out/install/vs64-nost-all", + "displayName": "Windows - Visual Studio - All Lib Components - Core, Tests, and Demo - No Stacktraces (64-bit)", + "description": "Configure the Visual Studio build with all Library options set and the Win64 toolchain architecture, but with no stacktraces (strict C++11).", + "cacheVariables": { + "TESTCPP_TEST_ENABLED": "1", + "TESTCPP_DEMO_ENABLED": "1" + } + }, + { + "name": "vs64-with-test", + "inherits": "vs64-base", + "binaryDir": "${sourceDir}/out/build/vs64-withtest", + "installDir": "${sourceDir}/out/install/vs64-withtest", + "displayName": "Windows - Visual Studio - Core Lib With Tests (64-bit)", + "description": "Configure the Visual Studio build with Core and Test Library build set and the Win64 toolchain architecture.", + "cacheVariables": { + "TESTCPP_TEST_ENABLED": "1" + } + }, + { + "name": "vs64-nost-with-test", + "inherits": "vs64-nost-base", + "binaryDir": "${sourceDir}/out/build/vs64-nost-withtest", + "installDir": "${sourceDir}/out/install/vs64-nost-withtest", + "displayName": "Windows - Visual Studio - Core Lib With Tests - No Stacktraces (64-bit)", + "description": "Configure the Visual Studio build with Core and Test Library build set and the Win64 toolchain architecture, but with no stacktraces (strict C++11).", + "cacheVariables": { + "TESTCPP_TEST_ENABLED": "1" + } + }, + { + "name": "vs64-with-demo", + "inherits": "vs64-base", + "binaryDir": "${sourceDir}/out/build/vs64-withdemo", + "installDir": "${sourceDir}/out/install/vs64-withdemo", + "displayName": "Windows - Visual Studio - Core Lib With Demo (64-bit)", + "description": "Configure the Visual Studio build with Core and Demo set and the Win64 toolchain architecture.", + "cacheVariables": { + "TESTCPP_DEMO_ENABLED": "1" + } + }, + { + "name": "vs64-nost-with-demo", + "inherits": "vs64-nost-base", + "binaryDir": "${sourceDir}/out/build/vs64-nost-withdemo", + "installDir": "${sourceDir}/out/install/vs64-nost-withdemo", + "displayName": "Windows - Visual Studio - Lib With Demo - No Stacktraces (64-bit)", + "description": "Configure the Visual Studio build with Core and Demo library build set and the Win64 toolchain architecture, but with no stacktraces (strict C++11).", + "cacheVariables": { + "TESTCPP_DEMO_ENABLED": "1" + } + }, + { + "name": "vs64-ct", + "inherits": "vs64-nost-base", + "binaryDir": "${sourceDir}/out/build/vs64-ct", + "installDir": "${sourceDir}/out/install/vs64-ct", + "displayName": "Windows - Visual Studio - Clang Tidy analysis (64-bit)", + "description": "Configure the Visual Studio build with clang-tidy analysis and the Win64 toolchain architecture.", + "cacheVariables": { + "TESTCPP_ANALYSIS_ENABLED": "1" + } + } + ] +} diff --git a/cmake/presets/packaging.json b/cmake/presets/packaging.json new file mode 100644 index 0000000..5898531 --- /dev/null +++ b/cmake/presets/packaging.json @@ -0,0 +1,43 @@ +{ + "packagePresets": [ + { + "name": "base-pack", + "generators": [ + "ZIP" + ], + "output": { + "verbose": true + } + }, + { + "name": "vs-pack", + "configurePreset": "vs-base", + "inherits": "base-pack", + "generators": [ + "7Z", + "NSIS", + "WIX" + ], + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Windows" + } + }, + { + "name": "vs-nost-pack", + "configurePreset": "vs-nost-base", + "inherits": "vs-pack" + }, + { + "name": "vs64-pack", + "configurePreset": "vs64-base", + "inherits": "vs-pack" + }, + { + "name": "vs64-nost-pack", + "configurePreset": "vs64-nost-base", + "inherits": "vs-nost-pack" + } + ] +} \ No newline at end of file diff --git a/cmake/presets/testing.json b/cmake/presets/testing.json new file mode 100644 index 0000000..eb1f0bf --- /dev/null +++ b/cmake/presets/testing.json @@ -0,0 +1,47 @@ +{ + "testPresets": [ + { + "name": "vs-test", + "configurePreset": "vs-with-test", + "output": { + "shortProgress": true, + "verbosity": "verbose", + "outputOnFailure": true, + "outputJUnitFile": "${sourceDir}/out/test/vs-test/results.xml" + }, + "execution": { + "noTestsAction": "error", + "stopOnFailure": false + }, + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Windows" + } + }, + { + "name": "vs-nost-test", + "configurePreset": "vs-nost-with-test", + "inherits": "vs-test", + "output": { + "outputJUnitFile": "${sourceDir}/out/test/vs-nost-test/results.xml" + } + }, + { + "name": "vs64-test", + "configurePreset": "vs64-with-test", + "inherits": "vs-test", + "output": { + "outputJUnitFile": "${sourceDir}/out/test/vs64-test/results.xml" + } + }, + { + "name": "vs64-nost-test", + "configurePreset": "vs64-nost-with-test", + "inherits": "vs-nost-test", + "output": { + "outputJUnitFile": "${sourceDir}/out/test/vs64-nost-test/results.xml" + } + } + ] +} \ No newline at end of file From e8ae9b79e493d984657f11c9a6023a41aabec561 Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Fri, 24 Jan 2025 01:52:35 -0800 Subject: [PATCH 42/59] Update CMakePresets.json Move "included" files into the CMakePresets.json file since having the include block didn't work like I thought it would. --- CMakePresets.json | 449 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 444 insertions(+), 5 deletions(-) diff --git a/CMakePresets.json b/CMakePresets.json index 0ebdf77..9c5069b 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -5,10 +5,449 @@ "minor": 25, "patch": 0 }, - "include": [ - "cmake/presets/configuring.json", - "cmake/presets/building.json", - "cmake/presets/packaging.json", - "cmake/presets/testing.json" + "configurePresets": [ + { + "name": "base", + "cacheVariables": { + "CMAKE_EXPORT_COMPILE_COMMANDS": "0", + "TESTCPP_STACKTRACE_ENABLED": "0", + "TESTCPP_ANALYSIS_ENABLED": "0", + "TESTCPP_TEST_ENABLED": "0", + "TESTCPP_DEMO_ENABLED": "0", + "TESTCPP_COVERAGE_ENABLED": "0" + }, + "warnings": { + "dev": false, + "deprecated": false, + "uninitialized": true, + "unusedCli": false, + "systemVars": false + } + }, + { + "name": "base-dev-checks", + "description": "Base config preset with dev checks enabled.", + "inherits": "base", + "warnings": { + "dev": true, + "deprecated": true, + "uninitialized": true, + "unusedCli": true, + "systemVars": true + } + }, + { + "name": "export-cc-st-base", + "inherits": "base", + "cacheVariables": { + "CMAKE_EXPORT_COMPILE_COMMANDS": "1", + "TESTCPP_STACKTRACE_ENABLED": "1" + } + }, + { + "name": "export-cc-nost-base", + "inherits": "base", + "cacheVariables": { + "CMAKE_EXPORT_COMPILE_COMMANDS": "1" + } + }, + { + "name": "vs-dev-checks", + "inherits": "base-dev-checks", + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Windows" + } + }, + { + "name": "vs-base", + "inherits": "export-cc-st-base", + "binaryDir": "${sourceDir}/out/build/vs-base", + "installDir": "${sourceDir}/out/install/vs-base", + "displayName": "Windows - Visual Studio - Base (Minimal, Core Lib only) (32-bit)", + "description": "Configure the base Visual Studio Minimal build with the Win32 toolchain architecture.", + "generator": "Visual Studio 17 2022", + "architecture": "Win32", + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Windows" + } + }, + { + "name": "vs-nost-base", + "inherits": "export-cc-nost-base", + "binaryDir": "${sourceDir}/out/build/vs-nost-base", + "installDir": "${sourceDir}/out/install/vs-nost-base", + "displayName": "Windows - Visual Studio - Base (Minimal, Core Lib only) - No Stacktraces (32-bit)", + "description": "Configure the base Visual Studio Minimal build with the Win32 toolchain architecture, but with no stacktraces (strict C++11).", + "cacheVariables": { + "TESTCPP_STACKTRACE_ENABLED": "0" + } + }, + { + "name": "vs-msanalysis", + "inherits": "vs-nost-base", + "binaryDir": "${sourceDir}/out/build/vs-msanalysis", + "installDir": "${sourceDir}/out/install/vs-msanalysis", + "displayName": "Windows - Visual Studio - Base (Minimal, Core Lib only) - MSVC++ Analysis (32-bit)", + "description": "Configure the base Visual Studio Minimal build with the Win32 toolchain architecture, then run the MSVC++ analyzer.", + "generator": "Visual Studio 17 2022", + "architecture": "Win32" + }, + { + "name": "vs-all", + "inherits": "vs-base", + "binaryDir": "${sourceDir}/out/build/vs-all", + "installDir": "${sourceDir}/out/install/vs-all", + "displayName": "Windows - Visual Studio - All Lib Components - Core, Tests, and Demo (32-bit)", + "description": "Configure the Visual Studio build with all Library options set and the Win32 toolchain architecture.", + "cacheVariables": { + "TESTCPP_TEST_ENABLED": "1", + "TESTCPP_DEMO_ENABLED": "1" + } + }, + { + "name": "vs-nost-all", + "inherits": "vs-nost-base", + "binaryDir": "${sourceDir}/out/build/vs-nost-all", + "installDir": "${sourceDir}/out/install/vs-nost-all", + "displayName": "Windows - Visual Studio - All Lib Components - Core, Tests, and Demo - No Stacktraces (32-bit)", + "description": "Configure the Visual Studio build with all Library options set and the Win32 toolchain architecture, but with no stacktraces (strict C++11).", + "cacheVariables": { + "TESTCPP_TEST_ENABLED": "1", + "TESTCPP_DEMO_ENABLED": "1" + } + }, + { + "name": "vs-with-test", + "inherits": "vs-base", + "binaryDir": "${sourceDir}/out/build/vs-withtest", + "installDir": "${sourceDir}/out/install/vs-withtest", + "displayName": "Windows - Visual Studio - Core Lib With Tests (32-bit)", + "description": "Configure the Visual Studio build with Core and Test Library build set and the Win32 toolchain architecture.", + "cacheVariables": { + "TESTCPP_TEST_ENABLED": "1" + } + }, + { + "name": "vs-nost-with-test", + "inherits": "vs-nost-base", + "binaryDir": "${sourceDir}/out/build/vs-nost-withtest", + "installDir": "${sourceDir}/out/install/vs-nost-withtest", + "displayName": "Windows - Visual Studio - Core Lib With Tests - No Stacktraces (32-bit)", + "description": "Configure the Visual Studio build with Core and Test Library build set and the Win32 toolchain architecture, but with no stacktraces (strict C++11).", + "cacheVariables": { + "TESTCPP_TEST_ENABLED": "1" + } + }, + { + "name": "vs-with-demo", + "inherits": "vs-base", + "binaryDir": "${sourceDir}/out/build/vs-withdemo", + "installDir": "${sourceDir}/out/install/vs-withdemo", + "displayName": "Windows - Visual Studio - Core Lib With Demo (32-bit)", + "description": "Configure the Visual Studio build with Core and Demo set and the Win32 toolchain architecture.", + "cacheVariables": { + "TESTCPP_DEMO_ENABLED": "1" + } + }, + { + "name": "vs-nost-with-demo", + "inherits": "vs-nost-base", + "binaryDir": "${sourceDir}/out/build/vs-nost-withdemo", + "installDir": "${sourceDir}/out/install/vs-nost-withdemo", + "displayName": "Windows - Visual Studio - Lib With Demo - No Stacktraces (32-bit)", + "description": "Configure the Visual Studio build with Core and Demo library build set and the Win32 toolchain architecture, but with no stacktraces (strict C++11).", + "cacheVariables": { + "TESTCPP_DEMO_ENABLED": "1" + } + }, + { + "name": "vs-ct", + "inherits": "vs-nost-base", + "binaryDir": "${sourceDir}/out/build/vs-ct", + "installDir": "${sourceDir}/out/install/vs-ct", + "displayName": "Windows - Visual Studio - Clang Tidy analysis (32-bit)", + "description": "Configure the Visual Studio build with clang-tidy analysis and the Win32 toolchain architecture.", + "cacheVariables": { + "TESTCPP_ANALYSIS_ENABLED": "1" + } + }, + { + "name": "vs64-base", + "inherits": "vs-base", + "binaryDir": "${sourceDir}/out/build/vs64-base", + "installDir": "${sourceDir}/out/install/vs64-base", + "displayName": "Windows - Visual Studio - Base (64-bit)", + "description": "Configure the base Visual Studio build with the Win64 toolchain architecture.", + "architecture": "Win64" + }, + { + "name": "vs64-nost-base", + "inherits": "vs64-base", + "binaryDir": "${sourceDir}/out/build/vs64-nost-base", + "installDir": "${sourceDir}/out/install/vs64-nost-base", + "displayName": "Windows - Visual Studio - Base - No Stacktraces (64-bit)", + "description": "Configure the base Visual Studio build with the Win64 toolchain architecture, but with no stacktraces (strict C++11).", + "cacheVariables": { + "TESTCPP_STACKTRACE_ENABLED": "0" + } + }, + { + "name": "vs64-msanalysis", + "inherits": "vs64-nost-base", + "binaryDir": "${sourceDir}/out/build/vs64-msanalysis", + "installDir": "${sourceDir}/out/install/vs64-msanalysis", + "displayName": "Windows - Visual Studio - Base (Minimal, Core Lib only) - MSVC++ Analysis (64-bit)", + "description": "Configure the base Visual Studio Minimal build with the Win64 toolchain architecture, then run the MSVC++ analyzer.", + "generator": "Visual Studio 17 2022", + "architecture": "Win64" + }, + { + "name": "vs64-all", + "inherits": "vs64-base", + "binaryDir": "${sourceDir}/out/build/vs64-all", + "installDir": "${sourceDir}/out/install/vs64-all", + "displayName": "Windows - Visual Studio - All Lib Components - Core, Tests, and Demo (64-bit)", + "description": "Configure the Visual Studio build with all Library options set and the Win64 toolchain architecture.", + "cacheVariables": { + "TESTCPP_TEST_ENABLED": "1", + "TESTCPP_DEMO_ENABLED": "1" + } + }, + { + "name": "vs64-nost-all", + "inherits": "vs64-nost-base", + "binaryDir": "${sourceDir}/out/build/vs64-nost-all", + "installDir": "${sourceDir}/out/install/vs64-nost-all", + "displayName": "Windows - Visual Studio - All Lib Components - Core, Tests, and Demo - No Stacktraces (64-bit)", + "description": "Configure the Visual Studio build with all Library options set and the Win64 toolchain architecture, but with no stacktraces (strict C++11).", + "cacheVariables": { + "TESTCPP_TEST_ENABLED": "1", + "TESTCPP_DEMO_ENABLED": "1" + } + }, + { + "name": "vs64-with-test", + "inherits": "vs64-base", + "binaryDir": "${sourceDir}/out/build/vs64-withtest", + "installDir": "${sourceDir}/out/install/vs64-withtest", + "displayName": "Windows - Visual Studio - Core Lib With Tests (64-bit)", + "description": "Configure the Visual Studio build with Core and Test Library build set and the Win64 toolchain architecture.", + "cacheVariables": { + "TESTCPP_TEST_ENABLED": "1" + } + }, + { + "name": "vs64-nost-with-test", + "inherits": "vs64-nost-base", + "binaryDir": "${sourceDir}/out/build/vs64-nost-withtest", + "installDir": "${sourceDir}/out/install/vs64-nost-withtest", + "displayName": "Windows - Visual Studio - Core Lib With Tests - No Stacktraces (64-bit)", + "description": "Configure the Visual Studio build with Core and Test Library build set and the Win64 toolchain architecture, but with no stacktraces (strict C++11).", + "cacheVariables": { + "TESTCPP_TEST_ENABLED": "1" + } + }, + { + "name": "vs64-with-demo", + "inherits": "vs64-base", + "binaryDir": "${sourceDir}/out/build/vs64-withdemo", + "installDir": "${sourceDir}/out/install/vs64-withdemo", + "displayName": "Windows - Visual Studio - Core Lib With Demo (64-bit)", + "description": "Configure the Visual Studio build with Core and Demo set and the Win64 toolchain architecture.", + "cacheVariables": { + "TESTCPP_DEMO_ENABLED": "1" + } + }, + { + "name": "vs64-nost-with-demo", + "inherits": "vs64-nost-base", + "binaryDir": "${sourceDir}/out/build/vs64-nost-withdemo", + "installDir": "${sourceDir}/out/install/vs64-nost-withdemo", + "displayName": "Windows - Visual Studio - Lib With Demo - No Stacktraces (64-bit)", + "description": "Configure the Visual Studio build with Core and Demo library build set and the Win64 toolchain architecture, but with no stacktraces (strict C++11).", + "cacheVariables": { + "TESTCPP_DEMO_ENABLED": "1" + } + }, + { + "name": "vs64-ct", + "inherits": "vs64-nost-base", + "binaryDir": "${sourceDir}/out/build/vs64-ct", + "installDir": "${sourceDir}/out/install/vs64-ct", + "displayName": "Windows - Visual Studio - Clang Tidy analysis (64-bit)", + "description": "Configure the Visual Studio build with clang-tidy analysis and the Win64 toolchain architecture.", + "cacheVariables": { + "TESTCPP_ANALYSIS_ENABLED": "1" + } + } + ], + "buildPresets": [ + { + "name": "vs-base-build", + "configurePreset": "vs-base", + "resolvePackageReferences": "on", + "nativeToolOptions": [ + "/ds", + "/m:4", + "/nologo", + "/warnAsError" + ], + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Windows" + } + }, + { + "name": "vs-base-clean-build", + "inherits": "vs-base-build", + "cleanFirst": true + }, + { + "name": "vs-msanalysis", + "inherits": "vs-base-clean-build", + "configurePreset": "vs-nost-base", + "nativeToolOptions": [ + "/external:anglebrackets", + "/external:I${sourceDir}/3rdparty", + "/analyze", + "/analyze:external-", + "/analyze:autolog", + "/analyze:ruleset NativeRecommendedRules.ruleset" + ] + }, + { + "name": "vs-msanalysis-xml", + "inherits": "vs-msanalysis", + "nativeToolOptions": [ + "/analyze:log:format:xml" + ] + }, + { + "name": "vs-msanalysis-sarif", + "inherits": "vs-msanalysis", + "nativeToolOptions": [ + "/analyze:log:format:sarif" + ] + }, + { + "name": "vs64-base-build", + "configurePreset": "vs64-base", + "inherits": "vs-base-build" + }, + { + "name": "vs64-base-clean-build", + "configurePreset": "vs64-base", + "inherits": "vs-base-clean-build" + }, + { + "name": "vs64-msanalysis", + "inherits": "vs-msanalysis", + "configurePreset": "vs64-nost-base" + }, + { + "name": "vs64-msanalysis-xml", + "inherits": "vs64-msanalysis", + "nativeToolOptions": [ + "/analyze:log:format:xml" + ] + }, + { + "name": "vs64-msanalysis-sarif", + "inherits": "vs64-msanalysis", + "nativeToolOptions": [ + "/analyze:log:format:sarif" + ] + } + ], + "testPresets": [ + { + "name": "vs-test", + "configurePreset": "vs-with-test", + "output": { + "shortProgress": true, + "verbosity": "verbose", + "outputOnFailure": true, + "outputJUnitFile": "${sourceDir}/out/test/vs-test/results.xml" + }, + "execution": { + "noTestsAction": "error", + "stopOnFailure": false + }, + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Windows" + } + }, + { + "name": "vs-nost-test", + "configurePreset": "vs-nost-with-test", + "inherits": "vs-test", + "output": { + "outputJUnitFile": "${sourceDir}/out/test/vs-nost-test/results.xml" + } + }, + { + "name": "vs64-test", + "configurePreset": "vs64-with-test", + "inherits": "vs-test", + "output": { + "outputJUnitFile": "${sourceDir}/out/test/vs64-test/results.xml" + } + }, + { + "name": "vs64-nost-test", + "configurePreset": "vs64-nost-with-test", + "inherits": "vs-nost-test", + "output": { + "outputJUnitFile": "${sourceDir}/out/test/vs64-nost-test/results.xml" + } + } + ], + "packagePresets": [ + { + "name": "base-pack", + "generators": [ + "ZIP" + ], + "output": { + "verbose": true + } + }, + { + "name": "vs-pack", + "configurePreset": "vs-base", + "inherits": "base-pack", + "generators": [ + "7Z", + "NSIS", + "WIX" + ], + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Windows" + } + }, + { + "name": "vs-nost-pack", + "configurePreset": "vs-nost-base", + "inherits": "vs-pack" + }, + { + "name": "vs64-pack", + "configurePreset": "vs64-base", + "inherits": "vs-pack" + }, + { + "name": "vs64-nost-pack", + "configurePreset": "vs64-nost-base", + "inherits": "vs-nost-pack" + } ] } \ No newline at end of file From a2280406d935d4715842297413ef4d8fe9308cff Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Fri, 24 Jan 2025 14:33:55 -0800 Subject: [PATCH 43/59] Remove split out preset files, they are all now in CMakePresets.json --- cmake/presets/building.json | 81 ---------- cmake/presets/configuring.json | 282 --------------------------------- cmake/presets/packaging.json | 43 ----- cmake/presets/testing.json | 47 ------ 4 files changed, 453 deletions(-) delete mode 100644 cmake/presets/building.json delete mode 100644 cmake/presets/configuring.json delete mode 100644 cmake/presets/packaging.json delete mode 100644 cmake/presets/testing.json diff --git a/cmake/presets/building.json b/cmake/presets/building.json deleted file mode 100644 index 999c7a5..0000000 --- a/cmake/presets/building.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "buildPresets": [ - { - "name": "vs-base-build", - "configurePreset": "vs-base", - "resolvePackageReferences": "on", - "nativeToolOptions": [ - "/ds", - "/m:4", - "/nologo", - "/warnAsError" - ], - "condition": { - "type": "equals", - "lhs": "${hostSystemName}", - "rhs": "Windows" - } - }, - { - "name": "vs-base-clean-build", - "inherits": "vs-base-build", - "cleanFirst": true - }, - { - "name": "vs-msanalysis", - "inherits": "vs-base-clean-build", - "configurePreset": "vs-nost-base", - "nativeToolOptions": [ - "/external:anglebrackets", - "/external:I${sourceDir}/3rdparty", - "/analyze", - "/analyze:external-", - "/analyze:autolog", - "/analyze:ruleset NativeRecommendedRules.ruleset" - ] - }, - { - "name": "vs-msanalysis-xml", - "inherits": "vs-msanalysis", - "nativeToolOptions": [ - "/analyze:log:format:xml" - ] - }, - { - "name": "vs-msanalysis-sarif", - "inherits": "vs-msanalysis", - "nativeToolOptions": [ - "/analyze:log:format:sarif" - ] - }, - { - "name": "vs64-base-build", - "configurePreset": "vs64-base", - "inherits": "vs-base-build" - }, - { - "name": "vs64-base-clean-build", - "configurePreset": "vs64-base", - "inherits": "vs-base-clean-build" - }, - { - "name": "vs64-msanalysis", - "inherits": "vs-msanalysis", - "configurePreset": "vs64-nost-base" - }, - { - "name": "vs64-msanalysis-xml", - "inherits": "vs64-msanalysis", - "nativeToolOptions": [ - "/analyze:log:format:xml" - ] - }, - { - "name": "vs64-msanalysis-sarif", - "inherits": "vs64-msanalysis", - "nativeToolOptions": [ - "/analyze:log:format:sarif" - ] - } - ] -} \ No newline at end of file diff --git a/cmake/presets/configuring.json b/cmake/presets/configuring.json deleted file mode 100644 index 1a70764..0000000 --- a/cmake/presets/configuring.json +++ /dev/null @@ -1,282 +0,0 @@ -{ - "configurePresets": [ - { - "name": "base", - "cacheVariables": { - "CMAKE_EXPORT_COMPILE_COMMANDS": "0", - "TESTCPP_STACKTRACE_ENABLED": "0", - "TESTCPP_ANALYSIS_ENABLED": "0", - "TESTCPP_TEST_ENABLED": "0", - "TESTCPP_DEMO_ENABLED": "0", - "TESTCPP_COVERAGE_ENABLED": "0" - }, - "warnings": { - "dev": false, - "deprecated": false, - "uninitialized": true, - "unusedCli": false, - "systemVars": false - } - }, - { - "name": "base-dev-checks", - "description": "Base config preset with dev checks enabled.", - "inherits": "base", - "warnings": { - "dev": true, - "deprecated": true, - "uninitialized": true, - "unusedCli": true, - "systemVars": true - } - }, - { - "name": "export-cc-st-base", - "inherits": "base", - "cacheVariables": { - "CMAKE_EXPORT_COMPILE_COMMANDS": "1", - "TESTCPP_STACKTRACE_ENABLED": "1" - } - }, - { - "name": "export-cc-nost-base", - "inherits": "base", - "cacheVariables": { - "CMAKE_EXPORT_COMPILE_COMMANDS": "1" - } - }, - { - "name": "vs-dev-checks", - "inherits": "base-dev-checks", - "condition": { - "type": "equals", - "lhs": "${hostSystemName}", - "rhs": "Windows" - } - }, - { - "name": "vs-base", - "inherits": "export-cc-st-base", - "binaryDir": "${sourceDir}/out/build/vs-base", - "installDir": "${sourceDir}/out/install/vs-base", - "displayName": "Windows - Visual Studio - Base (Minimal, Core Lib only) (32-bit)", - "description": "Configure the base Visual Studio Minimal build with the Win32 toolchain architecture.", - "generator": "Visual Studio 17 2022", - "architecture": "Win32", - "condition": { - "type": "equals", - "lhs": "${hostSystemName}", - "rhs": "Windows" - } - }, - { - "name": "vs-nost-base", - "inherits": "export-cc-nost-base", - "binaryDir": "${sourceDir}/out/build/vs-nost-base", - "installDir": "${sourceDir}/out/install/vs-nost-base", - "displayName": "Windows - Visual Studio - Base (Minimal, Core Lib only) - No Stacktraces (32-bit)", - "description": "Configure the base Visual Studio Minimal build with the Win32 toolchain architecture, but with no stacktraces (strict C++11).", - "cacheVariables": { - "TESTCPP_STACKTRACE_ENABLED": "0" - } - }, - { - "name": "vs-msanalysis", - "inherits": "vs-nost-base", - "binaryDir": "${sourceDir}/out/build/vs-msanalysis", - "installDir": "${sourceDir}/out/install/vs-msanalysis", - "displayName": "Windows - Visual Studio - Base (Minimal, Core Lib only) - MSVC++ Analysis (32-bit)", - "description": "Configure the base Visual Studio Minimal build with the Win32 toolchain architecture, then run the MSVC++ analyzer.", - "generator": "Visual Studio 17 2022", - "architecture": "Win32" - }, - { - "name": "vs-all", - "inherits": "vs-base", - "binaryDir": "${sourceDir}/out/build/vs-all", - "installDir": "${sourceDir}/out/install/vs-all", - "displayName": "Windows - Visual Studio - All Lib Components - Core, Tests, and Demo (32-bit)", - "description": "Configure the Visual Studio build with all Library options set and the Win32 toolchain architecture.", - "cacheVariables": { - "TESTCPP_TEST_ENABLED": "1", - "TESTCPP_DEMO_ENABLED": "1" - } - }, - { - "name": "vs-nost-all", - "inherits": "vs-nost-base", - "binaryDir": "${sourceDir}/out/build/vs-nost-all", - "installDir": "${sourceDir}/out/install/vs-nost-all", - "displayName": "Windows - Visual Studio - All Lib Components - Core, Tests, and Demo - No Stacktraces (32-bit)", - "description": "Configure the Visual Studio build with all Library options set and the Win32 toolchain architecture, but with no stacktraces (strict C++11).", - "cacheVariables": { - "TESTCPP_TEST_ENABLED": "1", - "TESTCPP_DEMO_ENABLED": "1" - } - }, - { - "name": "vs-with-test", - "inherits": "vs-base", - "binaryDir": "${sourceDir}/out/build/vs-withtest", - "installDir": "${sourceDir}/out/install/vs-withtest", - "displayName": "Windows - Visual Studio - Core Lib With Tests (32-bit)", - "description": "Configure the Visual Studio build with Core and Test Library build set and the Win32 toolchain architecture.", - "cacheVariables": { - "TESTCPP_TEST_ENABLED": "1" - } - }, - { - "name": "vs-nost-with-test", - "inherits": "vs-nost-base", - "binaryDir": "${sourceDir}/out/build/vs-nost-withtest", - "installDir": "${sourceDir}/out/install/vs-nost-withtest", - "displayName": "Windows - Visual Studio - Core Lib With Tests - No Stacktraces (32-bit)", - "description": "Configure the Visual Studio build with Core and Test Library build set and the Win32 toolchain architecture, but with no stacktraces (strict C++11).", - "cacheVariables": { - "TESTCPP_TEST_ENABLED": "1" - } - }, - { - "name": "vs-with-demo", - "inherits": "vs-base", - "binaryDir": "${sourceDir}/out/build/vs-withdemo", - "installDir": "${sourceDir}/out/install/vs-withdemo", - "displayName": "Windows - Visual Studio - Core Lib With Demo (32-bit)", - "description": "Configure the Visual Studio build with Core and Demo set and the Win32 toolchain architecture.", - "cacheVariables": { - "TESTCPP_DEMO_ENABLED": "1" - } - }, - { - "name": "vs-nost-with-demo", - "inherits": "vs-nost-base", - "binaryDir": "${sourceDir}/out/build/vs-nost-withdemo", - "installDir": "${sourceDir}/out/install/vs-nost-withdemo", - "displayName": "Windows - Visual Studio - Lib With Demo - No Stacktraces (32-bit)", - "description": "Configure the Visual Studio build with Core and Demo library build set and the Win32 toolchain architecture, but with no stacktraces (strict C++11).", - "cacheVariables": { - "TESTCPP_DEMO_ENABLED": "1" - } - }, - { - "name": "vs-ct", - "inherits": "vs-nost-base", - "binaryDir": "${sourceDir}/out/build/vs-ct", - "installDir": "${sourceDir}/out/install/vs-ct", - "displayName": "Windows - Visual Studio - Clang Tidy analysis (32-bit)", - "description": "Configure the Visual Studio build with clang-tidy analysis and the Win32 toolchain architecture.", - "cacheVariables": { - "TESTCPP_ANALYSIS_ENABLED": "1" - } - }, - { - "name": "vs64-base", - "inherits": "vs-base", - "binaryDir": "${sourceDir}/out/build/vs64-base", - "installDir": "${sourceDir}/out/install/vs64-base", - "displayName": "Windows - Visual Studio - Base (64-bit)", - "description": "Configure the base Visual Studio build with the Win64 toolchain architecture.", - "architecture": "Win64" - }, - { - "name": "vs64-nost-base", - "inherits": "vs64-base", - "binaryDir": "${sourceDir}/out/build/vs64-nost-base", - "installDir": "${sourceDir}/out/install/vs64-nost-base", - "displayName": "Windows - Visual Studio - Base - No Stacktraces (64-bit)", - "description": "Configure the base Visual Studio build with the Win64 toolchain architecture, but with no stacktraces (strict C++11).", - "cacheVariables": { - "TESTCPP_STACKTRACE_ENABLED": "0" - } - }, - { - "name": "vs64-msanalysis", - "inherits": "vs64-nost-base", - "binaryDir": "${sourceDir}/out/build/vs64-msanalysis", - "installDir": "${sourceDir}/out/install/vs64-msanalysis", - "displayName": "Windows - Visual Studio - Base (Minimal, Core Lib only) - MSVC++ Analysis (64-bit)", - "description": "Configure the base Visual Studio Minimal build with the Win64 toolchain architecture, then run the MSVC++ analyzer.", - "generator": "Visual Studio 17 2022", - "architecture": "Win64" - }, - { - "name": "vs64-all", - "inherits": "vs64-base", - "binaryDir": "${sourceDir}/out/build/vs64-all", - "installDir": "${sourceDir}/out/install/vs64-all", - "displayName": "Windows - Visual Studio - All Lib Components - Core, Tests, and Demo (64-bit)", - "description": "Configure the Visual Studio build with all Library options set and the Win64 toolchain architecture.", - "cacheVariables": { - "TESTCPP_TEST_ENABLED": "1", - "TESTCPP_DEMO_ENABLED": "1" - } - }, - { - "name": "vs64-nost-all", - "inherits": "vs64-nost-base", - "binaryDir": "${sourceDir}/out/build/vs64-nost-all", - "installDir": "${sourceDir}/out/install/vs64-nost-all", - "displayName": "Windows - Visual Studio - All Lib Components - Core, Tests, and Demo - No Stacktraces (64-bit)", - "description": "Configure the Visual Studio build with all Library options set and the Win64 toolchain architecture, but with no stacktraces (strict C++11).", - "cacheVariables": { - "TESTCPP_TEST_ENABLED": "1", - "TESTCPP_DEMO_ENABLED": "1" - } - }, - { - "name": "vs64-with-test", - "inherits": "vs64-base", - "binaryDir": "${sourceDir}/out/build/vs64-withtest", - "installDir": "${sourceDir}/out/install/vs64-withtest", - "displayName": "Windows - Visual Studio - Core Lib With Tests (64-bit)", - "description": "Configure the Visual Studio build with Core and Test Library build set and the Win64 toolchain architecture.", - "cacheVariables": { - "TESTCPP_TEST_ENABLED": "1" - } - }, - { - "name": "vs64-nost-with-test", - "inherits": "vs64-nost-base", - "binaryDir": "${sourceDir}/out/build/vs64-nost-withtest", - "installDir": "${sourceDir}/out/install/vs64-nost-withtest", - "displayName": "Windows - Visual Studio - Core Lib With Tests - No Stacktraces (64-bit)", - "description": "Configure the Visual Studio build with Core and Test Library build set and the Win64 toolchain architecture, but with no stacktraces (strict C++11).", - "cacheVariables": { - "TESTCPP_TEST_ENABLED": "1" - } - }, - { - "name": "vs64-with-demo", - "inherits": "vs64-base", - "binaryDir": "${sourceDir}/out/build/vs64-withdemo", - "installDir": "${sourceDir}/out/install/vs64-withdemo", - "displayName": "Windows - Visual Studio - Core Lib With Demo (64-bit)", - "description": "Configure the Visual Studio build with Core and Demo set and the Win64 toolchain architecture.", - "cacheVariables": { - "TESTCPP_DEMO_ENABLED": "1" - } - }, - { - "name": "vs64-nost-with-demo", - "inherits": "vs64-nost-base", - "binaryDir": "${sourceDir}/out/build/vs64-nost-withdemo", - "installDir": "${sourceDir}/out/install/vs64-nost-withdemo", - "displayName": "Windows - Visual Studio - Lib With Demo - No Stacktraces (64-bit)", - "description": "Configure the Visual Studio build with Core and Demo library build set and the Win64 toolchain architecture, but with no stacktraces (strict C++11).", - "cacheVariables": { - "TESTCPP_DEMO_ENABLED": "1" - } - }, - { - "name": "vs64-ct", - "inherits": "vs64-nost-base", - "binaryDir": "${sourceDir}/out/build/vs64-ct", - "installDir": "${sourceDir}/out/install/vs64-ct", - "displayName": "Windows - Visual Studio - Clang Tidy analysis (64-bit)", - "description": "Configure the Visual Studio build with clang-tidy analysis and the Win64 toolchain architecture.", - "cacheVariables": { - "TESTCPP_ANALYSIS_ENABLED": "1" - } - } - ] -} diff --git a/cmake/presets/packaging.json b/cmake/presets/packaging.json deleted file mode 100644 index 5898531..0000000 --- a/cmake/presets/packaging.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "packagePresets": [ - { - "name": "base-pack", - "generators": [ - "ZIP" - ], - "output": { - "verbose": true - } - }, - { - "name": "vs-pack", - "configurePreset": "vs-base", - "inherits": "base-pack", - "generators": [ - "7Z", - "NSIS", - "WIX" - ], - "condition": { - "type": "equals", - "lhs": "${hostSystemName}", - "rhs": "Windows" - } - }, - { - "name": "vs-nost-pack", - "configurePreset": "vs-nost-base", - "inherits": "vs-pack" - }, - { - "name": "vs64-pack", - "configurePreset": "vs64-base", - "inherits": "vs-pack" - }, - { - "name": "vs64-nost-pack", - "configurePreset": "vs64-nost-base", - "inherits": "vs-nost-pack" - } - ] -} \ No newline at end of file diff --git a/cmake/presets/testing.json b/cmake/presets/testing.json deleted file mode 100644 index eb1f0bf..0000000 --- a/cmake/presets/testing.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "testPresets": [ - { - "name": "vs-test", - "configurePreset": "vs-with-test", - "output": { - "shortProgress": true, - "verbosity": "verbose", - "outputOnFailure": true, - "outputJUnitFile": "${sourceDir}/out/test/vs-test/results.xml" - }, - "execution": { - "noTestsAction": "error", - "stopOnFailure": false - }, - "condition": { - "type": "equals", - "lhs": "${hostSystemName}", - "rhs": "Windows" - } - }, - { - "name": "vs-nost-test", - "configurePreset": "vs-nost-with-test", - "inherits": "vs-test", - "output": { - "outputJUnitFile": "${sourceDir}/out/test/vs-nost-test/results.xml" - } - }, - { - "name": "vs64-test", - "configurePreset": "vs64-with-test", - "inherits": "vs-test", - "output": { - "outputJUnitFile": "${sourceDir}/out/test/vs64-test/results.xml" - } - }, - { - "name": "vs64-nost-test", - "configurePreset": "vs64-nost-with-test", - "inherits": "vs-nost-test", - "output": { - "outputJUnitFile": "${sourceDir}/out/test/vs64-nost-test/results.xml" - } - } - ] -} \ No newline at end of file From 4915fcb17a4c261791ed01432bfd0f8fc250acf4 Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Fri, 24 Jan 2025 14:36:45 -0800 Subject: [PATCH 44/59] Remove outputJUnitFile since VS appears to not support version 6, reduce version to 5 --- CMakePresets.json | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/CMakePresets.json b/CMakePresets.json index 9c5069b..bf76016 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -1,8 +1,8 @@ { - "version": 6, + "version": 5, "cmakeMinimumRequired": { "major": 3, - "minor": 25, + "minor": 24, "patch": 0 }, "configurePresets": [ @@ -371,8 +371,7 @@ "output": { "shortProgress": true, "verbosity": "verbose", - "outputOnFailure": true, - "outputJUnitFile": "${sourceDir}/out/test/vs-test/results.xml" + "outputOnFailure": true }, "execution": { "noTestsAction": "error", @@ -387,26 +386,17 @@ { "name": "vs-nost-test", "configurePreset": "vs-nost-with-test", - "inherits": "vs-test", - "output": { - "outputJUnitFile": "${sourceDir}/out/test/vs-nost-test/results.xml" - } + "inherits": "vs-test" }, { "name": "vs64-test", "configurePreset": "vs64-with-test", - "inherits": "vs-test", - "output": { - "outputJUnitFile": "${sourceDir}/out/test/vs64-test/results.xml" - } + "inherits": "vs-test" }, { "name": "vs64-nost-test", "configurePreset": "vs64-nost-with-test", - "inherits": "vs-nost-test", - "output": { - "outputJUnitFile": "${sourceDir}/out/test/vs64-nost-test/results.xml" - } + "inherits": "vs-nost-test" } ], "packagePresets": [ From 712af9c04e079d76ca566e752fd3938820b41ce9 Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Wed, 5 Feb 2025 19:37:54 -0800 Subject: [PATCH 45/59] Update presets so all configurations are covered as buildPresets, fixes CMakePresets is now modified such that: - there are buildPresets that correspond to all configurationPresets, so the proper base native tool options are applied to all relevant configurations when running a build in VS or on the command line - issues are addressed - added descriptions/names where missing - made presets hidden where appropriate so they don't show up in the VS build configurations menu, and so they can't be referenced when the cmake tool is invoked on the command line Fixed an issue in BuildTypeHandling.cmake where when building with ClangCL for running clang-tidy on Windows with (or without) VS, it was selecting MSVC++ tool options instead of GCC/Clang tool options since it is indeed running an MSBuild build, but the underlying toolchain is ClangCL Added some whitespace where it seemed to make it easier to read. Added the following gcc/clang switches: -Wno-c++98-compat - Because there are C++11 and greater features that conflict with C++98 compatibility, but that's ok because the project is only intended to be built with C++11 or newer -Wno-c++98-compat-pedantic - Same reason as for Wno-c++98-compat -Wno-covered-switch-default - Clang was giving me some confusing results... keep the default: case in my switch, and it would output this from -Wcovered-switch-default: error : default label in switch which covers all enumeration values [-Werror,-Wcovered-switch-default] Then in rewriting it so there's no default: case but basically works the same way, Clang would output this from -Wswitch-default: error : 'switch' missing 'default' label [-Werror,-Wswitch-default] So I go look it up and find this gem on SE-SoftwareEngineering-design: https://lnkd.in/gg8d7U2T I opted for defensive programming, as I usually do, left the default: case in the switch, and added -Wno-covered-switch-default to my build. It seems like it's probably the most correct thing to do... at risk of having an extremely weird (read: improbable) situation where disabling this warning would cause me to miss a bug. I think it's more likely that there would be a bug as a result of not having a default case to handle erroneous values since enums in C/C++ are not strongly-typed (a la Java). I'm not using -Weverything, so I find it odd that there are clashes in warnings, but it was an interesting exercise to work through this issue. I would much rather have -Wswitch-default enabled, because that can catch some really nasty issues; this is just a weird pedantic annoyance, where the default: case is for "just in case" because of the lack of type checking, as I mentioned already. I did not find arguments on StackOverflow very compelling that argued against a default case when all known explicitly-defined cases are covered; since enums are value-based types, they can hold any value of the underlying type, which the compiler might or might not warn about/catch; the collection of known cases is typically a very tiny subset of the set of all possible values (4+ billion with the default underlying int type), so there should be an escape hatch for if the programmer knowningly or unknowingly ventures outside those explicitly-defined cases, where it would make sense to do so and a sensible default can be used or an error/exception can be generated, instead of just crashing the host application with no information about why there was a crash; I didn't want to use an assert because the values can change and are not tied explicitly to the symbols, so an assert could easily be broken. --- CMakePresets.json | 980 ++++++++++++++++++++++++------ cmake/BuildTypeHandling.cmake | 12 +- cmake/Targets.cmake | 1 + cmake/build/GCCClangDebug.cmake | 47 +- cmake/build/GCCClangRelease.cmake | 45 +- cmake/build/GCCCoverage.cmake | 30 +- 6 files changed, 892 insertions(+), 223 deletions(-) diff --git a/CMakePresets.json b/CMakePresets.json index bf76016..9bfc520 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -8,7 +8,10 @@ "configurePresets": [ { "name": "base", + "description": "Base configuration that defines Cache Variables and Dev Warnings, using the Debug build options.", + "hidden": true, "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", "CMAKE_EXPORT_COMPILE_COMMANDS": "0", "TESTCPP_STACKTRACE_ENABLED": "0", "TESTCPP_ANALYSIS_ENABLED": "0", @@ -26,8 +29,9 @@ }, { "name": "base-dev-checks", - "description": "Base config preset with dev checks enabled.", + "description": "Base config preset with dev checks enabled, using the Debug build options.", "inherits": "base", + "hidden": true, "warnings": { "dev": true, "deprecated": true, @@ -37,36 +41,43 @@ } }, { - "name": "export-cc-st-base", - "inherits": "base", - "cacheVariables": { - "CMAKE_EXPORT_COMPILE_COMMANDS": "1", - "TESTCPP_STACKTRACE_ENABLED": "1" + "name": "vs-dev-checks", + "displayName": "CMake - Windows - Visual Studio - Dev Checks", + "description": "Windows VS config preset with dev checks enabled, using the Debug build options.", + "inherits": "base-dev-checks", + "binaryDir": "${sourceDir}/out/build/vs-dev-checks", + "installDir": "${sourceDir}/out/install/vs-dev-checks", + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Windows" } }, { "name": "export-cc-nost-base", + "description": "Base configuration ensures Compile Commands are exported, using the Debug build options, with no stacktraces (strict C++11).", "inherits": "base", + "hidden": true, "cacheVariables": { "CMAKE_EXPORT_COMPILE_COMMANDS": "1" } }, { - "name": "vs-dev-checks", - "inherits": "base-dev-checks", - "condition": { - "type": "equals", - "lhs": "${hostSystemName}", - "rhs": "Windows" + "name": "export-cc-st-base", + "description": "Base configuration ensures Compile Commands are exported and Stack Traces are enabled, using the Debug build options.", + "inherits": "export-cc-nost-base", + "hidden": true, + "cacheVariables": { + "TESTCPP_STACKTRACE_ENABLED": "1" } }, { "name": "vs-base", + "displayName": "Generate - x86 - Debug - Windows - Visual Studio - Core Lib", + "description": "Configure the base Visual Studio Minimal build with the Win32 toolchain architecture, using the Debug build options.", "inherits": "export-cc-st-base", - "binaryDir": "${sourceDir}/out/build/vs-base", - "installDir": "${sourceDir}/out/install/vs-base", - "displayName": "Windows - Visual Studio - Base (Minimal, Core Lib only) (32-bit)", - "description": "Configure the base Visual Studio Minimal build with the Win32 toolchain architecture.", + "binaryDir": "${sourceDir}/out/build/Debug/vs-base", + "installDir": "${sourceDir}/out/install/Debug/vs-base", "generator": "Visual Studio 17 2022", "architecture": "Win32", "condition": { @@ -75,219 +86,408 @@ "rhs": "Windows" } }, + { + "name": "vs-base-rel", + "displayName": "Generate - x86 - Release - Windows - Visual Studio - Core Lib", + "description": "Configure the base Visual Studio Minimal build with the Win32 toolchain architecture, using the Release build options.", + "inherits": "vs-base", + "binaryDir": "${sourceDir}/out/build/Release/vs-base", + "installDir": "${sourceDir}/out/install/Release/vs-base", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release" + } + }, { "name": "vs-nost-base", + "displayName": "Generate - x86 - Debug - Windows - Visual Studio - Core Lib - No Stacktraces", + "description": "Configure the base Visual Studio Minimal build with the Win32 toolchain architecture, using the Debug build options, but with no stacktraces (strict C++11).", "inherits": "export-cc-nost-base", - "binaryDir": "${sourceDir}/out/build/vs-nost-base", - "installDir": "${sourceDir}/out/install/vs-nost-base", - "displayName": "Windows - Visual Studio - Base (Minimal, Core Lib only) - No Stacktraces (32-bit)", - "description": "Configure the base Visual Studio Minimal build with the Win32 toolchain architecture, but with no stacktraces (strict C++11).", + "binaryDir": "${sourceDir}/out/build/Debug/vs-nost-base", + "installDir": "${sourceDir}/out/install/Debug/vs-nost-base", + "generator": "Visual Studio 17 2022", + "architecture": "Win32", + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Windows" + } + }, + { + "name": "vs-nost-base-rel", + "displayName": "Generate - x86 - Release - Windows - Visual Studio - Core Lib - No Stacktraces", + "description": "Configure the base Visual Studio Minimal build with the Win32 toolchain architecture, using the Release build options, but with no stacktraces (strict C++11).", + "inherits": "vs-nost-base", + "binaryDir": "${sourceDir}/out/build/Release/vs-nost-base", + "installDir": "${sourceDir}/out/install/Release/vs-nost-base", "cacheVariables": { - "TESTCPP_STACKTRACE_ENABLED": "0" + "CMAKE_BUILD_TYPE": "Release" } }, { "name": "vs-msanalysis", + "displayName": "Generate - x86 - Windows - Visual Studio - MSVC Analysis", + "description": "Configure the base Visual Studio Minimal build to prepare for running the MSVC++ analyzer.", "inherits": "vs-nost-base", "binaryDir": "${sourceDir}/out/build/vs-msanalysis", "installDir": "${sourceDir}/out/install/vs-msanalysis", - "displayName": "Windows - Visual Studio - Base (Minimal, Core Lib only) - MSVC++ Analysis (32-bit)", - "description": "Configure the base Visual Studio Minimal build with the Win32 toolchain architecture, then run the MSVC++ analyzer.", - "generator": "Visual Studio 17 2022", - "architecture": "Win32" + "vendor": { + "microsoft.com/VisualStudioSettings/CMake/1.0": { + "intelliSenseMode": "windows-msvc-x86", + "enableMicrosoftCodeAnalysis": true + } + } }, { - "name": "vs-all", + "name": "vs-with-test", + "displayName": "Generate - x86 - Debug - Windows - Visual Studio - Core Lib With Tests", + "description": "Configure the Visual Studio build with Core and Test Library build set and the Win32 toolchain architecture, using the Debug build options.", "inherits": "vs-base", - "binaryDir": "${sourceDir}/out/build/vs-all", - "installDir": "${sourceDir}/out/install/vs-all", - "displayName": "Windows - Visual Studio - All Lib Components - Core, Tests, and Demo (32-bit)", - "description": "Configure the Visual Studio build with all Library options set and the Win32 toolchain architecture.", + "binaryDir": "${sourceDir}/out/build/Debug/vs-withtest", + "installDir": "${sourceDir}/out/install/Debug/vs-withtest", "cacheVariables": { - "TESTCPP_TEST_ENABLED": "1", - "TESTCPP_DEMO_ENABLED": "1" + "TESTCPP_TEST_ENABLED": "1" } }, { - "name": "vs-nost-all", - "inherits": "vs-nost-base", - "binaryDir": "${sourceDir}/out/build/vs-nost-all", - "installDir": "${sourceDir}/out/install/vs-nost-all", - "displayName": "Windows - Visual Studio - All Lib Components - Core, Tests, and Demo - No Stacktraces (32-bit)", - "description": "Configure the Visual Studio build with all Library options set and the Win32 toolchain architecture, but with no stacktraces (strict C++11).", + "name": "vs-with-test-rel", + "displayName": "Generate - x86 - Release - Windows - Visual Studio - Core Lib With Tests", + "description": "Configure the Visual Studio build with Core and Test Library build set and the Win32 toolchain architecture, using the Release build options.", + "inherits": "vs-base-rel", + "binaryDir": "${sourceDir}/out/build/Release/vs-withtest", + "installDir": "${sourceDir}/out/install/Release/vs-withtest", "cacheVariables": { - "TESTCPP_TEST_ENABLED": "1", - "TESTCPP_DEMO_ENABLED": "1" + "TESTCPP_TEST_ENABLED": "1" } }, { - "name": "vs-with-test", - "inherits": "vs-base", - "binaryDir": "${sourceDir}/out/build/vs-withtest", - "installDir": "${sourceDir}/out/install/vs-withtest", - "displayName": "Windows - Visual Studio - Core Lib With Tests (32-bit)", - "description": "Configure the Visual Studio build with Core and Test Library build set and the Win32 toolchain architecture.", + "name": "vs-nost-with-test", + "displayName": "Generate - x86 - Debug - Windows - Visual Studio - Core Lib With Tests - No Stacktraces", + "description": "Configure the Visual Studio build with Core and Test Library build set and the Win32 toolchain architecture, using the Debug build options, but with no stacktraces (strict C++11).", + "inherits": "vs-nost-base", + "binaryDir": "${sourceDir}/out/build/Debug/vs-nost-withtest", + "installDir": "${sourceDir}/out/install/Debug/vs-nost-withtest", "cacheVariables": { "TESTCPP_TEST_ENABLED": "1" } }, { - "name": "vs-nost-with-test", - "inherits": "vs-nost-base", - "binaryDir": "${sourceDir}/out/build/vs-nost-withtest", - "installDir": "${sourceDir}/out/install/vs-nost-withtest", - "displayName": "Windows - Visual Studio - Core Lib With Tests - No Stacktraces (32-bit)", - "description": "Configure the Visual Studio build with Core and Test Library build set and the Win32 toolchain architecture, but with no stacktraces (strict C++11).", + "name": "vs-nost-with-test-rel", + "displayName": "Generate - x86 - Release - Windows - Visual Studio - Core Lib With Tests - No Stacktraces", + "description": "Configure the Visual Studio build with Core and Test Library build set and the Win32 toolchain architecture, using the Release build options, but with no stacktraces (strict C++11).", + "inherits": "vs-nost-base-rel", + "binaryDir": "${sourceDir}/out/build/Release/vs-nost-withtest", + "installDir": "${sourceDir}/out/install/Release/vs-nost-withtest", "cacheVariables": { "TESTCPP_TEST_ENABLED": "1" } }, { "name": "vs-with-demo", + "displayName": "Generate - x86 - Debug - Windows - Visual Studio - Core Lib With Demo", + "description": "Configure the Visual Studio build with Core and Demo set and the Win32 toolchain architecture, using the Debug build options.", "inherits": "vs-base", - "binaryDir": "${sourceDir}/out/build/vs-withdemo", - "installDir": "${sourceDir}/out/install/vs-withdemo", - "displayName": "Windows - Visual Studio - Core Lib With Demo (32-bit)", - "description": "Configure the Visual Studio build with Core and Demo set and the Win32 toolchain architecture.", + "binaryDir": "${sourceDir}/out/build/Debug/vs-withdemo", + "installDir": "${sourceDir}/out/install/Debug/vs-withdemo", + "cacheVariables": { + "TESTCPP_DEMO_ENABLED": "1" + } + }, + { + "name": "vs-with-demo-rel", + "displayName": "Generate - x86 - Release - Windows - Visual Studio - Core Lib With Demo", + "description": "Configure the Visual Studio build with Core and Demo set and the Win32 toolchain architecture, using the Release build options.", + "inherits": "vs-base-rel", + "binaryDir": "${sourceDir}/out/build/Release/vs-withdemo", + "installDir": "${sourceDir}/out/install/Release/vs-withdemo", "cacheVariables": { "TESTCPP_DEMO_ENABLED": "1" } }, { "name": "vs-nost-with-demo", + "displayName": "Generate - x86 - Debug - Windows - Visual Studio - Core Lib With Demo - No Stacktraces", + "description": "Configure the Visual Studio build with Core and Demo library build set and the Win32 toolchain architecture, using the Debug build options, but with no stacktraces (strict C++11).", "inherits": "vs-nost-base", - "binaryDir": "${sourceDir}/out/build/vs-nost-withdemo", - "installDir": "${sourceDir}/out/install/vs-nost-withdemo", - "displayName": "Windows - Visual Studio - Lib With Demo - No Stacktraces (32-bit)", - "description": "Configure the Visual Studio build with Core and Demo library build set and the Win32 toolchain architecture, but with no stacktraces (strict C++11).", + "binaryDir": "${sourceDir}/out/build/Debug/vs-nost-withdemo", + "installDir": "${sourceDir}/out/install/Debug/vs-nost-withdemo", + "cacheVariables": { + "TESTCPP_DEMO_ENABLED": "1" + } + }, + { + "name": "vs-nost-with-demo-rel", + "displayName": "Generate - x86 - Release - Windows - Visual Studio - Core Lib With Demo - No Stacktraces", + "description": "Configure the Visual Studio build with Core and Demo library build set and the Win32 toolchain architecture, using the Release build options, but with no stacktraces (strict C++11).", + "inherits": "vs-nost-base-rel", + "binaryDir": "${sourceDir}/out/build/Release/vs-nost-withdemo", + "installDir": "${sourceDir}/out/install/Release/vs-nost-withdemo", + "cacheVariables": { + "TESTCPP_DEMO_ENABLED": "1" + } + }, + { + "name": "vs-all", + "displayName": "Generate - x86 - Debug - Windows - Visual Studio - All Components - Core, Tests, and Demo", + "description": "Configure the Visual Studio build with all Library options set and the Win32 toolchain architecture, using the Debug build options.", + "inherits": "vs-with-test", + "binaryDir": "${sourceDir}/out/build/Debug/vs-all", + "installDir": "${sourceDir}/out/install/Debug/vs-all", + "cacheVariables": { + "TESTCPP_DEMO_ENABLED": "1" + } + }, + { + "name": "vs-all-rel", + "displayName": "Generate - x86 - Release - Windows - Visual Studio - All Components - Core, Tests, and Demo", + "description": "Configure the Visual Studio build with all Library options set and the Win32 toolchain architecture, using the Release build options.", + "inherits": "vs-with-test-rel", + "binaryDir": "${sourceDir}/out/build/Release/vs-all", + "installDir": "${sourceDir}/out/install/Release/vs-all", + "cacheVariables": { + "TESTCPP_DEMO_ENABLED": "1" + } + }, + { + "name": "vs-nost-all", + "displayName": "Generate - x86 - Debug - Windows - Visual Studio - All Components - Core, Tests, and Demo - No Stacktraces", + "description": "Configure the Visual Studio build with all Library options set and the Win32 toolchain architecture, using the Debug build options, but with no stacktraces (strict C++11).", + "inherits": "vs-nost-with-test", + "binaryDir": "${sourceDir}/out/build/Debug/vs-nost-all", + "installDir": "${sourceDir}/out/install/Debug/vs-nost-all", + "cacheVariables": { + "TESTCPP_DEMO_ENABLED": "1" + } + }, + { + "name": "vs-nost-all-rel", + "displayName": "Generate - x86 - Release - Windows - Visual Studio - All Components - Core, Tests, and Demo - No Stacktraces", + "description": "Configure the Visual Studio build with all Library options set and the Win32 toolchain architecture, using the Release build options, but with no stacktraces (strict C++11).", + "inherits": "vs-nost-with-test-rel", + "binaryDir": "${sourceDir}/out/build/Release/vs-nost-all", + "installDir": "${sourceDir}/out/install/Release/vs-nost-all", "cacheVariables": { "TESTCPP_DEMO_ENABLED": "1" } }, { "name": "vs-ct", + "displayName": "Generate - x86 - Windows - Visual Studio - Clang Tidy analysis", + "description": "Configure the Visual Studio build with clang-tidy analysis and the x86 toolchain architecture.", "inherits": "vs-nost-base", "binaryDir": "${sourceDir}/out/build/vs-ct", "installDir": "${sourceDir}/out/install/vs-ct", - "displayName": "Windows - Visual Studio - Clang Tidy analysis (32-bit)", - "description": "Configure the Visual Studio build with clang-tidy analysis and the Win32 toolchain architecture.", "cacheVariables": { "TESTCPP_ANALYSIS_ENABLED": "1" + }, + "toolset": "ClangCL", + "vendor": { + "microsoft.com/VisualStudioSettings/CMake/1.0": { + "intelliSenseMode": "windows-clang-x86" + } } }, { "name": "vs64-base", + "displayName": "Generate - x64 - Debug - Windows - Visual Studio - Core Lib", + "description": "Configure the base Visual Studio build with the x64 toolchain architecture, using the Debug build options.", "inherits": "vs-base", - "binaryDir": "${sourceDir}/out/build/vs64-base", - "installDir": "${sourceDir}/out/install/vs64-base", - "displayName": "Windows - Visual Studio - Base (64-bit)", - "description": "Configure the base Visual Studio build with the Win64 toolchain architecture.", - "architecture": "Win64" + "binaryDir": "${sourceDir}/out/build/Debug/vs64-base", + "installDir": "${sourceDir}/out/install/Debug/vs64-base", + "architecture": "x64" + }, + { + "name": "vs64-base-rel", + "displayName": "Generate - x64 - Release - Windows - Visual Studio - Core Lib", + "description": "Configure the base Visual Studio build with the x64 toolchain architecture, using the Release build options.", + "inherits": "vs-base-rel", + "binaryDir": "${sourceDir}/out/build/Release/vs64-base", + "installDir": "${sourceDir}/out/install/Release/vs64-base", + "architecture": "x64" }, { "name": "vs64-nost-base", - "inherits": "vs64-base", - "binaryDir": "${sourceDir}/out/build/vs64-nost-base", - "installDir": "${sourceDir}/out/install/vs64-nost-base", - "displayName": "Windows - Visual Studio - Base - No Stacktraces (64-bit)", - "description": "Configure the base Visual Studio build with the Win64 toolchain architecture, but with no stacktraces (strict C++11).", - "cacheVariables": { - "TESTCPP_STACKTRACE_ENABLED": "0" - } + "displayName": "Generate - x64 - Debug - Windows - Visual Studio - Core Lib - No Stacktraces", + "description": "Configure the base Visual Studio build with the x64 toolchain architecture, using the Debug build options, but with no stacktraces (strict C++11).", + "inherits": "vs-nost-base", + "binaryDir": "${sourceDir}/out/build/Debug/vs64-nost-base", + "installDir": "${sourceDir}/out/install/Debug/vs64-nost-base", + "architecture": "x64" + }, + { + "name": "vs64-nost-base-rel", + "displayName": "Generate - x64 - Release - Windows - Visual Studio - Core Lib - No Stacktraces", + "description": "Configure the base Visual Studio build with the x64 toolchain architecture, using the Release build options, but with no stacktraces (strict C++11).", + "inherits": "vs-nost-base-rel", + "binaryDir": "${sourceDir}/out/build/Release/vs64-nost-base", + "installDir": "${sourceDir}/out/install/Release/vs64-nost-base", + "architecture": "x64" }, { "name": "vs64-msanalysis", - "inherits": "vs64-nost-base", + "displayName": "Generate - x64 - Windows - Visual Studio - MSVC Analysis", + "description": "Configure the base Visual Studio Minimal build with the x64 toolchain architecture, then run the MSVC++ analyzer.", + "inherits": "vs-msanalysis", "binaryDir": "${sourceDir}/out/build/vs64-msanalysis", "installDir": "${sourceDir}/out/install/vs64-msanalysis", - "displayName": "Windows - Visual Studio - Base (Minimal, Core Lib only) - MSVC++ Analysis (64-bit)", - "description": "Configure the base Visual Studio Minimal build with the Win64 toolchain architecture, then run the MSVC++ analyzer.", - "generator": "Visual Studio 17 2022", - "architecture": "Win64" + "architecture": "x64", + "vendor": { + "microsoft.com/VisualStudioSettings/CMake/1.0": { + "intelliSenseMode": "windows-msvc-x64" + } + } }, { - "name": "vs64-all", + "name": "vs64-with-test", + "displayName": "Generate - x64 - Debug - Windows - Visual Studio - Core Lib With Tests", + "description": "Configure the Visual Studio build with Core and Test Library build set and the x64 toolchain architecture, using the Debug build options.", "inherits": "vs64-base", - "binaryDir": "${sourceDir}/out/build/vs64-all", - "installDir": "${sourceDir}/out/install/vs64-all", - "displayName": "Windows - Visual Studio - All Lib Components - Core, Tests, and Demo (64-bit)", - "description": "Configure the Visual Studio build with all Library options set and the Win64 toolchain architecture.", + "binaryDir": "${sourceDir}/out/build/Debug/vs64-withtest", + "installDir": "${sourceDir}/out/install/Debug/vs64-withtest", "cacheVariables": { - "TESTCPP_TEST_ENABLED": "1", - "TESTCPP_DEMO_ENABLED": "1" + "TESTCPP_TEST_ENABLED": "1" } }, { - "name": "vs64-nost-all", - "inherits": "vs64-nost-base", - "binaryDir": "${sourceDir}/out/build/vs64-nost-all", - "installDir": "${sourceDir}/out/install/vs64-nost-all", - "displayName": "Windows - Visual Studio - All Lib Components - Core, Tests, and Demo - No Stacktraces (64-bit)", - "description": "Configure the Visual Studio build with all Library options set and the Win64 toolchain architecture, but with no stacktraces (strict C++11).", + "name": "vs64-with-test-rel", + "displayName": "Generate - x64 - Release - Windows - Visual Studio - Core Lib With Tests", + "description": "Configure the Visual Studio build with Core and Test Library build set and the x64 toolchain architecture, using the Release build options.", + "inherits": "vs64-base-rel", + "binaryDir": "${sourceDir}/out/build/Release/vs64-withtest", + "installDir": "${sourceDir}/out/install/Release/vs64-withtest", "cacheVariables": { - "TESTCPP_TEST_ENABLED": "1", - "TESTCPP_DEMO_ENABLED": "1" + "TESTCPP_TEST_ENABLED": "1" } }, { - "name": "vs64-with-test", - "inherits": "vs64-base", - "binaryDir": "${sourceDir}/out/build/vs64-withtest", - "installDir": "${sourceDir}/out/install/vs64-withtest", - "displayName": "Windows - Visual Studio - Core Lib With Tests (64-bit)", - "description": "Configure the Visual Studio build with Core and Test Library build set and the Win64 toolchain architecture.", + "name": "vs64-nost-with-test", + "displayName": "Generate - x64 - Debug - Windows - Visual Studio - Core Lib With Tests - No Stacktraces", + "description": "Configure the Visual Studio build with Core and Test Library build set and the x64 toolchain architecture, using the Debug build options, but with no stacktraces (strict C++11).", + "inherits": "vs64-nost-base", + "binaryDir": "${sourceDir}/out/build/Debug/vs64-nost-withtest", + "installDir": "${sourceDir}/out/install/Debug/vs64-nost-withtest", "cacheVariables": { "TESTCPP_TEST_ENABLED": "1" } }, { - "name": "vs64-nost-with-test", - "inherits": "vs64-nost-base", - "binaryDir": "${sourceDir}/out/build/vs64-nost-withtest", - "installDir": "${sourceDir}/out/install/vs64-nost-withtest", - "displayName": "Windows - Visual Studio - Core Lib With Tests - No Stacktraces (64-bit)", - "description": "Configure the Visual Studio build with Core and Test Library build set and the Win64 toolchain architecture, but with no stacktraces (strict C++11).", + "name": "vs64-nost-with-test-rel", + "displayName": "Generate - x64 - Release - Windows - Visual Studio - Core Lib With Tests - No Stacktraces", + "description": "Configure the Visual Studio build with Core and Test Library build set and the x64 toolchain architecture, using the Release build options, but with no stacktraces (strict C++11).", + "inherits": "vs64-nost-base-rel", + "binaryDir": "${sourceDir}/out/build/Release/vs64-nost-withtest", + "installDir": "${sourceDir}/out/install/Release/vs64-nost-withtest", "cacheVariables": { "TESTCPP_TEST_ENABLED": "1" } }, { "name": "vs64-with-demo", + "displayName": "Generate - x64 - Debug - Windows - Visual Studio - Core Lib With Demo", + "description": "Configure the Visual Studio build with Core and Demo set and the x64 toolchain architecture, using the Debug build options.", "inherits": "vs64-base", - "binaryDir": "${sourceDir}/out/build/vs64-withdemo", - "installDir": "${sourceDir}/out/install/vs64-withdemo", - "displayName": "Windows - Visual Studio - Core Lib With Demo (64-bit)", - "description": "Configure the Visual Studio build with Core and Demo set and the Win64 toolchain architecture.", + "binaryDir": "${sourceDir}/out/build/Debug/vs64-withdemo", + "installDir": "${sourceDir}/out/install/Debug/vs64-withdemo", + "cacheVariables": { + "TESTCPP_DEMO_ENABLED": "1" + } + }, + { + "name": "vs64-with-demo-rel", + "displayName": "Generate - x64 - Release - Windows - Visual Studio - Core Lib With Demo", + "description": "Configure the Visual Studio build with Core and Demo set and the x64 toolchain architecture, using the Release build options.", + "inherits": "vs64-base-rel", + "binaryDir": "${sourceDir}/out/build/Release/vs64-withdemo", + "installDir": "${sourceDir}/out/install/Release/vs64-withdemo", "cacheVariables": { "TESTCPP_DEMO_ENABLED": "1" } }, { "name": "vs64-nost-with-demo", + "displayName": "Generate - x64 - Debug - Windows - Visual Studio - Core Lib With Demo - No Stacktraces", + "description": "Configure the Visual Studio build with Core and Demo library build set and the x64 toolchain architecture, using the Debug build options, but with no stacktraces (strict C++11).", "inherits": "vs64-nost-base", - "binaryDir": "${sourceDir}/out/build/vs64-nost-withdemo", - "installDir": "${sourceDir}/out/install/vs64-nost-withdemo", - "displayName": "Windows - Visual Studio - Lib With Demo - No Stacktraces (64-bit)", - "description": "Configure the Visual Studio build with Core and Demo library build set and the Win64 toolchain architecture, but with no stacktraces (strict C++11).", + "binaryDir": "${sourceDir}/out/build/Debug/vs64-nost-withdemo", + "installDir": "${sourceDir}/out/install/Debug/vs64-nost-withdemo", + "cacheVariables": { + "TESTCPP_DEMO_ENABLED": "1" + } + }, + { + "name": "vs64-nost-with-demo-rel", + "displayName": "Generate - x64 - Release - Windows - Visual Studio - Core Lib With Demo - No Stacktraces", + "description": "Configure the Visual Studio build with Core and Demo library build set and the x64 toolchain architecture, using the Release build options, but with no stacktraces (strict C++11).", + "inherits": "vs64-nost-base-rel", + "binaryDir": "${sourceDir}/out/build/Release/vs64-nost-withdemo", + "installDir": "${sourceDir}/out/install/Release/vs64-nost-withdemo", + "cacheVariables": { + "TESTCPP_DEMO_ENABLED": "1" + } + }, + { + "name": "vs64-all", + "displayName": "Generate - x64 - Debug - Windows - Visual Studio - All Components - Core, Tests, and Demo", + "description": "Configure the Visual Studio build with all Library options set and the x64 toolchain architecture, using the Debug build options.", + "inherits": "vs64-with-test", + "binaryDir": "${sourceDir}/out/build/Debug/vs64-all", + "installDir": "${sourceDir}/out/install/Debug/vs64-all", + "cacheVariables": { + "TESTCPP_DEMO_ENABLED": "1" + } + }, + { + "name": "vs64-all-rel", + "displayName": "Generate - x64 - Release - Windows - Visual Studio - All Components - Core, Tests, and Demo", + "description": "Configure the Visual Studio build with all Library options set and the x64 toolchain architecture, using the Release build options.", + "inherits": "vs64-with-test-rel", + "binaryDir": "${sourceDir}/out/build/Release/vs64-all", + "installDir": "${sourceDir}/out/install/Release/vs64-all", + "cacheVariables": { + "TESTCPP_DEMO_ENABLED": "1" + } + }, + { + "name": "vs64-nost-all", + "displayName": "Generate - x64 - Debug - Windows - Visual Studio - All Components - Core, Tests, and Demo - No Stacktraces", + "description": "Configure the Visual Studio build with all Library options set and the x64 toolchain architecture, using the Debug build options, but with no stacktraces (strict C++11).", + "inherits": "vs64-nost-with-test", + "binaryDir": "${sourceDir}/out/build/Debug/vs64-nost-all", + "installDir": "${sourceDir}/out/install/Debug/vs64-nost-all", + "cacheVariables": { + "TESTCPP_DEMO_ENABLED": "1" + } + }, + { + "name": "vs64-nost-all-rel", + "displayName": "Generate - x64 - Release - Windows - Visual Studio - All Components - Core, Tests, and Demo - No Stacktraces", + "description": "Configure the Visual Studio build with all Library options set and the x64 toolchain architecture, using the Release build options, but with no stacktraces (strict C++11).", + "inherits": "vs64-nost-with-test-rel", + "binaryDir": "${sourceDir}/out/build/Release/vs64-nost-all", + "installDir": "${sourceDir}/out/install/Release/vs64-nost-all", "cacheVariables": { "TESTCPP_DEMO_ENABLED": "1" } }, { "name": "vs64-ct", - "inherits": "vs64-nost-base", + "displayName": "Generate - x64 - Windows - Visual Studio - Clang Tidy analysis", + "description": "Configure the Visual Studio build with clang-tidy analysis and the x64 toolchain architecture.", + "inherits": "vs-ct", "binaryDir": "${sourceDir}/out/build/vs64-ct", "installDir": "${sourceDir}/out/install/vs64-ct", - "displayName": "Windows - Visual Studio - Clang Tidy analysis (64-bit)", - "description": "Configure the Visual Studio build with clang-tidy analysis and the Win64 toolchain architecture.", - "cacheVariables": { - "TESTCPP_ANALYSIS_ENABLED": "1" + "architecture": "x64", + "vendor": { + "microsoft.com/VisualStudioSettings/CMake/1.0": { + "intelliSenseMode": "windows-clang-x64" + } } } ], "buildPresets": [ { "name": "vs-base-build", + "displayName": "Build - x86 - Debug - Windows - Visual Studio - Core Lib", + "description": "Build only the Core Lib with VS-Win32 with the necessary base MSBuild options in Debug mode.", "configurePreset": "vs-base", "resolvePackageReferences": "on", "nativeToolOptions": [ @@ -304,13 +504,228 @@ }, { "name": "vs-base-clean-build", + "displayName": "Build - x86 - Debug - Windows - Visual Studio - Core Lib - Clean First", + "description": "Build only the Core Lib with VS-Win32 with the necessary base MSBuild options in Debug mode, and clean up the previous build first.", "inherits": "vs-base-build", "cleanFirst": true }, { - "name": "vs-msanalysis", - "inherits": "vs-base-clean-build", + "name": "vs-base-build-rel", + "displayName": "Build - x86 - Release - Windows - Visual Studio - Core Lib", + "description": "Build only the Core Lib with VS-Win32 with the necessary base MSBuild options in Release mode.", + "configurePreset": "vs-base-rel", + "inherits": "vs-base-build" + }, + { + "name": "vs-base-clean-build-rel", + "displayName": "Build - x86 - Release - Windows - Visual Studio - Core Lib - Clean First", + "description": "Build only the Core Lib with VS-Win32 with the necessary base MSBuild options in Release mode, and clean up the previous build first.", + "inherits": "vs-base-build-rel", + "cleanFirst": true + }, + { + "name": "vs-nost-base-build", + "displayName": "Build - x86 - Debug - Windows - Visual Studio - Core Lib - No Stacktraces", + "description": "Build only the Core Lib with VS-Win32 with the necessary base MSBuild options in Debug mode, but with no stacktraces (strict C++11).", "configurePreset": "vs-nost-base", + "inherits": "vs-base-build" + }, + { + "name": "vs-nost-base-clean-build", + "displayName": "Build - x86 - Debug - Windows - Visual Studio - Core Lib - No Stacktraces - Clean First", + "description": "Build only the Core Lib with VS-Win32 with the necessary base MSBuild options in Debug mode, but with no stacktraces (strict C++11), and clean up the previous build first.", + "inherits": "vs-nost-base-build", + "cleanFirst": true + }, + { + "name": "vs-nost-base-build-rel", + "displayName": "Build - x86 - Release - Windows - Visual Studio - Core Lib - No Stacktraces", + "description": "Build only the Core Lib with VS-Win32 with the necessary base MSBuild options in Release mode, but with no stacktraces (strict C++11).", + "configurePreset": "vs-nost-base-rel", + "inherits": "vs-base-build" + }, + { + "name": "vs-nost-base-clean-build-rel", + "displayName": "Build - x86 - Release - Windows - Visual Studio - Core Lib - No Stacktraces - Clean First", + "description": "Build only the Core Lib with VS-Win32 with the necessary base MSBuild options in Release mode, but with no stacktraces (strict C++11), and clean up the previous build first.", + "inherits": "vs-nost-base-build-rel", + "cleanFirst": true + }, + { + "name": "vs-with-test-build", + "displayName": "Build - x86 - Debug - Windows - Visual Studio - Core Lib With Tests", + "description": "Build the Core Lib, and Tests, with VS-Win32 with the necessary base MSBuild options in Debug mode.", + "configurePreset": "vs-with-test", + "inherits": "vs-base-build" + }, + { + "name": "vs-with-test-clean-build", + "displayName": "Build - x86 - Debug - Windows - Visual Studio - Core Lib With Tests - Clean First", + "description": "Build the Core Lib, and Tests, with VS-Win32 with the necessary base MSBuild options in Debug mode, and clean up the previous build first.", + "inherits": "vs-with-test-build", + "cleanFirst": true + }, + { + "name": "vs-with-test-build-rel", + "displayName": "Build - x86 - Release - Windows - Visual Studio - Core Lib With Tests", + "description": "Build the Core Lib, and Tests, with VS-Win32 with the necessary base MSBuild options in Release mode.", + "configurePreset": "vs-with-test-rel", + "inherits": "vs-base-build" + }, + { + "name": "vs-with-test-clean-build-rel", + "displayName": "Build - x86 - Release - Windows - Visual Studio - Core Lib With Tests - Clean First", + "description": "Build the Core Lib, and Tests, with VS-Win32 with the necessary base MSBuild options in Release mode, and clean up the previous build first.", + "inherits": "vs-with-test-build-rel", + "cleanFirst": true + }, + { + "name": "vs-nost-with-test-build", + "displayName": "Build - x86 - Debug - Windows - Visual Studio - Core Lib With Tests - No Stacktraces", + "description": "Build the Core Lib, and Tests, with VS-Win32 with the necessary base MSBuild options in Debug mode, but with no stacktraces (strict C++11).", + "configurePreset": "vs-nost-with-test", + "inherits": "vs-base-build" + }, + { + "name": "vs-nost-with-test-clean-build", + "displayName": "Build - x86 - Debug - Windows - Visual Studio - Core Lib With Tests - No Stacktraces - Clean First", + "description": "Build the Core Lib, and Tests, with VS-Win32 with the necessary base MSBuild options in Debug mode, but with no stacktraces (strict C++11), and clean up the previous build first.", + "inherits": "vs-nost-with-test-build", + "cleanFirst": true + }, + { + "name": "vs-nost-with-test-build-rel", + "displayName": "Build - x86 - Release - Windows - Visual Studio - Core Lib With Tests - No Stacktraces", + "description": "Build the Core Lib, and Tests, with VS-Win32 with the necessary base MSBuild options in Release mode, but with no stacktraces (strict C++11).", + "configurePreset": "vs-nost-with-test-rel", + "inherits": "vs-base-build" + }, + { + "name": "vs-nost-with-test-clean-build-rel", + "displayName": "Build - x86 - Release - Windows - Visual Studio - Core Lib With Tests - No Stacktraces - Clean First", + "description": "Build the Core Lib, and Tests, with VS-Win32 with the necessary base MSBuild options in Release mode, but with no stacktraces (strict C++11), and clean up the previous build first.", + "inherits": "vs-nost-with-test-build-rel", + "cleanFirst": true + }, + { + "name": "vs-with-demo-build", + "displayName": "Build - x86 - Debug - Windows - Visual Studio - Core Lib With Demo", + "description": "Build the Core Lib, and Demo, with VS-Win32 with the necessary base MSBuild options in Debug mode.", + "configurePreset": "vs-with-demo", + "inherits": "vs-base-build" + }, + { + "name": "vs-with-demo-clean-build", + "displayName": "Build - x86 - Debug - Windows - Visual Studio - Core Lib With Demo - Clean First", + "description": "Build the Core Lib, and Demo, with VS-Win32 with the necessary base MSBuild options in Debug mode, and clean up the previous build first.", + "inherits": "vs-with-demo-build", + "cleanFirst": true + }, + { + "name": "vs-with-demo-build-rel", + "displayName": "Build - x86 - Release - Windows - Visual Studio - Core Lib With Demo", + "description": "Build the Core Lib, and Demo, with VS-Win32 with the necessary base MSBuild options in Release mode.", + "configurePreset": "vs-with-demo-rel", + "inherits": "vs-base-build" + }, + { + "name": "vs-with-demo-clean-build-rel", + "displayName": "Build - x86 - Release - Windows - Visual Studio - Core Lib With Demo - Clean First", + "description": "Build the Core Lib, and Demo, with VS-Win32 with the necessary base MSBuild options in Release mode, and clean up the previous build first.", + "inherits": "vs-with-demo-build-rel", + "cleanFirst": true + }, + { + "name": "vs-nost-with-demo-build", + "displayName": "Build - x86 - Debug - Windows - Visual Studio - Core Lib With Demo - No Stacktraces", + "description": "Build the Core Lib, and Demo, with VS-Win32 with the necessary base MSBuild options in Debug mode, but with no stacktraces (strict C++11).", + "configurePreset": "vs-nost-with-demo", + "inherits": "vs-base-build" + }, + { + "name": "vs-nost-with-demo-clean-build", + "displayName": "Build - x86 - Debug - Windows - Visual Studio - Core Lib With Demo - No Stacktraces - Clean First", + "description": "Build the Core Lib, and Demo, with VS-Win32 with the necessary base MSBuild options in Debug mode, but with no stacktraces (strict C++11), and clean up the previous build first.", + "inherits": "vs-nost-with-demo-build", + "cleanFirst": true + }, + { + "name": "vs-nost-with-demo-build-rel", + "displayName": "Build - x86 - Release - Windows - Visual Studio - Core Lib With Demo - No Stacktraces", + "description": "Build the Core Lib, and Demo, with VS-Win32 with the necessary base MSBuild options in Release mode, but with no stacktraces (strict C++11).", + "configurePreset": "vs-nost-with-demo-rel", + "inherits": "vs-base-build" + }, + { + "name": "vs-nost-with-demo-clean-build-rel", + "displayName": "Build - x86 - Release - Windows - Visual Studio - Core Lib With Demo - No Stacktraces - Clean First", + "description": "Build the Core Lib, and Demo, with VS-Win32 with the necessary base MSBuild options in Release mode, but with no stacktraces (strict C++11), and clean up the previous build first.", + "inherits": "vs-nost-with-demo-build-rel", + "cleanFirst": true + }, + { + "name": "vs-all-build", + "displayName": "Build - x86 - Debug - Windows - Visual Studio - All Components - Core, Tests, and Demo", + "description": "Build the Core Lib, Tests, and Demo, with VS-Win32 with the necessary base MSBuild options in Debug mode.", + "configurePreset": "vs-all", + "inherits": "vs-base-build" + }, + { + "name": "vs-all-clean-build", + "displayName": "Build - x86 - Debug - Windows - Visual Studio - All Components - Core, Tests, and Demo - Clean First", + "description": "Build the Core Lib, Tests, and Demo, with VS-Win32 with the necessary base MSBuild options in Debug mode, and clean up the previous build first.", + "inherits": "vs-all-build", + "cleanFirst": true + }, + { + "name": "vs-all-build-rel", + "displayName": "Build - x86 - Release - Windows - Visual Studio - All Components - Core, Tests, and Demo", + "description": "Build the Core Lib, Tests, and Demo, with VS-Win32 with the necessary base MSBuild options in Release mode.", + "configurePreset": "vs-all-rel", + "inherits": "vs-base-build" + }, + { + "name": "vs-all-clean-build-rel", + "displayName": "Build - x86 - Release - Windows - Visual Studio - All Components - Core, Tests, and Demo - Clean First", + "description": "Build the Core Lib, Tests, and Demo, with VS-Win32 with the necessary base MSBuild options in Release mode, and clean up the previous build first.", + "inherits": "vs-all-build-rel", + "cleanFirst": true + }, + { + "name": "vs-nost-all-build", + "displayName": "Build - x86 - Debug - Windows - Visual Studio - All Components - Core, Tests, and Demo - No Stacktraces", + "description": "Build the Core Lib, Tests, and Demo, with VS-Win32 with the necessary base MSBuild options in Debug mode, but with no stacktraces (strict C++11).", + "configurePreset": "vs-nost-all", + "inherits": "vs-base-build" + }, + { + "name": "vs-nost-all-clean-build", + "displayName": "Build - x86 - Debug - Windows - Visual Studio - All Components - Core, Tests, and Demo - No Stacktraces - Clean First", + "description": "Build the Core Lib, Tests, and Demo, with VS-Win32 with the necessary base MSBuild options in Debug mode, but with no stacktraces (strict C++11), and clean up the previous build first.", + "inherits": "vs-nost-all-build", + "cleanFirst": true + }, + { + "name": "vs-nost-all-build-rel", + "displayName": "Build - x86 - Release - Windows - Visual Studio - All Components - Core, Tests, and Demo - No Stacktraces", + "description": "Build the Core Lib, Tests, and Demo, with VS-Win32 with the necessary base MSBuild options in Release mode, but with no stacktraces (strict C++11).", + "configurePreset": "vs-nost-all-rel", + "inherits": "vs-base-build" + }, + { + "name": "vs-nost-all-clean-build-rel", + "displayName": "Build - x86 - Release - Windows - Visual Studio - All Components - Core, Tests, and Demo - No Stacktraces - Clean First", + "description": "Build the Core Lib, Tests, and Demo, with VS-Win32 with the necessary base MSBuild options in Release mode, but with no stacktraces (strict C++11), and clean up the previous build first.", + "inherits": "vs-nost-all-build-rel", + "cleanFirst": true + }, + { + "name": "vs-msanalysis-build", + "displayName": "Analyze - x86 - Windows - Visual Studio", + "description": "Analyze the code with MSBuild using the Win32 toolchain architecture.", + "inherits": "vs-base-clean-build", + "cleanFirst": true, + "configurePreset": "vs-msanalysis", "nativeToolOptions": [ "/external:anglebrackets", "/external:I${sourceDir}/3rdparty", @@ -322,43 +737,267 @@ }, { "name": "vs-msanalysis-xml", - "inherits": "vs-msanalysis", + "displayName": "Analyze - x86 - Windows - Visual Studio - XML output", + "description": "Analyze the code with MSBuild using the Win32 toolchain architecture, then output the analysis results in XML format.", + "inherits": "vs-msanalysis-build", "nativeToolOptions": [ "/analyze:log:format:xml" ] }, { "name": "vs-msanalysis-sarif", - "inherits": "vs-msanalysis", + "displayName": "Analyze - x86 - Windows - Visual Studio - SARIF output", + "description": "Analyze the code with MSBuild using the Win32 toolchain architecture, then output the analysis results in SARIF format.", + "inherits": "vs-msanalysis-build", "nativeToolOptions": [ "/analyze:log:format:sarif" ] }, { "name": "vs64-base-build", + "displayName": "Build - x64 - Debug - Windows - Visual Studio - Core Lib", + "description": "Build with VS-x64 with the necessary base MSBuild options in Debug mode.", "configurePreset": "vs64-base", "inherits": "vs-base-build" }, { "name": "vs64-base-clean-build", - "configurePreset": "vs64-base", - "inherits": "vs-base-clean-build" + "displayName": "Build - x64 - Debug - Windows - Visual Studio - Core Lib - Clean First", + "description": "Build with VS-x64 with the necessary base MSBuild options in Debug mode, and clean up the previous build first.", + "inherits": "vs64-base-build", + "cleanFirst": true }, { - "name": "vs64-msanalysis", - "inherits": "vs-msanalysis", - "configurePreset": "vs64-nost-base" + "name": "vs64-base-build-rel", + "displayName": "Build - x64 - Release - Windows - Visual Studio - Core Lib", + "description": "Build with VS-x64 with the necessary base MSBuild options in Release mode.", + "configurePreset": "vs64-base-rel", + "inherits": "vs-base-build-rel" + }, + { + "name": "vs64-base-clean-build-rel", + "displayName": "Build - x64 - Release - Windows - Visual Studio - Core Lib - Clean First", + "description": "Build with VS-x64 with the necessary base MSBuild options in Release mode, and clean up the previous build first.", + "inherits": "vs64-base-build-rel", + "cleanFirst": true + }, + { + "name": "vs64-nost-base-build", + "displayName": "Build - x64 - Debug - Windows - Visual Studio - Core Lib - No Stacktraces", + "description": "Build only the Core Lib with VS-x64 with the necessary base MSBuild options in Debug mode, but with no stacktraces (strict C++11).", + "configurePreset": "vs64-nost-base", + "inherits": "vs64-base-build" + }, + { + "name": "vs64-nost-base-clean-build", + "displayName": "Build - x64 - Debug - Windows - Visual Studio - Core Lib - No Stacktraces - Clean First", + "description": "Build only the Core Lib with VS-x64 with the necessary base MSBuild options in Debug mode, but with no stacktraces (strict C++11), and clean up the previous build first.", + "inherits": "vs64-nost-base-build", + "cleanFirst": true + }, + { + "name": "vs64-nost-base-build-rel", + "displayName": "Build - x64 - Release - Windows - Visual Studio - Core Lib - No Stacktraces", + "description": "Build only the Core Lib with VS-x64 with the necessary base MSBuild options in Release mode, but with no stacktraces (strict C++11).", + "configurePreset": "vs64-nost-base-rel", + "inherits": "vs64-base-build" + }, + { + "name": "vs64-nost-base-clean-build-rel", + "displayName": "Build - x64 - Release - Windows - Visual Studio - Core Lib - No Stacktraces - Clean First", + "description": "Build only the Core Lib with VS-x64 with the necessary base MSBuild options in Release mode, but with no stacktraces (strict C++11), and clean up the previous build first.", + "inherits": "vs64-nost-base-build-rel", + "cleanFirst": true + }, + { + "name": "vs64-with-test-build", + "displayName": "Build - x64 - Debug - Windows - Visual Studio - Core Lib With Tests", + "description": "Build the Core Lib, and Tests, with VS-x64 with the necessary base MSBuild options in Debug mode.", + "configurePreset": "vs64-with-test", + "inherits": "vs64-base-build" + }, + { + "name": "vs64-with-test-clean-build", + "displayName": "Build - x64 - Debug - Windows - Visual Studio - Core Lib With Tests - Clean First", + "description": "Build the Core Lib, and Tests, with VS-x64 with the necessary base MSBuild options in Debug mode, and clean up the previous build first.", + "inherits": "vs64-with-test-build", + "cleanFirst": true + }, + { + "name": "vs64-with-test-build-rel", + "displayName": "Build - x64 - Release - Windows - Visual Studio - Core Lib With Tests", + "description": "Build the Core Lib, and Tests, with VS-x64 with the necessary base MSBuild options in Release mode.", + "configurePreset": "vs64-with-test-rel", + "inherits": "vs64-base-build" + }, + { + "name": "vs64-with-test-clean-build-rel", + "displayName": "Build - x64 - Release - Windows - Visual Studio - Core Lib With Tests - Clean First", + "description": "Build the Core Lib, and Tests, with VS-x64 with the necessary base MSBuild options in Release mode, and clean up the previous build first.", + "inherits": "vs64-with-test-build-rel", + "cleanFirst": true + }, + { + "name": "vs64-nost-with-test-build", + "displayName": "Build - x64 - Debug - Windows - Visual Studio - Core Lib With Tests - No Stacktraces", + "description": "Build the Core Lib, and Tests, with VS-x64 with the necessary base MSBuild options in Debug mode, but with no stacktraces (strict C++11).", + "configurePreset": "vs64-nost-with-test", + "inherits": "vs64-base-build" + }, + { + "name": "vs64-nost-with-test-clean-build", + "displayName": "Build - x64 - Debug - Windows - Visual Studio - Core Lib With Tests - No Stacktraces - Clean First", + "description": "Build the Core Lib, and Tests, with VS-x64 with the necessary base MSBuild options in Debug mode, but with no stacktraces (strict C++11), and clean up the previous build first.", + "inherits": "vs64-nost-with-test-build", + "cleanFirst": true + }, + { + "name": "vs64-nost-with-test-build-rel", + "displayName": "Build - x64 - Release - Windows - Visual Studio - Core Lib With Tests - No Stacktraces", + "description": "Build the Core Lib, and Tests, with VS-x64 with the necessary base MSBuild options in Release mode, but with no stacktraces (strict C++11).", + "configurePreset": "vs64-nost-with-test-rel", + "inherits": "vs64-base-build" + }, + { + "name": "vs64-nost-with-test-clean-build-rel", + "displayName": "Build - x64 - Release - Windows - Visual Studio - Core Lib With Tests - No Stacktraces - Clean First", + "description": "Build the Core Lib, and Tests, with VS-x64 with the necessary base MSBuild options in Release mode, but with no stacktraces (strict C++11), and clean up the previous build first.", + "inherits": "vs64-nost-with-test-build-rel", + "cleanFirst": true + }, + { + "name": "vs64-with-demo-build", + "displayName": "Build - x64 - Debug - Windows - Visual Studio - Core Lib With Demo", + "description": "Build the Core Lib, and Demo, with VS-x64 with the necessary base MSBuild options in Debug mode.", + "configurePreset": "vs64-with-demo", + "inherits": "vs64-base-build" + }, + { + "name": "vs64-with-demo-clean-build", + "displayName": "Build - x64 - Debug - Windows - Visual Studio - Core Lib With Demo - Clean First", + "description": "Build the Core Lib, and Demo, with VS-x64 with the necessary base MSBuild options in Debug mode, and clean up the previous build first.", + "inherits": "vs64-with-demo-build", + "cleanFirst": true + }, + { + "name": "vs64-with-demo-build-rel", + "displayName": "Build - x64 - Release - Windows - Visual Studio - Core Lib With Demo", + "description": "Build the Core Lib, and Demo, with VS-x64 with the necessary base MSBuild options in Release mode.", + "configurePreset": "vs64-with-demo-rel", + "inherits": "vs64-base-build" + }, + { + "name": "vs64-with-demo-clean-build-rel", + "displayName": "Build - x64 - Release - Windows - Visual Studio - Core Lib With Demo - Clean First", + "description": "Build the Core Lib, and Demo, with VS-x64 with the necessary base MSBuild options in Release mode, and clean up the previous build first.", + "inherits": "vs64-with-demo-build-rel", + "cleanFirst": true + }, + { + "name": "vs64-nost-with-demo-build", + "displayName": "Build - x64 - Debug - Windows - Visual Studio - Core Lib With Demo - No Stacktraces", + "description": "Build the Core Lib, and Demo, with VS-x64 with the necessary base MSBuild options in Debug mode, but with no stacktraces (strict C++11).", + "configurePreset": "vs64-nost-with-demo", + "inherits": "vs64-base-build" + }, + { + "name": "vs64-nost-with-demo-clean-build", + "displayName": "Build - x64 - Debug - Windows - Visual Studio - Core Lib With Demo - No Stacktraces - Clean First", + "description": "Build the Core Lib, and Demo, with VS-x64 with the necessary base MSBuild options in Debug mode, but with no stacktraces (strict C++11), and clean up the previous build first.", + "inherits": "vs64-nost-with-demo-build", + "cleanFirst": true + }, + { + "name": "vs64-nost-with-demo-build-rel", + "displayName": "Build - x64 - Release - Windows - Visual Studio - Core Lib With Demo - No Stacktraces", + "description": "Build the Core Lib, and Demo, with VS-x64 with the necessary base MSBuild options in Release mode, but with no stacktraces (strict C++11).", + "configurePreset": "vs64-nost-with-demo-rel", + "inherits": "vs64-base-build" + }, + { + "name": "vs64-nost-with-demo-clean-build-rel", + "displayName": "Build - x64 - Release - Windows - Visual Studio - Core Lib With Demo - No Stacktraces - Clean First", + "description": "Build the Core Lib, and Demo, with VS-x64 with the necessary base MSBuild options in Release mode, but with no stacktraces (strict C++11), and clean up the previous build first.", + "inherits": "vs64-nost-with-demo-build-rel", + "cleanFirst": true + }, + { + "name": "vs64-all-build", + "displayName": "Build - x64 - Debug - Windows - Visual Studio - All Components - Core, Tests, and Demo", + "description": "Build the Core Lib, Tests, and Demo, with VS-x64 with the necessary base MSBuild options in Debug mode.", + "configurePreset": "vs64-all", + "inherits": "vs64-base-build" + }, + { + "name": "vs64-all-clean-build", + "displayName": "Build - x64 - Debug - Windows - Visual Studio - All Components - Core, Tests, and Demo - Clean First", + "description": "Build the Core Lib, Tests, and Demo, with VS-x64 with the necessary base MSBuild options in Debug mode, and clean up the previous build first.", + "inherits": "vs64-all-build", + "cleanFirst": true + }, + { + "name": "vs64-all-build-rel", + "displayName": "Build - x64 - Release - Windows - Visual Studio - All Components - Core, Tests, and Demo", + "description": "Build the Core Lib, Tests, and Demo, with VS-x64 with the necessary base MSBuild options in Release mode.", + "configurePreset": "vs64-all-rel", + "inherits": "vs64-base-build" + }, + { + "name": "vs64-all-clean-build-rel", + "displayName": "Build - x64 - Release - Windows - Visual Studio - All Components - Core, Tests, and Demo - Clean First", + "description": "Build the Core Lib, Tests, and Demo, with VS-x64 with the necessary base MSBuild options in Release mode, and clean up the previous build first.", + "inherits": "vs64-all-build-rel", + "cleanFirst": true + }, + { + "name": "vs64-nost-all-build", + "displayName": "Build - x64 - Debug - Windows - Visual Studio - All Components - Core, Tests, and Demo - No Stacktraces", + "description": "Build the Core Lib, Tests, and Demo, with VS-x64 with the necessary base MSBuild options in Debug mode, but with no stacktraces (strict C++11).", + "configurePreset": "vs64-nost-all", + "inherits": "vs64-base-build" + }, + { + "name": "vs64-nost-all-clean-build", + "displayName": "Build - x64 - Debug - Windows - Visual Studio - All Components - Core, Tests, and Demo - No Stacktraces - Clean First", + "description": "Build the Core Lib, Tests, and Demo, with VS-x64 with the necessary base MSBuild options in Debug mode, but with no stacktraces (strict C++11), and clean up the previous build first.", + "inherits": "vs64-nost-all-build", + "cleanFirst": true + }, + { + "name": "vs64-nost-all-build-rel", + "displayName": "Build - x64 - Release - Windows - Visual Studio - All Components - Core, Tests, and Demo - No Stacktraces", + "description": "Build the Core Lib, Tests, and Demo, with VS-x64 with the necessary base MSBuild options in Release mode, but with no stacktraces (strict C++11).", + "configurePreset": "vs64-nost-all-rel", + "inherits": "vs64-base-build" + }, + { + "name": "vs64-nost-all-clean-build-rel", + "displayName": "Build - x64 - Release - Windows - Visual Studio - All Components - Core, Tests, and Demo - No Stacktraces - Clean First", + "description": "Build the Core Lib, Tests, and Demo, with VS-x64 with the necessary base MSBuild options in Release mode, but with no stacktraces (strict C++11), and clean up the previous build first.", + "inherits": "vs64-nost-all-build-rel", + "cleanFirst": true + }, + { + "name": "vs64-msanalysis-build", + "displayName": "Analyze - x64 - Windows - Visual Studio", + "description": "Analyze the code with MSBuild using the x64 toolchain architecture.", + "inherits": "vs-msanalysis-build", + "configurePreset": "vs64-msanalysis" }, { "name": "vs64-msanalysis-xml", - "inherits": "vs64-msanalysis", + "displayName": "Analyze - x64 - Windows - Visual Studio - XML output", + "description": "Analyze the code with MSBuild using the x64 toolchain architecture, then output the analysis results in XML format.", + "inherits": "vs64-msanalysis-build", "nativeToolOptions": [ "/analyze:log:format:xml" ] }, { "name": "vs64-msanalysis-sarif", - "inherits": "vs64-msanalysis", + "displayName": "Analyze - x64 - Windows - Visual Studio - SARIF output", + "description": "Analyze the code with MSBuild using the x64 toolchain architecture, then output the analysis results in SARIF format.", + "inherits": "vs64-msanalysis-build", "nativeToolOptions": [ "/analyze:log:format:sarif" ] @@ -367,11 +1006,17 @@ "testPresets": [ { "name": "vs-test", + "displayName": "Test - x86 - Debug - Windows - Visual Studio", + "description": "Test with VS-Win32 with the necessary base MSBuild options in Debug mode.", "configurePreset": "vs-with-test", "output": { "shortProgress": true, "verbosity": "verbose", - "outputOnFailure": true + "outputOnFailure": true, + "outputLogFile": "testcpp-tests.log", + "maxFailedTestOutputSize": 104857600, + "maxPassedTestOutputSize": 104857600, + "testOutputTruncation": "tail" }, "execution": { "noTestsAction": "error", @@ -383,61 +1028,54 @@ "rhs": "Windows" } }, + { + "name": "vs-test-rel", + "displayName": "Test - x86 - Release - Windows - Visual Studio", + "description": "Test with VS-Win32 with the necessary base MSBuild options in Release mode.", + "configurePreset": "vs-with-test-rel", + "inherits": "vs-test" + }, { "name": "vs-nost-test", + "displayName": "Test - x86 - Debug - Windows - Visual Studio - No Stacktraces", + "description": "Test with VS-Win32 with the necessary base MSBuild options in Debug mode, but with no stacktraces (strict C++11).", "configurePreset": "vs-nost-with-test", "inherits": "vs-test" }, + { + "name": "vs-nost-test-rel", + "displayName": "Test - x86 - Release - Windows - Visual Studio - No Stacktraces", + "description": "Test with VS-Win32 with the necessary base MSBuild options in Release mode, but with no stacktraces (strict C++11).", + "configurePreset": "vs-nost-with-test-rel", + "inherits": "vs-test" + }, { "name": "vs64-test", + "displayName": "Test - x64 - Debug - Windows - Visual Studio", + "description": "Test with VS-x64 with the necessary base MSBuild options in Debug mode.", "configurePreset": "vs64-with-test", "inherits": "vs-test" }, + { + "name": "vs64-test-rel", + "displayName": "Test - x64 - Release - Windows - Visual Studio", + "description": "Test with VS-x64 with the necessary base MSBuild options in Release mode.", + "configurePreset": "vs64-with-test-rel", + "inherits": "vs-test" + }, { "name": "vs64-nost-test", + "displayName": "Test - x64 - Debug - Windows - Visual Studio - No Stacktraces", + "description": "Test with VS-x64 with the necessary base MSBuild options in Debug mode, but with no stacktraces (strict C++11).", "configurePreset": "vs64-nost-with-test", "inherits": "vs-nost-test" - } - ], - "packagePresets": [ - { - "name": "base-pack", - "generators": [ - "ZIP" - ], - "output": { - "verbose": true - } - }, - { - "name": "vs-pack", - "configurePreset": "vs-base", - "inherits": "base-pack", - "generators": [ - "7Z", - "NSIS", - "WIX" - ], - "condition": { - "type": "equals", - "lhs": "${hostSystemName}", - "rhs": "Windows" - } - }, - { - "name": "vs-nost-pack", - "configurePreset": "vs-nost-base", - "inherits": "vs-pack" }, { - "name": "vs64-pack", - "configurePreset": "vs64-base", - "inherits": "vs-pack" - }, - { - "name": "vs64-nost-pack", - "configurePreset": "vs64-nost-base", - "inherits": "vs-nost-pack" + "name": "vs64-nost-test-rel", + "displayName": "Test - x64 - Release - Windows - Visual Studio - No Stacktraces", + "description": "Test with VS-x64 with the necessary base MSBuild options in Release mode, but with no stacktraces (strict C++11).", + "configurePreset": "vs64-nost-with-test-rel", + "inherits": "vs-nost-test" } ] } \ No newline at end of file diff --git a/cmake/BuildTypeHandling.cmake b/cmake/BuildTypeHandling.cmake index 403a5da..de82312 100644 --- a/cmake/BuildTypeHandling.cmake +++ b/cmake/BuildTypeHandling.cmake @@ -7,10 +7,14 @@ endif () if (${CMAKE_BUILD_TYPE} STREQUAL "Release") message (STATUS "Release build compilation options enabled") - if (MSVC) + if (MSVC AND NOT ("${CMAKE_VS_PLATFORM_TOOLSET}" STREQUAL "ClangCL")) + message (STATUS "MSVC Release build compilation options enabled") + include (MSVCRelease) else () + message (STATUS "GCC/Clang Release build compilation options enabled") + include (GCCClangRelease) endif () @@ -18,11 +22,15 @@ else () message (STATUS "Debug build compilation options enabled") include (DebugCompileDefs) + + if (MSVC AND NOT ("${CMAKE_VS_PLATFORM_TOOLSET}" STREQUAL "ClangCL")) + message (STATUS "MSVC Debug build compilation options enabled") - if (MSVC) include (MSVCDebug) else () + message (STATUS "GCC/Clang Debug build compilation options enabled") + include (GCCClangDebug) endif () endif () diff --git a/cmake/Targets.cmake b/cmake/Targets.cmake index 66b198e..cba9f4d 100644 --- a/cmake/Targets.cmake +++ b/cmake/Targets.cmake @@ -6,6 +6,7 @@ add_library ( src/TestCPPTestSuite.cpp src/TestCPPUtil.cpp ) + add_library ( ${PROJECT_GROUP_NAME}::${PROJECT_NAME} ALIAS diff --git a/cmake/build/GCCClangDebug.cmake b/cmake/build/GCCClangDebug.cmake index a27dcda..377c6cc 100644 --- a/cmake/build/GCCClangDebug.cmake +++ b/cmake/build/GCCClangDebug.cmake @@ -1,26 +1,33 @@ list ( APPEND GCC_CLANG_DEBUG_BUILD_OPTS - -g # Enable all debugging information. - -Og # Ensure the compiler doesn't use - # optimizations that would harm - # debuggability of the resulting code. - -Wall # Enable most warnings. - -Wextra # Enable even more warnings. - -Wpedantic # Enable most of the rest of the - # warnings. - -Werror # Treat all warnings as errors. - -Wno-unused-lambda-capture # Avoid MSVC error C3493 - There is - # implementation divergence here and - # since we're not using >=C++14 there - # is no workaround other than to ignore - # this warning (the MSVC issue is an - # error). - # A workaround for >=C++14 is to use an - # explicit capture - if ever I change - # the library to use >=C++14 I can - # remove this and use an explicit - # capture. + -g # Enable all debugging information. + -Og # Ensure the compiler doesn't use + # optimizations that would harm + # debuggability of the resulting code. + -Wall # Enable most warnings. + -Wextra # Enable even more warnings. + -Wpedantic # Enable most of the rest of the + # warnings. + -Werror # Treat all warnings as errors. + -Wno-c++98-compat # We're compiling for C++11, so it's not + # necessary to maintain compatibility + # with C++98. + -Wno-c++98-compat-pedantic # We're compiling for C++11, so, again, + # it's not necessary to maintain + # compatibility with C++98. + -Wno-covered-switch-default # -Wswitch-default is more important. + -Wno-unused-lambda-capture # Avoid MSVC error C3493 - There is + # implementation divergence here and + # since we're not using >=C++14 there + # is no workaround other than to ignore + # this warning (the MSVC issue is an + # error). + # A workaround for >=C++14 is to use an + # explicit capture - if ever I change + # the library to use >=C++14 I can + # remove this and use an explicit + # capture. ) if (${TESTCPP_DEMO_ENABLED}) diff --git a/cmake/build/GCCClangRelease.cmake b/cmake/build/GCCClangRelease.cmake index 73e6c2b..50989b6 100644 --- a/cmake/build/GCCClangRelease.cmake +++ b/cmake/build/GCCClangRelease.cmake @@ -1,25 +1,32 @@ list ( APPEND GCC_CLANG_RELEASE_BUILD_OPTS - -O3 # Optimize the Release build. - -Wall # Enable most warnings. - -Wextra # Enable even more warnings. - -Wpedantic # Enable most of the rest of the - # warnings. - -Werror # Treat all warnings as errors. - -Wno-unused-parameter # Unused parameters occur in the Release - # build in debugLog. - -Wno-unused-lambda-capture # Avoid MSVC error C3493 - There is - # implementation divergence here and - # since we're not using >=C++14 there - # is no workaround other than to ignore - # this warning (the MSVC issue is an - # error). - # A workaround for >=C++14 is to use an - # explicit capture - if ever I change - # the library to use >=C++14 I can - # remove this and use an explicit - # capture. + -O3 # Optimize the Release build. + -Wall # Enable most warnings. + -Wextra # Enable even more warnings. + -Wpedantic # Enable most of the rest of the + # warnings. + -Werror # Treat all warnings as errors. + -Wno-c++98-compat # We're compiling for C++11, so it's not + # necessary to maintain compatibility + # with C++98. + -Wno-c++98-compat-pedantic # We're compiling for C++11, so, again, + # it's not necessary to maintain + # compatibility with C++98. + -Wno-covered-switch-default # -Wswitch-default is more important. + -Wno-unused-parameter # Unused parameters occur in the Release + # build in debugLog. + -Wno-unused-lambda-capture # Avoid MSVC error C3493 - There is + # implementation divergence here and + # since we're not using >=C++14 there + # is no workaround other than to ignore + # this warning (the MSVC issue is an + # error). + # A workaround for >=C++14 is to use an + # explicit capture - if ever I change + # the library to use >=C++14 I can + # remove this and use an explicit + # capture. ) target_compile_options ( diff --git a/cmake/build/GCCCoverage.cmake b/cmake/build/GCCCoverage.cmake index a6b69ab..6eac602 100644 --- a/cmake/build/GCCCoverage.cmake +++ b/cmake/build/GCCCoverage.cmake @@ -1,17 +1,25 @@ list ( APPEND COVERAGE_BUILD_OPTS - -g # Enable all debugging information. - -Og # Ensure the compiler doesn't use optimizations - # that would harm debuggability of the resulting - # code. - -Wall # Enable most warnings. - -Wextra # Enable even more warnings. - -Wpedantic # Enable most of the rest of the warnings. - -Werror # Treat all warnings as errors. - -fprofile-arcs # Enable profile points that help with code - # coverage. - -ftest-coverage # Enable core code coverage compilation. + -g # Enable all debugging information. + -Og # Ensure the compiler doesn't use + # optimizations that would harm + # debuggability of the resulting code. + -Wall # Enable most warnings. + -Wextra # Enable even more warnings. + -Wpedantic # Enable most of the rest of the + # warnings. + -Werror # Treat all warnings as errors. + -Wno-c++98-compat # We're compiling for C++11, so it's not + # necessary to maintain compatibility + # with C++98. + -Wno-c++98-compat-pedantic # We're compiling for C++11, so, again, + # it's not necessary to maintain + # compatibility with C++98. + -Wno-covered-switch-default # -Wswitch-default is more important. + -fprofile-arcs # Enable profile points that help with + # code coverage. + -ftest-coverage # Enable core code coverage compilation. ) target_compile_options ( From fdbe1f331704f858a2efdc86d43d8c094535dcaf Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Wed, 5 Feb 2025 20:24:41 -0800 Subject: [PATCH 46/59] Fixes for issues revealed through ClangCL compilation Fixed documentation - wrong parameter name, @return on a constructor Fixed not explicitly specifying that the fail function never returns a value with [[noreturn]] even though it's void Fix problematic names of constants No need to have unsigned long long when std::chrono::nanoseconds. count() returns long long, as implicit conversions can cause unexpected problems. --- include/internal/TestCPPAssertions.h | 4 ++-- include/internal/TestCPPCommon.h | 30 ++++++++++++++-------------- include/internal/TestCPPTestSuite.h | 2 +- include/internal/TestCPPUtil.h | 4 ++-- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/include/internal/TestCPPAssertions.h b/include/internal/TestCPPAssertions.h index 8032643..83ff2e9 100644 --- a/include/internal/TestCPPAssertions.h +++ b/include/internal/TestCPPAssertions.h @@ -193,7 +193,7 @@ namespace TestCPP { /** * @brief Verify that a function does not throw something. - * @param shouldThrow The function to check, to ensure that it + * @param shouldNotThrow The function to check, to ensure that it * does not throw something. * @param failureMessage Failure message that should be logged * if the assertion fails. This @@ -251,7 +251,7 @@ namespace TestCPP { * - Forcing test failure in certain circumstances where there * is nothing to assert but a certain code path is taken. */ - static void fail ( + static void fail [[noreturn]] ( string failureMessage = "Forced test failure!" ); }; diff --git a/include/internal/TestCPPCommon.h b/include/internal/TestCPPCommon.h index 5747719..5e0e726 100644 --- a/include/internal/TestCPPCommon.h +++ b/include/internal/TestCPPCommon.h @@ -65,42 +65,42 @@ namespace TestCPP { * denote leading and trailing spaces, respectively. */ struct Strings { - static constexpr const char * ALL_ = "All "; + static constexpr const char * ALL = "All "; static constexpr const char * APOS = "'"; - static constexpr const char * _FAIL_ = " failed! "; - static constexpr const char * FINISHED_SUITE_ = + static constexpr const char * FAIL = " failed! "; + static constexpr const char * FINISHED_SUITE = "Finished running test suite "; static constexpr const char * FWSL = "/"; - static constexpr const char * _IN_ABOUT_ = " in about "; - static constexpr const char * _NCONTAIN_ = + static constexpr const char * IN_ABOUT = " in about "; + static constexpr const char * NCONTAIN = " does not contain "; - static constexpr const char * _NEQUIV_ = + static constexpr const char * NEQUIV = " is not equivalent to "; static constexpr const char * NTR = "No tests to run!"; static constexpr const char * NVTN = "Not a valid test name!"; static constexpr const char * PARENL = "("; static constexpr const char * PARENR = ")"; - static constexpr const char * _PASS_ = " passed! "; - static constexpr const char * _PASSED = " passed"; + static constexpr const char * PASS = " passed! "; + static constexpr const char * PASSED = " passed"; static constexpr const char * REASON_ = "Reason: "; static constexpr const char * SEC = "s"; static constexpr const char * SP = " "; static constexpr const char * START_RUN = "Starting run of test "; - static constexpr const char * SUITE_ = "Suite "; - static constexpr const char * _SUITE_TESTS_PASSED = + static constexpr const char * SUITE = "Suite "; + static constexpr const char * SUITE_TESTS_PASSED = " suite tests passed!"; - static constexpr const char * TEST_ = "Test "; - static constexpr const char * TEST_EXC_ = + static constexpr const char * TEST = "Test "; + static constexpr const char * TEST_EXC = "Exception occurred during test run: "; - static constexpr const char * UNK_CMP_OPT_ = + static constexpr const char * UNK_CMP_OPT = "Unknown comparison option! "; static constexpr const char * UNK_EXC = "Unknown error occurred in test!"; - static constexpr const char * UNK_OPT_ = "Unknown option "; + static constexpr const char * UNK_OPT = "Unknown option "; }; }; } -#endif \ No newline at end of file +#endif diff --git a/include/internal/TestCPPTestSuite.h b/include/internal/TestCPPTestSuite.h index e47717b..10950f5 100644 --- a/include/internal/TestCPPTestSuite.h +++ b/include/internal/TestCPPTestSuite.h @@ -163,7 +163,7 @@ namespace TestCPP { bool lastRunSucceeded; unsigned lastRunSuccessCount; unsigned lastRunFailCount; - unsigned long long totalRuntime; + long long totalRuntime; TestObjName suiteName; vector tests; diff --git a/include/internal/TestCPPUtil.h b/include/internal/TestCPPUtil.h index 1c97f34..0601102 100644 --- a/include/internal/TestCPPUtil.h +++ b/include/internal/TestCPPUtil.h @@ -62,8 +62,8 @@ namespace TestCPP { /** * @brief Construct a Test Object Name object with a string * literal or existing const char *. - * @return The TestObjName, where it is verified that the name - * used to construct it was not null. + * Results in the TestObjName, where it is verified that the + * name used to construct it was not null. */ // // This is intended to be used for implicit conversions and copy From 099ebc5673d4acfc5e18e090afc9c8d99313036b Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Wed, 5 Feb 2025 20:30:53 -0800 Subject: [PATCH 47/59] Fixes for issues revealed through ClangCL compilation Fix std::move being unqualified in a whole bunch of places; remove using std::move where it is no longer needed because std::move is supposed to be qualified. Specify explicitly that auto-destructors are not to be created and used with stream buffer and string stream pointers, because these "exit-destructors" can cause segfaults because the type destructor handles dismantling and destroying these unique_ptr objects. Refactoring problematic names of constants. Fixed missing EOF newlines. Fixed implicitly casting INT_MIN to unsigned. --- src/TestCPPAssertions.cpp | 11 +++---- src/TestCPPExceptions.cpp | 5 ++- src/TestCPPTestCase.cpp | 65 +++++++++++++++++++-------------------- src/TestCPPTestSuite.cpp | 17 +++++----- src/TestCPPUtil.cpp | 4 +-- 5 files changed, 49 insertions(+), 53 deletions(-) diff --git a/src/TestCPPAssertions.cpp b/src/TestCPPAssertions.cpp index f689234..6680cc2 100644 --- a/src/TestCPPAssertions.cpp +++ b/src/TestCPPAssertions.cpp @@ -33,7 +33,6 @@ using std::endl; using std::exception; using std::exception_ptr; using std::function; -using std::move; using std::rethrow_exception; using std::string; using std::stringstream; @@ -72,7 +71,7 @@ namespace TestCPP { return; } - throw TestFailedException(move(failureMessage)); + throw TestFailedException(std::move(failureMessage)); } void Assertions::assertNoThrows ( @@ -84,7 +83,7 @@ namespace TestCPP { shouldNotThrow(); } catch (...) { - throw TestFailedException(move(failureMessage)); + throw TestFailedException(std::move(failureMessage)); } } @@ -118,7 +117,7 @@ namespace TestCPP { } } - void Assertions::fail(string failureMessage) { - throw TestFailedException(move(failureMessage)); + [[noreturn]] void Assertions::fail(string failureMessage) { + throw TestFailedException(std::move(failureMessage)); } -} \ No newline at end of file +} diff --git a/src/TestCPPExceptions.cpp b/src/TestCPPExceptions.cpp index 78d6ae0..dc939c6 100644 --- a/src/TestCPPExceptions.cpp +++ b/src/TestCPPExceptions.cpp @@ -34,7 +34,6 @@ For more information, please refer to #endif using std::clog; -using std::move; using std::string; using std::runtime_error; @@ -48,7 +47,7 @@ namespace TestCPP { #endif } TestCPPException::TestCPPException (string&& msg) : - runtime_error(move(msg)) + runtime_error(std::move(msg)) { #ifdef TESTCPP_STACKTRACE_ENABLED clog << boost::stacktrace::stacktrace(); @@ -64,7 +63,7 @@ namespace TestCPP { } TestFailedException::TestFailedException (string&& msg) : - TestCPPException(move(msg)) + TestCPPException(std::move(msg)) { #ifdef TESTCPP_STACKTRACE_ENABLED clog << boost::stacktrace::stacktrace(); diff --git a/src/TestCPPTestCase.cpp b/src/TestCPPTestCase.cpp index 475aae4..7f9d28d 100644 --- a/src/TestCPPTestCase.cpp +++ b/src/TestCPPTestCase.cpp @@ -48,7 +48,6 @@ using std::exception; using std::fixed; using std::function; using std::invalid_argument; -using std::move; using std::rethrow_exception; using std::runtime_error; using std::setprecision; @@ -67,46 +66,46 @@ namespace TestCPP { atomic_int TestCase::logCaptureCasesDestroyed; atomic_int TestCase::stderrCaptureCasesDestroyed; - unique_ptr + [[clang::no_destroy]] unique_ptr TestCase::stdoutBuffer = unique_ptr( nullptr, [](stringstream*){} ); - unique_ptr + [[clang::no_destroy]] unique_ptr TestCase::clogBuffer = unique_ptr( nullptr, [](stringstream*){} ); - unique_ptr + [[clang::no_destroy]] unique_ptr TestCase::stderrBuffer = unique_ptr( nullptr, [](stringstream*){} ); - unique_ptr + [[clang::no_destroy]] unique_ptr TestCase::stdoutOriginal = unique_ptr( nullptr, [](streambuf*){} ); - unique_ptr + [[clang::no_destroy]] unique_ptr TestCase::clogOriginal = unique_ptr( nullptr, [](streambuf*){} ); - unique_ptr + [[clang::no_destroy]] unique_ptr TestCase::stderrOriginal = unique_ptr( nullptr, [](streambuf*){} ); TestCase::TestCase (TestObjName&& name, - function test, + function testFn, bool msg, bool captureOut, bool captureLog, bool captureErr, TestCase::TestCaseOutCompareOptions opt) { this->notifyTestPassed = msg; - this->test = test; + this->test = testFn; this->testName = name; @@ -155,15 +154,15 @@ namespace TestCPP { } TestCase::TestCase (TestCase&& o) { - this->outCompareOption(move(o.option)); - this->setNotifyPassed(move(o.notifyTestPassed)); + this->outCompareOption(std::move(o.option)); + this->setNotifyPassed(std::move(o.notifyTestPassed)); - this->pass = move(o.pass); - this->lastRunTime = move(o.lastRunTime); + this->pass = std::move(o.pass); + this->lastRunTime = std::move(o.lastRunTime); - this->stdoutCaptured = move(o.stdoutCaptured); - this->clogCaptured = move(o.clogCaptured); - this->stderrCaptured = move(o.stderrCaptured); + this->stdoutCaptured = std::move(o.stdoutCaptured); + this->clogCaptured = std::move(o.clogCaptured); + this->stderrCaptured = std::move(o.stderrCaptured); if (this->stdoutCaptured) { captureStdout(); @@ -175,8 +174,8 @@ namespace TestCPP { captureStdErr(); } - this->testName = move(o.testName); - this->test = move(o.test); + this->testName = std::move(o.testName); + this->test = std::move(o.test); } TestCase::~TestCase () { @@ -246,15 +245,15 @@ namespace TestCPP { } TestCase& TestCase::operator= (TestCase&& rhs) { - this->outCompareOption(move(rhs.option)); - this->setNotifyPassed(move(rhs.notifyTestPassed)); + this->outCompareOption(std::move(rhs.option)); + this->setNotifyPassed(std::move(rhs.notifyTestPassed)); - this->pass = move(rhs.pass); - this->lastRunTime = move(rhs.lastRunTime); + this->pass = std::move(rhs.pass); + this->lastRunTime = std::move(rhs.lastRunTime); - this->stdoutCaptured = move(rhs.stdoutCaptured); - this->clogCaptured = move(rhs.clogCaptured); - this->stderrCaptured = move(rhs.stderrCaptured); + this->stdoutCaptured = std::move(rhs.stdoutCaptured); + this->clogCaptured = std::move(rhs.clogCaptured); + this->stderrCaptured = std::move(rhs.stderrCaptured); if (this->stdoutCaptured) { captureStdout(); @@ -266,8 +265,8 @@ namespace TestCPP { captureStdErr(); } - this->testName = move(rhs.testName); - this->test = move(rhs.test); + this->testName = std::move(rhs.testName); + this->test = std::move(rhs.test); return *this; } @@ -279,7 +278,7 @@ namespace TestCPP { void TestCase::logFailure(ostream& out, string& reason) { out << fixed; out << setprecision(TCPPNum::TIME_PRECISION); - out << TCPPStr::TEST_ << this->testName << TCPPStr::_FAIL_ + out << TCPPStr::TEST << this->testName << TCPPStr::FAIL << TCPPStr::PARENL << static_cast(this->lastRunTime)/ TCPPNum::NANOS_IN_SEC @@ -320,7 +319,7 @@ namespace TestCPP { if (this->notifyTestPassed) { clog << fixed; clog << setprecision(TCPPNum::TIME_PRECISION); - clog << TCPPStr::TEST_ << this->testName << TCPPStr::_PASS_ + clog << TCPPStr::TEST << this->testName << TCPPStr::PASS << TCPPStr::PARENL << static_cast(this->lastRunTime)/ TCPPNum::NANOS_IN_SEC @@ -428,7 +427,7 @@ namespace TestCPP { default: stringstream error; - error << TCPPStr::UNK_OPT_ << opt; + error << TCPPStr::UNK_OPT << opt; throw TestCPPException(error.str()); } } @@ -476,7 +475,7 @@ namespace TestCPP { else { stringstream nomatch; nomatch << TCPPStr::APOS << source << TCPPStr::APOS; - nomatch << TCPPStr::_NEQUIV_ << TCPPStr::APOS; + nomatch << TCPPStr::NEQUIV << TCPPStr::APOS; nomatch << against << TCPPStr::APOS; if (this->clogOriginal != nullptr) { @@ -498,7 +497,7 @@ namespace TestCPP { else { stringstream nomatch; nomatch << TCPPStr::APOS << source << TCPPStr::APOS; - nomatch << TCPPStr::_NCONTAIN_ << TCPPStr::APOS; + nomatch << TCPPStr::NCONTAIN << TCPPStr::APOS; nomatch << against << TCPPStr::APOS; if (this->clogOriginal != nullptr) { @@ -515,7 +514,7 @@ namespace TestCPP { default: stringstream re; - re << TCPPStr::UNK_CMP_OPT_ << this->option; + re << TCPPStr::UNK_CMP_OPT << this->option; throw TestCPPException(re.str()); } } diff --git a/src/TestCPPTestSuite.cpp b/src/TestCPPTestSuite.cpp index c5b04fa..ecaf3d6 100644 --- a/src/TestCPPTestSuite.cpp +++ b/src/TestCPPTestSuite.cpp @@ -41,7 +41,6 @@ using std::exception; using std::fixed; using std::function; using std::invalid_argument; -using std::move; using std::ostream; using std::rethrow_exception; using std::runtime_error; @@ -68,7 +67,7 @@ namespace TestCPP { } void TestSuite::setSuiteName (TestObjName&& testSuiteName) { - this->suiteName = move(testSuiteName); + this->suiteName = std::move(testSuiteName); } unsigned TestSuite::getLastRunFailCount () { @@ -87,7 +86,7 @@ namespace TestCPP { this->totalRuntime = 0; clog << endl - << TCPPStr::START_RUN << TCPPStr::SUITE_ + << TCPPStr::START_RUN << TCPPStr::SUITE << TCPPStr::APOS << this->suiteName << TCPPStr::APOS << endl << endl; @@ -98,7 +97,7 @@ namespace TestCPP { testPassed = test.go(); } catch (exception& e) { - clog << TCPPStr::TEST_EXC_ << e.what() + clog << TCPPStr::TEST_EXC << e.what() << endl; } catch (...) { @@ -124,8 +123,8 @@ namespace TestCPP { if (this->testSuitePassedMessage && this->lastRunFailCount == 0) { - clog << TCPPStr::ALL_ << TCPPStr::APOS << this->suiteName - << TCPPStr::APOS << TCPPStr::_SUITE_TESTS_PASSED + clog << TCPPStr::ALL << TCPPStr::APOS << this->suiteName + << TCPPStr::APOS << TCPPStr::SUITE_TESTS_PASSED << endl; } @@ -134,11 +133,11 @@ namespace TestCPP { clog << fixed; clog << setprecision(0); - clog << TCPPStr::FINISHED_SUITE_ << TCPPStr::APOS - << this->suiteName << TCPPStr::APOS << TCPPStr::_IN_ABOUT_ + clog << TCPPStr::FINISHED_SUITE << TCPPStr::APOS + << this->suiteName << TCPPStr::APOS << TCPPStr::IN_ABOUT << suiteRuntimeElapsed << TCPPStr::SEC << TCPPStr::SP << TCPPStr::PARENL << this->lastRunSuccessCount - << TCPPStr::FWSL << this->tests.size() << TCPPStr::_PASSED + << TCPPStr::FWSL << this->tests.size() << TCPPStr::PASSED << TCPPStr::PARENR << endl; } diff --git a/src/TestCPPUtil.cpp b/src/TestCPPUtil.cpp index 671d8ea..7d13eb1 100644 --- a/src/TestCPPUtil.cpp +++ b/src/TestCPPUtil.cpp @@ -92,7 +92,7 @@ namespace TestCPP { } if (toCast >= static_cast(INT_MIN)) { - return static_cast(toCast - INT_MIN) + INT_MIN; + return static_cast(toCast - static_cast(INT_MIN)) + INT_MIN; } throw std::runtime_error( @@ -100,4 +100,4 @@ namespace TestCPP { ); } } -} \ No newline at end of file +} From 948fc444462306e4d050c6f47e46b76a9691e5c3 Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Sat, 8 Feb 2025 01:55:39 -0800 Subject: [PATCH 48/59] Update the CMake Presets version to 6, as that is what we are intending to use. --- CMakePresets.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakePresets.json b/CMakePresets.json index 9bfc520..99244a6 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -1,8 +1,8 @@ { - "version": 5, + "version": 6, "cmakeMinimumRequired": { "major": 3, - "minor": 24, + "minor": 25, "patch": 0 }, "configurePresets": [ From cdbc74f8131a77eb3f3e4c2a39644f4c97f320b0 Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Mon, 17 Feb 2025 00:55:16 -0800 Subject: [PATCH 49/59] Expand/fix/refmt .clang-tidy, enhance CMakePresets, toolchains, cmake Clang-Tidy configuration and .clang-tidy file: - Disable *-use-nullptr clang-tidy checks because they are broken on Windows in the Visual Studio 2022-provided Clang builds, as evidenced by the following issues I discovered in researching why clang-tidy was failing with an ACCESS_VIOLATION (0xc0000005) error: > https://developercommunity.visualstudio.com/t/clang-tidy-terminates-with-Exception-Cod/10822069?pageSize=15&sort=active&openOnly=false&closedOnly=false&topics=repos > https://github.com/llvm/llvm-project/issues/53778 - Set FormatStyle to none so clang-tidy doesn't auto-format files, that is not what I want - Added HeaderFilterRegex that includes all headers, then added ExcludeHeaderFilterRegex to exclude the external headers (boost) - Added WarningsAsErrors * to treat all warnings as errors - Added SystemHeaders false so all system headers are excluded from analysis - Added ExtraArgs: > -Iinclude so library headers are discovered and included in analysis > -I3rdparty/include so boost headers are discovered and properly excluded from analysis - Now formatted as JSON so its format is more obvious without the weird opening/closing 3-character strings that indicate YAML but cause issues. Added hidden windows-specific presets that are intended to be inherited so the descendant presets will have the proper toolchain loaded; these are new to the presets here and have the toolchainFile property defined so as to load a toolchain from the cmake/toolchains location. There are ancestor toolchain presets defined for MSVC and ClangCL. ClangCL is only used for running clang-tidy analysis on Windows with the VS-packaged LLVM distribution. Split MSVC ancestor toolchain presets into stacktrace-enabled and no- stacktrace variants. Set CMAKE_SYSTEM_PROCESSOR so the toolchain scripts select the proper toolchain tools. Changed all VS-specific names, descriptions, and display names to be architecture-specific and also either Windows- or MSVC-specific, depending on context. Add CMAKE_C_FLAGS, CMAKE_CXX_FLAGS, and CMAKE_EXE_LINKER_FLAGS where appropriate and necessary, particularly where static code analysis is to be run. Fix nativeToolOptions since we're now using Ninja instead of MSBuild. Moved nativeToolOptions in code analysis buildPresets to CMAKE_C_FLAGS and CMAKE_CXX_FLAGS in the corresponding configurePresets, because these are cl arguments, not MSBuild/Ninja arguments. Added buildPresets for clang-tidy configurePresets. Added an EOF newline. Added toolchain files since we're no longer using MSBuild, courtesy of https://github.com/MarkSchofield/WindowsToolchain, with some great CMake toolchain files; thank you @MarkSchofield; awesome work, they work wonderfully: - cmake/toolchains/VSWhere.cmake - cmake/toolchains/Windows.Clang.toolchain.cmake - cmake/toolchains/Windows.Kits.cmake - cmake/toolchains/Windows.MSVC.toolchain.cmake These are referenced through CMakePresets.json and are loaded such that the build has all the necessary tools. Fixed find_program for clang-tidy so it is now NO_CACHE. Fixed CLANG_TIDY_COMMAND such that it now uses the --config-file parameter, so all configurations are loaded through that instead of specified on the command line; added cache string description, and force-load the new value. Ignore the global-constructors warnings, as explained in the comment in the CMake files that define the GCC/Clang build flags for different configurations; this only applies to Clang until this issue gets resolved: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71482 Noted in GCCCoverage.cmake for if/when that ref issue gets resolved. Add /external:anglebrackets, /external:W0, and in the case where stacktraces are enabled /external:I3rdparty/include, so warnings in these external headers are ignored. Removed warning suppressions that are now unnecessary because warnings in external headers (boost, system headers) are now ignored thanks to the above CL parameters: - /wd4625 > Implicitly-deleted copy constructors. - /wd4626 > Implicitly-deleted copy assignment operators. - /wd4668 > Undefined preprocessor macros in the Windows SDK internal headers. - /wd5026 > Implicitly-deleted move constructors. - /wd5027 > Implicitly-deleted move assignment operators. - /wd5039 > Windows SDK functions that are passed to extern 'C' APIs that are not marked as noexcept. Added /nologo so if CMake doesn't configure the build to have it, it will be there. Added /Zi to the debug build ensuring all debug information is generated. /FS to avoid file locking issues. Added explicit exception handling enablement in MSVC to fix issues with noexcept generating warnings because there's no exception handling mode specified: /EHscr for Debug (adds noexcept runtime checks with the r), and /EHsc for Release (no runtime noexcept checks). Added runtime checks to Debug (/RTC1) so running the debug build can catch issues during testing or give more information if there's user code that is causing an issue inside the library. Make sure that if we are running an MSVC analysis build, and a ruleset file is explicitly selected, that we add the standard location for built-in ruleset files with /analyze:rulesetdirectory and the VS_INSTALLATION_PATH specified by the toolchain. CMake for some reason automatically adds /RTC1 to Release builds, which causes compilation to fail because /RTC1 and /O2 are incompatible, so the build generator now manually removes the RTC flags from release build compilation commands. --- .clang-tidy | 14 +- CMakePresets.json | 1423 +++++++++-------- cmake/Analyzing.cmake | 12 +- cmake/build/GCCClangDebug.cmake | 35 + cmake/build/GCCClangRelease.cmake | 35 + cmake/build/GCCCoverage.cmake | 4 + cmake/build/MSVCDebug.cmake | 87 +- cmake/build/MSVCRelease.cmake | 89 +- cmake/toolchains/VSWhere.cmake | 132 ++ .../toolchains/Windows.Clang.toolchain.cmake | 271 ++++ cmake/toolchains/Windows.Kits.cmake | 153 ++ cmake/toolchains/Windows.MSVC.toolchain.cmake | 279 ++++ 12 files changed, 1791 insertions(+), 743 deletions(-) create mode 100644 cmake/toolchains/VSWhere.cmake create mode 100644 cmake/toolchains/Windows.Clang.toolchain.cmake create mode 100644 cmake/toolchains/Windows.Kits.cmake create mode 100644 cmake/toolchains/Windows.MSVC.toolchain.cmake diff --git a/.clang-tidy b/.clang-tidy index a98339f..7fb79fd 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,2 +1,12 @@ -Checks: '-*,bugprone-*,cert-*,clang-analyzer-*,cppcoreguidelines-*,hicpp-*,misc-*,modernize-*,performance-*,portability-*,readability-*' -FormatStyle: "file" +{ + "Checks": "-*,bugprone-*,cert-*,clang-analyzer-*,cppcoreguidelines-*,hicpp-*,misc-*,modernize-*,performance-*,portability-*,readability-*,-modernize-use-nullptr,-hicpp-use-nullptr", + "HeaderFilterRegex": ".*", + "ExcludeHeaderFilterRegex": "boost/.*", + "WarningsAsErrors": "*", + "FormatStyle": "none", + "SystemHeaders": false, + "ExtraArgs": [ + "-Iinclude", + "-I3rdparty/include" + ] +} diff --git a/CMakePresets.json b/CMakePresets.json index 99244a6..4311e28 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -27,32 +27,6 @@ "systemVars": false } }, - { - "name": "base-dev-checks", - "description": "Base config preset with dev checks enabled, using the Debug build options.", - "inherits": "base", - "hidden": true, - "warnings": { - "dev": true, - "deprecated": true, - "uninitialized": true, - "unusedCli": true, - "systemVars": true - } - }, - { - "name": "vs-dev-checks", - "displayName": "CMake - Windows - Visual Studio - Dev Checks", - "description": "Windows VS config preset with dev checks enabled, using the Debug build options.", - "inherits": "base-dev-checks", - "binaryDir": "${sourceDir}/out/build/vs-dev-checks", - "installDir": "${sourceDir}/out/install/vs-dev-checks", - "condition": { - "type": "equals", - "lhs": "${hostSystemName}", - "rhs": "Windows" - } - }, { "name": "export-cc-nost-base", "description": "Base configuration ensures Compile Commands are exported, using the Debug build options, with no stacktraces (strict C++11).", @@ -72,14 +46,12 @@ } }, { - "name": "vs-base", - "displayName": "Generate - x86 - Debug - Windows - Visual Studio - Core Lib", - "description": "Configure the base Visual Studio Minimal build with the Win32 toolchain architecture, using the Debug build options.", + "name": "windows-msvc", "inherits": "export-cc-st-base", - "binaryDir": "${sourceDir}/out/build/Debug/vs-base", - "installDir": "${sourceDir}/out/install/Debug/vs-base", - "generator": "Visual Studio 17 2022", - "architecture": "Win32", + "hidden": true, + "description": "Configure the build for MSVC CL on Windows, with stacktraces enabled.", + "generator": "Ninja", + "toolchainFile": "${sourceDir}/cmake/toolchains/Windows.MSVC.toolchain.cmake", "condition": { "type": "equals", "lhs": "${hostSystemName}", @@ -87,25 +59,29 @@ } }, { - "name": "vs-base-rel", - "displayName": "Generate - x86 - Release - Windows - Visual Studio - Core Lib", - "description": "Configure the base Visual Studio Minimal build with the Win32 toolchain architecture, using the Release build options.", - "inherits": "vs-base", - "binaryDir": "${sourceDir}/out/build/Release/vs-base", - "installDir": "${sourceDir}/out/install/Release/vs-base", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Release" + "name": "windows-msvc-nost", + "inherits": "export-cc-nost-base", + "hidden": true, + "description": "Configure the build for MSVC CL on Windows, with no stacktraces.", + "generator": "Ninja", + "toolchainFile": "${sourceDir}/cmake/toolchains/Windows.MSVC.toolchain.cmake", + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Windows" } }, { - "name": "vs-nost-base", - "displayName": "Generate - x86 - Debug - Windows - Visual Studio - Core Lib - No Stacktraces", - "description": "Configure the base Visual Studio Minimal build with the Win32 toolchain architecture, using the Debug build options, but with no stacktraces (strict C++11).", + "name": "windows-clangcl", "inherits": "export-cc-nost-base", - "binaryDir": "${sourceDir}/out/build/Debug/vs-nost-base", - "installDir": "${sourceDir}/out/install/Debug/vs-nost-base", - "generator": "Visual Studio 17 2022", - "architecture": "Win32", + "hidden": true, + "description": "Configure the build for ClangCL on Windows, only used for running clang-tidy on Windows.", + "generator": "Ninja", + "toolchainFile": "${sourceDir}/cmake/toolchains/Windows.Clang.toolchain.cmake", + "cacheVariables": { + "CMAKE_C_COMPILER_FRONTEND_VARIANT": "MSVC", + "CMAKE_CXX_COMPILER_FRONTEND_VARIANT": "MSVC" + }, "condition": { "type": "equals", "lhs": "${hostSystemName}", @@ -113,223 +89,359 @@ } }, { - "name": "vs-nost-base-rel", - "displayName": "Generate - x86 - Release - Windows - Visual Studio - Core Lib - No Stacktraces", - "description": "Configure the base Visual Studio Minimal build with the Win32 toolchain architecture, using the Release build options, but with no stacktraces (strict C++11).", - "inherits": "vs-nost-base", - "binaryDir": "${sourceDir}/out/build/Release/vs-nost-base", - "installDir": "${sourceDir}/out/install/Release/vs-nost-base", + "name": "base-dev-checks", + "displayName": "CMake - Dev Checks", + "description": "Base config preset with dev checks enabled, using the Debug build options.", + "inherits": "base", + "warnings": { + "dev": true, + "deprecated": true, + "uninitialized": true, + "unusedCli": true, + "systemVars": true + } + }, + { + "name": "win32-base", + "displayName": "Generate - x86 - Debug - Windows - Core Lib", + "description": "Configure the base Windows Minimal build with the x86 toolchain architecture, using the Debug build options.", + "inherits": "windows-msvc", + "binaryDir": "${sourceDir}/out/build/Debug/win32-base", + "installDir": "${sourceDir}/out/install/Debug/win32-base", + "cacheVariables": { + "CMAKE_SYSTEM_PROCESSOR": "X86" + } + }, + { + "name": "win32-base-rel", + "displayName": "Generate - x86 - Release - Windows - Core Lib", + "description": "Configure the base Windows Minimal build with the x86 toolchain architecture, using the Release build options.", + "inherits": "win32-base", + "binaryDir": "${sourceDir}/out/build/Release/win32-base", + "installDir": "${sourceDir}/out/install/Release/win32-base", "cacheVariables": { "CMAKE_BUILD_TYPE": "Release" } }, { - "name": "vs-msanalysis", - "displayName": "Generate - x86 - Windows - Visual Studio - MSVC Analysis", - "description": "Configure the base Visual Studio Minimal build to prepare for running the MSVC++ analyzer.", - "inherits": "vs-nost-base", - "binaryDir": "${sourceDir}/out/build/vs-msanalysis", - "installDir": "${sourceDir}/out/install/vs-msanalysis", + "name": "win32-nost-base", + "displayName": "Generate - x86 - Debug - Windows - Core Lib - No Stacktraces", + "description": "Configure the base Windows Minimal build with the x86 toolchain architecture, using the Debug build options, but with no stacktraces (strict C++11).", + "inherits": "windows-msvc-nost", + "binaryDir": "${sourceDir}/out/build/Debug/win32-nost-base", + "installDir": "${sourceDir}/out/install/Debug/win32-nost-base", + "cacheVariables": { + "CMAKE_SYSTEM_PROCESSOR": "X86" + } + }, + { + "name": "win32-nost-base-rel", + "displayName": "Generate - x86 - Release - Windows - Core Lib - No Stacktraces", + "description": "Configure the base Windows Minimal build with the x86 toolchain architecture, using the Release build options, but with no stacktraces (strict C++11).", + "inherits": "win32-nost-base", + "binaryDir": "${sourceDir}/out/build/Release/win32-nost-base", + "installDir": "${sourceDir}/out/install/Release/win32-nost-base", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release" + } + }, + { + "name": "win32-msanalysis", + "displayName": "Generate - x86 - Windows - MSVC Analysis", + "description": "Configure the base Windows Minimal build to prepare for running the MSVC++ analyzer.", + "inherits": "win32-nost-base", + "binaryDir": "${sourceDir}/out/build/win32-msanalysis", + "installDir": "${sourceDir}/out/install/win32-msanalysis", + "cacheVariables": { + "CMAKE_C_FLAGS": "/analyze /analyze:external- /analyze:autolog /analyze:ruleset NativeRecommendedRules.ruleset", + "CMAKE_CXX_FLAGS": "/analyze /analyze:external- /analyze:autolog /analyze:ruleset NativeRecommendedRules.ruleset" + }, "vendor": { "microsoft.com/VisualStudioSettings/CMake/1.0": { "intelliSenseMode": "windows-msvc-x86", - "enableMicrosoftCodeAnalysis": true + "enableMicrosoftCodeAnalysis": true, + "disableExternalAnalysis": true, + "intelliSenseOptions": { + "additionalCompilerArgs": [ + "/analyze", + "/analyze:external-", + "/analyze:autolog", + "/analyze:ruleset NativeRecommendedRules.ruleset" + ] + } + } + } + }, + { + "name": "win32-msanalysis-sarif", + "displayName": "Generate - x86 - Windows - MSVC Analysis - SARIF Output", + "description": "Configure the base Windows Minimal build to prepare for running the MSVC++ analyzer, and output the results to a SARIF format.", + "inherits": "win32-msanalysis", + "binaryDir": "${sourceDir}/out/build/win32-msanalysis-sarif", + "installDir": "${sourceDir}/out/install/win32-msanalysis-sarif", + "cacheVariables": { + "CMAKE_C_FLAGS": "/analyze /analyze:external- /analyze:autolog /analyze:ruleset NativeRecommendedRules.ruleset /analyze:log:format:sarif", + "CMAKE_CXX_FLAGS": "/analyze /analyze:external- /analyze:autolog /analyze:ruleset NativeRecommendedRules.ruleset /analyze:log:format:sarif" + }, + "vendor": { + "microsoft.com/VisualStudioSettings/CMake/1.0": { + "intelliSenseOptions": { + "additionalCompilerArgs": [ + "/analyze:log:format:sarif" + ] + } + } + } + }, + { + "name": "win32-msanalysis-xml", + "displayName": "Generate - x86 - Windows - MSVC Analysis - XML Output", + "description": "Configure the base Windows Minimal build to prepare for running the MSVC++ analyzer, and output the results to a XML format.", + "inherits": "win32-msanalysis", + "binaryDir": "${sourceDir}/out/build/win32-msanalysis-xml", + "installDir": "${sourceDir}/out/install/win32-msanalysis-xml", + "cacheVariables": { + "CMAKE_C_FLAGS": "/analyze /analyze:external- /analyze:autolog /analyze:ruleset NativeRecommendedRules.ruleset /analyze:log:format:xml", + "CMAKE_CXX_FLAGS": "/analyze /analyze:external- /analyze:autolog /analyze:ruleset NativeRecommendedRules.ruleset /analyze:log:format:xml" + }, + "vendor": { + "microsoft.com/VisualStudioSettings/CMake/1.0": { + "intelliSenseOptions": { + "additionalCompilerArgs": [ + "/analyze:log:format:xml" + ] + } } } }, { - "name": "vs-with-test", - "displayName": "Generate - x86 - Debug - Windows - Visual Studio - Core Lib With Tests", - "description": "Configure the Visual Studio build with Core and Test Library build set and the Win32 toolchain architecture, using the Debug build options.", - "inherits": "vs-base", - "binaryDir": "${sourceDir}/out/build/Debug/vs-withtest", - "installDir": "${sourceDir}/out/install/Debug/vs-withtest", + "name": "win32-with-test", + "displayName": "Generate - x86 - Debug - Windows - Core Lib With Tests", + "description": "Configure the Windows build with Core and Test Library build set and the x86 toolchain architecture, using the Debug build options.", + "inherits": "win32-base", + "binaryDir": "${sourceDir}/out/build/Debug/win32-withtest", + "installDir": "${sourceDir}/out/install/Debug/win32-withtest", "cacheVariables": { "TESTCPP_TEST_ENABLED": "1" } }, { - "name": "vs-with-test-rel", - "displayName": "Generate - x86 - Release - Windows - Visual Studio - Core Lib With Tests", - "description": "Configure the Visual Studio build with Core and Test Library build set and the Win32 toolchain architecture, using the Release build options.", - "inherits": "vs-base-rel", - "binaryDir": "${sourceDir}/out/build/Release/vs-withtest", - "installDir": "${sourceDir}/out/install/Release/vs-withtest", + "name": "win32-with-test-rel", + "displayName": "Generate - x86 - Release - Windows - Core Lib With Tests", + "description": "Configure the Windows build with Core and Test Library build set and the x86 toolchain architecture, using the Release build options.", + "inherits": "win32-base-rel", + "binaryDir": "${sourceDir}/out/build/Release/win32-withtest", + "installDir": "${sourceDir}/out/install/Release/win32-withtest", "cacheVariables": { "TESTCPP_TEST_ENABLED": "1" } }, { - "name": "vs-nost-with-test", - "displayName": "Generate - x86 - Debug - Windows - Visual Studio - Core Lib With Tests - No Stacktraces", - "description": "Configure the Visual Studio build with Core and Test Library build set and the Win32 toolchain architecture, using the Debug build options, but with no stacktraces (strict C++11).", - "inherits": "vs-nost-base", - "binaryDir": "${sourceDir}/out/build/Debug/vs-nost-withtest", - "installDir": "${sourceDir}/out/install/Debug/vs-nost-withtest", + "name": "win32-nost-with-test", + "displayName": "Generate - x86 - Debug - Windows - Core Lib With Tests - No Stacktraces", + "description": "Configure the Windows build with Core and Test Library build set and the x86 toolchain architecture, using the Debug build options, but with no stacktraces (strict C++11).", + "inherits": "win32-nost-base", + "binaryDir": "${sourceDir}/out/build/Debug/win32-nost-withtest", + "installDir": "${sourceDir}/out/install/Debug/win32-nost-withtest", "cacheVariables": { "TESTCPP_TEST_ENABLED": "1" } }, { - "name": "vs-nost-with-test-rel", - "displayName": "Generate - x86 - Release - Windows - Visual Studio - Core Lib With Tests - No Stacktraces", - "description": "Configure the Visual Studio build with Core and Test Library build set and the Win32 toolchain architecture, using the Release build options, but with no stacktraces (strict C++11).", - "inherits": "vs-nost-base-rel", - "binaryDir": "${sourceDir}/out/build/Release/vs-nost-withtest", - "installDir": "${sourceDir}/out/install/Release/vs-nost-withtest", + "name": "win32-nost-with-test-rel", + "displayName": "Generate - x86 - Release - Windows - Core Lib With Tests - No Stacktraces", + "description": "Configure the Windows build with Core and Test Library build set and the x86 toolchain architecture, using the Release build options, but with no stacktraces (strict C++11).", + "inherits": "win32-nost-base-rel", + "binaryDir": "${sourceDir}/out/build/Release/win32-nost-withtest", + "installDir": "${sourceDir}/out/install/Release/win32-nost-withtest", "cacheVariables": { "TESTCPP_TEST_ENABLED": "1" } }, { - "name": "vs-with-demo", - "displayName": "Generate - x86 - Debug - Windows - Visual Studio - Core Lib With Demo", - "description": "Configure the Visual Studio build with Core and Demo set and the Win32 toolchain architecture, using the Debug build options.", - "inherits": "vs-base", - "binaryDir": "${sourceDir}/out/build/Debug/vs-withdemo", - "installDir": "${sourceDir}/out/install/Debug/vs-withdemo", + "name": "win32-with-demo", + "displayName": "Generate - x86 - Debug - Windows - Core Lib With Demo", + "description": "Configure the Windows build with Core and Demo set and the x86 toolchain architecture, using the Debug build options.", + "inherits": "win32-base", + "binaryDir": "${sourceDir}/out/build/Debug/win32-withdemo", + "installDir": "${sourceDir}/out/install/Debug/win32-withdemo", "cacheVariables": { "TESTCPP_DEMO_ENABLED": "1" } }, { - "name": "vs-with-demo-rel", - "displayName": "Generate - x86 - Release - Windows - Visual Studio - Core Lib With Demo", - "description": "Configure the Visual Studio build with Core and Demo set and the Win32 toolchain architecture, using the Release build options.", - "inherits": "vs-base-rel", - "binaryDir": "${sourceDir}/out/build/Release/vs-withdemo", - "installDir": "${sourceDir}/out/install/Release/vs-withdemo", + "name": "win32-with-demo-rel", + "displayName": "Generate - x86 - Release - Windows - Core Lib With Demo", + "description": "Configure the Windows build with Core and Demo set and the x86 toolchain architecture, using the Release build options.", + "inherits": "win32-base-rel", + "binaryDir": "${sourceDir}/out/build/Release/win32-withdemo", + "installDir": "${sourceDir}/out/install/Release/win32-withdemo", "cacheVariables": { "TESTCPP_DEMO_ENABLED": "1" } }, { - "name": "vs-nost-with-demo", - "displayName": "Generate - x86 - Debug - Windows - Visual Studio - Core Lib With Demo - No Stacktraces", - "description": "Configure the Visual Studio build with Core and Demo library build set and the Win32 toolchain architecture, using the Debug build options, but with no stacktraces (strict C++11).", - "inherits": "vs-nost-base", - "binaryDir": "${sourceDir}/out/build/Debug/vs-nost-withdemo", - "installDir": "${sourceDir}/out/install/Debug/vs-nost-withdemo", + "name": "win32-nost-with-demo", + "displayName": "Generate - x86 - Debug - Windows - Core Lib With Demo - No Stacktraces", + "description": "Configure the Windows build with Core and Demo library build set and the x86 toolchain architecture, using the Debug build options, but with no stacktraces (strict C++11).", + "inherits": "win32-nost-base", + "binaryDir": "${sourceDir}/out/build/Debug/win32-nost-withdemo", + "installDir": "${sourceDir}/out/install/Debug/win32-nost-withdemo", "cacheVariables": { "TESTCPP_DEMO_ENABLED": "1" } }, { - "name": "vs-nost-with-demo-rel", - "displayName": "Generate - x86 - Release - Windows - Visual Studio - Core Lib With Demo - No Stacktraces", - "description": "Configure the Visual Studio build with Core and Demo library build set and the Win32 toolchain architecture, using the Release build options, but with no stacktraces (strict C++11).", - "inherits": "vs-nost-base-rel", - "binaryDir": "${sourceDir}/out/build/Release/vs-nost-withdemo", - "installDir": "${sourceDir}/out/install/Release/vs-nost-withdemo", + "name": "win32-nost-with-demo-rel", + "displayName": "Generate - x86 - Release - Windows - Core Lib With Demo - No Stacktraces", + "description": "Configure the Windows build with Core and Demo library build set and the x86 toolchain architecture, using the Release build options, but with no stacktraces (strict C++11).", + "inherits": "win32-nost-base-rel", + "binaryDir": "${sourceDir}/out/build/Release/win32-nost-withdemo", + "installDir": "${sourceDir}/out/install/Release/win32-nost-withdemo", "cacheVariables": { "TESTCPP_DEMO_ENABLED": "1" } }, { - "name": "vs-all", - "displayName": "Generate - x86 - Debug - Windows - Visual Studio - All Components - Core, Tests, and Demo", - "description": "Configure the Visual Studio build with all Library options set and the Win32 toolchain architecture, using the Debug build options.", - "inherits": "vs-with-test", - "binaryDir": "${sourceDir}/out/build/Debug/vs-all", - "installDir": "${sourceDir}/out/install/Debug/vs-all", + "name": "win32-all", + "displayName": "Generate - x86 - Debug - Windows - All Components - Core, Tests, and Demo", + "description": "Configure the Windows build with all Library options set and the x86 toolchain architecture, using the Debug build options.", + "inherits": "win32-with-test", + "binaryDir": "${sourceDir}/out/build/Debug/win32-all", + "installDir": "${sourceDir}/out/install/Debug/win32-all", "cacheVariables": { "TESTCPP_DEMO_ENABLED": "1" } }, { - "name": "vs-all-rel", - "displayName": "Generate - x86 - Release - Windows - Visual Studio - All Components - Core, Tests, and Demo", - "description": "Configure the Visual Studio build with all Library options set and the Win32 toolchain architecture, using the Release build options.", - "inherits": "vs-with-test-rel", - "binaryDir": "${sourceDir}/out/build/Release/vs-all", - "installDir": "${sourceDir}/out/install/Release/vs-all", + "name": "win32-all-rel", + "displayName": "Generate - x86 - Release - Windows - All Components - Core, Tests, and Demo", + "description": "Configure the Windows build with all Library options set and the x86 toolchain architecture, using the Release build options.", + "inherits": "win32-with-test-rel", + "binaryDir": "${sourceDir}/out/build/Release/win32-all", + "installDir": "${sourceDir}/out/install/Release/win32-all", "cacheVariables": { "TESTCPP_DEMO_ENABLED": "1" } }, { - "name": "vs-nost-all", - "displayName": "Generate - x86 - Debug - Windows - Visual Studio - All Components - Core, Tests, and Demo - No Stacktraces", - "description": "Configure the Visual Studio build with all Library options set and the Win32 toolchain architecture, using the Debug build options, but with no stacktraces (strict C++11).", - "inherits": "vs-nost-with-test", - "binaryDir": "${sourceDir}/out/build/Debug/vs-nost-all", - "installDir": "${sourceDir}/out/install/Debug/vs-nost-all", + "name": "win32-nost-all", + "displayName": "Generate - x86 - Debug - Windows - All Components - Core, Tests, and Demo - No Stacktraces", + "description": "Configure the Windows build with all Library options set and the x86 toolchain architecture, using the Debug build options, but with no stacktraces (strict C++11).", + "inherits": "win32-nost-with-test", + "binaryDir": "${sourceDir}/out/build/Debug/win32-nost-all", + "installDir": "${sourceDir}/out/install/Debug/win32-nost-all", "cacheVariables": { "TESTCPP_DEMO_ENABLED": "1" } }, { - "name": "vs-nost-all-rel", - "displayName": "Generate - x86 - Release - Windows - Visual Studio - All Components - Core, Tests, and Demo - No Stacktraces", - "description": "Configure the Visual Studio build with all Library options set and the Win32 toolchain architecture, using the Release build options, but with no stacktraces (strict C++11).", - "inherits": "vs-nost-with-test-rel", - "binaryDir": "${sourceDir}/out/build/Release/vs-nost-all", - "installDir": "${sourceDir}/out/install/Release/vs-nost-all", + "name": "win32-nost-all-rel", + "displayName": "Generate - x86 - Release - Windows - All Components - Core, Tests, and Demo - No Stacktraces", + "description": "Configure the Windows build with all Library options set and the x86 toolchain architecture, using the Release build options, but with no stacktraces (strict C++11).", + "inherits": "win32-nost-with-test-rel", + "binaryDir": "${sourceDir}/out/build/Release/win32-nost-all", + "installDir": "${sourceDir}/out/install/Release/win32-nost-all", "cacheVariables": { "TESTCPP_DEMO_ENABLED": "1" } }, { - "name": "vs-ct", - "displayName": "Generate - x86 - Windows - Visual Studio - Clang Tidy analysis", - "description": "Configure the Visual Studio build with clang-tidy analysis and the x86 toolchain architecture.", - "inherits": "vs-nost-base", - "binaryDir": "${sourceDir}/out/build/vs-ct", - "installDir": "${sourceDir}/out/install/vs-ct", + "name": "win32-ct", + "displayName": "Generate - x86 - Windows - Clang Tidy analysis", + "description": "Configure the Windows build with clang-tidy analysis and the x86 toolchain architecture.", + "inherits": "windows-clangcl", + "binaryDir": "${sourceDir}/out/build/win32-ct", + "installDir": "${sourceDir}/out/install/win32-ct", "cacheVariables": { + "CMAKE_C_FLAGS": "-v -m32", + "CMAKE_CXX_FLAGS": "-v -m32", + "CMAKE_EXE_LINKER_FLAGS": "/machine:x86", + "CMAKE_SYSTEM_PROCESSOR": "X86", "TESTCPP_ANALYSIS_ENABLED": "1" }, - "toolset": "ClangCL", "vendor": { "microsoft.com/VisualStudioSettings/CMake/1.0": { - "intelliSenseMode": "windows-clang-x86" + "intelliSenseMode": "windows-clangcl-x86", + "clangTidyChecks": "-*,bugprone-*,cert-*,clang-analyzer-*,cppcoreguidelines-*,hicpp-*,misc-*,modernize-*,performance-*,portability-*,readability-*,-modernize-use-nullptr,-hicpp-use-nullptr", + "enableClangTidyCodeAnalysis": true + } + } + }, + { + "name": "win64-base", + "displayName": "Generate - x64 - Debug - Windows - Core Lib", + "description": "Configure the base Windows build with the x64 toolchain architecture, using the Debug build options.", + "inherits": "win32-base", + "binaryDir": "${sourceDir}/out/build/Debug/win64-base", + "installDir": "${sourceDir}/out/install/Debug/win64-base", + "cacheVariables": { + "CMAKE_SYSTEM_PROCESSOR": "AMD64" + } + }, + { + "name": "win64-base-rel", + "displayName": "Generate - x64 - Release - Windows - Core Lib", + "description": "Configure the base Windows build with the x64 toolchain architecture, using the Release build options.", + "inherits": "win32-base-rel", + "binaryDir": "${sourceDir}/out/build/Release/win64-base", + "installDir": "${sourceDir}/out/install/Release/win64-base", + "cacheVariables": { + "CMAKE_SYSTEM_PROCESSOR": "AMD64" + } + }, + { + "name": "win64-nost-base", + "displayName": "Generate - x64 - Debug - Windows - Core Lib - No Stacktraces", + "description": "Configure the base Windows build with the x64 toolchain architecture, using the Debug build options, but with no stacktraces (strict C++11).", + "inherits": "win32-nost-base", + "binaryDir": "${sourceDir}/out/build/Debug/win64-nost-base", + "installDir": "${sourceDir}/out/install/Debug/win64-nost-base", + "cacheVariables": { + "CMAKE_SYSTEM_PROCESSOR": "AMD64" + } + }, + { + "name": "win64-nost-base-rel", + "displayName": "Generate - x64 - Release - Windows - Core Lib - No Stacktraces", + "description": "Configure the base Windows build with the x64 toolchain architecture, using the Release build options, but with no stacktraces (strict C++11).", + "inherits": "win32-nost-base-rel", + "binaryDir": "${sourceDir}/out/build/Release/win64-nost-base", + "installDir": "${sourceDir}/out/install/Release/win64-nost-base", + "cacheVariables": { + "CMAKE_SYSTEM_PROCESSOR": "AMD64" + } + }, + { + "name": "win64-msanalysis", + "displayName": "Generate - x64 - Windows - MSVC Analysis", + "description": "Configure the base Windows Minimal build with the x64 toolchain architecture, then run the MSVC++ analyzer.", + "inherits": "win32-msanalysis", + "binaryDir": "${sourceDir}/out/build/win64-msanalysis", + "installDir": "${sourceDir}/out/install/win64-msanalysis", + "cacheVariables": { + "CMAKE_C_FLAGS": "/analyze /analyze:external- /analyze:autolog /analyze:ruleset NativeRecommendedRules.ruleset", + "CMAKE_CXX_FLAGS": "/analyze /analyze:external- /analyze:autolog /analyze:ruleset NativeRecommendedRules.ruleset", + "CMAKE_SYSTEM_PROCESSOR": "AMD64" + }, + "vendor": { + "microsoft.com/VisualStudioSettings/CMake/1.0": { + "intelliSenseMode": "windows-msvc-x64" } } }, { - "name": "vs64-base", - "displayName": "Generate - x64 - Debug - Windows - Visual Studio - Core Lib", - "description": "Configure the base Visual Studio build with the x64 toolchain architecture, using the Debug build options.", - "inherits": "vs-base", - "binaryDir": "${sourceDir}/out/build/Debug/vs64-base", - "installDir": "${sourceDir}/out/install/Debug/vs64-base", - "architecture": "x64" - }, - { - "name": "vs64-base-rel", - "displayName": "Generate - x64 - Release - Windows - Visual Studio - Core Lib", - "description": "Configure the base Visual Studio build with the x64 toolchain architecture, using the Release build options.", - "inherits": "vs-base-rel", - "binaryDir": "${sourceDir}/out/build/Release/vs64-base", - "installDir": "${sourceDir}/out/install/Release/vs64-base", - "architecture": "x64" - }, - { - "name": "vs64-nost-base", - "displayName": "Generate - x64 - Debug - Windows - Visual Studio - Core Lib - No Stacktraces", - "description": "Configure the base Visual Studio build with the x64 toolchain architecture, using the Debug build options, but with no stacktraces (strict C++11).", - "inherits": "vs-nost-base", - "binaryDir": "${sourceDir}/out/build/Debug/vs64-nost-base", - "installDir": "${sourceDir}/out/install/Debug/vs64-nost-base", - "architecture": "x64" - }, - { - "name": "vs64-nost-base-rel", - "displayName": "Generate - x64 - Release - Windows - Visual Studio - Core Lib - No Stacktraces", - "description": "Configure the base Visual Studio build with the x64 toolchain architecture, using the Release build options, but with no stacktraces (strict C++11).", - "inherits": "vs-nost-base-rel", - "binaryDir": "${sourceDir}/out/build/Release/vs64-nost-base", - "installDir": "${sourceDir}/out/install/Release/vs64-nost-base", - "architecture": "x64" - }, - { - "name": "vs64-msanalysis", - "displayName": "Generate - x64 - Windows - Visual Studio - MSVC Analysis", - "description": "Configure the base Visual Studio Minimal build with the x64 toolchain architecture, then run the MSVC++ analyzer.", - "inherits": "vs-msanalysis", - "binaryDir": "${sourceDir}/out/build/vs64-msanalysis", - "installDir": "${sourceDir}/out/install/vs64-msanalysis", - "architecture": "x64", + "name": "win64-msanalysis-sarif", + "displayName": "Generate - x64 - Windows - MSVC Analysis - SARIF Output", + "description": "Configure the base Windows Minimal build with the x64 toolchain architecture, then run the MSVC++ analyzer, and output the results to a SARIF format.", + "inherits": "win32-msanalysis-sarif", + "binaryDir": "${sourceDir}/out/build/win64-msanalysis-sarif", + "installDir": "${sourceDir}/out/install/win64-msanalysis-sarif", + "cacheVariables": { + "CMAKE_C_FLAGS": "/analyze /analyze:external- /analyze:autolog /analyze:ruleset NativeRecommendedRules.ruleset /analyze:log:format:sarif", + "CMAKE_CXX_FLAGS": "/analyze /analyze:external- /analyze:autolog /analyze:ruleset NativeRecommendedRules.ruleset /analyze:log:format:sarif", + "CMAKE_SYSTEM_PROCESSOR": "AMD64" + }, "vendor": { "microsoft.com/VisualStudioSettings/CMake/1.0": { "intelliSenseMode": "windows-msvc-x64" @@ -337,164 +449,184 @@ } }, { - "name": "vs64-with-test", - "displayName": "Generate - x64 - Debug - Windows - Visual Studio - Core Lib With Tests", - "description": "Configure the Visual Studio build with Core and Test Library build set and the x64 toolchain architecture, using the Debug build options.", - "inherits": "vs64-base", - "binaryDir": "${sourceDir}/out/build/Debug/vs64-withtest", - "installDir": "${sourceDir}/out/install/Debug/vs64-withtest", + "name": "win64-msanalysis-xml", + "displayName": "Generate - x64 - Windows - MSVC Analysis - XML Output", + "description": "Configure the base Windows Minimal build with the x64 toolchain architecture, then run the MSVC++ analyzer, and output the results to a XML format.", + "inherits": "win32-msanalysis-xml", + "binaryDir": "${sourceDir}/out/build/win64-msanalysis-xml", + "installDir": "${sourceDir}/out/install/win64-msanalysis-xml", + "cacheVariables": { + "CMAKE_C_FLAGS": "/analyze /analyze:external- /analyze:autolog /analyze:ruleset NativeRecommendedRules.ruleset /analyze:log:format:xml", + "CMAKE_CXX_FLAGS": "/analyze /analyze:external- /analyze:autolog /analyze:ruleset NativeRecommendedRules.ruleset /analyze:log:format:xml", + "CMAKE_SYSTEM_PROCESSOR": "AMD64" + }, + "vendor": { + "microsoft.com/VisualStudioSettings/CMake/1.0": { + "intelliSenseMode": "windows-msvc-x64" + } + } + }, + { + "name": "win64-with-test", + "displayName": "Generate - x64 - Debug - Windows - Core Lib With Tests", + "description": "Configure the Windows build with Core and Test Library build set and the x64 toolchain architecture, using the Debug build options.", + "inherits": "win64-base", + "binaryDir": "${sourceDir}/out/build/Debug/win64-withtest", + "installDir": "${sourceDir}/out/install/Debug/win64-withtest", "cacheVariables": { "TESTCPP_TEST_ENABLED": "1" } }, { - "name": "vs64-with-test-rel", - "displayName": "Generate - x64 - Release - Windows - Visual Studio - Core Lib With Tests", - "description": "Configure the Visual Studio build with Core and Test Library build set and the x64 toolchain architecture, using the Release build options.", - "inherits": "vs64-base-rel", - "binaryDir": "${sourceDir}/out/build/Release/vs64-withtest", - "installDir": "${sourceDir}/out/install/Release/vs64-withtest", + "name": "win64-with-test-rel", + "displayName": "Generate - x64 - Release - Windows - Core Lib With Tests", + "description": "Configure the Windows build with Core and Test Library build set and the x64 toolchain architecture, using the Release build options.", + "inherits": "win64-base-rel", + "binaryDir": "${sourceDir}/out/build/Release/win64-withtest", + "installDir": "${sourceDir}/out/install/Release/win64-withtest", "cacheVariables": { "TESTCPP_TEST_ENABLED": "1" } }, { - "name": "vs64-nost-with-test", - "displayName": "Generate - x64 - Debug - Windows - Visual Studio - Core Lib With Tests - No Stacktraces", - "description": "Configure the Visual Studio build with Core and Test Library build set and the x64 toolchain architecture, using the Debug build options, but with no stacktraces (strict C++11).", - "inherits": "vs64-nost-base", - "binaryDir": "${sourceDir}/out/build/Debug/vs64-nost-withtest", - "installDir": "${sourceDir}/out/install/Debug/vs64-nost-withtest", + "name": "win64-nost-with-test", + "displayName": "Generate - x64 - Debug - Windows - Core Lib With Tests - No Stacktraces", + "description": "Configure the Windows build with Core and Test Library build set and the x64 toolchain architecture, using the Debug build options, but with no stacktraces (strict C++11).", + "inherits": "win64-nost-base", + "binaryDir": "${sourceDir}/out/build/Debug/win64-nost-withtest", + "installDir": "${sourceDir}/out/install/Debug/win64-nost-withtest", "cacheVariables": { "TESTCPP_TEST_ENABLED": "1" } }, { - "name": "vs64-nost-with-test-rel", - "displayName": "Generate - x64 - Release - Windows - Visual Studio - Core Lib With Tests - No Stacktraces", - "description": "Configure the Visual Studio build with Core and Test Library build set and the x64 toolchain architecture, using the Release build options, but with no stacktraces (strict C++11).", - "inherits": "vs64-nost-base-rel", - "binaryDir": "${sourceDir}/out/build/Release/vs64-nost-withtest", - "installDir": "${sourceDir}/out/install/Release/vs64-nost-withtest", + "name": "win64-nost-with-test-rel", + "displayName": "Generate - x64 - Release - Windows - Core Lib With Tests - No Stacktraces", + "description": "Configure the Windows build with Core and Test Library build set and the x64 toolchain architecture, using the Release build options, but with no stacktraces (strict C++11).", + "inherits": "win64-nost-base-rel", + "binaryDir": "${sourceDir}/out/build/Release/win64-nost-withtest", + "installDir": "${sourceDir}/out/install/Release/win64-nost-withtest", "cacheVariables": { "TESTCPP_TEST_ENABLED": "1" } }, { - "name": "vs64-with-demo", - "displayName": "Generate - x64 - Debug - Windows - Visual Studio - Core Lib With Demo", - "description": "Configure the Visual Studio build with Core and Demo set and the x64 toolchain architecture, using the Debug build options.", - "inherits": "vs64-base", - "binaryDir": "${sourceDir}/out/build/Debug/vs64-withdemo", - "installDir": "${sourceDir}/out/install/Debug/vs64-withdemo", + "name": "win64-with-demo", + "displayName": "Generate - x64 - Debug - Windows - Core Lib With Demo", + "description": "Configure the Windows build with Core and Demo set and the x64 toolchain architecture, using the Debug build options.", + "inherits": "win64-base", + "binaryDir": "${sourceDir}/out/build/Debug/win64-withdemo", + "installDir": "${sourceDir}/out/install/Debug/win64-withdemo", "cacheVariables": { "TESTCPP_DEMO_ENABLED": "1" } }, { - "name": "vs64-with-demo-rel", - "displayName": "Generate - x64 - Release - Windows - Visual Studio - Core Lib With Demo", - "description": "Configure the Visual Studio build with Core and Demo set and the x64 toolchain architecture, using the Release build options.", - "inherits": "vs64-base-rel", - "binaryDir": "${sourceDir}/out/build/Release/vs64-withdemo", - "installDir": "${sourceDir}/out/install/Release/vs64-withdemo", + "name": "win64-with-demo-rel", + "displayName": "Generate - x64 - Release - Windows - Core Lib With Demo", + "description": "Configure the Windows build with Core and Demo set and the x64 toolchain architecture, using the Release build options.", + "inherits": "win64-base-rel", + "binaryDir": "${sourceDir}/out/build/Release/win64-withdemo", + "installDir": "${sourceDir}/out/install/Release/win64-withdemo", "cacheVariables": { "TESTCPP_DEMO_ENABLED": "1" } }, { - "name": "vs64-nost-with-demo", - "displayName": "Generate - x64 - Debug - Windows - Visual Studio - Core Lib With Demo - No Stacktraces", - "description": "Configure the Visual Studio build with Core and Demo library build set and the x64 toolchain architecture, using the Debug build options, but with no stacktraces (strict C++11).", - "inherits": "vs64-nost-base", - "binaryDir": "${sourceDir}/out/build/Debug/vs64-nost-withdemo", - "installDir": "${sourceDir}/out/install/Debug/vs64-nost-withdemo", + "name": "win64-nost-with-demo", + "displayName": "Generate - x64 - Debug - Windows - Core Lib With Demo - No Stacktraces", + "description": "Configure the Windows build with Core and Demo library build set and the x64 toolchain architecture, using the Debug build options, but with no stacktraces (strict C++11).", + "inherits": "win64-nost-base", + "binaryDir": "${sourceDir}/out/build/Debug/win64-nost-withdemo", + "installDir": "${sourceDir}/out/install/Debug/win64-nost-withdemo", "cacheVariables": { "TESTCPP_DEMO_ENABLED": "1" } }, { - "name": "vs64-nost-with-demo-rel", - "displayName": "Generate - x64 - Release - Windows - Visual Studio - Core Lib With Demo - No Stacktraces", - "description": "Configure the Visual Studio build with Core and Demo library build set and the x64 toolchain architecture, using the Release build options, but with no stacktraces (strict C++11).", - "inherits": "vs64-nost-base-rel", - "binaryDir": "${sourceDir}/out/build/Release/vs64-nost-withdemo", - "installDir": "${sourceDir}/out/install/Release/vs64-nost-withdemo", + "name": "win64-nost-with-demo-rel", + "displayName": "Generate - x64 - Release - Windows - Core Lib With Demo - No Stacktraces", + "description": "Configure the Windows build with Core and Demo library build set and the x64 toolchain architecture, using the Release build options, but with no stacktraces (strict C++11).", + "inherits": "win64-nost-base-rel", + "binaryDir": "${sourceDir}/out/build/Release/win64-nost-withdemo", + "installDir": "${sourceDir}/out/install/Release/win64-nost-withdemo", "cacheVariables": { "TESTCPP_DEMO_ENABLED": "1" } }, { - "name": "vs64-all", - "displayName": "Generate - x64 - Debug - Windows - Visual Studio - All Components - Core, Tests, and Demo", - "description": "Configure the Visual Studio build with all Library options set and the x64 toolchain architecture, using the Debug build options.", - "inherits": "vs64-with-test", - "binaryDir": "${sourceDir}/out/build/Debug/vs64-all", - "installDir": "${sourceDir}/out/install/Debug/vs64-all", + "name": "win64-all", + "displayName": "Generate - x64 - Debug - Windows - All Components - Core, Tests, and Demo", + "description": "Configure the Windows build with all Library options set and the x64 toolchain architecture, using the Debug build options.", + "inherits": "win64-with-test", + "binaryDir": "${sourceDir}/out/build/Debug/win64-all", + "installDir": "${sourceDir}/out/install/Debug/win64-all", "cacheVariables": { "TESTCPP_DEMO_ENABLED": "1" } }, { - "name": "vs64-all-rel", - "displayName": "Generate - x64 - Release - Windows - Visual Studio - All Components - Core, Tests, and Demo", - "description": "Configure the Visual Studio build with all Library options set and the x64 toolchain architecture, using the Release build options.", - "inherits": "vs64-with-test-rel", - "binaryDir": "${sourceDir}/out/build/Release/vs64-all", - "installDir": "${sourceDir}/out/install/Release/vs64-all", + "name": "win64-all-rel", + "displayName": "Generate - x64 - Release - Windows - All Components - Core, Tests, and Demo", + "description": "Configure the Windows build with all Library options set and the x64 toolchain architecture, using the Release build options.", + "inherits": "win64-with-test-rel", + "binaryDir": "${sourceDir}/out/build/Release/win64-all", + "installDir": "${sourceDir}/out/install/Release/win64-all", "cacheVariables": { "TESTCPP_DEMO_ENABLED": "1" } }, { - "name": "vs64-nost-all", - "displayName": "Generate - x64 - Debug - Windows - Visual Studio - All Components - Core, Tests, and Demo - No Stacktraces", - "description": "Configure the Visual Studio build with all Library options set and the x64 toolchain architecture, using the Debug build options, but with no stacktraces (strict C++11).", - "inherits": "vs64-nost-with-test", - "binaryDir": "${sourceDir}/out/build/Debug/vs64-nost-all", - "installDir": "${sourceDir}/out/install/Debug/vs64-nost-all", + "name": "win64-nost-all", + "displayName": "Generate - x64 - Debug - Windows - All Components - Core, Tests, and Demo - No Stacktraces", + "description": "Configure the Windows build with all Library options set and the x64 toolchain architecture, using the Debug build options, but with no stacktraces (strict C++11).", + "inherits": "win64-nost-with-test", + "binaryDir": "${sourceDir}/out/build/Debug/win64-nost-all", + "installDir": "${sourceDir}/out/install/Debug/win64-nost-all", "cacheVariables": { "TESTCPP_DEMO_ENABLED": "1" } }, { - "name": "vs64-nost-all-rel", - "displayName": "Generate - x64 - Release - Windows - Visual Studio - All Components - Core, Tests, and Demo - No Stacktraces", - "description": "Configure the Visual Studio build with all Library options set and the x64 toolchain architecture, using the Release build options, but with no stacktraces (strict C++11).", - "inherits": "vs64-nost-with-test-rel", - "binaryDir": "${sourceDir}/out/build/Release/vs64-nost-all", - "installDir": "${sourceDir}/out/install/Release/vs64-nost-all", + "name": "win64-nost-all-rel", + "displayName": "Generate - x64 - Release - Windows - All Components - Core, Tests, and Demo - No Stacktraces", + "description": "Configure the Windows build with all Library options set and the x64 toolchain architecture, using the Release build options, but with no stacktraces (strict C++11).", + "inherits": "win64-nost-with-test-rel", + "binaryDir": "${sourceDir}/out/build/Release/win64-nost-all", + "installDir": "${sourceDir}/out/install/Release/win64-nost-all", "cacheVariables": { "TESTCPP_DEMO_ENABLED": "1" } }, { - "name": "vs64-ct", - "displayName": "Generate - x64 - Windows - Visual Studio - Clang Tidy analysis", - "description": "Configure the Visual Studio build with clang-tidy analysis and the x64 toolchain architecture.", - "inherits": "vs-ct", - "binaryDir": "${sourceDir}/out/build/vs64-ct", - "installDir": "${sourceDir}/out/install/vs64-ct", - "architecture": "x64", + "name": "win64-ct", + "displayName": "Generate - x64 - Windows - Clang Tidy analysis", + "description": "Configure the Windows build with clang-tidy analysis and the x64 toolchain architecture.", + "inherits": "win32-ct", + "binaryDir": "${sourceDir}/out/build/win64-ct", + "installDir": "${sourceDir}/out/install/win64-ct", + "cacheVariables": { + "CMAKE_C_FLAGS": "-v", + "CMAKE_CXX_FLAGS": "-v", + "CMAKE_EXE_LINKER_FLAGS": "/machine:x64", + "CMAKE_SYSTEM_PROCESSOR": "AMD64" + }, "vendor": { "microsoft.com/VisualStudioSettings/CMake/1.0": { - "intelliSenseMode": "windows-clang-x64" + "intelliSenseMode": "windows-clangcl-x64" } } } ], "buildPresets": [ { - "name": "vs-base-build", - "displayName": "Build - x86 - Debug - Windows - Visual Studio - Core Lib", - "description": "Build only the Core Lib with VS-Win32 with the necessary base MSBuild options in Debug mode.", - "configurePreset": "vs-base", + "name": "win32-base-build", + "displayName": "Build - x86 - Debug - Windows - Core Lib", + "description": "Build only the Core Lib with MSVC-x86 with the necessary Ninja options in Debug mode.", + "configurePreset": "win32-base", "resolvePackageReferences": "on", "nativeToolOptions": [ - "/ds", - "/m:4", - "/nologo", - "/warnAsError" + "-v" ], "condition": { "type": "equals", @@ -503,512 +635,515 @@ } }, { - "name": "vs-base-clean-build", - "displayName": "Build - x86 - Debug - Windows - Visual Studio - Core Lib - Clean First", - "description": "Build only the Core Lib with VS-Win32 with the necessary base MSBuild options in Debug mode, and clean up the previous build first.", - "inherits": "vs-base-build", + "name": "win32-base-clean-build", + "displayName": "Clean Build - x86 - Debug - Windows - Core Lib", + "description": "Build only the Core Lib with MSVC-x86 with the necessary Ninja options in Debug mode, and clean up the previous build first.", + "inherits": "win32-base-build", "cleanFirst": true }, { - "name": "vs-base-build-rel", - "displayName": "Build - x86 - Release - Windows - Visual Studio - Core Lib", - "description": "Build only the Core Lib with VS-Win32 with the necessary base MSBuild options in Release mode.", - "configurePreset": "vs-base-rel", - "inherits": "vs-base-build" + "name": "win32-base-build-rel", + "displayName": "Build - x86 - Release - Windows - Core Lib", + "description": "Build only the Core Lib with MSVC-x86 with the necessary Ninja options in Release mode.", + "configurePreset": "win32-base-rel", + "inherits": "win32-base-build" }, { - "name": "vs-base-clean-build-rel", - "displayName": "Build - x86 - Release - Windows - Visual Studio - Core Lib - Clean First", - "description": "Build only the Core Lib with VS-Win32 with the necessary base MSBuild options in Release mode, and clean up the previous build first.", - "inherits": "vs-base-build-rel", + "name": "win32-base-clean-build-rel", + "displayName": "Clean Build - x86 - Release - Windows - Core Lib", + "description": "Build only the Core Lib with MSVC-x86 with the necessary Ninja options in Release mode, and clean up the previous build first.", + "inherits": "win32-base-build-rel", "cleanFirst": true }, { - "name": "vs-nost-base-build", - "displayName": "Build - x86 - Debug - Windows - Visual Studio - Core Lib - No Stacktraces", - "description": "Build only the Core Lib with VS-Win32 with the necessary base MSBuild options in Debug mode, but with no stacktraces (strict C++11).", - "configurePreset": "vs-nost-base", - "inherits": "vs-base-build" + "name": "win32-nost-base-build", + "displayName": "Build - x86 - Debug - Windows - Core Lib - No Stacktraces", + "description": "Build only the Core Lib with MSVC-x86 with the necessary Ninja options in Debug mode, but with no stacktraces (strict C++11).", + "configurePreset": "win32-nost-base", + "inherits": "win32-base-build" }, { - "name": "vs-nost-base-clean-build", - "displayName": "Build - x86 - Debug - Windows - Visual Studio - Core Lib - No Stacktraces - Clean First", - "description": "Build only the Core Lib with VS-Win32 with the necessary base MSBuild options in Debug mode, but with no stacktraces (strict C++11), and clean up the previous build first.", - "inherits": "vs-nost-base-build", + "name": "win32-nost-base-clean-build", + "displayName": "Clean Build - x86 - Debug - Windows - Core Lib - No Stacktraces", + "description": "Build only the Core Lib with MSVC-x86 with the necessary Ninja options in Debug mode, but with no stacktraces (strict C++11), and clean up the previous build first.", + "inherits": "win32-nost-base-build", "cleanFirst": true }, { - "name": "vs-nost-base-build-rel", - "displayName": "Build - x86 - Release - Windows - Visual Studio - Core Lib - No Stacktraces", - "description": "Build only the Core Lib with VS-Win32 with the necessary base MSBuild options in Release mode, but with no stacktraces (strict C++11).", - "configurePreset": "vs-nost-base-rel", - "inherits": "vs-base-build" + "name": "win32-nost-base-build-rel", + "displayName": "Build - x86 - Release - Windows - Core Lib - No Stacktraces", + "description": "Build only the Core Lib with MSVC-x86 with the necessary Ninja options in Release mode, but with no stacktraces (strict C++11).", + "configurePreset": "win32-nost-base-rel", + "inherits": "win32-base-build" }, { - "name": "vs-nost-base-clean-build-rel", - "displayName": "Build - x86 - Release - Windows - Visual Studio - Core Lib - No Stacktraces - Clean First", - "description": "Build only the Core Lib with VS-Win32 with the necessary base MSBuild options in Release mode, but with no stacktraces (strict C++11), and clean up the previous build first.", - "inherits": "vs-nost-base-build-rel", + "name": "win32-nost-base-clean-build-rel", + "displayName": "Clean Build - x86 - Release - Windows - Core Lib - No Stacktraces", + "description": "Build only the Core Lib with MSVC-x86 with the necessary Ninja options in Release mode, but with no stacktraces (strict C++11), and clean up the previous build first.", + "inherits": "win32-nost-base-build-rel", "cleanFirst": true }, { - "name": "vs-with-test-build", - "displayName": "Build - x86 - Debug - Windows - Visual Studio - Core Lib With Tests", - "description": "Build the Core Lib, and Tests, with VS-Win32 with the necessary base MSBuild options in Debug mode.", - "configurePreset": "vs-with-test", - "inherits": "vs-base-build" + "name": "win32-with-test-build", + "displayName": "Build - x86 - Debug - Windows - Core Lib With Tests", + "description": "Build the Core Lib, and Tests, with MSVC-x86 with the necessary Ninja options in Debug mode.", + "configurePreset": "win32-with-test", + "inherits": "win32-base-build" }, { - "name": "vs-with-test-clean-build", - "displayName": "Build - x86 - Debug - Windows - Visual Studio - Core Lib With Tests - Clean First", - "description": "Build the Core Lib, and Tests, with VS-Win32 with the necessary base MSBuild options in Debug mode, and clean up the previous build first.", - "inherits": "vs-with-test-build", + "name": "win32-with-test-clean-build", + "displayName": "Clean Build - x86 - Debug - Windows - Core Lib With Tests", + "description": "Build the Core Lib, and Tests, with MSVC-x86 with the necessary Ninja options in Debug mode, and clean up the previous build first.", + "inherits": "win32-with-test-build", "cleanFirst": true }, { - "name": "vs-with-test-build-rel", - "displayName": "Build - x86 - Release - Windows - Visual Studio - Core Lib With Tests", - "description": "Build the Core Lib, and Tests, with VS-Win32 with the necessary base MSBuild options in Release mode.", - "configurePreset": "vs-with-test-rel", - "inherits": "vs-base-build" + "name": "win32-with-test-build-rel", + "displayName": "Build - x86 - Release - Windows - Core Lib With Tests", + "description": "Build the Core Lib, and Tests, with MSVC-x86 with the necessary Ninja options in Release mode.", + "configurePreset": "win32-with-test-rel", + "inherits": "win32-base-build" }, { - "name": "vs-with-test-clean-build-rel", - "displayName": "Build - x86 - Release - Windows - Visual Studio - Core Lib With Tests - Clean First", - "description": "Build the Core Lib, and Tests, with VS-Win32 with the necessary base MSBuild options in Release mode, and clean up the previous build first.", - "inherits": "vs-with-test-build-rel", + "name": "win32-with-test-clean-build-rel", + "displayName": "Clean Build - x86 - Release - Windows - Core Lib With Tests", + "description": "Build the Core Lib, and Tests, with MSVC-x86 with the necessary Ninja options in Release mode, and clean up the previous build first.", + "inherits": "win32-with-test-build-rel", "cleanFirst": true }, { - "name": "vs-nost-with-test-build", - "displayName": "Build - x86 - Debug - Windows - Visual Studio - Core Lib With Tests - No Stacktraces", - "description": "Build the Core Lib, and Tests, with VS-Win32 with the necessary base MSBuild options in Debug mode, but with no stacktraces (strict C++11).", - "configurePreset": "vs-nost-with-test", - "inherits": "vs-base-build" + "name": "win32-nost-with-test-build", + "displayName": "Build - x86 - Debug - Windows - Core Lib With Tests - No Stacktraces", + "description": "Build the Core Lib, and Tests, with MSVC-x86 with the necessary Ninja options in Debug mode, but with no stacktraces (strict C++11).", + "configurePreset": "win32-nost-with-test", + "inherits": "win32-base-build" }, { - "name": "vs-nost-with-test-clean-build", - "displayName": "Build - x86 - Debug - Windows - Visual Studio - Core Lib With Tests - No Stacktraces - Clean First", - "description": "Build the Core Lib, and Tests, with VS-Win32 with the necessary base MSBuild options in Debug mode, but with no stacktraces (strict C++11), and clean up the previous build first.", - "inherits": "vs-nost-with-test-build", + "name": "win32-nost-with-test-clean-build", + "displayName": "Clean Build - x86 - Debug - Windows - Core Lib With Tests - No Stacktraces", + "description": "Build the Core Lib, and Tests, with MSVC-x86 with the necessary Ninja options in Debug mode, but with no stacktraces (strict C++11), and clean up the previous build first.", + "inherits": "win32-nost-with-test-build", "cleanFirst": true }, { - "name": "vs-nost-with-test-build-rel", - "displayName": "Build - x86 - Release - Windows - Visual Studio - Core Lib With Tests - No Stacktraces", - "description": "Build the Core Lib, and Tests, with VS-Win32 with the necessary base MSBuild options in Release mode, but with no stacktraces (strict C++11).", - "configurePreset": "vs-nost-with-test-rel", - "inherits": "vs-base-build" + "name": "win32-nost-with-test-build-rel", + "displayName": "Build - x86 - Release - Windows - Core Lib With Tests - No Stacktraces", + "description": "Build the Core Lib, and Tests, with MSVC-x86 with the necessary Ninja options in Release mode, but with no stacktraces (strict C++11).", + "configurePreset": "win32-nost-with-test-rel", + "inherits": "win32-base-build" }, { - "name": "vs-nost-with-test-clean-build-rel", - "displayName": "Build - x86 - Release - Windows - Visual Studio - Core Lib With Tests - No Stacktraces - Clean First", - "description": "Build the Core Lib, and Tests, with VS-Win32 with the necessary base MSBuild options in Release mode, but with no stacktraces (strict C++11), and clean up the previous build first.", - "inherits": "vs-nost-with-test-build-rel", + "name": "win32-nost-with-test-clean-build-rel", + "displayName": "Clean Build - x86 - Release - Windows - Core Lib With Tests - No Stacktraces", + "description": "Build the Core Lib, and Tests, with MSVC-x86 with the necessary Ninja options in Release mode, but with no stacktraces (strict C++11), and clean up the previous build first.", + "inherits": "win32-nost-with-test-build-rel", "cleanFirst": true }, { - "name": "vs-with-demo-build", - "displayName": "Build - x86 - Debug - Windows - Visual Studio - Core Lib With Demo", - "description": "Build the Core Lib, and Demo, with VS-Win32 with the necessary base MSBuild options in Debug mode.", - "configurePreset": "vs-with-demo", - "inherits": "vs-base-build" + "name": "win32-with-demo-build", + "displayName": "Build - x86 - Debug - Windows - Core Lib With Demo", + "description": "Build the Core Lib, and Demo, with MSVC-x86 with the necessary Ninja options in Debug mode.", + "configurePreset": "win32-with-demo", + "inherits": "win32-base-build" }, { - "name": "vs-with-demo-clean-build", - "displayName": "Build - x86 - Debug - Windows - Visual Studio - Core Lib With Demo - Clean First", - "description": "Build the Core Lib, and Demo, with VS-Win32 with the necessary base MSBuild options in Debug mode, and clean up the previous build first.", - "inherits": "vs-with-demo-build", + "name": "win32-with-demo-clean-build", + "displayName": "Clean Build - x86 - Debug - Windows - Core Lib With Demo", + "description": "Build the Core Lib, and Demo, with MSVC-x86 with the necessary Ninja options in Debug mode, and clean up the previous build first.", + "inherits": "win32-with-demo-build", "cleanFirst": true }, { - "name": "vs-with-demo-build-rel", - "displayName": "Build - x86 - Release - Windows - Visual Studio - Core Lib With Demo", - "description": "Build the Core Lib, and Demo, with VS-Win32 with the necessary base MSBuild options in Release mode.", - "configurePreset": "vs-with-demo-rel", - "inherits": "vs-base-build" + "name": "win32-with-demo-build-rel", + "displayName": "Build - x86 - Release - Windows - Core Lib With Demo", + "description": "Build the Core Lib, and Demo, with MSVC-x86 with the necessary Ninja options in Release mode.", + "configurePreset": "win32-with-demo-rel", + "inherits": "win32-base-build" }, { - "name": "vs-with-demo-clean-build-rel", - "displayName": "Build - x86 - Release - Windows - Visual Studio - Core Lib With Demo - Clean First", - "description": "Build the Core Lib, and Demo, with VS-Win32 with the necessary base MSBuild options in Release mode, and clean up the previous build first.", - "inherits": "vs-with-demo-build-rel", + "name": "win32-with-demo-clean-build-rel", + "displayName": "Clean Build - x86 - Release - Windows - Core Lib With Demo", + "description": "Build the Core Lib, and Demo, with MSVC-x86 with the necessary Ninja options in Release mode, and clean up the previous build first.", + "inherits": "win32-with-demo-build-rel", "cleanFirst": true }, { - "name": "vs-nost-with-demo-build", - "displayName": "Build - x86 - Debug - Windows - Visual Studio - Core Lib With Demo - No Stacktraces", - "description": "Build the Core Lib, and Demo, with VS-Win32 with the necessary base MSBuild options in Debug mode, but with no stacktraces (strict C++11).", - "configurePreset": "vs-nost-with-demo", - "inherits": "vs-base-build" + "name": "win32-nost-with-demo-build", + "displayName": "Build - x86 - Debug - Windows - Core Lib With Demo - No Stacktraces", + "description": "Build the Core Lib, and Demo, with MSVC-x86 with the necessary Ninja options in Debug mode, but with no stacktraces (strict C++11).", + "configurePreset": "win32-nost-with-demo", + "inherits": "win32-base-build" }, { - "name": "vs-nost-with-demo-clean-build", - "displayName": "Build - x86 - Debug - Windows - Visual Studio - Core Lib With Demo - No Stacktraces - Clean First", - "description": "Build the Core Lib, and Demo, with VS-Win32 with the necessary base MSBuild options in Debug mode, but with no stacktraces (strict C++11), and clean up the previous build first.", - "inherits": "vs-nost-with-demo-build", + "name": "win32-nost-with-demo-clean-build", + "displayName": "Clean Build - x86 - Debug - Windows - Core Lib With Demo - No Stacktraces", + "description": "Build the Core Lib, and Demo, with MSVC-x86 with the necessary Ninja options in Debug mode, but with no stacktraces (strict C++11), and clean up the previous build first.", + "inherits": "win32-nost-with-demo-build", "cleanFirst": true }, { - "name": "vs-nost-with-demo-build-rel", - "displayName": "Build - x86 - Release - Windows - Visual Studio - Core Lib With Demo - No Stacktraces", - "description": "Build the Core Lib, and Demo, with VS-Win32 with the necessary base MSBuild options in Release mode, but with no stacktraces (strict C++11).", - "configurePreset": "vs-nost-with-demo-rel", - "inherits": "vs-base-build" + "name": "win32-nost-with-demo-build-rel", + "displayName": "Build - x86 - Release - Windows - Core Lib With Demo - No Stacktraces", + "description": "Build the Core Lib, and Demo, with MSVC-x86 with the necessary Ninja options in Release mode, but with no stacktraces (strict C++11).", + "configurePreset": "win32-nost-with-demo-rel", + "inherits": "win32-base-build" }, { - "name": "vs-nost-with-demo-clean-build-rel", - "displayName": "Build - x86 - Release - Windows - Visual Studio - Core Lib With Demo - No Stacktraces - Clean First", - "description": "Build the Core Lib, and Demo, with VS-Win32 with the necessary base MSBuild options in Release mode, but with no stacktraces (strict C++11), and clean up the previous build first.", - "inherits": "vs-nost-with-demo-build-rel", + "name": "win32-nost-with-demo-clean-build-rel", + "displayName": "Clean Build - x86 - Release - Windows - Core Lib With Demo - No Stacktraces", + "description": "Build the Core Lib, and Demo, with MSVC-x86 with the necessary Ninja options in Release mode, but with no stacktraces (strict C++11), and clean up the previous build first.", + "inherits": "win32-nost-with-demo-build-rel", "cleanFirst": true }, { - "name": "vs-all-build", - "displayName": "Build - x86 - Debug - Windows - Visual Studio - All Components - Core, Tests, and Demo", - "description": "Build the Core Lib, Tests, and Demo, with VS-Win32 with the necessary base MSBuild options in Debug mode.", - "configurePreset": "vs-all", - "inherits": "vs-base-build" + "name": "win32-all-build", + "displayName": "Build - x86 - Debug - Windows - All Components - Core, Tests, and Demo", + "description": "Build the Core Lib, Tests, and Demo, with MSVC-x86 with the necessary Ninja options in Debug mode.", + "configurePreset": "win32-all", + "inherits": "win32-base-build" }, { - "name": "vs-all-clean-build", - "displayName": "Build - x86 - Debug - Windows - Visual Studio - All Components - Core, Tests, and Demo - Clean First", - "description": "Build the Core Lib, Tests, and Demo, with VS-Win32 with the necessary base MSBuild options in Debug mode, and clean up the previous build first.", - "inherits": "vs-all-build", + "name": "win32-all-clean-build", + "displayName": "Clean Build - x86 - Debug - Windows - All Components - Core, Tests, and Demo", + "description": "Build the Core Lib, Tests, and Demo, with MSVC-x86 with the necessary Ninja options in Debug mode, and clean up the previous build first.", + "inherits": "win32-all-build", "cleanFirst": true }, { - "name": "vs-all-build-rel", - "displayName": "Build - x86 - Release - Windows - Visual Studio - All Components - Core, Tests, and Demo", - "description": "Build the Core Lib, Tests, and Demo, with VS-Win32 with the necessary base MSBuild options in Release mode.", - "configurePreset": "vs-all-rel", - "inherits": "vs-base-build" + "name": "win32-all-build-rel", + "displayName": "Build - x86 - Release - Windows - All Components - Core, Tests, and Demo", + "description": "Build the Core Lib, Tests, and Demo, with MSVC-x86 with the necessary Ninja options in Release mode.", + "configurePreset": "win32-all-rel", + "inherits": "win32-base-build" }, { - "name": "vs-all-clean-build-rel", - "displayName": "Build - x86 - Release - Windows - Visual Studio - All Components - Core, Tests, and Demo - Clean First", - "description": "Build the Core Lib, Tests, and Demo, with VS-Win32 with the necessary base MSBuild options in Release mode, and clean up the previous build first.", - "inherits": "vs-all-build-rel", + "name": "win32-all-clean-build-rel", + "displayName": "Clean Build - x86 - Release - Windows - All Components - Core, Tests, and Demo", + "description": "Build the Core Lib, Tests, and Demo, with MSVC-x86 with the necessary Ninja options in Release mode, and clean up the previous build first.", + "inherits": "win32-all-build-rel", "cleanFirst": true }, { - "name": "vs-nost-all-build", - "displayName": "Build - x86 - Debug - Windows - Visual Studio - All Components - Core, Tests, and Demo - No Stacktraces", - "description": "Build the Core Lib, Tests, and Demo, with VS-Win32 with the necessary base MSBuild options in Debug mode, but with no stacktraces (strict C++11).", - "configurePreset": "vs-nost-all", - "inherits": "vs-base-build" + "name": "win32-nost-all-build", + "displayName": "Build - x86 - Debug - Windows - All Components - Core, Tests, and Demo - No Stacktraces", + "description": "Build the Core Lib, Tests, and Demo, with MSVC-x86 with the necessary Ninja options in Debug mode, but with no stacktraces (strict C++11).", + "configurePreset": "win32-nost-all", + "inherits": "win32-base-build" }, { - "name": "vs-nost-all-clean-build", - "displayName": "Build - x86 - Debug - Windows - Visual Studio - All Components - Core, Tests, and Demo - No Stacktraces - Clean First", - "description": "Build the Core Lib, Tests, and Demo, with VS-Win32 with the necessary base MSBuild options in Debug mode, but with no stacktraces (strict C++11), and clean up the previous build first.", - "inherits": "vs-nost-all-build", + "name": "win32-nost-all-clean-build", + "displayName": "Clean Build - x86 - Debug - Windows - All Components - Core, Tests, and Demo - No Stacktraces", + "description": "Build the Core Lib, Tests, and Demo, with MSVC-x86 with the necessary Ninja options in Debug mode, but with no stacktraces (strict C++11), and clean up the previous build first.", + "inherits": "win32-nost-all-build", "cleanFirst": true }, { - "name": "vs-nost-all-build-rel", - "displayName": "Build - x86 - Release - Windows - Visual Studio - All Components - Core, Tests, and Demo - No Stacktraces", - "description": "Build the Core Lib, Tests, and Demo, with VS-Win32 with the necessary base MSBuild options in Release mode, but with no stacktraces (strict C++11).", - "configurePreset": "vs-nost-all-rel", - "inherits": "vs-base-build" + "name": "win32-nost-all-build-rel", + "displayName": "Build - x86 - Release - Windows - All Components - Core, Tests, and Demo - No Stacktraces", + "description": "Build the Core Lib, Tests, and Demo, with MSVC-x86 with the necessary Ninja options in Release mode, but with no stacktraces (strict C++11).", + "configurePreset": "win32-nost-all-rel", + "inherits": "win32-base-build" }, { - "name": "vs-nost-all-clean-build-rel", - "displayName": "Build - x86 - Release - Windows - Visual Studio - All Components - Core, Tests, and Demo - No Stacktraces - Clean First", - "description": "Build the Core Lib, Tests, and Demo, with VS-Win32 with the necessary base MSBuild options in Release mode, but with no stacktraces (strict C++11), and clean up the previous build first.", - "inherits": "vs-nost-all-build-rel", + "name": "win32-nost-all-clean-build-rel", + "displayName": "Clean Build - x86 - Release - Windows - All Components - Core, Tests, and Demo - No Stacktraces", + "description": "Build the Core Lib, Tests, and Demo, with MSVC-x86 with the necessary Ninja options in Release mode, but with no stacktraces (strict C++11), and clean up the previous build first.", + "inherits": "win32-nost-all-build-rel", "cleanFirst": true }, { - "name": "vs-msanalysis-build", - "displayName": "Analyze - x86 - Windows - Visual Studio", - "description": "Analyze the code with MSBuild using the Win32 toolchain architecture.", - "inherits": "vs-base-clean-build", - "cleanFirst": true, - "configurePreset": "vs-msanalysis", - "nativeToolOptions": [ - "/external:anglebrackets", - "/external:I${sourceDir}/3rdparty", - "/analyze", - "/analyze:external-", - "/analyze:autolog", - "/analyze:ruleset NativeRecommendedRules.ruleset" - ] - }, - { - "name": "vs-msanalysis-xml", - "displayName": "Analyze - x86 - Windows - Visual Studio - XML output", - "description": "Analyze the code with MSBuild using the Win32 toolchain architecture, then output the analysis results in XML format.", - "inherits": "vs-msanalysis-build", - "nativeToolOptions": [ - "/analyze:log:format:xml" - ] + "name": "win32-msanalysis-build", + "displayName": "Analyze - x86 - Windows", + "description": "Analyze the code with MSVC CL using the x86 toolchain architecture.", + "inherits": "win32-base-clean-build", + "configurePreset": "win32-msanalysis", + "cleanFirst": true }, { - "name": "vs-msanalysis-sarif", - "displayName": "Analyze - x86 - Windows - Visual Studio - SARIF output", - "description": "Analyze the code with MSBuild using the Win32 toolchain architecture, then output the analysis results in SARIF format.", - "inherits": "vs-msanalysis-build", - "nativeToolOptions": [ - "/analyze:log:format:sarif" - ] + "name": "win32-msanalysis-xml-build", + "displayName": "Analyze - x86 - Windows - XML output", + "description": "Analyze the code with MSVC CL using the x86 toolchain architecture, then output the analysis results in XML format.", + "inherits": "win32-msanalysis-build", + "configurePreset": "win32-msanalysis-xml" + }, + { + "name": "win32-msanalysis-sarif-build", + "displayName": "Analyze - x86 - Windows - SARIF output", + "description": "Analyze the code with MSVC CL using the x86 toolchain architecture, then output the analysis results in SARIF format.", + "inherits": "win32-msanalysis-build", + "configurePreset": "win32-msanalysis-sarif" + }, + { + "name": "win32-ct-build", + "displayName": "Analyze - x86 - Windows - Clang Tidy", + "description": "Analyze the code with Clang Tidy using the x86 toolchain architecture.", + "configurePreset": "win32-ct", + "cleanFirst": true, + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Windows" + } }, { - "name": "vs64-base-build", - "displayName": "Build - x64 - Debug - Windows - Visual Studio - Core Lib", - "description": "Build with VS-x64 with the necessary base MSBuild options in Debug mode.", - "configurePreset": "vs64-base", - "inherits": "vs-base-build" + "name": "win64-base-build", + "displayName": "Build - x64 - Debug - Windows - Core Lib", + "description": "Build with MSVC-x64 with the necessary Ninja options in Debug mode.", + "configurePreset": "win64-base", + "inherits": "win32-base-build" }, { - "name": "vs64-base-clean-build", - "displayName": "Build - x64 - Debug - Windows - Visual Studio - Core Lib - Clean First", - "description": "Build with VS-x64 with the necessary base MSBuild options in Debug mode, and clean up the previous build first.", - "inherits": "vs64-base-build", + "name": "win64-base-clean-build", + "displayName": "Clean Build - x64 - Debug - Windows - Core Lib", + "description": "Build with MSVC-x64 with the necessary Ninja options in Debug mode, and clean up the previous build first.", + "inherits": "win64-base-build", "cleanFirst": true }, { - "name": "vs64-base-build-rel", - "displayName": "Build - x64 - Release - Windows - Visual Studio - Core Lib", - "description": "Build with VS-x64 with the necessary base MSBuild options in Release mode.", - "configurePreset": "vs64-base-rel", - "inherits": "vs-base-build-rel" + "name": "win64-base-build-rel", + "displayName": "Build - x64 - Release - Windows - Core Lib", + "description": "Build with MSVC-x64 with the necessary Ninja options in Release mode.", + "configurePreset": "win64-base-rel", + "inherits": "win32-base-build-rel" }, { - "name": "vs64-base-clean-build-rel", - "displayName": "Build - x64 - Release - Windows - Visual Studio - Core Lib - Clean First", - "description": "Build with VS-x64 with the necessary base MSBuild options in Release mode, and clean up the previous build first.", - "inherits": "vs64-base-build-rel", + "name": "win64-base-clean-build-rel", + "displayName": "Clean Build - x64 - Release - Windows - Core Lib", + "description": "Build with MSVC-x64 with the necessary Ninja options in Release mode, and clean up the previous build first.", + "inherits": "win64-base-build-rel", "cleanFirst": true }, { - "name": "vs64-nost-base-build", - "displayName": "Build - x64 - Debug - Windows - Visual Studio - Core Lib - No Stacktraces", - "description": "Build only the Core Lib with VS-x64 with the necessary base MSBuild options in Debug mode, but with no stacktraces (strict C++11).", - "configurePreset": "vs64-nost-base", - "inherits": "vs64-base-build" + "name": "win64-nost-base-build", + "displayName": "Build - x64 - Debug - Windows - Core Lib - No Stacktraces", + "description": "Build only the Core Lib with MSVC-x64 with the necessary Ninja options in Debug mode, but with no stacktraces (strict C++11).", + "configurePreset": "win64-nost-base", + "inherits": "win64-base-build" }, { - "name": "vs64-nost-base-clean-build", - "displayName": "Build - x64 - Debug - Windows - Visual Studio - Core Lib - No Stacktraces - Clean First", - "description": "Build only the Core Lib with VS-x64 with the necessary base MSBuild options in Debug mode, but with no stacktraces (strict C++11), and clean up the previous build first.", - "inherits": "vs64-nost-base-build", + "name": "win64-nost-base-clean-build", + "displayName": "Clean Build - x64 - Debug - Windows - Core Lib - No Stacktraces", + "description": "Build only the Core Lib with MSVC-x64 with the necessary Ninja options in Debug mode, but with no stacktraces (strict C++11), and clean up the previous build first.", + "inherits": "win64-nost-base-build", "cleanFirst": true }, { - "name": "vs64-nost-base-build-rel", - "displayName": "Build - x64 - Release - Windows - Visual Studio - Core Lib - No Stacktraces", - "description": "Build only the Core Lib with VS-x64 with the necessary base MSBuild options in Release mode, but with no stacktraces (strict C++11).", - "configurePreset": "vs64-nost-base-rel", - "inherits": "vs64-base-build" + "name": "win64-nost-base-build-rel", + "displayName": "Build - x64 - Release - Windows - Core Lib - No Stacktraces", + "description": "Build only the Core Lib with MSVC-x64 with the necessary Ninja options in Release mode, but with no stacktraces (strict C++11).", + "configurePreset": "win64-nost-base-rel", + "inherits": "win64-base-build" }, { - "name": "vs64-nost-base-clean-build-rel", - "displayName": "Build - x64 - Release - Windows - Visual Studio - Core Lib - No Stacktraces - Clean First", - "description": "Build only the Core Lib with VS-x64 with the necessary base MSBuild options in Release mode, but with no stacktraces (strict C++11), and clean up the previous build first.", - "inherits": "vs64-nost-base-build-rel", + "name": "win64-nost-base-clean-build-rel", + "displayName": "Clean Build - x64 - Release - Windows - Core Lib - No Stacktraces", + "description": "Build only the Core Lib with MSVC-x64 with the necessary Ninja options in Release mode, but with no stacktraces (strict C++11), and clean up the previous build first.", + "inherits": "win64-nost-base-build-rel", "cleanFirst": true }, { - "name": "vs64-with-test-build", - "displayName": "Build - x64 - Debug - Windows - Visual Studio - Core Lib With Tests", - "description": "Build the Core Lib, and Tests, with VS-x64 with the necessary base MSBuild options in Debug mode.", - "configurePreset": "vs64-with-test", - "inherits": "vs64-base-build" + "name": "win64-with-test-build", + "displayName": "Build - x64 - Debug - Windows - Core Lib With Tests", + "description": "Build the Core Lib, and Tests, with MSVC-x64 with the necessary Ninja options in Debug mode.", + "configurePreset": "win64-with-test", + "inherits": "win64-base-build" }, { - "name": "vs64-with-test-clean-build", - "displayName": "Build - x64 - Debug - Windows - Visual Studio - Core Lib With Tests - Clean First", - "description": "Build the Core Lib, and Tests, with VS-x64 with the necessary base MSBuild options in Debug mode, and clean up the previous build first.", - "inherits": "vs64-with-test-build", + "name": "win64-with-test-clean-build", + "displayName": "Clean Build - x64 - Debug - Windows - Core Lib With Tests", + "description": "Build the Core Lib, and Tests, with MSVC-x64 with the necessary Ninja options in Debug mode, and clean up the previous build first.", + "inherits": "win64-with-test-build", "cleanFirst": true }, { - "name": "vs64-with-test-build-rel", - "displayName": "Build - x64 - Release - Windows - Visual Studio - Core Lib With Tests", - "description": "Build the Core Lib, and Tests, with VS-x64 with the necessary base MSBuild options in Release mode.", - "configurePreset": "vs64-with-test-rel", - "inherits": "vs64-base-build" + "name": "win64-with-test-build-rel", + "displayName": "Build - x64 - Release - Windows - Core Lib With Tests", + "description": "Build the Core Lib, and Tests, with MSVC-x64 with the necessary Ninja options in Release mode.", + "configurePreset": "win64-with-test-rel", + "inherits": "win64-base-build" }, { - "name": "vs64-with-test-clean-build-rel", - "displayName": "Build - x64 - Release - Windows - Visual Studio - Core Lib With Tests - Clean First", - "description": "Build the Core Lib, and Tests, with VS-x64 with the necessary base MSBuild options in Release mode, and clean up the previous build first.", - "inherits": "vs64-with-test-build-rel", + "name": "win64-with-test-clean-build-rel", + "displayName": "Clean Build - x64 - Release - Windows - Core Lib With Tests", + "description": "Build the Core Lib, and Tests, with MSVC-x64 with the necessary Ninja options in Release mode, and clean up the previous build first.", + "inherits": "win64-with-test-build-rel", "cleanFirst": true }, { - "name": "vs64-nost-with-test-build", - "displayName": "Build - x64 - Debug - Windows - Visual Studio - Core Lib With Tests - No Stacktraces", - "description": "Build the Core Lib, and Tests, with VS-x64 with the necessary base MSBuild options in Debug mode, but with no stacktraces (strict C++11).", - "configurePreset": "vs64-nost-with-test", - "inherits": "vs64-base-build" + "name": "win64-nost-with-test-build", + "displayName": "Build - x64 - Debug - Windows - Core Lib With Tests - No Stacktraces", + "description": "Build the Core Lib, and Tests, with MSVC-x64 with the necessary Ninja options in Debug mode, but with no stacktraces (strict C++11).", + "configurePreset": "win64-nost-with-test", + "inherits": "win64-base-build" }, { - "name": "vs64-nost-with-test-clean-build", - "displayName": "Build - x64 - Debug - Windows - Visual Studio - Core Lib With Tests - No Stacktraces - Clean First", - "description": "Build the Core Lib, and Tests, with VS-x64 with the necessary base MSBuild options in Debug mode, but with no stacktraces (strict C++11), and clean up the previous build first.", - "inherits": "vs64-nost-with-test-build", + "name": "win64-nost-with-test-clean-build", + "displayName": "Clean Build - x64 - Debug - Windows - Core Lib With Tests - No Stacktraces", + "description": "Build the Core Lib, and Tests, with MSVC-x64 with the necessary Ninja options in Debug mode, but with no stacktraces (strict C++11), and clean up the previous build first.", + "inherits": "win64-nost-with-test-build", "cleanFirst": true }, { - "name": "vs64-nost-with-test-build-rel", - "displayName": "Build - x64 - Release - Windows - Visual Studio - Core Lib With Tests - No Stacktraces", - "description": "Build the Core Lib, and Tests, with VS-x64 with the necessary base MSBuild options in Release mode, but with no stacktraces (strict C++11).", - "configurePreset": "vs64-nost-with-test-rel", - "inherits": "vs64-base-build" + "name": "win64-nost-with-test-build-rel", + "displayName": "Build - x64 - Release - Windows - Core Lib With Tests - No Stacktraces", + "description": "Build the Core Lib, and Tests, with MSVC-x64 with the necessary Ninja options in Release mode, but with no stacktraces (strict C++11).", + "configurePreset": "win64-nost-with-test-rel", + "inherits": "win64-base-build" }, { - "name": "vs64-nost-with-test-clean-build-rel", - "displayName": "Build - x64 - Release - Windows - Visual Studio - Core Lib With Tests - No Stacktraces - Clean First", - "description": "Build the Core Lib, and Tests, with VS-x64 with the necessary base MSBuild options in Release mode, but with no stacktraces (strict C++11), and clean up the previous build first.", - "inherits": "vs64-nost-with-test-build-rel", + "name": "win64-nost-with-test-clean-build-rel", + "displayName": "Clean Build - x64 - Release - Windows - Core Lib With Tests - No Stacktraces", + "description": "Build the Core Lib, and Tests, with MSVC-x64 with the necessary Ninja options in Release mode, but with no stacktraces (strict C++11), and clean up the previous build first.", + "inherits": "win64-nost-with-test-build-rel", "cleanFirst": true }, { - "name": "vs64-with-demo-build", - "displayName": "Build - x64 - Debug - Windows - Visual Studio - Core Lib With Demo", - "description": "Build the Core Lib, and Demo, with VS-x64 with the necessary base MSBuild options in Debug mode.", - "configurePreset": "vs64-with-demo", - "inherits": "vs64-base-build" + "name": "win64-with-demo-build", + "displayName": "Build - x64 - Debug - Windows - Core Lib With Demo", + "description": "Build the Core Lib, and Demo, with MSVC-x64 with the necessary Ninja options in Debug mode.", + "configurePreset": "win64-with-demo", + "inherits": "win64-base-build" }, { - "name": "vs64-with-demo-clean-build", - "displayName": "Build - x64 - Debug - Windows - Visual Studio - Core Lib With Demo - Clean First", - "description": "Build the Core Lib, and Demo, with VS-x64 with the necessary base MSBuild options in Debug mode, and clean up the previous build first.", - "inherits": "vs64-with-demo-build", + "name": "win64-with-demo-clean-build", + "displayName": "Clean Build - x64 - Debug - Windows - Core Lib With Demo", + "description": "Build the Core Lib, and Demo, with MSVC-x64 with the necessary Ninja options in Debug mode, and clean up the previous build first.", + "inherits": "win64-with-demo-build", "cleanFirst": true }, { - "name": "vs64-with-demo-build-rel", - "displayName": "Build - x64 - Release - Windows - Visual Studio - Core Lib With Demo", - "description": "Build the Core Lib, and Demo, with VS-x64 with the necessary base MSBuild options in Release mode.", - "configurePreset": "vs64-with-demo-rel", - "inherits": "vs64-base-build" + "name": "win64-with-demo-build-rel", + "displayName": "Build - x64 - Release - Windows - Core Lib With Demo", + "description": "Build the Core Lib, and Demo, with MSVC-x64 with the necessary Ninja options in Release mode.", + "configurePreset": "win64-with-demo-rel", + "inherits": "win64-base-build" }, { - "name": "vs64-with-demo-clean-build-rel", - "displayName": "Build - x64 - Release - Windows - Visual Studio - Core Lib With Demo - Clean First", - "description": "Build the Core Lib, and Demo, with VS-x64 with the necessary base MSBuild options in Release mode, and clean up the previous build first.", - "inherits": "vs64-with-demo-build-rel", + "name": "win64-with-demo-clean-build-rel", + "displayName": "Clean Build - x64 - Release - Windows - Core Lib With Demo", + "description": "Build the Core Lib, and Demo, with MSVC-x64 with the necessary Ninja options in Release mode, and clean up the previous build first.", + "inherits": "win64-with-demo-build-rel", "cleanFirst": true }, { - "name": "vs64-nost-with-demo-build", - "displayName": "Build - x64 - Debug - Windows - Visual Studio - Core Lib With Demo - No Stacktraces", - "description": "Build the Core Lib, and Demo, with VS-x64 with the necessary base MSBuild options in Debug mode, but with no stacktraces (strict C++11).", - "configurePreset": "vs64-nost-with-demo", - "inherits": "vs64-base-build" + "name": "win64-nost-with-demo-build", + "displayName": "Build - x64 - Debug - Windows - Core Lib With Demo - No Stacktraces", + "description": "Build the Core Lib, and Demo, with MSVC-x64 with the necessary Ninja options in Debug mode, but with no stacktraces (strict C++11).", + "configurePreset": "win64-nost-with-demo", + "inherits": "win64-base-build" }, { - "name": "vs64-nost-with-demo-clean-build", - "displayName": "Build - x64 - Debug - Windows - Visual Studio - Core Lib With Demo - No Stacktraces - Clean First", - "description": "Build the Core Lib, and Demo, with VS-x64 with the necessary base MSBuild options in Debug mode, but with no stacktraces (strict C++11), and clean up the previous build first.", - "inherits": "vs64-nost-with-demo-build", + "name": "win64-nost-with-demo-clean-build", + "displayName": "Clean Build - x64 - Debug - Windows - Core Lib With Demo - No Stacktraces", + "description": "Build the Core Lib, and Demo, with MSVC-x64 with the necessary Ninja options in Debug mode, but with no stacktraces (strict C++11), and clean up the previous build first.", + "inherits": "win64-nost-with-demo-build", "cleanFirst": true }, { - "name": "vs64-nost-with-demo-build-rel", - "displayName": "Build - x64 - Release - Windows - Visual Studio - Core Lib With Demo - No Stacktraces", - "description": "Build the Core Lib, and Demo, with VS-x64 with the necessary base MSBuild options in Release mode, but with no stacktraces (strict C++11).", - "configurePreset": "vs64-nost-with-demo-rel", - "inherits": "vs64-base-build" + "name": "win64-nost-with-demo-build-rel", + "displayName": "Build - x64 - Release - Windows - Core Lib With Demo - No Stacktraces", + "description": "Build the Core Lib, and Demo, with MSVC-x64 with the necessary Ninja options in Release mode, but with no stacktraces (strict C++11).", + "configurePreset": "win64-nost-with-demo-rel", + "inherits": "win64-base-build" }, { - "name": "vs64-nost-with-demo-clean-build-rel", - "displayName": "Build - x64 - Release - Windows - Visual Studio - Core Lib With Demo - No Stacktraces - Clean First", - "description": "Build the Core Lib, and Demo, with VS-x64 with the necessary base MSBuild options in Release mode, but with no stacktraces (strict C++11), and clean up the previous build first.", - "inherits": "vs64-nost-with-demo-build-rel", + "name": "win64-nost-with-demo-clean-build-rel", + "displayName": "Clean Build - x64 - Release - Windows - Core Lib With Demo - No Stacktraces", + "description": "Build the Core Lib, and Demo, with MSVC-x64 with the necessary Ninja options in Release mode, but with no stacktraces (strict C++11), and clean up the previous build first.", + "inherits": "win64-nost-with-demo-build-rel", "cleanFirst": true }, { - "name": "vs64-all-build", - "displayName": "Build - x64 - Debug - Windows - Visual Studio - All Components - Core, Tests, and Demo", - "description": "Build the Core Lib, Tests, and Demo, with VS-x64 with the necessary base MSBuild options in Debug mode.", - "configurePreset": "vs64-all", - "inherits": "vs64-base-build" + "name": "win64-all-build", + "displayName": "Build - x64 - Debug - Windows - All Components - Core, Tests, and Demo", + "description": "Build the Core Lib, Tests, and Demo, with MSVC-x64 with the necessary Ninja options in Debug mode.", + "configurePreset": "win64-all", + "inherits": "win64-base-build" }, { - "name": "vs64-all-clean-build", - "displayName": "Build - x64 - Debug - Windows - Visual Studio - All Components - Core, Tests, and Demo - Clean First", - "description": "Build the Core Lib, Tests, and Demo, with VS-x64 with the necessary base MSBuild options in Debug mode, and clean up the previous build first.", - "inherits": "vs64-all-build", + "name": "win64-all-clean-build", + "displayName": "Clean Build - x64 - Debug - Windows - All Components - Core, Tests, and Demo", + "description": "Build the Core Lib, Tests, and Demo, with MSVC-x64 with the necessary Ninja options in Debug mode, and clean up the previous build first.", + "inherits": "win64-all-build", "cleanFirst": true }, { - "name": "vs64-all-build-rel", - "displayName": "Build - x64 - Release - Windows - Visual Studio - All Components - Core, Tests, and Demo", - "description": "Build the Core Lib, Tests, and Demo, with VS-x64 with the necessary base MSBuild options in Release mode.", - "configurePreset": "vs64-all-rel", - "inherits": "vs64-base-build" + "name": "win64-all-build-rel", + "displayName": "Build - x64 - Release - Windows - All Components - Core, Tests, and Demo", + "description": "Build the Core Lib, Tests, and Demo, with MSVC-x64 with the necessary Ninja options in Release mode.", + "configurePreset": "win64-all-rel", + "inherits": "win64-base-build" }, { - "name": "vs64-all-clean-build-rel", - "displayName": "Build - x64 - Release - Windows - Visual Studio - All Components - Core, Tests, and Demo - Clean First", - "description": "Build the Core Lib, Tests, and Demo, with VS-x64 with the necessary base MSBuild options in Release mode, and clean up the previous build first.", - "inherits": "vs64-all-build-rel", + "name": "win64-all-clean-build-rel", + "displayName": "Clean Build - x64 - Release - Windows - All Components - Core, Tests, and Demo", + "description": "Build the Core Lib, Tests, and Demo, with MSVC-x64 with the necessary Ninja options in Release mode, and clean up the previous build first.", + "inherits": "win64-all-build-rel", "cleanFirst": true }, { - "name": "vs64-nost-all-build", - "displayName": "Build - x64 - Debug - Windows - Visual Studio - All Components - Core, Tests, and Demo - No Stacktraces", - "description": "Build the Core Lib, Tests, and Demo, with VS-x64 with the necessary base MSBuild options in Debug mode, but with no stacktraces (strict C++11).", - "configurePreset": "vs64-nost-all", - "inherits": "vs64-base-build" + "name": "win64-nost-all-build", + "displayName": "Build - x64 - Debug - Windows - All Components - Core, Tests, and Demo - No Stacktraces", + "description": "Build the Core Lib, Tests, and Demo, with MSVC-x64 with the necessary Ninja options in Debug mode, but with no stacktraces (strict C++11).", + "configurePreset": "win64-nost-all", + "inherits": "win64-base-build" }, { - "name": "vs64-nost-all-clean-build", - "displayName": "Build - x64 - Debug - Windows - Visual Studio - All Components - Core, Tests, and Demo - No Stacktraces - Clean First", - "description": "Build the Core Lib, Tests, and Demo, with VS-x64 with the necessary base MSBuild options in Debug mode, but with no stacktraces (strict C++11), and clean up the previous build first.", - "inherits": "vs64-nost-all-build", + "name": "win64-nost-all-clean-build", + "displayName": "Clean Build - x64 - Debug - Windows - All Components - Core, Tests, and Demo - No Stacktraces", + "description": "Build the Core Lib, Tests, and Demo, with MSVC-x64 with the necessary Ninja options in Debug mode, but with no stacktraces (strict C++11), and clean up the previous build first.", + "inherits": "win64-nost-all-build", "cleanFirst": true }, { - "name": "vs64-nost-all-build-rel", - "displayName": "Build - x64 - Release - Windows - Visual Studio - All Components - Core, Tests, and Demo - No Stacktraces", - "description": "Build the Core Lib, Tests, and Demo, with VS-x64 with the necessary base MSBuild options in Release mode, but with no stacktraces (strict C++11).", - "configurePreset": "vs64-nost-all-rel", - "inherits": "vs64-base-build" + "name": "win64-nost-all-build-rel", + "displayName": "Build - x64 - Release - Windows - All Components - Core, Tests, and Demo - No Stacktraces", + "description": "Build the Core Lib, Tests, and Demo, with MSVC-x64 with the necessary Ninja options in Release mode, but with no stacktraces (strict C++11).", + "configurePreset": "win64-nost-all-rel", + "inherits": "win64-base-build" }, { - "name": "vs64-nost-all-clean-build-rel", - "displayName": "Build - x64 - Release - Windows - Visual Studio - All Components - Core, Tests, and Demo - No Stacktraces - Clean First", - "description": "Build the Core Lib, Tests, and Demo, with VS-x64 with the necessary base MSBuild options in Release mode, but with no stacktraces (strict C++11), and clean up the previous build first.", - "inherits": "vs64-nost-all-build-rel", + "name": "win64-nost-all-clean-build-rel", + "displayName": "Clean Build - x64 - Release - Windows - All Components - Core, Tests, and Demo - No Stacktraces", + "description": "Build the Core Lib, Tests, and Demo, with MSVC-x64 with the necessary Ninja options in Release mode, but with no stacktraces (strict C++11), and clean up the previous build first.", + "inherits": "win64-nost-all-build-rel", "cleanFirst": true }, { - "name": "vs64-msanalysis-build", - "displayName": "Analyze - x64 - Windows - Visual Studio", - "description": "Analyze the code with MSBuild using the x64 toolchain architecture.", - "inherits": "vs-msanalysis-build", - "configurePreset": "vs64-msanalysis" + "name": "win64-msanalysis-build", + "displayName": "Analyze - x64 - Windows", + "description": "Analyze the code with MSVC CL using the x64 toolchain architecture.", + "inherits": "win32-msanalysis-build", + "configurePreset": "win64-msanalysis" }, { - "name": "vs64-msanalysis-xml", - "displayName": "Analyze - x64 - Windows - Visual Studio - XML output", - "description": "Analyze the code with MSBuild using the x64 toolchain architecture, then output the analysis results in XML format.", - "inherits": "vs64-msanalysis-build", - "nativeToolOptions": [ - "/analyze:log:format:xml" - ] + "name": "win64-msanalysis-xml-build", + "displayName": "Analyze - x64 - Windows - XML output", + "description": "Analyze the code with MSVC CL using the x64 toolchain architecture, then output the analysis results in XML format.", + "inherits": "win64-msanalysis-build", + "configurePreset": "win64-msanalysis-xml" }, { - "name": "vs64-msanalysis-sarif", - "displayName": "Analyze - x64 - Windows - Visual Studio - SARIF output", - "description": "Analyze the code with MSBuild using the x64 toolchain architecture, then output the analysis results in SARIF format.", - "inherits": "vs64-msanalysis-build", - "nativeToolOptions": [ - "/analyze:log:format:sarif" - ] + "name": "win64-msanalysis-sarif-build", + "displayName": "Analyze - x64 - Windows - SARIF output", + "description": "Analyze the code with MSVC CL using the x64 toolchain architecture, then output the analysis results in SARIF format.", + "inherits": "win64-msanalysis-build", + "configurePreset": "win64-msanalysis-sarif" + }, + { + "name": "win64-ct-build", + "displayName": "Analyze - x64 - Windows - Clang Tidy", + "description": "Analyze the code with Clang Tidy using the x64 toolchain architecture.", + "inherits": "win32-ct-build", + "configurePreset": "win64-ct" } ], "testPresets": [ { - "name": "vs-test", - "displayName": "Test - x86 - Debug - Windows - Visual Studio", - "description": "Test with VS-Win32 with the necessary base MSBuild options in Debug mode.", - "configurePreset": "vs-with-test", + "name": "win32-test", + "displayName": "Test - x86 - Debug - Windows", + "description": "Test with MSVC-x86 with the necessary Ninja options in Debug mode.", + "configurePreset": "win32-with-test", "output": { "shortProgress": true, "verbosity": "verbose", @@ -1029,53 +1164,53 @@ } }, { - "name": "vs-test-rel", - "displayName": "Test - x86 - Release - Windows - Visual Studio", - "description": "Test with VS-Win32 with the necessary base MSBuild options in Release mode.", - "configurePreset": "vs-with-test-rel", - "inherits": "vs-test" + "name": "win32-test-rel", + "displayName": "Test - x86 - Release - Windows", + "description": "Test with MSVC-x86 with the necessary Ninja options in Release mode.", + "configurePreset": "win32-with-test-rel", + "inherits": "win32-test" }, { - "name": "vs-nost-test", - "displayName": "Test - x86 - Debug - Windows - Visual Studio - No Stacktraces", - "description": "Test with VS-Win32 with the necessary base MSBuild options in Debug mode, but with no stacktraces (strict C++11).", - "configurePreset": "vs-nost-with-test", - "inherits": "vs-test" + "name": "win32-nost-test", + "displayName": "Test - x86 - Debug - Windows - No Stacktraces", + "description": "Test with MSVC-x86 with the necessary Ninja options in Debug mode, but with no stacktraces (strict C++11).", + "configurePreset": "win32-nost-with-test", + "inherits": "win32-test" }, { - "name": "vs-nost-test-rel", - "displayName": "Test - x86 - Release - Windows - Visual Studio - No Stacktraces", - "description": "Test with VS-Win32 with the necessary base MSBuild options in Release mode, but with no stacktraces (strict C++11).", - "configurePreset": "vs-nost-with-test-rel", - "inherits": "vs-test" + "name": "win32-nost-test-rel", + "displayName": "Test - x86 - Release - Windows - No Stacktraces", + "description": "Test with MSVC-x86 with the necessary Ninja options in Release mode, but with no stacktraces (strict C++11).", + "configurePreset": "win32-nost-with-test-rel", + "inherits": "win32-test" }, { - "name": "vs64-test", - "displayName": "Test - x64 - Debug - Windows - Visual Studio", - "description": "Test with VS-x64 with the necessary base MSBuild options in Debug mode.", - "configurePreset": "vs64-with-test", - "inherits": "vs-test" + "name": "win64-test", + "displayName": "Test - x64 - Debug - Windows", + "description": "Test with MSVC-x64 with the necessary Ninja options in Debug mode.", + "configurePreset": "win64-with-test", + "inherits": "win32-test" }, { - "name": "vs64-test-rel", - "displayName": "Test - x64 - Release - Windows - Visual Studio", - "description": "Test with VS-x64 with the necessary base MSBuild options in Release mode.", - "configurePreset": "vs64-with-test-rel", - "inherits": "vs-test" + "name": "win64-test-rel", + "displayName": "Test - x64 - Release - Windows", + "description": "Test with MSVC-x64 with the necessary Ninja options in Release mode.", + "configurePreset": "win64-with-test-rel", + "inherits": "win32-test" }, { - "name": "vs64-nost-test", - "displayName": "Test - x64 - Debug - Windows - Visual Studio - No Stacktraces", - "description": "Test with VS-x64 with the necessary base MSBuild options in Debug mode, but with no stacktraces (strict C++11).", - "configurePreset": "vs64-nost-with-test", - "inherits": "vs-nost-test" + "name": "win64-nost-test", + "displayName": "Test - x64 - Debug - Windows - No Stacktraces", + "description": "Test with MSVC-x64 with the necessary Ninja options in Debug mode, but with no stacktraces (strict C++11).", + "configurePreset": "win64-nost-with-test", + "inherits": "win32-nost-test" }, { - "name": "vs64-nost-test-rel", - "displayName": "Test - x64 - Release - Windows - Visual Studio - No Stacktraces", - "description": "Test with VS-x64 with the necessary base MSBuild options in Release mode, but with no stacktraces (strict C++11).", - "configurePreset": "vs64-nost-with-test-rel", - "inherits": "vs-nost-test" + "name": "win64-nost-test-rel", + "displayName": "Test - x64 - Release - Windows - No Stacktraces", + "description": "Test with MSVC-x64 with the necessary Ninja options in Release mode, but with no stacktraces (strict C++11).", + "configurePreset": "win64-nost-with-test-rel", + "inherits": "win32-nost-test" } ] -} \ No newline at end of file +} diff --git a/cmake/Analyzing.cmake b/cmake/Analyzing.cmake index 2da8883..6ec0c22 100644 --- a/cmake/Analyzing.cmake +++ b/cmake/Analyzing.cmake @@ -1,5 +1,10 @@ if (TESTCPP_ANALYSIS_ENABLED) - find_program (CLANG_TIDY_COMMAND NAMES clang-tidy) + find_program ( + CLANG_TIDY_COMMAND + NAMES + clang-tidy + NO_CACHE + ) if (NOT CLANG_TIDY_COMMAND) message (WARNING "clang-tidy is not found!") @@ -8,8 +13,9 @@ if (TESTCPP_ANALYSIS_ENABLED) else() set ( CLANG_TIDY_COMMAND -"${CLANG_TIDY_COMMAND};--header-filter=.*;--format-style=file;\ --p=${CMAKE_BINARY_DIR}" +"${CLANG_TIDY_COMMAND};--config-file=${CMAKE_SOURCE_DIR}/.clang-tidy;-p=${CMAKE_BINARY_DIR}" + CACHE STRING "Clang Tidy command" + FORCE ) set_target_properties ( diff --git a/cmake/build/GCCClangDebug.cmake b/cmake/build/GCCClangDebug.cmake index 377c6cc..d04935a 100644 --- a/cmake/build/GCCClangDebug.cmake +++ b/cmake/build/GCCClangDebug.cmake @@ -30,6 +30,41 @@ list ( # capture. ) +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" or + "${CMAKE_VS_PLATFORM_TOOLSET}" STREQUAL "ClangCL") + + # GCC doesn't support -Wno-global-constructors yet, so only add it + # if we are building with Clang, either with MSVC as a frontend + # or straight-up LLVM. + # Ref https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71482 + + list ( + APPEND + GCC_CLANG_DEBUG_BUILD_OPTS + -Wno-global-constructors # The performance degradation pointed + # out by this warning is non-trivial + # but not enough to work through any + # issues that might be caused by it; + # there were already constructors + # from built-in types that were being + # called (particularly unique_ptr), + # but this points out that the type I + # added (no_destroy) adds custom and + # additional start-up code that can + # change startup performance by + # making it slower. + # How much slower is a matter of + # micro-optimization for this library + # project in particular, but could + # significantly decrease startup + # performance if there were n-many of + # these objects being created. + # At this point there are only 6, so + # this should not cause a noticeable + # hit to startup performance. + ) +endif () + if (${TESTCPP_DEMO_ENABLED}) target_compile_options ( ${PROJECT_NAME}_run diff --git a/cmake/build/GCCClangRelease.cmake b/cmake/build/GCCClangRelease.cmake index 50989b6..fe0d39f 100644 --- a/cmake/build/GCCClangRelease.cmake +++ b/cmake/build/GCCClangRelease.cmake @@ -29,6 +29,41 @@ list ( # capture. ) +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" or + "${CMAKE_VS_PLATFORM_TOOLSET}" STREQUAL "ClangCL") + + # GCC doesn't support -Wno-global-constructors yet, so only add it + # if we are building with Clang, either with MSVC as a frontend + # or straight-up LLVM. + # Ref https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71482 + + list ( + APPEND + GCC_CLANG_RELEASE_BUILD_OPTS + -Wno-global-constructors # The performance degradation pointed + # out by this warning is non-trivial + # but not enough to work through any + # issues that might be caused by it; + # there were already constructors + # from built-in types that were being + # called (particularly unique_ptr), + # but this points out that the type I + # added (no_destroy) adds custom and + # additional start-up code that can + # change startup performance by + # making it slower. + # How much slower is a matter of + # micro-optimization for this library + # project in particular, but could + # significantly decrease startup + # performance if there were n-many of + # these objects being created. + # At this point there are only 6, so + # this should not cause a noticeable + # hit to startup performance. + ) +endif () + target_compile_options ( ${PROJECT_NAME} PUBLIC diff --git a/cmake/build/GCCCoverage.cmake b/cmake/build/GCCCoverage.cmake index 6eac602..6131b5e 100644 --- a/cmake/build/GCCCoverage.cmake +++ b/cmake/build/GCCCoverage.cmake @@ -22,6 +22,10 @@ list ( -ftest-coverage # Enable core code coverage compilation. ) +# Add -Wno-global-constructors to the GCC build options after it exists +# like in GCCClangRelease.cmake and GCCClangDebug.cmake. +# Ref https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71482 + target_compile_options ( ${PROJECT_NAME} PUBLIC diff --git a/cmake/build/MSVCDebug.cmake b/cmake/build/MSVCDebug.cmake index 908486a..be646db 100644 --- a/cmake/build/MSVCDebug.cmake +++ b/cmake/build/MSVCDebug.cmake @@ -1,58 +1,53 @@ - list ( APPEND MSVC_DEBUG_BUILD_OPTS - /Wall # Enable all warnings and treat them as errors. - /WX # Treat linker warnings as errors also. - /Od # Perform no optimization; the resulting code is optimized - # for debugging and debuggability. - /wd4820 # Struct/class data member padding is ok, we're concerned - # about speed, not space, and the natural alignment is - # generally fastest. - # Let the compiler add the padding. - /wd4668 # There are undefined preprocessor macros in the Windows - # SDK in internal headers. - # This is a workaround until these issues are fixed by - # Microsoft. - /wd5045 # Warns about code that can cause the Spectre - # vulnerability to become exploitable, does not go away - # when /Qspectre is specified. - # Applied this warning suppression since /Qspectre is - # specified. - /Qspectre # Instructs the compiler to apply Spectre vulnerability - # mitigations. + /nologo # Suppress the compiler version and + # copyright information. + /Zi # Generate complete debugging information. + /FS # Force synchronous PDB writes. + /EHscr # Enable C++ exceptions, including RTCs for + # noexcept verification at runtime. + /RTC1 # Enable Runtime Checks. + /Wall # Enable all warnings and treat them as + # errors. + /WX # Treat linker warnings as errors also. + /Od # Perform no optimization; the resulting + # code is optimized for debugging and + # debuggability. + /wd4820 # Struct/class data member padding is ok, + # we're concerned about speed, not space, + # and the natural alignment is generally + # fastest. + # Let the compiler add the padding. + /wd5045 # Warns about code that can cause the + # Spectre vulnerability to become + # exploitable, does not go away when + # /Qspectre is specified. + # Applied this warning suppression since + # /Qspectre is specified. + /Qspectre # Instructs the compiler to apply Spectre + # vulnerability mitigations. + /external:anglebrackets # Treat angle-bracket includes as system + # includes. + /external:W0 # Suppress all warnings from external + # headers. ) if (${TESTCPP_STACKTRACE_ENABLED}) list ( APPEND MSVC_DEBUG_BUILD_OPTS - /wd5039 # There's a function or two in the Windows SDK that is/ - # are passed to extern 'C' APIs that are not marked as - # noexcept which causes this warning, which is treated - # as an error. - # There's nothing we can do about this so this is added - # as a workaround. - /wd4625 # In the Boost.StackTrace code, there are copy - # constructors that are implicitly deleted. - # Since this is in an external library, suppress the - # warning to work around this to ensure clean - # compilation. - /wd4626 # In the Boost.StackTrace code, there are copy - # assignment operators that are implicitly deleted. - # Since this is in an external library, suppress the - # warning to work around this to ensure clean - # compilation. - /wd5026 # In the Boost.StackTrace code, there are move - # constructors that are implicitly deleted. - # Since this is in an external library, suppress the - # warning to work around this to ensure clean - # compilation. - /wd5027 # In the Boost.StackTrace code, there are move - # assignment operators that are implicitly deleted. - # Since this is in an external library, suppress the - # warning to work around this to ensure clean - # compilation. + "/external:I3rdparty/include" # Include the 3rdparty directory + # as an external include + # directory. + ) +endif () + +if ("${CMAKE_CXX_FLAGS}" MATCHES "/analyze:ruleset") + list ( + APPEND + MSVC_DEBUG_BUILD_OPTS + /analyze:rulesetdirectory "${VS_INSTALLATION_PATH}/Team Tools/Static Analysis Tools/Rule Sets" ) endif () diff --git a/cmake/build/MSVCRelease.cmake b/cmake/build/MSVCRelease.cmake index a0be314..6dc1772 100644 --- a/cmake/build/MSVCRelease.cmake +++ b/cmake/build/MSVCRelease.cmake @@ -1,60 +1,43 @@ list ( APPEND MSVC_RELEASE_BUILD_OPTS - /Wall # Enable all warnings and treat them as errors. - /WX # Treat linker warnings as errors also. - /O2 # Do optimizations for the Release build. - /wd4668 # There are undefined preprocessor macros in the Windows - # SDK in internal headers. - # This is a workaround until these issues are fixed by - # Microsoft. - /wd4710 # It's ok if functions are not inlined. - /wd4711 # It's also ok if functions are inlined. - /wd4820 # Struct/class data member padding is ok, we're concerned - # about speed, not space, and the natural alignment is - # generally fastest. - # Let the compiler add the padding. - /wd4100 # Unused parameters occur in the Release build in - # debugLog. - /wd5045 # Warns about code that can cause the Spectre - # vulnerability to become exploitable, does not go away - # when /Qspectre is specified. - # Applied this warning suppression since /Qspectre is - # specified. - /Qspectre # Instructs the compiler to apply Spectre vulnerability - # mitigations. + /nologo # Suppress the compiler version and + # copyright information. + /EHsc # Enable C++ exceptions. + /Wall # Enable all warnings and treat them as + # errors. + /WX # Treat linker warnings as errors also. + /O2 # Do optimizations for the Release build. + /wd4710 # It's ok if functions are not inlined. + /wd4711 # It's also ok if functions are inlined. + /wd4820 # Struct/class data member padding is ok, + # we're concerned about speed, not space, + # and the natural alignment is generally + # fastest. + # Let the compiler add the padding. + /wd4100 # Unused parameters occur in the Release + # build in debugLog. + /wd5045 # Warns about code that can cause the + # Spectre vulnerability to become + # exploitable, does not go away when + # /Qspectre is specified. + # Applied this warning suppression since + # /Qspectre is specified. + /Qspectre # Instructs the compiler to apply Spectre + # vulnerability mitigations. + /external:anglebrackets # Treat angle-bracket includes as system + # includes. + /external:W0 # Suppress all warnings from external + # headers. ) if (${TESTCPP_STACKTRACE_ENABLED}) list ( APPEND MSVC_RELEASE_BUILD_OPTS - /wd5039 # There's a function or two in the Windows SDK that is/ - # are passed to extern 'C' APIs that are not marked as - # noexcept which causes this warning, which is treated - # as an error. - # There's nothing we can do about this so this is added - # as a workaround. - /wd4625 # In the Boost.StackTrace code, there are copy - # constructors that are implicitly deleted. - # Since this is in an external library, suppress the - # warning to work around this to ensure clean - # compilation. - /wd4626 # In the Boost.StackTrace code, there are copy - # assignment operators that are implicitly deleted. - # Since this is in an external library, suppress the - # warning to work around this to ensure clean - # compilation. - /wd5026 # In the Boost.StackTrace code, there are move - # constructors that are implicitly deleted. - # Since this is in an external library, suppress the - # warning to work around this to ensure clean - # compilation. - /wd5027 # In the Boost.StackTrace code, there are move - # assignment operators that are implicitly deleted. - # Since this is in an external library, suppress the - # warning to work around this to ensure clean - # compilation. + "/external:I3rdparty/include" # Include the 3rdparty directory + # as an external include + # directory. ) endif () @@ -100,3 +83,13 @@ if (BUILD_TESTING) ${MSVC_RELEASE_BUILD_OPTS} ) endif () + +# This section removes the /RTC flags from the CMAKE_CXX_FLAGS_* +# variables, because CMake is automatically adding them to the +# generated VS MSBuild builds without me specifying them, +# specifically because they should not be in a Release build. +foreach (flag_var + CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE + CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) + STRING (REGEX REPLACE "[/\-]RTC[1csu]*" "" ${flag_var} "${${flag_var}}") +endforeach (flag_var) diff --git a/cmake/toolchains/VSWhere.cmake b/cmake/toolchains/VSWhere.cmake new file mode 100644 index 0000000..c2ea310 --- /dev/null +++ b/cmake/toolchains/VSWhere.cmake @@ -0,0 +1,132 @@ +#---------------------------------------------------------------------------------------------------------------------- +# MIT License +# +# Copyright (c) 2021 Mark Schofield +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +#---------------------------------------------------------------------------------------------------------------------- +include_guard() + +#[[==================================================================================================================== + toolchain_validate_vs_files + --------------------------- + + Note: Not supported for consumption outside of the toolchain files. + + Validates the the specified folder exists and contains the specified files. + + toolchain_validate_vs_files( + > + > + ...> + ) + + If the folder or files are missing, then a FATAL_ERROR is reported. +====================================================================================================================]]# +function(toolchain_validate_vs_files) + set(OPTIONS) + set(ONE_VALUE_KEYWORDS FOLDER DESCRIPTION) + set(MULTI_VALUE_KEYWORDS FILES) + + cmake_parse_arguments(PARSE_ARGV 0 VS "${OPTIONS}" "${ONE_VALUE_KEYWORDS}" "${MULTI_VALUE_KEYWORDS}") + + if(NOT EXISTS ${VS_FOLDER}) + message(FATAL_ERROR "Folder not present - ${VS_FOLDER} - ensure that the ${VS_DESCRIPTION} are installed with Visual Studio.") + endif() + + foreach(FILE ${VS_FILES}) + if(NOT EXISTS "${VS_FOLDER}/${FILE}") + message(FATAL_ERROR "File not present - ${VS_FOLDER}/${FILE} - ensure that the ${VS_DESCRIPTION} are installed with Visual Studio.") + endif() + endforeach() +endfunction() + +#[[==================================================================================================================== + findVisualStudio + ---------------- + + Finds a Visual Studio instance, and sets CMake variables based on properties of the found instance. + + findVisualStudio( + [VERSION ] + [PRERELEASE ] + [PRODUCTS ] + [REQUIRES ...] + PROPERTIES + < > + ) +====================================================================================================================]]# +function(findVisualStudio) + set(OPTIONS) + set(ONE_VALUE_KEYWORDS VERSION PRERELEASE PRODUCTS) + set(MULTI_VALUE_KEYWORDS REQUIRES PROPERTIES) + + cmake_parse_arguments(PARSE_ARGV 0 FIND_VS "${OPTIONS}" "${ONE_VALUE_KEYWORDS}" "${MULTI_VALUE_KEYWORDS}") + + find_program(VSWHERE_PATH + NAMES vswhere vswhere.exe + HINTS "$ENV{ProgramFiles\(x86\)}/Microsoft Visual Studio/Installer" + ) + + if(VSWHERE_PATH STREQUAL "VSWHERE_PATH-NOTFOUND") + message(FATAL_ERROR "'vswhere' isn't found.") + endif() + + set(VSWHERE_COMMAND ${VSWHERE_PATH} -latest) + + if(FIND_VS_PRERELEASE) + list(APPEND VSWHERE_COMMAND -prerelease) + endif() + + if(FIND_VS_PRODUCTS) + list(APPEND VSWHERE_COMMAND -products ${FIND_VS_PRODUCTS}) + endif() + + if(FIND_VS_REQUIRES) + list(APPEND VSWHERE_COMMAND -requires ${FIND_VS_REQUIRES}) + endif() + + if(FIND_VS_VERSION) + list(APPEND VSWHERE_COMMAND -version "${FIND_VS_VERSION}") + endif() + + message(VERBOSE "findVisualStudio: VSWHERE_COMMAND = ${VSWHERE_COMMAND}") + + execute_process( + COMMAND ${VSWHERE_COMMAND} + OUTPUT_VARIABLE VSWHERE_OUTPUT + ) + + message(VERBOSE "findVisualStudio: VSWHERE_OUTPUT = ${VSWHERE_OUTPUT}") + + # Matches `VSWHERE_PROPERTY` in the `VSWHERE_OUTPUT` text in the format written by vswhere. + # The matched value is assigned to the variable `VARIABLE_NAME` in the parent scope. + function(getVSWhereProperty VSWHERE_OUTPUT VSWHERE_PROPERTY VARIABLE_NAME) + string(REGEX MATCH "${VSWHERE_PROPERTY}: [^\r\n]*" VSWHERE_VALUE "${VSWHERE_OUTPUT}") + string(REPLACE "${VSWHERE_PROPERTY}: " "" VSWHERE_VALUE "${VSWHERE_VALUE}") + set(${VARIABLE_NAME} "${VSWHERE_VALUE}" PARENT_SCOPE) + endfunction() + + while(FIND_VS_PROPERTIES) + list(POP_FRONT FIND_VS_PROPERTIES VSWHERE_PROPERTY) + list(POP_FRONT FIND_VS_PROPERTIES VSWHERE_CMAKE_VARIABLE) + getVSWhereProperty("${VSWHERE_OUTPUT}" ${VSWHERE_PROPERTY} VSWHERE_VALUE) + set(${VSWHERE_CMAKE_VARIABLE} ${VSWHERE_VALUE} PARENT_SCOPE) + endwhile() +endfunction() diff --git a/cmake/toolchains/Windows.Clang.toolchain.cmake b/cmake/toolchains/Windows.Clang.toolchain.cmake new file mode 100644 index 0000000..82f45d3 --- /dev/null +++ b/cmake/toolchains/Windows.Clang.toolchain.cmake @@ -0,0 +1,271 @@ +#---------------------------------------------------------------------------------------------------------------------- +# MIT License +# +# Copyright (c) 2021 Mark Schofield +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +#---------------------------------------------------------------------------------------------------------------------- +# +# This CMake toolchain file configures a CMake, non-'Visual Studio Generator' build to use +# the Clang compilers and tools on Windows. +# +# The following variables can be used to configure the behavior of this toolchain file: +# +# | CMake Variable | Description | +# |---------------------------------------------|-----------------------------------------------------------------------------------------------------------------| +# | CMAKE_SYSTEM_VERSION | The version of the operating system for which CMake is to build. Defaults to '10.0.19041.0'. | +# | CMAKE_SYSTEM_PROCESSOR | The processor to compiler for. One of 'X86', 'AMD64', 'ARM', 'ARM64'. Defaults to ${CMAKE_HOST_SYSTEM_PROCESSOR}. | +# | CMAKE_WINDOWS_KITS_10_DIR | The location of the root of the Windows Kits 10 directory. | +# | CLANG_TIDY_CHECKS | List of rules clang-tidy should check. Defaults not set. | +# | TOOLCHAIN_UPDATE_PROGRAM_PATH | Whether the toolchain should update CMAKE_PROGRAM_PATH. Defaults to 'ON'. | +# | TOOLCHAIN_ADD_VS_NINJA_PATH | Whether the toolchain should add the path to the VS Ninja to the CMAKE_SYSTEM_PROGRAM_PATH. Defaults to 'ON'. | +# +# The toolchain file will set the following variables: +# +# | CMake Variable | Description | +# |---------------------------------------------|-------------------------------------------------------------------------------------------------------| +# | CMAKE_C_COMPILER | The path to the C compiler to use. | +# | CMAKE_CXX_COMPILER | The path to the C++ compiler to use. | +# | CMAKE_MT | The path to the 'mt.exe' tool to use. | +# | CMAKE_RC_COMPILER | The path tp the 'rc.exe' tool to use. | +# | CMAKE_SYSTEM_NAME | "Windows", when cross-compiling | +# | WIN32 | 1 | +# | CMAKE_CXX_CLANG_TIDY | The commandline clang-tidy is used if CLANG_TIDY_CHECKS was set. | +# +# Resources: +# +# +cmake_minimum_required(VERSION 3.20) + +include_guard() + +# If `CMAKE_HOST_SYSTEM_NAME` is not 'Windows', there's nothing to do. +if(NOT (CMAKE_HOST_SYSTEM_NAME STREQUAL Windows)) + return() +endif() + +option(TOOLCHAIN_UPDATE_PROGRAM_PATH "Whether the toolchain should update CMAKE_PROGRAM_PATH." ON) +option(TOOLCHAIN_ADD_VS_NINJA_PATH "Whether the toolchain should add the path to the VS Ninja to the CMAKE_SYSTEM_PROGRAM_PATH." ON) + +set(UNUSED ${CMAKE_TOOLCHAIN_FILE}) # Note: only to prevent cmake unused variable warninig +list(APPEND CMAKE_TRY_COMPILE_PLATFORM_VARIABLES "CMAKE_SYSTEM_PROCESSOR") +set(WIN32 1) + +# If `CMAKE_SYSTEM_PROCESSOR` isn't set, default to `CMAKE_HOST_SYSTEM_PROCESSOR` +if(NOT CMAKE_SYSTEM_PROCESSOR) + set(CMAKE_SYSTEM_PROCESSOR ${CMAKE_HOST_SYSTEM_PROCESSOR}) +endif() + +# If `CMAKE_SYSTEM_PROCESSOR` is not equal to `CMAKE_HOST_SYSTEM_PROCESSOR`, this is cross-compilation. +# CMake expects `CMAKE_SYSTEM_NAME` to be set to reflect cross-compilation. +if(NOT (CMAKE_SYSTEM_PROCESSOR STREQUAL ${CMAKE_HOST_SYSTEM_PROCESSOR})) + set(CMAKE_SYSTEM_NAME Windows) +endif() + +if(NOT CMAKE_VS_VERSION_RANGE) + set(CMAKE_VS_VERSION_RANGE "[16.0,)") +endif() + +if(NOT CMAKE_VS_VERSION_PRERELEASE) + set(CMAKE_VS_VERSION_PRERELEASE OFF) +endif() + +include("${CMAKE_CURRENT_LIST_DIR}/VSWhere.cmake") + +if(NOT CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE) + if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL ARM64) + set(CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE arm64) + else() + set(CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE x64) + endif() +endif() + +# Find Clang +# +findVisualStudio( + VERSION ${CMAKE_VS_VERSION_RANGE} + PRERELEASE ${CMAKE_VS_VERSION_PRERELEASE} + REQUIRES + Microsoft.VisualStudio.Component.VC.Llvm.Clang + PROPERTIES + installationVersion VS_INSTALLATION_VERSION + installationPath VS_INSTALLATION_PATH +) + +if(NOT VS_INSTALLATION_PATH) + # If there's no Visual Studio with Clang, look for a Visual Studio without Clang so that other Visual Studio + # components can be found. + findVisualStudio( + VERSION ${CMAKE_VS_VERSION_RANGE} + PRERELEASE ${CMAKE_VS_VERSION_PRERELEASE} + PROPERTIES + installationVersion VS_INSTALLATION_VERSION + installationPath VS_INSTALLATION_PATH + ) +endif() + +message(VERBOSE "VS_INSTALLATION_VERSION = ${VS_INSTALLATION_VERSION}") +message(VERBOSE "VS_INSTALLATION_PATH = ${VS_INSTALLATION_PATH}") + +if(NOT VS_INSTALLATION_PATH) + message(FATAL_ERROR "Unable to find Visual Studio") +endif() + +cmake_path(NORMAL_PATH VS_INSTALLATION_PATH) + +set(VS_MSVC_PATH "${VS_INSTALLATION_PATH}/VC/Tools/MSVC") + +# Use 'VS_PLATFORM_TOOLSET_VERSION' to resolve 'CMAKE_VS_PLATFORM_TOOLSET_VERSION' +# +if(NOT VS_PLATFORM_TOOLSET_VERSION) + if(VS_TOOLSET_VERSION) + message(WARNING "Old versions of WindowsToolchain incorrectly used 'VS_TOOLSET_VERSION' to specify the VS toolset version. This functionality is being deprecated - please use 'VS_PLATFORM_TOOLSET_VERSION' instead.") + set(VS_PLATFORM_TOOLSET_VERSION ${VS_TOOLSET_VERSION}) + else() + file(GLOB VS_PLATFORM_TOOLSET_VERSIONS RELATIVE ${VS_MSVC_PATH} ${VS_MSVC_PATH}/*) + list(SORT VS_PLATFORM_TOOLSET_VERSIONS COMPARE NATURAL ORDER DESCENDING) + list(POP_FRONT VS_PLATFORM_TOOLSET_VERSIONS VS_PLATFORM_TOOLSET_VERSION) + unset(VS_PLATFORM_TOOLSET_VERSIONS) + endif() +endif() + +set(CMAKE_VS_PLATFORM_TOOLSET_VERSION ${VS_PLATFORM_TOOLSET_VERSION}) +set(VS_TOOLSET_PATH "${VS_INSTALLATION_PATH}/VC/Tools/MSVC/${CMAKE_VS_PLATFORM_TOOLSET_VERSION}") + +# Set the tooling variables, include_directories and link_directories +# + +# Map CMAKE_SYSTEM_PROCESSOR values to CMAKE_VS_PLATFORM_TOOLSET_ARCHITECTURE that identifies the tools that should +# be used to produce code for the CMAKE_SYSTEM_PROCESSOR. +if(CMAKE_SYSTEM_PROCESSOR STREQUAL AMD64) + set(CMAKE_VS_PLATFORM_TOOLSET_ARCHITECTURE x64) +elseif((CMAKE_SYSTEM_PROCESSOR STREQUAL ARM) + OR (CMAKE_SYSTEM_PROCESSOR STREQUAL ARM64) + OR (CMAKE_SYSTEM_PROCESSOR STREQUAL X86)) + set(CMAKE_VS_PLATFORM_TOOLSET_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR}) +elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL x64) + message(WARNING "CMAKE_SYSTEM_PROCESSOR should be 'AMD64', not 'x64'. WindowsToolchain will stop recognizing 'x64' in a future release.") + set(CMAKE_VS_PLATFORM_TOOLSET_ARCHITECTURE x64) +elseif((CMAKE_SYSTEM_PROCESSOR STREQUAL arm) + OR (CMAKE_SYSTEM_PROCESSOR STREQUAL arm64) + OR (CMAKE_SYSTEM_PROCESSOR STREQUAL x86)) + message(WARNING "CMAKE_SYSTEM_PROCESSOR (${CMAKE_SYSTEM_PROCESSOR}) should be upper-case. WindowsToolchain will stop recognizing non-upper-case forms in a future release.") + set(CMAKE_VS_PLATFORM_TOOLSET_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR}) +else() + message(FATAL_ERROR "Unable identify compiler architecture for CMAKE_SYSTEM_PROCESSOR ${CMAKE_SYSTEM_PROCESSOR}") +endif() + +set(TOOLCHAIN_C_COMPILER_EXE clang.exe) +if(CMAKE_C_COMPILER_FRONTEND_VARIANT STREQUAL MSVC) + set(TOOLCHAIN_C_COMPILER_EXE clang-cl.exe) +endif() + +find_program(CMAKE_C_COMPILER + ${TOOLCHAIN_C_COMPILER_EXE} + HINTS + "${VS_INSTALLATION_PATH}/VC/Tools/Llvm/x64/bin" + "$ENV{ProgramFiles}/LLVM/bin" + REQUIRED +) + +set(TOOLCHAIN_CXX_COMPILER_EXE clang++.exe) +if(CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL MSVC) + set(TOOLCHAIN_CXX_COMPILER_EXE clang-cl.exe) +endif() + +find_program(CMAKE_CXX_COMPILER + ${TOOLCHAIN_CXX_COMPILER_EXE} + HINTS + "${VS_INSTALLATION_PATH}/VC/Tools/Llvm/x64/bin" + "$ENV{ProgramFiles}/LLVM/bin" + REQUIRED +) + +if(CMAKE_SYSTEM_PROCESSOR STREQUAL ARM) + set(CMAKE_CXX_FLAGS_INIT "${CMAKE_CXX_FLAGS_INIT} /EHsc") +elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL arm) + message(WARNING "CMAKE_SYSTEM_PROCESSOR (${CMAKE_SYSTEM_PROCESSOR}) should be upper-case. WindowsToolchain will stop recognizing non-upper-case forms in a future release.") + set(CMAKE_CXX_FLAGS_INIT "${CMAKE_CXX_FLAGS_INIT} /EHsc") +endif() + +# Compiler +foreach(LANG C CXX RC) + list(APPEND CMAKE_${LANG}_STANDARD_INCLUDE_DIRECTORIES "${VS_TOOLSET_PATH}/ATLMFC/include") + list(APPEND CMAKE_${LANG}_STANDARD_INCLUDE_DIRECTORIES "${VS_TOOLSET_PATH}/include") +endforeach() + +foreach(LANG C CXX) + if(CMAKE_${LANG}_COMPILER_FRONTEND_VARIANT STREQUAL MSVC) + # Add '/X': Do not add %INCLUDE% to include search path + set(CMAKE_${LANG}_FLAGS_INIT "${CMAKE_${LANG}_FLAGS_INIT} /X") + endif() +endforeach() + +if(VS_USE_SPECTRE_MITIGATION_ATLMFC_RUNTIME) + # Ensure that the necessary folder and files are present before adding the 'link_directories' + toolchain_validate_vs_files( + DESCRIPTION "ATLMFC Spectre libraries" + FOLDER "${VS_TOOLSET_PATH}/ATLMFC/lib/spectre/${CMAKE_VS_PLATFORM_TOOLSET_ARCHITECTURE}" + FILES + atls.lib + ) + link_directories("${VS_TOOLSET_PATH}/ATLMFC/lib/spectre/${CMAKE_VS_PLATFORM_TOOLSET_ARCHITECTURE}") +else() + link_directories("${VS_TOOLSET_PATH}/ATLMFC/lib/${CMAKE_VS_PLATFORM_TOOLSET_ARCHITECTURE}") +endif() + +if(VS_USE_SPECTRE_MITIGATION_RUNTIME) + # Ensure that the necessary folder and files are present before adding the 'link_directories' + toolchain_validate_vs_files( + DESCRIPTION "Spectre libraries" + FOLDER "${VS_TOOLSET_PATH}/lib/spectre/${CMAKE_VS_PLATFORM_TOOLSET_ARCHITECTURE}" + FILES + msvcrt.lib vcruntime.lib vcruntimed.lib + ) + link_directories("${VS_TOOLSET_PATH}/lib/spectre/${CMAKE_VS_PLATFORM_TOOLSET_ARCHITECTURE}") +else() + link_directories("${VS_TOOLSET_PATH}/lib/${CMAKE_VS_PLATFORM_TOOLSET_ARCHITECTURE}") +endif() + +link_directories("${VS_TOOLSET_PATH}/lib/x86/store/references") + +if(CLANG_TIDY_CHECKS) + get_filename_component(CLANG_PATH ${CMAKE_CXX_COMPILER} DIRECTORY CACHE) + set(CMAKE_CXX_CLANG_TIDY "${CLANG_PATH}/clang-tidy.exe;-checks=${CLANG_TIDY_CHECKS}") +endif() + +# Windows Kits +include("${CMAKE_CURRENT_LIST_DIR}/Windows.Kits.cmake") + +# If 'TOOLCHAIN_UPDATE_PROGRAM_PATH' is selected, update CMAKE_PROGRAM_PATH. +# +if(TOOLCHAIN_UPDATE_PROGRAM_PATH) + list(APPEND CMAKE_PROGRAM_PATH "${VS_TOOLSET_PATH}/bin/Host${CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE}/${CMAKE_VS_PLATFORM_TOOLSET_ARCHITECTURE}") + list(APPEND CMAKE_PROGRAM_PATH "${WINDOWS_KITS_BIN_PATH}/${CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE}") +endif() + +# If the CMAKE_GENERATOR is Ninja-based, and the path to the Visual Studio-installed Ninja is present, add it to +# the CMAKE_SYSTEM_PROGRAM_PATH. 'find_program' searches CMAKE_SYSTEM_PROGRAM_PATH after the environment path, so +# an installed Ninja would be preferred. +# +if( (CMAKE_GENERATOR MATCHES "^Ninja") AND + (EXISTS "${VS_INSTALLATION_PATH}/Common7/IDE/CommonExtensions/Microsoft/CMake/Ninja") AND + (TOOLCHAIN_ADD_VS_NINJA_PATH)) + list(APPEND CMAKE_SYSTEM_PROGRAM_PATH "${VS_INSTALLATION_PATH}/Common7/IDE/CommonExtensions/Microsoft/CMake/Ninja") +endif() diff --git a/cmake/toolchains/Windows.Kits.cmake b/cmake/toolchains/Windows.Kits.cmake new file mode 100644 index 0000000..fd33214 --- /dev/null +++ b/cmake/toolchains/Windows.Kits.cmake @@ -0,0 +1,153 @@ +#---------------------------------------------------------------------------------------------------------------------- +# MIT License +# +# Copyright (c) 2021 Mark Schofield +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +#---------------------------------------------------------------------------------------------------------------------- +# +# | CMake Variable | Description | +# |-----------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------| +# | CMAKE_SYSTEM_VERSION | The version of the operating system for which CMake is to build. Defaults to the host version. | +# | CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE | The architecture of the tooling to use. Defaults to 'arm64' on ARM64 systems, otherwise 'x64'. | +# | CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION | The version of the Windows SDK to use. Defaults to the highest installed, that is no higher than CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION_MAXIMUM | +# | CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION_MAXIMUM | The maximum version of the Windows SDK to use, for example '10.0.19041.0'. Defaults to nothing | +# | CMAKE_WINDOWS_KITS_10_DIR | The location of the root of the Windows Kits 10 directory. | +# +# The following variables will be set: +# +# | CMake Variable | Description | +# |---------------------------------------------|-------------------------------------------------------------------------------------------------------| +# | CMAKE_MT | The path to the 'mt' tool. | +# | CMAKE_RC_COMPILER | The path to the 'rc' tool. | +# | CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION | The version of the Windows SDK to be used. | +# | MDMERGE_TOOL | The path to the 'mdmerge' tool. | +# | MIDL_COMPILER | The path to the 'midl' compiler. | +# | WINDOWS_KITS_BIN_PATH | The path to the folder containing the Windows Kits binaries. | +# | WINDOWS_KITS_INCLUDE_PATH | The path to the folder containing the Windows Kits include files. | +# | WINDOWS_KITS_LIB_PATH | The path to the folder containing the Windows Kits library files. | +# | WINDOWS_KITS_REFERENCES_PATH | The path to the folder containing the Windows Kits references. | +# +include_guard() + +if(NOT CMAKE_SYSTEM_VERSION) + set(CMAKE_SYSTEM_VERSION ${CMAKE_HOST_SYSTEM_VERSION}) +endif() + +if(NOT CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE) + if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL ARM64) + set(CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE arm64) + else() + set(CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE x64) + endif() +endif() + +if(NOT CMAKE_WINDOWS_KITS_10_DIR) + get_filename_component(CMAKE_WINDOWS_KITS_10_DIR "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\v10.0;InstallationFolder]" ABSOLUTE CACHE) + if ("${CMAKE_WINDOWS_KITS_10_DIR}" STREQUAL "/registry") + unset(CMAKE_WINDOWS_KITS_10_DIR) + endif() +endif() + +if(NOT CMAKE_WINDOWS_KITS_10_DIR) + message(FATAL_ERROR "Unable to find an installed Windows SDK, and one wasn't specified.") +endif() + +# If a CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION wasn't specified, find the highest installed version that is no higher +# than the host version +if(NOT CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION) + file(GLOB WINDOWS_KITS_VERSIONS RELATIVE "${CMAKE_WINDOWS_KITS_10_DIR}/lib" "${CMAKE_WINDOWS_KITS_10_DIR}/lib/*") + list(FILTER WINDOWS_KITS_VERSIONS INCLUDE REGEX "10\\.0\\.") + list(SORT WINDOWS_KITS_VERSIONS COMPARE NATURAL ORDER DESCENDING) + while(WINDOWS_KITS_VERSIONS) + list(POP_FRONT WINDOWS_KITS_VERSIONS CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION) + if(NOT CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION_MAXIMUM) + message(VERBOSE "Windows.Kits: Defaulting version: ${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}") + break() + endif() + + if(CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION VERSION_LESS_EQUAL CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION_MAXIMUM) + message(VERBOSE "Windows.Kits: Choosing version: ${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}") + break() + endif() + + message(VERBOSE "Windows.Kits: Not suitable: ${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}") + set(CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION) + endwhile() +endif() + +if(NOT CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION) + message(FATAL_ERROR "A Windows SDK could not be found.") +endif() + +set(WINDOWS_KITS_BIN_PATH "${CMAKE_WINDOWS_KITS_10_DIR}/bin/${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}" CACHE PATH "" FORCE) +set(WINDOWS_KITS_INCLUDE_PATH "${CMAKE_WINDOWS_KITS_10_DIR}/include/${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}" CACHE PATH "" FORCE) +set(WINDOWS_KITS_LIB_PATH "${CMAKE_WINDOWS_KITS_10_DIR}/lib/${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}" CACHE PATH "" FORCE) +set(WINDOWS_KITS_REFERENCES_PATH "${CMAKE_WINDOWS_KITS_10_DIR}/References" CACHE PATH "" FORCE) +set(WINDOWS_KITS_PLATFORM_PATH "${CMAKE_WINDOWS_KITS_10_DIR}/Platforms/UAP/${CMAKE_SYSTEM_VERSION}/Platform.xml" CACHE PATH "" FORCE) + +if(NOT EXISTS ${WINDOWS_KITS_BIN_PATH}) + message(FATAL_ERROR "Windows SDK ${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION} cannot be found: Folder '${WINDOWS_KITS_BIN_PATH}' does not exist.") +endif() + +if(NOT EXISTS ${WINDOWS_KITS_INCLUDE_PATH}) + message(FATAL_ERROR "Windows SDK ${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION} cannot be found: Folder '${WINDOWS_KITS_INCLUDE_PATH}' does not exist.") +endif() + +if(NOT EXISTS ${WINDOWS_KITS_LIB_PATH}) + message(FATAL_ERROR "Windows SDK ${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION} cannot be found: Folder '${WINDOWS_KITS_LIB_PATH}' does not exist.") +endif() + +set(CMAKE_MT "${WINDOWS_KITS_BIN_PATH}/${CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE}/mt.exe") +set(CMAKE_RC_COMPILER_INIT "${WINDOWS_KITS_BIN_PATH}/${CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE}/rc.exe") +set(CMAKE_RC_FLAGS_INIT "/nologo") + +set(MIDL_COMPILER "${WINDOWS_KITS_BIN_PATH}/${CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE}/midl.exe") +set(MDMERGE_TOOL "${WINDOWS_KITS_BIN_PATH}/${CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE}/mdmerge.exe") + +# Windows SDK +if(CMAKE_SYSTEM_PROCESSOR STREQUAL AMD64) + set(WINDOWS_KITS_TARGET_ARCHITECTURE x64) +elseif((CMAKE_SYSTEM_PROCESSOR STREQUAL ARM) + OR (CMAKE_SYSTEM_PROCESSOR STREQUAL ARM64) + OR (CMAKE_SYSTEM_PROCESSOR STREQUAL X86)) + set(WINDOWS_KITS_TARGET_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR}) +elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL x64) + message(WARNING "CMAKE_SYSTEM_PROCESSOR should be 'AMD64', not 'x64'. WindowsToolchain will stop recognizing 'x64' in a future release.") + set(WINDOWS_KITS_TARGET_ARCHITECTURE x64) +elseif((CMAKE_SYSTEM_PROCESSOR STREQUAL arm) + OR (CMAKE_SYSTEM_PROCESSOR STREQUAL arm64) + OR (CMAKE_SYSTEM_PROCESSOR STREQUAL x86)) + message(WARNING "CMAKE_SYSTEM_PROCESSOR (${CMAKE_SYSTEM_PROCESSOR}) should be upper-case. WindowsToolchain will stop recognizing non-upper-case forms in a future release.") + set(WINDOWS_KITS_TARGET_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR}) +else() + message(FATAL_ERROR "Unable identify Windows Kits architecture for CMAKE_SYSTEM_PROCESSOR ${CMAKE_SYSTEM_PROCESSOR}") +endif() + +foreach(LANG C CXX RC ASM_MASM) + list(APPEND CMAKE_${LANG}_STANDARD_INCLUDE_DIRECTORIES "${WINDOWS_KITS_INCLUDE_PATH}/ucrt") + list(APPEND CMAKE_${LANG}_STANDARD_INCLUDE_DIRECTORIES "${WINDOWS_KITS_INCLUDE_PATH}/shared") + list(APPEND CMAKE_${LANG}_STANDARD_INCLUDE_DIRECTORIES "${WINDOWS_KITS_INCLUDE_PATH}/um") + list(APPEND CMAKE_${LANG}_STANDARD_INCLUDE_DIRECTORIES "${WINDOWS_KITS_INCLUDE_PATH}/winrt") + list(APPEND CMAKE_${LANG}_STANDARD_INCLUDE_DIRECTORIES "${WINDOWS_KITS_INCLUDE_PATH}/cppwinrt") +endforeach() + +link_directories("${WINDOWS_KITS_LIB_PATH}/ucrt/${WINDOWS_KITS_TARGET_ARCHITECTURE}") +link_directories("${WINDOWS_KITS_LIB_PATH}/um/${WINDOWS_KITS_TARGET_ARCHITECTURE}") +link_directories("${WINDOWS_KITS_REFERENCES_PATH}/${WINDOWS_KITS_TARGET_ARCHITECTURE}") diff --git a/cmake/toolchains/Windows.MSVC.toolchain.cmake b/cmake/toolchains/Windows.MSVC.toolchain.cmake new file mode 100644 index 0000000..7edab8e --- /dev/null +++ b/cmake/toolchains/Windows.MSVC.toolchain.cmake @@ -0,0 +1,279 @@ +#---------------------------------------------------------------------------------------------------------------------- +# MIT License +# +# Copyright (c) 2021 Mark Schofield +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +#---------------------------------------------------------------------------------------------------------------------- +# +# This CMake toolchain file configures a CMake, non-'Visual Studio Generator' build to use +# the MSVC compilers and tools. +# +# The following variables can be used to configure the behavior of this toolchain file: +# +# | CMake Variable | Description | +# |---------------------------------------------|--------------------------------------------------------------------------------------------------------------------------| +# | CMAKE_SYSTEM_PROCESSOR | The processor to compiler for. One of 'X86', 'AMD64', 'ARM', 'ARM64'. Defaults to ${CMAKE_HOST_SYSTEM_PROCESSOR}. | +# | CMAKE_SYSTEM_VERSION | The version of the operating system for which CMake is to build. Defaults to the host version. | +# | CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE | The architecture of the tooling to use. Defaults to 'arm64' on ARM64 systems, otherwise 'x64'. | +# | CMAKE_VS_PRODUCTS | One or more Visual Studio Product IDs to consider. Defaults to '*' | +# | CMAKE_VS_VERSION_PRERELEASE | Whether 'prerelease' versions of Visual Studio should be considered. Defaults to 'OFF' | +# | CMAKE_VS_VERSION_RANGE | A verson range for VS instances to find. For example, '[16.0,17.0)' will find versions '16.*'. Defaults to '[16.0,17.0)' | +# | CMAKE_WINDOWS_KITS_10_DIR | The location of the root of the Windows Kits 10 directory. | +# | TOOLCHAIN_UPDATE_PROGRAM_PATH | Whether the toolchain should update CMAKE_PROGRAM_PATH. Defaults to 'ON'. | +# | TOOLCHAIN_ADD_VS_NINJA_PATH | Whether the toolchain should add the path to the VS Ninja to the CMAKE_SYSTEM_PROGRAM_PATH. Defaults to 'ON'. | +# | VS_EXPERIMENTAL_MODULE | Whether experimental module support should be enabled. | +# | VS_INSTALLATION_PATH | The location of the root of the Visual Studio installation. If not specified VSWhere will be used to search for one. | +# | VS_PLATFORM_TOOLSET_VERSION | The version of the MSVC toolset to use. For example, 14.29.30133. Defaults to the highest available. | +# | VS_USE_SPECTRE_MITIGATION_ATLMFC_RUNTIME | Whether the compiler should link with the ATLMFC runtime that uses 'Spectre' mitigations. Defaults to 'OFF'. | +# | VS_USE_SPECTRE_MITIGATION_RUNTIME | Whether the compiler should link with a runtime that uses 'Spectre' mitigations. Defaults to 'OFF'. | +# +# The toolchain file will set the following variables: +# +# | CMake Variable | Description | +# |---------------------------------------------|-------------------------------------------------------------------------------------------------------| +# | CMAKE_C_COMPILER | The path to the C compiler to use. | +# | CMAKE_CXX_COMPILER | The path to the C++ compiler to use. | +# | CMAKE_MT | The path to the 'mt.exe' tool to use. | +# | CMAKE_RC_COMPILER | The path tp the 'rc.exe' tool to use. | +# | CMAKE_SYSTEM_NAME | "Windows", when cross-compiling | +# | CMAKE_VS_PLATFORM_TOOLSET_VERSION | The version of the MSVC toolset being used - e.g. 14.29.30133. | +# | WIN32 | 1 | +# | MSVC | 1 | +# | MSVC_VERSION | The '' version of the C++ compiler being used. For example, '1929' | +# +# Other configuration: +# +# * If the 'CMAKE_CUDA_COMPILER' is set, and 'CMAKE_CUDA_HOST_COMPILER' is not set, and ENV{CUDAHOSTCXX} not defined +# then 'CMAKE_CUDA_HOST_COMPILER' is set to the value of 'CMAKE_CXX_COMPILER'. +# +# Resources: +# +# +cmake_minimum_required(VERSION 3.20) + +include_guard() + +# If `CMAKE_HOST_SYSTEM_NAME` is not 'Windows', there's nothing to do. +if(NOT (CMAKE_HOST_SYSTEM_NAME STREQUAL Windows)) + return() +endif() + +option(TOOLCHAIN_UPDATE_PROGRAM_PATH "Whether the toolchain should update CMAKE_PROGRAM_PATH." ON) +option(TOOLCHAIN_ADD_VS_NINJA_PATH "Whether the toolchain should add the path to the VS Ninja to the CMAKE_SYSTEM_PROGRAM_PATH." ON) + +set(UNUSED ${CMAKE_TOOLCHAIN_FILE}) # Note: only to prevent cmake unused variable warninig +list(APPEND CMAKE_TRY_COMPILE_PLATFORM_VARIABLES + CMAKE_SYSTEM_PROCESSOR + CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE + CMAKE_VS_PRODUCTS + CMAKE_VS_VERSION_PRERELEASE + CMAKE_VS_VERSION_RANGE + VS_INSTALLATION_PATH + VS_INSTALLATION_VERSION + VS_PLATFORM_TOOLSET_VERSION +) +set(WIN32 1) +set(MSVC 1) + +include("${CMAKE_CURRENT_LIST_DIR}/VSWhere.cmake") + +# If `CMAKE_SYSTEM_PROCESSOR` isn't set, default to `CMAKE_HOST_SYSTEM_PROCESSOR` +if(NOT CMAKE_SYSTEM_PROCESSOR) + set(CMAKE_SYSTEM_PROCESSOR ${CMAKE_HOST_SYSTEM_PROCESSOR}) +endif() + +# If `CMAKE_SYSTEM_PROCESSOR` is not equal to `CMAKE_HOST_SYSTEM_PROCESSOR`, this is cross-compilation. +# CMake expects `CMAKE_SYSTEM_NAME` to be set to reflect cross-compilation. +if(NOT (CMAKE_SYSTEM_PROCESSOR STREQUAL ${CMAKE_HOST_SYSTEM_PROCESSOR})) + set(CMAKE_SYSTEM_NAME Windows) +endif() + +if(NOT CMAKE_VS_VERSION_RANGE) + set(CMAKE_VS_VERSION_RANGE "[16.0,)") +endif() + +if(NOT CMAKE_VS_VERSION_PRERELEASE) + set(CMAKE_VS_VERSION_PRERELEASE OFF) +endif() + +if(NOT CMAKE_VS_PRODUCTS) + set(CMAKE_VS_PRODUCTS "*") +endif() + +if(NOT CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE) + if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL ARM64) + set(CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE arm64) + else() + set(CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE x64) + endif() +endif() + +if(NOT VS_USE_SPECTRE_MITIGATION_RUNTIME) + set(VS_USE_SPECTRE_MITIGATION_RUNTIME OFF) +endif() + +# Find Visual Studio +# +if(NOT VS_INSTALLATION_PATH) + findVisualStudio( + VERSION ${CMAKE_VS_VERSION_RANGE} + PRERELEASE ${CMAKE_VS_VERSION_PRERELEASE} + PRODUCTS ${CMAKE_VS_PRODUCTS} + PROPERTIES + installationVersion VS_INSTALLATION_VERSION + installationPath VS_INSTALLATION_PATH + ) +endif() + +message(VERBOSE "VS_INSTALLATION_VERSION = ${VS_INSTALLATION_VERSION}") +message(VERBOSE "VS_INSTALLATION_PATH = ${VS_INSTALLATION_PATH}") + +if(NOT VS_INSTALLATION_PATH) + message(FATAL_ERROR "Unable to find Visual Studio") +endif() + +cmake_path(NORMAL_PATH VS_INSTALLATION_PATH) + +set(VS_MSVC_PATH "${VS_INSTALLATION_PATH}/VC/Tools/MSVC") + +# Use 'VS_PLATFORM_TOOLSET_VERSION' to resolve 'CMAKE_VS_PLATFORM_TOOLSET_VERSION' +# +if(NOT VS_PLATFORM_TOOLSET_VERSION) + if(VS_TOOLSET_VERSION) + message(WARNING "Old versions of WindowsToolchain incorrectly used 'VS_TOOLSET_VERSION' to specify the VS toolset version. This functionality is being deprecated - please use 'VS_PLATFORM_TOOLSET_VERSION' instead.") + set(VS_PLATFORM_TOOLSET_VERSION ${VS_TOOLSET_VERSION}) + else() + file(GLOB VS_PLATFORM_TOOLSET_VERSIONS RELATIVE ${VS_MSVC_PATH} ${VS_MSVC_PATH}/*) + list(SORT VS_PLATFORM_TOOLSET_VERSIONS COMPARE NATURAL ORDER DESCENDING) + list(POP_FRONT VS_PLATFORM_TOOLSET_VERSIONS VS_PLATFORM_TOOLSET_VERSION) + unset(VS_PLATFORM_TOOLSET_VERSIONS) + endif() +endif() + +set(CMAKE_VS_PLATFORM_TOOLSET_VERSION ${VS_PLATFORM_TOOLSET_VERSION}) +set(VS_TOOLSET_PATH "${VS_INSTALLATION_PATH}/VC/Tools/MSVC/${CMAKE_VS_PLATFORM_TOOLSET_VERSION}") + +# Set the tooling variables, include_directories and link_directories +# + +# Map CMAKE_SYSTEM_PROCESSOR values to CMAKE_VS_PLATFORM_TOOLSET_ARCHITECTURE that identifies the tools that should +# be used to produce code for the CMAKE_SYSTEM_PROCESSOR. +if(CMAKE_SYSTEM_PROCESSOR STREQUAL AMD64) + set(CMAKE_VS_PLATFORM_TOOLSET_ARCHITECTURE x64) +elseif((CMAKE_SYSTEM_PROCESSOR STREQUAL ARM) + OR (CMAKE_SYSTEM_PROCESSOR STREQUAL ARM64) + OR (CMAKE_SYSTEM_PROCESSOR STREQUAL X86)) + set(CMAKE_VS_PLATFORM_TOOLSET_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR}) +elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL x64) + message(WARNING "CMAKE_SYSTEM_PROCESSOR should be 'AMD64', not 'x64'. WindowsToolchain will stop recognizing 'x64' in a future release.") + set(CMAKE_VS_PLATFORM_TOOLSET_ARCHITECTURE x64) +elseif((CMAKE_SYSTEM_PROCESSOR STREQUAL arm) + OR (CMAKE_SYSTEM_PROCESSOR STREQUAL arm64) + OR (CMAKE_SYSTEM_PROCESSOR STREQUAL x86)) + message(WARNING "CMAKE_SYSTEM_PROCESSOR (${CMAKE_SYSTEM_PROCESSOR}) should be upper-case. WindowsToolchain will stop recognizing non-upper-case forms in a future release.") + set(CMAKE_VS_PLATFORM_TOOLSET_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR}) +else() + message(FATAL_ERROR "Unable identify compiler architecture for CMAKE_SYSTEM_PROCESSOR ${CMAKE_SYSTEM_PROCESSOR}") +endif() + +set(CMAKE_CXX_COMPILER "${VS_TOOLSET_PATH}/bin/Host${CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE}/${CMAKE_VS_PLATFORM_TOOLSET_ARCHITECTURE}/cl.exe") +set(CMAKE_C_COMPILER "${VS_TOOLSET_PATH}/bin/Host${CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE}/${CMAKE_VS_PLATFORM_TOOLSET_ARCHITECTURE}/cl.exe") + +if(CMAKE_SYSTEM_PROCESSOR STREQUAL ARM) + set(CMAKE_CXX_FLAGS_INIT "${CMAKE_CXX_FLAGS_INIT} /EHsc") +elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL arm) + message(WARNING "CMAKE_SYSTEM_PROCESSOR (${CMAKE_SYSTEM_PROCESSOR}) should be upper-case. WindowsToolchain will stop recognizing non-upper-case forms in a future release.") + set(CMAKE_CXX_FLAGS_INIT "${CMAKE_CXX_FLAGS_INIT} /EHsc") +endif() + +# Compiler +foreach(LANG C CXX RC) + list(APPEND CMAKE_${LANG}_STANDARD_INCLUDE_DIRECTORIES "${VS_TOOLSET_PATH}/ATLMFC/include") + list(APPEND CMAKE_${LANG}_STANDARD_INCLUDE_DIRECTORIES "${VS_TOOLSET_PATH}/include") +endforeach() + +foreach(LANG C CXX) + # Add '/X': Do not add %INCLUDE% to include search path + set(CMAKE_${LANG}_FLAGS_INIT "${CMAKE_${LANG}_FLAGS_INIT} /X") +endforeach() + +if(VS_USE_SPECTRE_MITIGATION_ATLMFC_RUNTIME) + # Ensure that the necessary folder and files are present before adding the 'link_directories' + toolchain_validate_vs_files( + DESCRIPTION "ATLMFC Spectre libraries" + FOLDER "${VS_TOOLSET_PATH}/ATLMFC/lib/spectre/${CMAKE_VS_PLATFORM_TOOLSET_ARCHITECTURE}" + FILES + atls.lib + ) + link_directories("${VS_TOOLSET_PATH}/ATLMFC/lib/spectre/${CMAKE_VS_PLATFORM_TOOLSET_ARCHITECTURE}") +else() + link_directories("${VS_TOOLSET_PATH}/ATLMFC/lib/${CMAKE_VS_PLATFORM_TOOLSET_ARCHITECTURE}") +endif() + +if(VS_USE_SPECTRE_MITIGATION_RUNTIME) + # Ensure that the necessary folder and files are present before adding the 'link_directories' + toolchain_validate_vs_files( + DESCRIPTION "Spectre libraries" + FOLDER "${VS_TOOLSET_PATH}/lib/spectre/${CMAKE_VS_PLATFORM_TOOLSET_ARCHITECTURE}" + FILES + msvcrt.lib vcruntime.lib vcruntimed.lib + ) + link_directories("${VS_TOOLSET_PATH}/lib/spectre/${CMAKE_VS_PLATFORM_TOOLSET_ARCHITECTURE}") +else() + link_directories("${VS_TOOLSET_PATH}/lib/${CMAKE_VS_PLATFORM_TOOLSET_ARCHITECTURE}") +endif() + +link_directories("${VS_TOOLSET_PATH}/lib/x86/store/references") + +# Module support +if(VS_EXPERIMENTAL_MODULE) + set(CMAKE_CXX_FLAGS_INIT "${CMAKE_CXX_FLAGS_INIT} /experimental:module") + set(CMAKE_CXX_FLAGS_INIT "${CMAKE_CXX_FLAGS_INIT} /stdIfcDir \"${VS_TOOLSET_PATH}/ifc/${CMAKE_VS_PLATFORM_TOOLSET_ARCHITECTURE}\"") +endif() + +# Windows Kits +include("${CMAKE_CURRENT_LIST_DIR}/Windows.Kits.cmake") + +# CUDA support +# +# If a CUDA compiler is specified, and a host compiler wasn't specified, set 'CMAKE_CXX_COMPILER' +# as the host compiler. +if(CMAKE_CUDA_COMPILER) + if((NOT CMAKE_CUDA_HOST_COMPILER) AND (NOT DEFINED ENV{CUDAHOSTCXX})) + set(CMAKE_CUDA_HOST_COMPILER "${CMAKE_CXX_COMPILER}") + endif() +endif() + +# If 'TOOLCHAIN_UPDATE_PROGRAM_PATH' is selected, update CMAKE_PROGRAM_PATH. +# +if(TOOLCHAIN_UPDATE_PROGRAM_PATH) + list(APPEND CMAKE_PROGRAM_PATH "${VS_TOOLSET_PATH}/bin/Host${CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE}/${CMAKE_VS_PLATFORM_TOOLSET_ARCHITECTURE}") + list(APPEND CMAKE_PROGRAM_PATH "${WINDOWS_KITS_BIN_PATH}/${CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE}") +endif() + +# If the CMAKE_GENERATOR is Ninja-based, and the path to the Visual Studio-installed Ninja is present, add it to +# the CMAKE_SYSTEM_PROGRAM_PATH. 'find_program' searches CMAKE_SYSTEM_PROGRAM_PATH after the environment path, so +# an installed Ninja would be preferred. +# +if( (CMAKE_GENERATOR MATCHES "^Ninja") AND + (EXISTS "${VS_INSTALLATION_PATH}/Common7/IDE/CommonExtensions/Microsoft/CMake/Ninja") AND + (TOOLCHAIN_ADD_VS_NINJA_PATH)) + list(APPEND CMAKE_SYSTEM_PROGRAM_PATH "${VS_INSTALLATION_PATH}/Common7/IDE/CommonExtensions/Microsoft/CMake/Ninja") +endif() From 41743ae832bd7d6bcf612d8b5abbddb003b55917 Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Mon, 17 Feb 2025 01:47:12 -0800 Subject: [PATCH 50/59] Fix boolean operator casing. --- cmake/build/GCCClangDebug.cmake | 2 +- cmake/build/GCCClangRelease.cmake | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/build/GCCClangDebug.cmake b/cmake/build/GCCClangDebug.cmake index d04935a..27ce4c3 100644 --- a/cmake/build/GCCClangDebug.cmake +++ b/cmake/build/GCCClangDebug.cmake @@ -30,7 +30,7 @@ list ( # capture. ) -if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" or +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_VS_PLATFORM_TOOLSET}" STREQUAL "ClangCL") # GCC doesn't support -Wno-global-constructors yet, so only add it diff --git a/cmake/build/GCCClangRelease.cmake b/cmake/build/GCCClangRelease.cmake index fe0d39f..476fce0 100644 --- a/cmake/build/GCCClangRelease.cmake +++ b/cmake/build/GCCClangRelease.cmake @@ -29,7 +29,7 @@ list ( # capture. ) -if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" or +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_VS_PLATFORM_TOOLSET}" STREQUAL "ClangCL") # GCC doesn't support -Wno-global-constructors yet, so only add it From 828fa48e638c4a9d8724b1564fce818c945acb49 Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Mon, 17 Feb 2025 02:00:56 -0800 Subject: [PATCH 51/59] Fix issues uncovered in finishing presets for Windows builds Add noexcept to constructors and operators that should not throw exceptions. Apply const to getLastRuntime function. Add no_destroy template type that replaces the clang::no_destroy attribute since it is not implemented in GCC or MSVC. There are some downsides, but they don't really bother me given the types it's applied to and the operations applied to those statics. For more info, see: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1247r0.html Applied some fixes based on this new level of indirection (calls to no_destroy::get). --- include/internal/TestCPPTestCase.h | 18 ++-- include/internal/TestCPPUtil.h | 10 ++ src/TestCPPTestCase.cpp | 154 +++++++++++++++++------------ 3 files changed, 109 insertions(+), 73 deletions(-) diff --git a/include/internal/TestCPPTestCase.h b/include/internal/TestCPPTestCase.h index 0d39113..dc2e5f7 100644 --- a/include/internal/TestCPPTestCase.h +++ b/include/internal/TestCPPTestCase.h @@ -150,7 +150,7 @@ namespace TestCPP { * TestCase. * @param o Move everything from this TestCase into the new one. */ - TestCase (TestCase&& o); + TestCase (TestCase&& o) noexcept; /** * @brief Copy a TestCase into another TestCase. @@ -166,7 +166,7 @@ namespace TestCPP { * @return A reference to the TestCase that everything from the * old TestCase was moved into. */ - TestCase& operator= (TestCase&& rhs); + TestCase& operator= (TestCase&& rhs) noexcept; /** * @brief Destroy a TestCase object. @@ -253,7 +253,7 @@ namespace TestCPP { * @return The duration of the last run of this TestCase in * nanoseconds. */ - long long getLastRuntime (); + long long getLastRuntime () const; private: bool notifyTestPassed = false; @@ -321,17 +321,17 @@ namespace TestCPP { static atomic_int logCaptureCasesDestroyed; static atomic_int stderrCaptureCasesDestroyed; - static unique_ptr + static Util::no_destroy> stdoutBuffer; - static unique_ptr + static Util::no_destroy> clogBuffer; - static unique_ptr + static Util::no_destroy> stderrBuffer; - static unique_ptr + static Util::no_destroy> stdoutOriginal; - static unique_ptr + static Util::no_destroy> clogOriginal; - static unique_ptr + static Util::no_destroy> stderrOriginal; /** diff --git a/include/internal/TestCPPUtil.h b/include/internal/TestCPPUtil.h index 0601102..256c450 100644 --- a/include/internal/TestCPPUtil.h +++ b/include/internal/TestCPPUtil.h @@ -100,6 +100,16 @@ namespace TestCPP { */ namespace Util { + /** + * This type is for suppressing exit-time destructors for statics. + */ + template class no_destroy { + alignas(T) unsigned char data[sizeof(T)]; + public: + template no_destroy(Ts&&... ts) { new (data) T(std::forward(ts)...); } + T& get() { return *reinterpret_cast(data); } + }; + /** * @brief Log a message that will only be output when debug * logging is enabled. diff --git a/src/TestCPPTestCase.cpp b/src/TestCPPTestCase.cpp index 7f9d28d..1c7dc6c 100644 --- a/src/TestCPPTestCase.cpp +++ b/src/TestCPPTestCase.cpp @@ -40,6 +40,8 @@ For more information, please refer to #include "internal/TestCPPUtil.h" using TestCPP::Util::debugLog; +using TestCPP::Util::no_destroy; + using std::cerr; using std::clog; using std::cout; @@ -66,35 +68,47 @@ namespace TestCPP { atomic_int TestCase::logCaptureCasesDestroyed; atomic_int TestCase::stderrCaptureCasesDestroyed; - [[clang::no_destroy]] unique_ptr + no_destroy> TestCase::stdoutBuffer = - unique_ptr( - nullptr, [](stringstream*){} + no_destroy>( + unique_ptr( + nullptr, [](stringstream*){} + ) ); - [[clang::no_destroy]] unique_ptr + no_destroy> TestCase::clogBuffer = - unique_ptr( - nullptr, [](stringstream*){} + no_destroy>( + unique_ptr( + nullptr, [](stringstream*){} + ) ); - [[clang::no_destroy]] unique_ptr + no_destroy> TestCase::stderrBuffer = - unique_ptr( - nullptr, [](stringstream*){} + no_destroy>( + unique_ptr( + nullptr, [](stringstream*){} + ) ); - [[clang::no_destroy]] unique_ptr + no_destroy> TestCase::stdoutOriginal = - unique_ptr( - nullptr, [](streambuf*){} + no_destroy>( + unique_ptr( + nullptr, [](streambuf*){} + ) ); - [[clang::no_destroy]] unique_ptr + no_destroy> TestCase::clogOriginal = - unique_ptr( - nullptr, [](streambuf*){} + no_destroy>( + unique_ptr( + nullptr, [](streambuf*){} + ) ); - [[clang::no_destroy]] unique_ptr + no_destroy> TestCase::stderrOriginal = - unique_ptr( - nullptr, [](streambuf*){} + no_destroy>( + unique_ptr( + nullptr, [](streambuf*){} + ) ); TestCase::TestCase (TestObjName&& name, @@ -153,7 +167,7 @@ namespace TestCPP { this->test = o.test; } - TestCase::TestCase (TestCase&& o) { + TestCase::TestCase (TestCase&& o) noexcept { this->outCompareOption(std::move(o.option)); this->setNotifyPassed(std::move(o.notifyTestPassed)); @@ -179,38 +193,38 @@ namespace TestCPP { } TestCase::~TestCase () { - if (TestCase::stdoutBuffer != nullptr) + if (TestCase::stdoutBuffer.get() != nullptr) { if (TestCase::stdoutCaptureCasesDestroyed == TestCase::stdoutCaptureCasesConstructed - 1) { - cout.rdbuf(TestCase::stdoutOriginal.release()); - delete TestCase::stdoutBuffer.get(); - TestCase::stdoutBuffer = nullptr; + cout.rdbuf(TestCase::stdoutOriginal.get().release()); + delete TestCase::stdoutBuffer.get().get(); + TestCase::stdoutBuffer.get() = nullptr; } TestCase::stdoutCaptureCasesDestroyed += 1; } - if (TestCase::clogBuffer != nullptr) + if (TestCase::clogBuffer.get() != nullptr) { if (TestCase::logCaptureCasesDestroyed == TestCase::logCaptureCasesConstructed - 1) { - clog.rdbuf(TestCase::clogOriginal.release()); - delete TestCase::clogBuffer.get(); - TestCase::clogBuffer = nullptr; + clog.rdbuf(TestCase::clogOriginal.get().release()); + delete TestCase::clogBuffer.get().get(); + TestCase::clogBuffer.get() = nullptr; } TestCase::logCaptureCasesDestroyed += 1; } - if (TestCase::stderrBuffer != nullptr) + if (TestCase::stderrBuffer.get() != nullptr) { if (TestCase::stderrCaptureCasesDestroyed == TestCase::stderrCaptureCasesConstructed - 1) { - cerr.rdbuf(TestCase::stderrOriginal.release()); - delete TestCase::stderrBuffer.get(); - TestCase::stderrBuffer = nullptr; + cerr.rdbuf(TestCase::stderrOriginal.get().release()); + delete TestCase::stderrBuffer.get().get(); + TestCase::stderrBuffer.get() = nullptr; } TestCase::stderrCaptureCasesDestroyed += 1; @@ -244,7 +258,7 @@ namespace TestCPP { return *this; } - TestCase& TestCase::operator= (TestCase&& rhs) { + TestCase& TestCase::operator= (TestCase&& rhs) noexcept { this->outCompareOption(std::move(rhs.option)); this->setNotifyPassed(std::move(rhs.notifyTestPassed)); @@ -271,7 +285,7 @@ namespace TestCPP { return *this; } - long long TestCase::getLastRuntime () { + long long TestCase::getLastRuntime () const { return this->lastRunTime; } @@ -290,9 +304,9 @@ namespace TestCPP { void TestCase::logTestFailure (string reason) { unique_ptr logStream = nullptr; - if (this->clogOriginal != nullptr) { + if (this->clogOriginal.get() != nullptr) { logStream = unique_ptr( - new ostream(this->clogOriginal.get()) + new ostream(this->clogOriginal.get().get()) ); } else { @@ -301,7 +315,7 @@ namespace TestCPP { logFailure(*logStream, reason); - if (this->clogOriginal != nullptr) { + if (this->clogOriginal.get() != nullptr) { logStream->flush(); // If someone is looking for something in the message, @@ -364,14 +378,18 @@ namespace TestCPP { { TestCase::stdoutCaptureCasesConstructed += 1; TestCase::stdoutBuffer = - unique_ptr( - new stringstream(), [](stringstream *) {} + no_destroy>( + unique_ptr( + new stringstream(), [](stringstream *) {} + ) ); TestCase::stdoutOriginal = - unique_ptr( - cout.rdbuf(), [](streambuf *) {} + no_destroy>( + unique_ptr( + cout.rdbuf(), [](streambuf *) {} + ) ); - cout.rdbuf(TestCase::stdoutBuffer->rdbuf()); + cout.rdbuf(TestCase::stdoutBuffer.get()->rdbuf()); } else { TestCase::stdoutCaptureCasesConstructed += 1; @@ -384,14 +402,18 @@ namespace TestCPP { { TestCase::logCaptureCasesConstructed += 1; TestCase::clogBuffer = - unique_ptr( - new stringstream(), [](stringstream *) {} + no_destroy>( + unique_ptr( + new stringstream(), [](stringstream *) {} + ) ); TestCase::clogOriginal = - unique_ptr( - clog.rdbuf(), [](streambuf *) {} + no_destroy>( + unique_ptr( + clog.rdbuf(), [](streambuf *) {} + ) ); - clog.rdbuf(TestCase::clogBuffer->rdbuf()); + clog.rdbuf(TestCase::clogBuffer.get()->rdbuf()); } else { TestCase::logCaptureCasesConstructed += 1; @@ -404,14 +426,18 @@ namespace TestCPP { { TestCase::stderrCaptureCasesConstructed += 1; TestCase::stderrBuffer = - unique_ptr( - new stringstream(), [](stringstream *) {} + no_destroy>( + unique_ptr( + new stringstream(), [](stringstream *) {} + ) ); TestCase::stderrOriginal = - unique_ptr( - cerr.rdbuf(), [](streambuf *) {} + no_destroy>( + unique_ptr( + cerr.rdbuf(), [](streambuf *) {} + ) ); - cerr.rdbuf(TestCase::stderrBuffer->rdbuf()); + cerr.rdbuf(TestCase::stderrBuffer.get()->rdbuf()); } else { TestCase::stderrCaptureCasesConstructed += 1; @@ -433,35 +459,35 @@ namespace TestCPP { } void TestCase::clearStdoutCapture () { - if (TestCase::stdoutBuffer) { - TestCase::stdoutBuffer->str(string()); + if (TestCase::stdoutBuffer.get()) { + TestCase::stdoutBuffer.get()->str(string()); } } void TestCase::clearLogCapture () { - if (TestCase::clogBuffer) { - TestCase::clogBuffer->str(string()); + if (TestCase::clogBuffer.get()) { + TestCase::clogBuffer.get()->str(string()); } } void TestCase::clearStderrCapture () { - if (TestCase::stderrBuffer) { - TestCase::stderrBuffer->str(string()); + if (TestCase::stderrBuffer.get()) { + TestCase::stderrBuffer.get()->str(string()); } } bool TestCase::checkStdout (string against) { - return checkOutput(TestCase::stdoutBuffer->str(), + return checkOutput(TestCase::stdoutBuffer.get()->str(), against); } bool TestCase::checkLog (string against) { - return checkOutput(TestCase::clogBuffer->str(), + return checkOutput(TestCase::clogBuffer.get()->str(), against); } bool TestCase::checkStderr (string against) { - return checkOutput(TestCase::stderrBuffer->str(), + return checkOutput(TestCase::stderrBuffer.get()->str(), against); } @@ -478,8 +504,8 @@ namespace TestCPP { nomatch << TCPPStr::NEQUIV << TCPPStr::APOS; nomatch << against << TCPPStr::APOS; - if (this->clogOriginal != nullptr) { - ostream tmp(this->clogOriginal.get()); + if (this->clogOriginal.get() != nullptr) { + ostream tmp(this->clogOriginal.get().get()); tmp << nomatch.str() << endl; tmp.flush(); } @@ -500,8 +526,8 @@ namespace TestCPP { nomatch << TCPPStr::NCONTAIN << TCPPStr::APOS; nomatch << against << TCPPStr::APOS; - if (this->clogOriginal != nullptr) { - ostream tmp(this->clogOriginal.get()); + if (this->clogOriginal.get() != nullptr) { + ostream tmp(this->clogOriginal.get().get()); tmp << nomatch.str() << endl; tmp.flush(); } From 41fb5eb06e93c5925ae57c3a5fa14154fe9e62cc Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Mon, 17 Feb 2025 02:07:55 -0800 Subject: [PATCH 52/59] Qualify calls to std::move, remove using std::move. --- include/internal/TestCPPTestSuite.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/include/internal/TestCPPTestSuite.h b/include/internal/TestCPPTestSuite.h index 10950f5..545a193 100644 --- a/include/internal/TestCPPTestSuite.h +++ b/include/internal/TestCPPTestSuite.h @@ -48,7 +48,6 @@ using std::enable_if; using std::endl; using std::forward; using std::function; -using std::move; using std::runtime_error; using std::string; using std::streambuf; @@ -82,7 +81,7 @@ namespace TestCPP { typename enable_if::type) { this->testSuitePassedMessage = true; - this->setSuiteName(move(suiteName)); + this->setSuiteName(std::move(suiteName)); this->tests = vector(); } @@ -93,7 +92,7 @@ namespace TestCPP { template TestSuite (TestObjName&& suiteName, TestType ...tests) { this->testSuitePassedMessage = true; - this->setSuiteName(move(suiteName)); + this->setSuiteName(std::move(suiteName)); this->tests = vector(); this->addTests(tests...); @@ -124,7 +123,7 @@ namespace TestCPP { */ template void addTests (Test test, OtherTests ...tests) { - addTest(move(test)); + addTest(std::move(test)); addTests(tests...); } From 10cfc16fd5538021d6c21db8d969e0c0948c07a8 Mon Sep 17 00:00:00 2001 From: Jonathan Hyry <3676933+eljonny@users.noreply.github.com> Date: Mon, 17 Feb 2025 12:15:43 -0800 Subject: [PATCH 53/59] Update codecov.yml Fix up codecov ignores --- codecov.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/codecov.yml b/codecov.yml index 715130c..c65bd15 100644 --- a/codecov.yml +++ b/codecov.yml @@ -1,4 +1,4 @@ ignore: - - "include/tests.hpp" - - "src/main.cpp" - - "test/**" \ No newline at end of file + - "demo/** + - "test/**" + - "3rdparty/** From 8394f024e7f2dc79ee27a2139d3b57848f4da5e9 Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Mon, 17 Feb 2025 18:56:52 -0800 Subject: [PATCH 54/59] Removed obsolete/generated CodeLite files and duplicate license file. --- Makefile | 8 ---- TestFramework.mk | 118 ---------------------------------------------- TestFramework.txt | 1 - UNLICENSE | 24 ---------- 4 files changed, 151 deletions(-) delete mode 100644 Makefile delete mode 100644 TestFramework.mk delete mode 100644 TestFramework.txt delete mode 100644 UNLICENSE diff --git a/Makefile b/Makefile deleted file mode 100644 index 114f98f..0000000 --- a/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -.PHONY: clean All - -All: - @echo "----------Building project:[ TestFramework - Debug ]----------" - @"$(MAKE)" -f "TestFramework.mk" -clean: - @echo "----------Cleaning project:[ TestFramework - Debug ]----------" - @"$(MAKE)" -f "TestFramework.mk" clean diff --git a/TestFramework.mk b/TestFramework.mk deleted file mode 100644 index f66e224..0000000 --- a/TestFramework.mk +++ /dev/null @@ -1,118 +0,0 @@ -## -## Auto Generated makefile by CodeLite IDE -## any manual changes will be erased -## -## Debug -ProjectName :=TestFramework -ConfigurationName :=Debug -WorkspacePath :=/home/jhyry/Dropbox/CSU-Fullerton/C++Cert/C++Fundamentals/TestFramework -ProjectPath :=/home/jhyry/Dropbox/CSU-Fullerton/C++Cert/C++Fundamentals/TestFramework -IntermediateDirectory :=./Debug -OutDir := $(IntermediateDirectory) -CurrentFileName := -CurrentFilePath := -CurrentFileFullPath := -User :=Jonathan Hyry -Date :=09/03/24 -CodeLitePath :=/home/jhyry/.codelite -LinkerName :=/usr/bin/i586-linux-gnu-g++ -SharedObjectLinkerName :=/usr/bin/i586-linux-gnu-g++ -shared -fPIC -ObjectSuffix :=.o -DependSuffix :=.o.d -PreprocessSuffix :=.i -DebugSwitch :=-g -IncludeSwitch :=-I -LibrarySwitch :=-l -OutputSwitch :=-o -LibraryPathSwitch :=-L -PreprocessorSwitch :=-D -SourceSwitch :=-c -OutputFile :=$(IntermediateDirectory)/$(ProjectName) -Preprocessors := -ObjectSwitch :=-o -ArchiveOutputSwitch := -PreprocessOnlySwitch :=-E -ObjectsFileList :="TestFramework.txt" -PCHCompileFlags := -MakeDirCommand :=mkdir -p -LinkOptions := -O0 -IncludePath := $(IncludeSwitch). $(IncludeSwitch). -IncludePCH := -RcIncludePath := -Libs := -ArLibs := -LibPath := $(LibraryPathSwitch). $(LibraryPathSwitch). $(LibraryPathSwitch)Debug - -## -## Common variables -## AR, CXX, CC, AS, CXXFLAGS and CFLAGS can be overriden using an environment variables -## -AR := /usr/bin/i586-linux-gnu-ar rcu -CXX := /usr/bin/i586-linux-gnu-g++ -CC := /usr/bin/i586-linux-gnu-gcc -CXXFLAGS := -g -Wall $(Preprocessors) -CFLAGS := $(Preprocessors) -ASFLAGS := -AS := /usr/bin/i586-linux-gnu-as - - -## -## User defined environment variables -## -CodeLiteDir:=/usr/share/codelite -Objects0=$(IntermediateDirectory)/Test.cpp$(ObjectSuffix) $(IntermediateDirectory)/main.cpp$(ObjectSuffix) - - - -Objects=$(Objects0) - -## -## Main Build Targets -## -.PHONY: all clean PreBuild PrePreBuild PostBuild MakeIntermediateDirs -all: $(OutputFile) - -$(OutputFile): $(IntermediateDirectory)/.d $(Objects) - @$(MakeDirCommand) $(@D) - @echo "" > $(IntermediateDirectory)/.d - @echo $(Objects0) > $(ObjectsFileList) - $(LinkerName) $(OutputSwitch)$(OutputFile) @$(ObjectsFileList) $(LibPath) $(Libs) $(LinkOptions) - -MakeIntermediateDirs: - @test -d ./Debug || $(MakeDirCommand) ./Debug - - -$(IntermediateDirectory)/.d: - @test -d ./Debug || $(MakeDirCommand) ./Debug - -PreBuild: - - -## -## Objects -## -$(IntermediateDirectory)/Test.cpp$(ObjectSuffix): Test.cpp $(IntermediateDirectory)/Test.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/jhyry/Dropbox/CSU-Fullerton/C++Cert/C++Fundamentals/TestFramework/Test.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/Test.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/Test.cpp$(DependSuffix): Test.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/Test.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/Test.cpp$(DependSuffix) -MM Test.cpp - -$(IntermediateDirectory)/Test.cpp$(PreprocessSuffix): Test.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/Test.cpp$(PreprocessSuffix) Test.cpp - -$(IntermediateDirectory)/main.cpp$(ObjectSuffix): main.cpp $(IntermediateDirectory)/main.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/jhyry/Dropbox/CSU-Fullerton/C++Cert/C++Fundamentals/TestFramework/main.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/main.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/main.cpp$(DependSuffix): main.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/main.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/main.cpp$(DependSuffix) -MM main.cpp - -$(IntermediateDirectory)/main.cpp$(PreprocessSuffix): main.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/main.cpp$(PreprocessSuffix) main.cpp - - --include $(IntermediateDirectory)/*$(DependSuffix) -## -## Clean -## -clean: - $(RM) -r ./Debug/ - - diff --git a/TestFramework.txt b/TestFramework.txt deleted file mode 100644 index 4304079..0000000 --- a/TestFramework.txt +++ /dev/null @@ -1 +0,0 @@ -./Debug/Test.cpp.o ./Debug/main.cpp.o diff --git a/UNLICENSE b/UNLICENSE deleted file mode 100644 index 68a49da..0000000 --- a/UNLICENSE +++ /dev/null @@ -1,24 +0,0 @@ -This is free and unencumbered software released into the public domain. - -Anyone is free to copy, modify, publish, use, compile, sell, or -distribute this software, either in source code form or as a compiled -binary, for any purpose, commercial or non-commercial, and by any -means. - -In jurisdictions that recognize copyright laws, the author or authors -of this software dedicate any and all copyright interest in the -software to the public domain. We make this dedication for the benefit -of the public at large and to the detriment of our heirs and -successors. We intend this dedication to be an overt act of -relinquishment in perpetuity of all present and future rights to this -software under copyright law. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR -OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - -For more information, please refer to From 7803f9c79f4f6c86d763ddb34dcd0b36a1f96f34 Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Mon, 17 Feb 2025 19:00:04 -0800 Subject: [PATCH 55/59] Ignore the cppcheck checkers report file. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 0cc0e73..048d48f 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ test_package/build CMakeUserPresets.json /.vs out/ +**/cppcheck-checkers.report From 194b1fc51a19e8060924a751948207f794aa94f0 Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Mon, 17 Feb 2025 19:43:33 -0800 Subject: [PATCH 56/59] New CI workflows - build MSIs, added image resources, readme updates Added TXZ package to linux packing workflows. Added 7z package to multi-platform packing workflows. In static analysis workflow, ignore files in 3rdparty (Boost headers). Fix up cppcheck args for static analysis workflow with additional suppressions and flags that enhance and hone what it is checking for. Add WiX packing workflows (stacktrace-enabled and no-stacktraces) so MSI packages will now be part of the distribution; they're pretty rough right now, I need to do some design work on the BMPs, but they do work. With this comes a collection of image resources and an RTF-format version of the license to conform to the Windows Installer guidelines. Huge updates to the README.md: - Added badges for the WiX packing workflows - Formatting so the column width is always 72 characters or less - Added a section about building the project in Visual Studio 2022 - Elaborated on the structure of the CMake meta-build after some significant changes in previous commits a while ago where the README was not updated. - Code block formatting. - Made a separate section for static analysis of the project, and expanded on what cppcheck arguments are suggested after some experimentation about what gives the most thorough results. - Added information about what is produced in the base cpack configurations for Linux and Windows. - Added information about the new CPack configuration for WiX on Windows and how to run it to generate the WiX package (MSI file). - Added a subsection to the Development section that informs people what GitHub Actions CI workflows are implemented and what they do. Updated the CPack configurations in cmake/Packing.cmake: - Updated my email address because Google/GMail are not reliable as they are linked to space available in my Google Drive which can fluctuate wildly and sometimes is not available. - Added WIX configurations for MSI packaging: > Added product GUID > Added reference to the new LICENSE.rtf > Added reference to the new TestCPP icon > Added reference to the new Windows Installer progress banner > Added reference to the new Windows Installer Welcome/Goodbye image Added icon image basis. --- .github/workflows/cmake-linux-pack-nost.yml | 1 + .github/workflows/cmake-linux-pack-st.yml | 1 + .github/workflows/cmake-multi-platform-st.yml | 1 + .github/workflows/cmake-static-analysis.yml | 6 +- .github/workflows/cmake-windows-pack-nost.yml | 66 +++++ .github/workflows/cmake-windows-pack-st.yml | 67 +++++ LICENSE.rtf | 62 +++++ README.md | 259 ++++++++++++++---- cmake/Packing.cmake | 9 +- res/img/testcpp-inst-banner.bmp | Bin 0 -> 85894 bytes res/img/testcpp-inst-dialog.bmp | Bin 0 -> 461814 bytes res/img/testcpp.ico | Bin 0 -> 198983 bytes res/img/testcpp.png | Bin 0 -> 330658 bytes 13 files changed, 414 insertions(+), 58 deletions(-) create mode 100644 .github/workflows/cmake-windows-pack-nost.yml create mode 100644 .github/workflows/cmake-windows-pack-st.yml create mode 100644 LICENSE.rtf create mode 100644 res/img/testcpp-inst-banner.bmp create mode 100644 res/img/testcpp-inst-dialog.bmp create mode 100644 res/img/testcpp.ico create mode 100644 res/img/testcpp.png diff --git a/.github/workflows/cmake-linux-pack-nost.yml b/.github/workflows/cmake-linux-pack-nost.yml index d9ad7b5..0aa17ca 100644 --- a/.github/workflows/cmake-linux-pack-nost.yml +++ b/.github/workflows/cmake-linux-pack-nost.yml @@ -59,6 +59,7 @@ jobs: - name: Pack working-directory: ${{ steps.strings.outputs.build-output-dir }} run: | + cpack -G TXZ cpack -G DEB cpack -G RPM diff --git a/.github/workflows/cmake-linux-pack-st.yml b/.github/workflows/cmake-linux-pack-st.yml index d0998ea..3715090 100644 --- a/.github/workflows/cmake-linux-pack-st.yml +++ b/.github/workflows/cmake-linux-pack-st.yml @@ -60,6 +60,7 @@ jobs: - name: Pack working-directory: ${{ steps.strings.outputs.build-output-dir }} run: | + cpack -G TXZ cpack -G DEB cpack -G RPM diff --git a/.github/workflows/cmake-multi-platform-st.yml b/.github/workflows/cmake-multi-platform-st.yml index 489bcb2..ae70bf8 100644 --- a/.github/workflows/cmake-multi-platform-st.yml +++ b/.github/workflows/cmake-multi-platform-st.yml @@ -74,6 +74,7 @@ jobs: run: | cpack --config CPackConfig.cmake -C ${{ matrix.build_type }} cpack --config CPackConfig.cmake -C ${{ matrix.build_type }} -G ZIP + cpack --config CPackConfig.cmake -C ${{ matrix.build_type }} -G 7Z - name: 'Artifact Storage' uses: actions/upload-artifact@v4 diff --git a/.github/workflows/cmake-static-analysis.yml b/.github/workflows/cmake-static-analysis.yml index 5df1015..3acb238 100644 --- a/.github/workflows/cmake-static-analysis.yml +++ b/.github/workflows/cmake-static-analysis.yml @@ -24,10 +24,10 @@ jobs: with: language: c++ - # Exclude any issues found in ${Project_root_dir}/lib - exclude_dir: lib + # Exclude any issues found in ${Project_root_dir}/3rdparty + exclude_dir: 3rdparty use_cmake: true cmake_args: -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -Wno-dev - cppcheck_args: --enable=all --suppress=missingIncludeSystem --suppress=unusedFunction --std=c++11 --inline-suppr + cppcheck_args: --quiet --enable=all --inconclusive --suppress=missingIncludeSystem --suppress=unusedFunction --suppress=checkersReport --suppress='*:3rdparty/*' --std=c++11 --inline-suppr --force --check-level=exhaustive diff --git a/.github/workflows/cmake-windows-pack-nost.yml b/.github/workflows/cmake-windows-pack-nost.yml new file mode 100644 index 0000000..220e18b --- /dev/null +++ b/.github/workflows/cmake-windows-pack-nost.yml @@ -0,0 +1,66 @@ +name: TestCPP CMake WIX Pack - No Stacktraces + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + build: + runs-on: ${{ matrix.os }} + + strategy: + # Set fail-fast to false to ensure that feedback is delivered for all matrix combinations. Consider changing this to true when your workflow is stable. + fail-fast: false + + # Set up a matrix to run the following 3 configurations: + # 1. + # 2. + # 3. + # + # To add more build types (Release, Debug, RelWithDebInfo, etc.) customize the build_type list. + matrix: + os: [windows-latest] + build_type: [Release, Debug] + c_compiler: [cl] + include: + - os: windows-latest + c_compiler: cl + cpp_compiler: cl + + steps: + - uses: actions/checkout@v4 + + - name: Set reusable strings + # Turn repeated input strings (such as the build output directory) into step outputs. These step outputs can be used throughout the workflow file. + id: strings + shell: bash + run: | + echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT" + + - name: Configure CMake + # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. + # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type + run: > + cmake -B ${{ steps.strings.outputs.build-output-dir }} + -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} + -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} + -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} + -S ${{ github.workspace }} + + - name: Build + # Build your program with the given configuration. Note that --config is needed because the default Windows generator is a multi-config generator (Visual Studio generator). + run: cmake --build ${{ steps.strings.outputs.build-output-dir }} --config ${{ matrix.build_type }} + + - name: Pack + working-directory: ${{ steps.strings.outputs.build-output-dir }} + run: | + cpack -G WIX + + - name: 'Artifact Storage' + uses: actions/upload-artifact@v4 + with: + name: linux-packages-${{ matrix.os }}-${{ matrix.c_compiler }}-${{ matrix.build_type }} + path: ${{ github.workspace }}/_packages/** + overwrite: true diff --git a/.github/workflows/cmake-windows-pack-st.yml b/.github/workflows/cmake-windows-pack-st.yml new file mode 100644 index 0000000..56bb99b --- /dev/null +++ b/.github/workflows/cmake-windows-pack-st.yml @@ -0,0 +1,67 @@ +name: TestCPP CMake WIX Pack + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + build: + runs-on: ${{ matrix.os }} + + strategy: + # Set fail-fast to false to ensure that feedback is delivered for all matrix combinations. Consider changing this to true when your workflow is stable. + fail-fast: false + + # Set up a matrix to run the following 3 configurations: + # 1. + # 2. + # 3. + # + # To add more build types (Release, Debug, RelWithDebInfo, etc.) customize the build_type list. + matrix: + os: [windows-latest] + build_type: [Release, Debug] + c_compiler: [cl] + include: + - os: windows-latest + c_compiler: cl + cpp_compiler: cl + + steps: + - uses: actions/checkout@v4 + + - name: Set reusable strings + # Turn repeated input strings (such as the build output directory) into step outputs. These step outputs can be used throughout the workflow file. + id: strings + shell: bash + run: | + echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT" + + - name: Configure CMake + # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. + # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type + run: > + cmake -B ${{ steps.strings.outputs.build-output-dir }} + -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} + -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} + -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} + -DTESTCPP_STACKTRACE_ENABLED=1 + -S ${{ github.workspace }} + + - name: Build + # Build your program with the given configuration. Note that --config is needed because the default Windows generator is a multi-config generator (Visual Studio generator). + run: cmake --build ${{ steps.strings.outputs.build-output-dir }} --config ${{ matrix.build_type }} + + - name: Pack + working-directory: ${{ steps.strings.outputs.build-output-dir }} + run: | + cpack -G WIX + + - name: 'Artifact Storage' + uses: actions/upload-artifact@v4 + with: + name: linux-packages-${{ matrix.os }}-${{ matrix.c_compiler }}-${{ matrix.build_type }} + path: ${{ github.workspace }}/_packages/** + overwrite: true diff --git a/LICENSE.rtf b/LICENSE.rtf new file mode 100644 index 0000000..c6d5184 --- /dev/null +++ b/LICENSE.rtf @@ -0,0 +1,62 @@ +{\rtf1\ansi\deff3\adeflang1025 +{\fonttbl{\f0\froman\fprq2\fcharset0 Times New Roman;}{\f1\froman\fprq2\fcharset2 Symbol;}{\f2\fswiss\fprq2\fcharset0 Arial;}{\f3\froman\fprq2\fcharset0 Liberation Serif{\*\falt Times New Roman};}{\f4\fswiss\fprq2\fcharset0 Liberation Sans{\*\falt Arial};}{\f5\fnil\fprq2\fcharset0 Cascadia Mono;}{\f6\fnil\fprq2\fcharset0 Microsoft YaHei;}{\f7\fnil\fprq2\fcharset0 Lucida Sans;}{\f8\fswiss\fprq0\fcharset128 Lucida Sans;}} +{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;\red0\green136\blue0;\red163\green21\blue21;} +{\stylesheet{\s0\snext0\rtlch\af7\afs24\alang1081 \ltrch\lang1033\langfe2052\hich\af3\loch\nowidctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang1033\kerning1\dbch\af9\langfe2052 Normal;} +{\s15\sbasedon0\snext16\rtlch\af7\afs28 \ltrch\hich\af4\loch\sb240\sa120\keepn\f4\fs28\dbch\af6 Heading;} +{\s16\sbasedon0\snext16\loch\sl276\slmult1\sb0\sa140 Body Text;} +{\s17\sbasedon16\snext17\rtlch\af8 \ltrch\loch\sl276\slmult1\sb0\sa140 List;} +{\s18\sbasedon0\snext18\rtlch\af8\afs24\ai \ltrch\loch\sb120\sa120\noline\fs24\i caption;} +{\s19\sbasedon0\snext19\rtlch\af8 \ltrch\loch\noline Index;} +}{\*\generator LibreOffice/24.8.4.2$Windows_X86_64 LibreOffice_project/bb3cfa12c7b1bf994ecc5649a80400d06cd71002}{\info{\creatim\yr0\mo0\dy0\hr0\min0}{\revtim\yr2025\mo2\dy17\hr14\min55}{\printim\yr0\mo0\dy0\hr0\min0}}{\*\userprops}\deftab709 +\hyphauto1\viewscale140\formshade\paperh15840\paperw12240\margl1134\margr1134\margt1134\margb1134\sectd\sbknone\sftnnar\saftnnrlc\sectunlocked1\pgwsxn12240\pghsxn15840\marglsxn1134\margrsxn1134\margtsxn1134\margbsxn1134\ftnbj\ftnstart1\ftnrstcont\ftnnar\fet\aftnrstcont\aftnstart1\aftnnrlc +{\*\ftnsep\chftnsep}\pgndec\pard\plain \s0\rtlch\af7\afs24\alang1081 \ltrch\lang1033\langfe2052\hich\af3\loch\nowidctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang1033\kerning1\dbch\af9\langfe2052\ql\ltrpar{\hich\af5\loch\cf1\fs19\highlight8\f5\loch +This is free and unencumbered software released into the public domain.} +\par \pard\plain \s0\rtlch\af7\afs24\alang1081 \ltrch\lang1033\langfe2052\hich\af3\loch\nowidctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang1033\kerning1\dbch\af9\langfe2052\ql\ltrpar\hich\af5\loch\cf1\fs19\highlight8\f5\loch + +\par \pard\plain \s0\rtlch\af7\afs24\alang1081 \ltrch\lang1033\langfe2052\hich\af3\loch\nowidctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang1033\kerning1\dbch\af9\langfe2052\ql\ltrpar{\hich\af5\loch\cf1\fs19\highlight8\f5\loch +Anyone is free to copy, modify, publish, use, compile, sell, or} +\par \pard\plain \s0\rtlch\af7\afs24\alang1081 \ltrch\lang1033\langfe2052\hich\af3\loch\nowidctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang1033\kerning1\dbch\af9\langfe2052\ql\ltrpar{\hich\af5\loch\cf1\fs19\highlight8\f5\loch +distribute this software, either in source code form or as a compiled} +\par \pard\plain \s0\rtlch\af7\afs24\alang1081 \ltrch\lang1033\langfe2052\hich\af3\loch\nowidctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang1033\kerning1\dbch\af9\langfe2052\ql\ltrpar{\hich\af5\loch\cf1\fs19\highlight8\f5\loch +binary, for any purpose, commercial or non-commercial, and by any} +\par \pard\plain \s0\rtlch\af7\afs24\alang1081 \ltrch\lang1033\langfe2052\hich\af3\loch\nowidctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang1033\kerning1\dbch\af9\langfe2052\ql\ltrpar{\hich\af5\loch\cf1\fs19\highlight8\f5\loch +means.} +\par \pard\plain \s0\rtlch\af7\afs24\alang1081 \ltrch\lang1033\langfe2052\hich\af3\loch\nowidctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang1033\kerning1\dbch\af9\langfe2052\ql\ltrpar\hich\af5\loch\cf1\fs19\highlight8\f5\loch + +\par \pard\plain \s0\rtlch\af7\afs24\alang1081 \ltrch\lang1033\langfe2052\hich\af3\loch\nowidctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang1033\kerning1\dbch\af9\langfe2052\ql\ltrpar{\hich\af5\loch\cf1\fs19\highlight8\f5\loch +In jurisdictions that recognize copyright laws, the author or authors} +\par \pard\plain \s0\rtlch\af7\afs24\alang1081 \ltrch\lang1033\langfe2052\hich\af3\loch\nowidctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang1033\kerning1\dbch\af9\langfe2052\ql\ltrpar{\hich\af5\loch\cf1\fs19\highlight8\f5\loch +of this software dedicate any and all copyright interest in the} +\par \pard\plain \s0\rtlch\af7\afs24\alang1081 \ltrch\lang1033\langfe2052\hich\af3\loch\nowidctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang1033\kerning1\dbch\af9\langfe2052\ql\ltrpar{\hich\af5\loch\cf1\fs19\highlight8\f5\loch +software to the public domain. We make this dedication for the benefit} +\par \pard\plain \s0\rtlch\af7\afs24\alang1081 \ltrch\lang1033\langfe2052\hich\af3\loch\nowidctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang1033\kerning1\dbch\af9\langfe2052\ql\ltrpar{\hich\af5\loch\cf1\fs19\highlight8\f5\loch +of the public at large and to the detriment of our heirs and} +\par \pard\plain \s0\rtlch\af7\afs24\alang1081 \ltrch\lang1033\langfe2052\hich\af3\loch\nowidctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang1033\kerning1\dbch\af9\langfe2052\ql\ltrpar{\hich\af5\loch\cf1\fs19\highlight8\f5\loch +successors. We intend this dedication to be an overt act of} +\par \pard\plain \s0\rtlch\af7\afs24\alang1081 \ltrch\lang1033\langfe2052\hich\af3\loch\nowidctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang1033\kerning1\dbch\af9\langfe2052\ql\ltrpar{\hich\af5\loch\cf1\fs19\highlight8\f5\loch +relinquishment in perpetuity of all present and future rights to this} +\par \pard\plain \s0\rtlch\af7\afs24\alang1081 \ltrch\lang1033\langfe2052\hich\af3\loch\nowidctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang1033\kerning1\dbch\af9\langfe2052\ql\ltrpar{\hich\af5\loch\cf1\fs19\highlight8\f5\loch +software under copyright law.} +\par \pard\plain \s0\rtlch\af7\afs24\alang1081 \ltrch\lang1033\langfe2052\hich\af3\loch\nowidctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang1033\kerning1\dbch\af9\langfe2052\ql\ltrpar\hich\af5\loch\cf1\fs19\highlight8\f5\loch + +\par \pard\plain \s0\rtlch\af7\afs24\alang1081 \ltrch\lang1033\langfe2052\hich\af3\loch\nowidctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang1033\kerning1\dbch\af9\langfe2052\ql\ltrpar{\hich\af5\loch\cf1\fs19\highlight8\f5\loch +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,} +\par \pard\plain \s0\rtlch\af7\afs24\alang1081 \ltrch\lang1033\langfe2052\hich\af3\loch\nowidctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang1033\kerning1\dbch\af9\langfe2052\ql\ltrpar{\hich\af5\loch\cf1\fs19\highlight8\f5\loch +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF} +\par \pard\plain \s0\rtlch\af7\afs24\alang1081 \ltrch\lang1033\langfe2052\hich\af3\loch\nowidctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang1033\kerning1\dbch\af9\langfe2052\ql\ltrpar{\hich\af5\loch\cf1\fs19\highlight8\f5\loch +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.} +\par \pard\plain \s0\rtlch\af7\afs24\alang1081 \ltrch\lang1033\langfe2052\hich\af3\loch\nowidctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang1033\kerning1\dbch\af9\langfe2052\ql\ltrpar{\hich\af5\loch\cf1\fs19\highlight8\f5\loch +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR} +\par \pard\plain \s0\rtlch\af7\afs24\alang1081 \ltrch\lang1033\langfe2052\hich\af3\loch\nowidctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang1033\kerning1\dbch\af9\langfe2052\ql\ltrpar{\hich\af5\loch\cf1\fs19\highlight8\f5\loch +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,} +\par \pard\plain \s0\rtlch\af7\afs24\alang1081 \ltrch\lang1033\langfe2052\hich\af3\loch\nowidctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang1033\kerning1\dbch\af9\langfe2052\ql\ltrpar{\hich\af5\loch\cf1\fs19\highlight8\f5\loch +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR} +\par \pard\plain \s0\rtlch\af7\afs24\alang1081 \ltrch\lang1033\langfe2052\hich\af3\loch\nowidctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang1033\kerning1\dbch\af9\langfe2052\ql\ltrpar{\hich\af5\loch\cf1\fs19\highlight8\f5\loch +OTHER DEALINGS IN THE SOFTWARE.} +\par \pard\plain \s0\rtlch\af7\afs24\alang1081 \ltrch\lang1033\langfe2052\hich\af3\loch\nowidctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang1033\kerning1\dbch\af9\langfe2052\ql\ltrpar\hich\af5\loch\cf1\fs19\highlight8\f5\loch + +\par \pard\plain \s0\rtlch\af7\afs24\alang1081 \ltrch\lang1033\langfe2052\hich\af3\loch\nowidctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang1033\kerning1\dbch\af9\langfe2052\ql\ltrpar{\hich\af5\loch\cf1\fs19\highlight8\f5\loch +For more information, please refer to } +\par \pard\plain \s0\rtlch\af7\afs24\alang1081 \ltrch\lang1033\langfe2052\hich\af3\loch\nowidctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang1033\kerning1\dbch\af9\langfe2052\ql\ltrpar\loch + +\par } \ No newline at end of file diff --git a/README.md b/README.md index 4c2acd3..01969c8 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ [![Test-NoStacktraces](https://github.com/eljonny/TestCPP/actions/workflows/cmake-build-test-nost.yml/badge.svg?event=push)](https://github.com/eljonny/TestCPP/actions/workflows/cmake-build-test-nost.yml) [![RPM_DEB-Packaging-WithStacktraces](https://github.com/eljonny/TestCPP/actions/workflows/cmake-linux-pack-st.yml/badge.svg?event=push)](https://github.com/eljonny/TestCPP/actions/workflows/cmake-linux-pack-st.yml) [![RPM_DEB-Packaging-NoStacktraces](https://github.com/eljonny/TestCPP/actions/workflows/cmake-linux-pack-nost.yml/badge.svg?event=push)](https://github.com/eljonny/TestCPP/actions/workflows/cmake-linux-pack-nost.yml) +[![WIX-Packaging-WithStacktraces](https://github.com/eljonny/TestCPP/actions/workflows/cmake-windows-pack-st.yml/badge.svg?event=push)](https://github.com/eljonny/TestCPP/actions/workflows/cmake-windows-pack-st.yml) +[![WIX-Packaging-NoStacktraces](https://github.com/eljonny/TestCPP/actions/workflows/cmake-windows-pack-nost.yml/badge.svg?event=push)](https://github.com/eljonny/TestCPP/actions/workflows/cmake-windows-pack-nost.yml) [![Coverage](https://github.com/eljonny/TestCPP/actions/workflows/cmake-build-cov-st.yml/badge.svg?event=push)](https://github.com/eljonny/TestCPP/actions/workflows/cmake-build-cov-st.yml) [![Security](https://github.com/eljonny/TestCPP/actions/workflows/codeql.yml/badge.svg?event=push)](https://github.com/eljonny/TestCPP/actions/workflows/codeql.yml) [![StaticAnalysis](https://github.com/eljonny/TestCPP/actions/workflows/cmake-static-analysis.yml/badge.svg?event=push)](https://github.com/eljonny/TestCPP/actions/workflows/cmake-static-analysis.yml) @@ -14,8 +16,8 @@ This is an implementation of a very simple test framework. It can be built with no dependencies (other than the C++ standard library) and can rely on only C++11 features. -It supports stack traces on test failures as of 0.2.1-beta.3, which uses - Boost.StackTrace, but this is not required to use the framework. +It supports stack traces on test failures as of 0.2.1-beta.3, which + uses Boost.StackTrace, but this is not required to use the framework. The library is most useful for educational projects or small personal/internal projects, as many features required for @@ -211,12 +213,66 @@ In the Custom Targets... context menu option there are also, depending causes the library to have link-time dependencies as explained in other elements of this README. +## Building in Visual Studio + +I have been able to successfully configure and build the project in + [Visual Studio 2022 Community](https://visualstudio.microsoft.com/vs/community/) + using the built-in CMake project integration, so this does work if you + would like to proceed this way. + +There are a number of CMake Presets defined in CMakePresets.json that + align with different build configurations and analysis profiles, + including all build feature variations (with/without the Demo project, + with/without the tests, and subsequently with/without stacktrace + support via Boost.StackTrace). + +To get started, open the root project folder in Visual Studio 2022 and + select the desired CMake Preset from the Build Configurations dropdown + which will be populated with all applicable buildPresets once the + project has fully loaded. Visual Studio automatically detects the + presence of the CMakePresets.json and CMakeLists.txt files and will + configure the project with the lexicographically-first build preset. +Subsequently, you can build the project from the Build menu or by + pressing F7 after successful configuration. + ## CMake build structure and variables The CMake build is split into components that get included into the main build file to make modifying each piece more logical and manageable. +The top-level components are as follows: +- CMake Build File: + The main build file that includes all the other components + (CMakeLists.txt). +- Code Analysis: + Configuring code analysis tools (Analysis.cmake). + Currently, this includes clang-tidy in the build process. + - CPPCheck is also included in the build process, but it is + not included in the Analysis.cmake file because it is + run as part of the static analysis GitHub Action (see + .github/workflows/cmake-static-analysis.yml). +- Build Type Handling: + Handling the build type which sets compile options for the platform + on which the build is being run based on the build type (Debug, + Release, I still need to work on getting RelWithDebugInfo + configured properly) (BuildTypeHandling.cmake). +- Target Includes: + Which includes should be applied to which targets (Includes.cmake). +- Installing: + Configuring installation of the library (Installing.cmake). +- Target Link Libraries: + Which libraries need to be linked in which build targets, based on + the result of VarChecks in terms of code coverage (Linking.cmake). +- Packaging: + Configuring library packaging parameters, enable CPack + (Packing.cmake). +- Build Targets Configuration: + Setting up the build targets (Targets.cmake). + Lists each translation unit that applies to each target. +- Testing: + Testing configuration, based on the result of VarChecks + (Testing.cmake). - Variable Checks: Checking the variables to enable or disable certain sections of the build (VarChecks.cmake). @@ -260,38 +316,62 @@ The CMake build is split into components that get included into the - dbgeng - Non-Windows - libdl -- Build Targets Configuration: - Setting up the build targets (Targets.cmake). - Lists each translation unit that applies to each target. -- Build Type Handling: - Handling the build type which sets compile options for the platform - on which the build is being run based on the build type (Debug, - Release, I still need to work on getting RelWithDebugInfo - configured properly) (BuildTypeHandling.cmake). -- Target Includes: - Which includes should be applied to which targets (Includes.cmake). -- Target Link Libraries: - Which libraries need to be linked in which build targets, based on - the result of VarChecks in terms of code coverage (Linking.cmake). -- Testing: - Testing configuration, based on the result of VarChecks - (Testing.cmake). -- Installing: - Configuring installation of the library (Installing.cmake). -- Packaging: - Configuring library packaging parameters, enable CPack - (Packing.cmake). + +There are a number of CMake modules in the cmake directory, including + the following: +- Build definitions: + - CompileDefs.cmake + Defines compile definitions for all configurations of the project. + - DebugCompileDefs.cmake + Defines compile definitions specific to the Debug configuration of + the project. + - GCCClangDebug.cmake + Defines compiler flags specific to the Debug configuration of the + project when building with GCC or Clang. + - GCCClangRelease.cmake + Defines compiler flags specific to the Release configuration of the + project when building with GCC or Clang. + - GCCCoverage.cmake + Defines compiler flags specific to the Debug configuration of the + project when building with GCC and generating code coverage data. + - MSVCDebug.cmake + Defines compiler flags specific to the Debug configuration of the + project when building with MSVC. + - MSVCRelease.cmake + Defines compiler flags specific to the Release configuration of the + project when building with MSVC. +- Linking definitions: + - Demo.cmake + Defines the linking for the demo targets. + - TestCPPWithCoverage.cmake + Defines the linking for the TestCPP library when code coverage is + enabled. + - Tests.cmake + Defines the linking for the test targets. + - TestsWithCoverage.cmake + Defines the linking for the test targets when code coverage is + enabled. +- Toolchain files: + - Windows + - Windows.Clang.toolchain.cmake + Toolchain file for Visual Studio-installed Clang on Windows. + - Windows.MSVC.toolchain.cmake + Toolchain file for MSVC on Windows. + - Windows.Kits.cmake + Toolchain file for Windows SDKs. + - VSWhere.cmake + Toolchain file for finding Visual Studio installations. ## Building outside the IDE To build outside of the CodeLite IDE, you can run the following commands, after cloning the repo, for the debug build: ``` - cd TestCPP - mkdir build-debug - cd build-debug - cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=1 - make +cd TestCPP +mkdir build-debug +cd build-debug +cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=1 +make ``` The Debug configuration supports testing and code coverage. To enable those in the build, add one or both of the following flags to `cmake`: @@ -300,11 +380,11 @@ The Debug configuration supports testing and code coverage. To enable For the release build: ``` - cd TestCPP - mkdir build-release - cd build-release - cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXPORT_COMPILE_COMMANDS=1 - make +cd TestCPP +mkdir build-release +cd build-release +cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXPORT_COMPILE_COMMANDS=1 +make ``` The Release configuration supports testing. To enable generation of the test target in the build, add the following flag to `cmake`: @@ -321,32 +401,57 @@ Both Release and Debug configurations support building with stack trace functionality with the folloeing flag: - `-DTESTCPP_STACKTRACE_ENABLED` +# Static Analysis of TestCPP + You can run cppcheck and clang-tidy on the generated compile_commands.json. + For clang-tidy, you can also use the CMake flag to have CMake run clang-tidy during the build. -My suggested options for cppcheck are: - - --project=compile_commands.json - - Uses the generated CMake output to define a check project - - -itest - - Ignores tests, in case building with tests enabled - - -idemo - - Ignores demo code, in case building with demo enabled - - --enable=all - - Enables all CPPCheck checks - - --suppress=missingIncludeSystem - - Then suppress missing system includes, there are no <>-enclosed - includes that need to be checked for this project. - - --suppress=unusedFunction - - Then suppress checking for unused functions. Most API functions - are not used within the library itself, and CPPCheck will generate - numerous errors saying the functions are unused. - clang-tidy uses the .clang-tidy configuration file so you don't need to specify any options unless you want to run it with different checks/ behavior from what I usually run for this project. +My suggested options for cppcheck are: +- --project=compile_commands.json + - Uses the generated CMake output to define a check project; you need + to adjust the argument to this parameter to match the path to the + compile_commands.json file that was generated. +- --enable=all + - Enables all CPPCheck checks applicable to the project. +- --suppress=missingIncludeSystem + - Then suppress missing system includes, there are no <>-enclosed + includes that need to be checked for this project. +- --suppress=unusedFunction + - Then suppress checking for unused functions. Most API functions + are not used within the library itself, and CPPCheck will generate + numerous errors saying the functions are unused. +- --suppress=checkersReport + - Then suppress the checkers report, which is a summary of the checks + that were run and how many were skipped. +- --suppress='\*:3rdparty/\*' + - Ignore all checks in the 3rdparty directory, which is where the + Boost headers are stored for this project. +- --inconclusive + - Allow inconclusive results to be reported, which can identify more + potential issues in the code. +- --force + - Forces checking of all preprocessor configurations +- --check-level=exhaustive + - Analysis covers all possible paths and more expensive checks +- --inline-suppr + - Obeys inline suppression of errors in the code, which are used in + this project to suppress specific instances of errors/warnings that + are not applicable or are false positives. +- --quiet + - Suppresses all output except for errors and warnings +- --std=c++11 + - Specifies the C++ standard to use for checking the code + +I would recommend against using the -j parameter with cppcheck because + it disables certain checks that are used in the project. + # Testing and Code Coverage The library is tested using itself. @@ -386,14 +491,14 @@ After building, run the variant of the commands that align with your build configuration (starting from the project directory). For the debug build: ``` - cd build-debug - sudo cmake --install . +cd build-debug +sudo cmake --install . ``` For the release build: ``` - cd build-release - sudo cmake --install . +cd build-release +sudo cmake --install . ``` # Packaging @@ -409,6 +514,10 @@ To create basic binary packages that can be used on the or build-release): - `cpack --config CPackConfig.cmake` +Building the basic binary packages on Windows will generate an NSIS + executable installer while building on Linux will generate multiple + tarballs and an executable sh installer file. + To create source packages, run the following command from the CMake build directory (either build-debug or build-release): - `cpack --config CPackSourceConfig.cmake` @@ -420,6 +529,11 @@ If you are building on Linux, the build supports generating - `cpack -G DEB` - `cpack -G RPM` +If you are building on Windows, the build supports generating MSI + packages. To build those (make sure you have the WiX toolkit installed + first), run the following command from the CMake build directory: + - `cpack -G WIX` + Both Windows and Linux builds also support generating a zip package by running the following command from the CMake build directory (either build-debug or build-release): @@ -436,3 +550,40 @@ Please submit an issue on the repo if there are problems I am semi-actively developing this library/framework, if anyone would like to contribute please do so by submitting pull requests on GitHub. + +## GitHub Actions + +The project is configured to use GitHub Actions for CI/CD. +There are several workflows that are used to build, test, and package + the library. +The workflows are as follows: +- cmake-multi-platform-st.yml + - Builds the library on Windows and Linux with stack traces enabled. +- cmake-multi-platform-nost.yml + - Builds the library on Windows and Linux with stack traces disabled. +- cmake-build-test-st.yml + - Builds and tests the library on Windows and Linux with stack traces + enabled. +- cmake-build-test-nost.yml + - Builds and tests the library on Windows and Linux with stack traces + disabled. +- cmake-linux-pack-st.yml + - Builds and packages the library on Linux with stack traces enabled. +- cmake-linux-pack-nost.yml + - Builds and packages the library on Linux with stack traces + disabled. +- cmake-windows-pack-st.yml + - Builds and packages the library on Windows with stack traces + enabled. +- cmake-windows-pack-nost.yml + - Builds and packages the library on Windows with stack traces + disabled. +- cmake-build-cov-st.yml + - Builds and tests the library on Linux with stack traces enabled and + generates code coverage reports that are then pushed to CodeCov for + helpful visualizations and reporting. +- codeql.yml + - Runs the CodeQL static analysis tool on the library code. +- cmake-static-analysis.yml + - Runs clang-tidy and cppcheck on the library code using + JacobDomagala/StaticAnalysis@master diff --git a/cmake/Packing.cmake b/cmake/Packing.cmake index 8de2ae9..32718af 100644 --- a/cmake/Packing.cmake +++ b/cmake/Packing.cmake @@ -24,7 +24,7 @@ set (CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR}) set (CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR}) set (CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH}) -set (CPACK_PACKAGE_CONTACT "el.jonny@gmail.com") +set (CPACK_PACKAGE_CONTACT "jonathan.hyry@outlook.com") set (CPACK_DEBIAN_PACKAGE_MAINTAINER "Jonathan Hyry <${CPACK_PACKAGE_CONTACT}>") set (CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://github.com/eljonny/TestCPP") @@ -45,6 +45,13 @@ set (CPACK_DEBIAN_FILE_NAME DEB-DEFAULT) set (CPACK_COMPONENTS_GROUPING ALL_COMPONENTS_IN_ONE) set (CPACK_DEB_COMPONENT_INSTALL YES) +set (CPACK_WIX_UPGRADE_GUID "EDB6D016-633E-4A35-AD5A-7734F6F3E6A5") +set (CPACK_WIX_LICENSE_RTF "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.rtf") +set (CPACK_WIX_PRODUCT_ICON "${CMAKE_CURRENT_SOURCE_DIR}/res/img/testcpp.ico") +set (CPACK_WIX_UI_BANNER "${CMAKE_CURRENT_SOURCE_DIR}/res/img/testcpp-inst-banner.bmp") +set (CPACK_WIX_UI_DIALOG "${CMAKE_CURRENT_SOURCE_DIR}/res/img/testcpp-inst-dialog.bmp") +set (CPACK_WIX_CMAKE_PACKAGE_REGISTRY "${PROJECT_NAME}") + include (CPack) include (CMakePackageConfigHelpers) diff --git a/res/img/testcpp-inst-banner.bmp b/res/img/testcpp-inst-banner.bmp new file mode 100644 index 0000000000000000000000000000000000000000..518de64a2dbbab70d516a2f10f4d43d239ce02b4 GIT binary patch literal 85894 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�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 HBwzIZJjOm7 literal 0 HcmV?d00001 diff --git a/res/img/testcpp-inst-dialog.bmp b/res/img/testcpp-inst-dialog.bmp new file mode 100644 index 0000000000000000000000000000000000000000..604d6793a74b2fac193f620e289653a730d2f2b4 GIT binary patch literal 461814 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 literal 0 HcmV?d00001 diff --git a/res/img/testcpp.ico b/res/img/testcpp.ico new file mode 100644 index 0000000000000000000000000000000000000000..a0a877353da94026ec138398ccb9181d7a19920f GIT binary patch literal 198983 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 O-uvUuwEw?8>VE-#;r-J9 literal 0 HcmV?d00001 diff --git a/res/img/testcpp.png b/res/img/testcpp.png new file mode 100644 index 0000000000000000000000000000000000000000..68361dcbe381c04a981921b91ed4e98ceebd8f41 GIT binary patch literal 330658 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%0DbFhvD*+O3Rizrabn%pN=8yEHv8StL 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∾%9^>pJ^u0th*>>u#6fnJtacqxu!UN9>2 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�sRY8r?d1C@&M8u}{PtCne*x;)3FS9ieyHmlc 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≷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 z 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 literal 0 HcmV?d00001 From 5fba03fdc4b6d99c04700ebdf57d46a9e1dd287c Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Mon, 17 Feb 2025 19:51:03 -0800 Subject: [PATCH 57/59] Fix cpack not using the built configuration --- .github/workflows/cmake-windows-pack-nost.yml | 2 +- .github/workflows/cmake-windows-pack-st.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cmake-windows-pack-nost.yml b/.github/workflows/cmake-windows-pack-nost.yml index 220e18b..c4701d5 100644 --- a/.github/workflows/cmake-windows-pack-nost.yml +++ b/.github/workflows/cmake-windows-pack-nost.yml @@ -56,7 +56,7 @@ jobs: - name: Pack working-directory: ${{ steps.strings.outputs.build-output-dir }} run: | - cpack -G WIX + cpack -G WIX --config ${{ matrix.build_type }} - name: 'Artifact Storage' uses: actions/upload-artifact@v4 diff --git a/.github/workflows/cmake-windows-pack-st.yml b/.github/workflows/cmake-windows-pack-st.yml index 56bb99b..28f93b4 100644 --- a/.github/workflows/cmake-windows-pack-st.yml +++ b/.github/workflows/cmake-windows-pack-st.yml @@ -57,7 +57,7 @@ jobs: - name: Pack working-directory: ${{ steps.strings.outputs.build-output-dir }} run: | - cpack -G WIX + cpack -G WIX --config ${{ matrix.build_type }} - name: 'Artifact Storage' uses: actions/upload-artifact@v4 From a115dbf427796b37779b63e2b486d4ef2e2918a1 Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Mon, 17 Feb 2025 22:35:37 -0800 Subject: [PATCH 58/59] Whoopsies --- .github/workflows/cmake-windows-pack-nost.yml | 2 +- .github/workflows/cmake-windows-pack-st.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cmake-windows-pack-nost.yml b/.github/workflows/cmake-windows-pack-nost.yml index c4701d5..b150bca 100644 --- a/.github/workflows/cmake-windows-pack-nost.yml +++ b/.github/workflows/cmake-windows-pack-nost.yml @@ -56,7 +56,7 @@ jobs: - name: Pack working-directory: ${{ steps.strings.outputs.build-output-dir }} run: | - cpack -G WIX --config ${{ matrix.build_type }} + cpack -G WIX -C ${{ matrix.build_type }} - name: 'Artifact Storage' uses: actions/upload-artifact@v4 diff --git a/.github/workflows/cmake-windows-pack-st.yml b/.github/workflows/cmake-windows-pack-st.yml index 28f93b4..6148184 100644 --- a/.github/workflows/cmake-windows-pack-st.yml +++ b/.github/workflows/cmake-windows-pack-st.yml @@ -57,7 +57,7 @@ jobs: - name: Pack working-directory: ${{ steps.strings.outputs.build-output-dir }} run: | - cpack -G WIX --config ${{ matrix.build_type }} + cpack -G WIX -C ${{ matrix.build_type }} - name: 'Artifact Storage' uses: actions/upload-artifact@v4 From 998dda3c0a34bf3371fd93ff4d99d2073711df53 Mon Sep 17 00:00:00 2001 From: Jonathan Hyry Date: Mon, 17 Feb 2025 23:31:17 -0800 Subject: [PATCH 59/59] Created a fork of StaticAnalysis action that uses clang-19, try using it --- .github/workflows/cmake-static-analysis.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/cmake-static-analysis.yml b/.github/workflows/cmake-static-analysis.yml index 3acb238..408b296 100644 --- a/.github/workflows/cmake-static-analysis.yml +++ b/.github/workflows/cmake-static-analysis.yml @@ -18,9 +18,8 @@ jobs: steps: - uses: actions/checkout@v4 - - - name: Run static analysis - uses: JacobDomagala/StaticAnalysis@master + - name: Static analysis for C++(Clang-19)/Python project + uses: eljonny/StaticAnalysis@clang-19 with: language: c++