diff --git a/.github/workflows/cpp-ci.yml b/.github/workflows/cpp-ci.yml new file mode 100644 index 0000000..bcc84bf --- /dev/null +++ b/.github/workflows/cpp-ci.yml @@ -0,0 +1,191 @@ +name: C++ - Continuous Integration + +on: + push: + branches: + - main + + pull_request: + branches: + - main + +jobs: + lint: + runs-on: ubuntu-22.04 + + steps: + - uses: actions/checkout@v3 + with: + submodules: 'recursive' + + - uses: actions/setup-python@v4 + with: { python-version: "3.12" } + + - name: Install LLVM 18 + run: | + wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | sudo tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc + sudo apt-add-repository "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-18 main" + sudo apt update + sudo apt install llvm-18 llvm-18-dev llvm-18-tools clang-18 clang-tidy-18 clang-format-18 clang-tools-18 libclang-18-dev -y + + - name: Install codespell + run: pip3 install codespell + + - name: Lint + run: cmake -D FORMAT_COMMAND=clang-format-18 -P cmake/lint.cmake + + - name: Spell check + run: cmake -P cmake/spell.cmake + + sanitize: + needs: [lint] + + runs-on: ubuntu-22.04 + + + env: + CC: clang-18 + CXX: clang++-18 + CLANG_DIR: '/usr/lib/llvm-18/lib/cmake/clang' + LLVM_DIR: '/usr/lib/llvm-18/lib/cmake/llvm' + + steps: + - uses: actions/checkout@v3 + with: + submodules: 'recursive' + + - name: Install Python + uses: actions/setup-python@v4 + with: { python-version: "3.12" } + + - name: Install Python Dev + uses: actions/setup-python@v4 + with: { python-version: "3.12-dev" } + + - name: Install LLVM 18 + run: | + wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | sudo tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc + sudo apt-add-repository "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-18 main" + sudo apt update + sudo apt install llvm-18 llvm-18-dev llvm-18-tools clang-18 clang-tidy-18 clang-tools-18 libclang-18-dev -y + + - name: Install Cache Conan dependencies + id: cache-conan + uses: actions/cache@v3 + env: + cache-name: cache-conan-deps + with: + path: ~/.conan2 + key: ${{ runner.os }}-builder-${{ env.cache-name }}-${{ hashFiles('conanfile.py') }} + restore-keys: ${{ runner.os }}-builder-${{ env.cache-name }}- + + - name: Install dependencies + run: | + pip3 install conan numpy + + sudo apt install libssl-dev -y + + bash < ../.github/scripts/conan-profile.sh + conan install . -s build_type=Release -b missing + + - name: Configure + run: cmake --preset=ci-sanitize + + - name: Build + run: cmake --build build/sanitize -j + + - name: Test + working-directory: src/cppsrc/build/sanitize + env: + ASAN_OPTIONS: "strict_string_checks=1:\ + detect_stack_use_after_return=1:\ + check_initialization_order=1:\ + strict_init_order=1:\ + detect_leaks=1" + UBSAN_OPTIONS: print_stacktrace=1 + run: ctest --output-on-failure --no-tests=error -j 2 + + tests: + needs: [lint] + + strategy: + matrix: + os: [ubuntu-22.04] + + runs-on: ${{ matrix.os }} + + + env: + CC: clang-18 + CXX: clang++-18 + CLANG_DIR: '/usr/lib/llvm-18/lib/cmake/clang' + LLVM_DIR: '/usr/lib/llvm-18/lib/cmake/llvm' + + steps: + - uses: actions/checkout@v3 + with: + submodules: 'recursive' + + - name: Install LLVM 18 + run: | + wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | sudo tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc + sudo apt-add-repository "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-18 main" + sudo apt update + sudo apt install llvm-18 llvm-18-dev llvm-18-tools clang-18 clang-tidy-18 clang-tools-18 libclang-18-dev -y + + - name: Install static analyzers + if: matrix.os == 'ubuntu-22.04' + run: >- + sudo apt install cppcheck -y -q + + sudo update-alternatives --install + /usr/bin/clang-tidy clang-tidy + /usr/bin/clang-tidy-18 160 + + - name: Install Python + uses: actions/setup-python@v4 + with: { python-version: "3.12" } + + - name: Install Python Dev + uses: actions/setup-python@v4 + with: { python-version: "3.12-dev" } + + - name: Install Cache Conan dependencies + id: cache-conan + uses: actions/cache@v3 + env: + cache-name: cache-conan-deps + with: + path: ~/.conan2 + key: ${{ runner.os }}-builder-${{ env.cache-name }}-${{ hashFiles('conanfile.py') }} + restore-keys: ${{ runner.os }}-builder-${{ env.cache-name }}- + + - name: Install dependencies + shell: bash + run: | + pip3 install conan numpy + + sudo apt install libssl-dev -y + + bash < ../.github/scripts/conan-profile.sh + conan install . -s build_type=Release -b missing + + - name: Setup MultiToolTask + if: matrix.os == 'windows-2022' + run: | + Add-Content "$env:GITHUB_ENV" 'UseMultiToolTask=true' + Add-Content "$env:GITHUB_ENV" 'EnforceProcessCountAcrossBuilds=true' + + - name: Configure + shell: pwsh + run: cmake "--preset=ci-$("${{ matrix.os }}".split("-")[0])" + + - name: Build + run: cmake --build build --config Release -j + + - name: Install + run: cmake --install build --config Release --prefix prefix + + - name: Test + run: ctest --output-on-failure --no-tests=error -C Release -j 2 + diff --git a/.gitignore b/.gitignore index ebbc99d..7305d73 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,6 @@ __pycache__ .mypy_cache .DS_Store .env +conan/ +build/ +**/compile_commands.json diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..1b1e871 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,62 @@ +cmake_minimum_required(VERSION 3.14) + +include(cmake/prelude.cmake) + +project( + desk_monorepo + VERSION 0.1.0 + DESCRIPTION "Short description" + HOMEPAGE_URL "https://example.com/" + LANGUAGES CXX +) + +include(cmake/project-is-top-level.cmake) +include(cmake/variables.cmake) + +# ---- Declare library ---- + +add_library( + desk_monorepo_lib OBJECT + src/cppsrc/src/lib.cpp +) + +target_include_directories( + desk_monorepo_lib ${warning_guard} + PUBLIC + "\$" +) + +target_compile_features(desk_monorepo_lib PUBLIC cxx_std_20) + +find_package(fmt REQUIRED) +target_link_libraries(desk_monorepo_lib PRIVATE fmt::fmt) + +# ---- Declare executable ---- + +add_executable(desk_monorepo_exe src/cppsrc/src/main.cpp) +add_executable(desk_monorepo::exe ALIAS desk_monorepo_exe) + +set_property(TARGET desk_monorepo_exe PROPERTY OUTPUT_NAME desk_monorepo) + +target_compile_features(desk_monorepo_exe PRIVATE cxx_std_20) + +target_link_libraries(desk_monorepo_exe PRIVATE desk_monorepo_lib) + +# ---- Install rules ---- + +if(NOT CMAKE_SKIP_INSTALL_RULES) + include(cmake/install-rules.cmake) +endif() + +# ---- Developer mode ---- + +if(NOT desk_monorepo_DEVELOPER_MODE) + return() +elseif(NOT PROJECT_IS_TOP_LEVEL) + message( + AUTHOR_WARNING + "Developer mode is intended for developers of desk_monorepo" + ) +endif() + +include(cmake/dev-mode.cmake) diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 0000000..1c2b3bf --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,169 @@ +{ + "version": 2, + "cmakeMinimumRequired": { + "major": 3, + "minor": 14, + "patch": 0 + }, + "configurePresets": [ + { + "name": "cmake-pedantic", + "hidden": true, + "warnings": { + "dev": true, + "deprecated": true, + "uninitialized": true, + "unusedCli": true, + "systemVars": false + }, + "errors": { + "dev": true, + "deprecated": true + } + }, + { + "name": "dev-mode", + "hidden": true, + "inherits": "cmake-pedantic", + "cacheVariables": { + "desk_monorepo_DEVELOPER_MODE": "ON" + } + }, + { + "name": "conan", + "hidden": true, + "cacheVariables": { + "CMAKE_TOOLCHAIN_FILE": "${sourceDir}/conan/conan_toolchain.cmake", + "CMAKE_POLICY_DEFAULT_CMP0091": "NEW" + } + }, + { + "name": "cppcheck", + "hidden": true, + "cacheVariables": { + "CMAKE_CXX_CPPCHECK": "cppcheck;--inline-suppr" + } + }, + { + "name": "clang-tidy", + "hidden": true, + "cacheVariables": { + "CMAKE_CXX_CLANG_TIDY": "clang-tidy;--header-filter=^${sourceDir}/" + } + }, + { + "name": "ci-std", + "description": "This preset makes sure the project actually builds with at least the specified standard", + "hidden": true, + "cacheVariables": { + "CMAKE_CXX_EXTENSIONS": "OFF", + "CMAKE_CXX_STANDARD": "20", + "CMAKE_CXX_STANDARD_REQUIRED": "ON" + } + }, + { + "name": "flags-gcc-clang", + "description": "These flags are supported by both GCC and Clang", + "hidden": true, + "cacheVariables": { + "CMAKE_CXX_FLAGS": "-D_GLIBCXX_ASSERTIONS=1 -fstack-protector-strong -fcf-protection=full -fstack-clash-protection -Wall -Wextra -Wpedantic -Wconversion -Wsign-conversion -Wcast-qual -Wformat=2 -Wundef -Werror=float-equal -Wshadow -Wcast-align -Wunused -Wnull-dereference -Wdouble-promotion -Wimplicit-fallthrough -Wextra-semi -Woverloaded-virtual -Wnon-virtual-dtor -Wold-style-cast", + "CMAKE_EXE_LINKER_FLAGS": "-Wl,--allow-shlib-undefined,--as-needed,-z,noexecstack,-z,relro,-z,now,-z,nodlopen", + "CMAKE_SHARED_LINKER_FLAGS": "-Wl,--allow-shlib-undefined,--as-needed,-z,noexecstack,-z,relro,-z,now,-z,nodlopen" + } + }, + { + "name": "flags-appleclang", + "hidden": true, + "cacheVariables": { + "CMAKE_CXX_FLAGS": "-fstack-protector-strong -Wall -Wextra -Wpedantic -Wconversion -Wsign-conversion -Wcast-qual -Wformat=2 -Wundef -Werror=float-equal -Wshadow -Wcast-align -Wunused -Wnull-dereference -Wdouble-promotion -Wimplicit-fallthrough -Wextra-semi -Woverloaded-virtual -Wnon-virtual-dtor -Wold-style-cast" + } + }, + { + "name": "flags-msvc", + "description": "Note that all the flags after /W4 are required for MSVC to conform to the language standard", + "hidden": true, + "cacheVariables": { + "CMAKE_CXX_FLAGS": "/sdl /guard:cf /utf-8 /diagnostics:caret /w14165 /w44242 /w44254 /w44263 /w34265 /w34287 /w44296 /w44365 /w44388 /w44464 /w14545 /w14546 /w14547 /w14549 /w14555 /w34619 /w34640 /w24826 /w14905 /w14906 /w14928 /w45038 /W4 /permissive- /volatile:iso /Zc:inline /Zc:preprocessor /Zc:enumTypes /Zc:lambda /Zc:__cplusplus /Zc:externConstexpr /Zc:throwingNew /EHsc", + "CMAKE_EXE_LINKER_FLAGS": "/machine:x64 /guard:cf" + } + }, + { + "name": "ci-linux", + "inherits": ["flags-gcc-clang", "ci-std"], + "generator": "Unix Makefiles", + "hidden": true, + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release" + } + }, + { + "name": "ci-darwin", + "inherits": ["flags-appleclang", "ci-std"], + "generator": "Xcode", + "hidden": true + }, + { + "name": "ci-win64", + "inherits": ["flags-msvc", "ci-std"], + "generator": "Visual Studio 17 2022", + "architecture": "x64", + "hidden": true + }, + { + "name": "coverage-linux", + "binaryDir": "${sourceDir}/build/coverage", + "inherits": "ci-linux", + "hidden": true, + "cacheVariables": { + "ENABLE_COVERAGE": "ON", + "CMAKE_BUILD_TYPE": "Coverage", + "CMAKE_CXX_FLAGS_COVERAGE": "-Og -g --coverage -fkeep-inline-functions -fkeep-static-functions", + "CMAKE_EXE_LINKER_FLAGS_COVERAGE": "--coverage", + "CMAKE_SHARED_LINKER_FLAGS_COVERAGE": "--coverage", + "CMAKE_MAP_IMPORTED_CONFIG_COVERAGE": "Coverage;RelWithDebInfo;Release;Debug;" + } + }, + { + "name": "ci-coverage", + "inherits": ["coverage-linux", "dev-mode", "conan"], + "cacheVariables": { + "COVERAGE_HTML_COMMAND": "" + } + }, + { + "name": "ci-sanitize", + "binaryDir": "${sourceDir}/build/sanitize", + "inherits": ["ci-linux", "dev-mode", "conan"], + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Sanitize", + "CMAKE_CXX_FLAGS_SANITIZE": "-U_FORTIFY_SOURCE -O2 -g -fsanitize=address,undefined -fno-omit-frame-pointer -fno-common", + "CMAKE_MAP_IMPORTED_CONFIG_SANITIZE": "Sanitize;RelWithDebInfo;Release;Debug;" + } + }, + { + "name": "ci-build", + "binaryDir": "${sourceDir}/build", + "hidden": true + }, + { + "name": "ci-multi-config", + "description": "Speed up multi-config generators by generating only one configuration instead of the defaults", + "hidden": true, + "cacheVariables": { + "CMAKE_CONFIGURATION_TYPES": "Release" + } + }, + { + "name": "ci-macos", + "inherits": ["ci-build", "ci-darwin", "dev-mode", "ci-multi-config", "conan"] + }, + { + "name": "ci-ubuntu", + "inherits": ["ci-build", "ci-linux", "clang-tidy", "conan", "cppcheck", "dev-mode"] + }, + { + "name": "ci-windows", + "inherits": ["ci-build", "ci-win64", "dev-mode", "ci-multi-config", "conan"] + } + ] +} diff --git a/CMakeUserPresets.json b/CMakeUserPresets.json new file mode 100644 index 0000000..efc41f5 --- /dev/null +++ b/CMakeUserPresets.json @@ -0,0 +1,70 @@ +{ + "version": 2, + "cmakeMinimumRequired": { + "major": 3, + "minor": 14, + "patch": 0 + }, + "configurePresets": [ + { + "name": "dev-common", + "hidden": true, + "inherits": ["dev-mode", "conan", "clang-tidy", "cppcheck"] + }, + { + "name": "dev-linux", + "binaryDir": "${sourceDir}/build/dev-linux", + "inherits": ["dev-common", "ci-linux"], + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "CMAKE_EXPORT_COMPILE_COMMANDS": "ON" + } + }, + { + "name": "dev-darwin", + "binaryDir": "${sourceDir}/build/dev-darwin", + "inherits": ["dev-common", "ci-darwin"] + }, + { + "name": "dev-win64", + "binaryDir": "${sourceDir}/build/dev-win64", + "inherits": ["dev-common", "ci-win64"], + "environment": { + "UseMultiToolTask": "true", + "EnforceProcessCountAcrossBuilds": "true" + } + }, + { + "name": "dev", + "binaryDir": "${sourceDir}/build/dev", + "inherits": "dev-linux" + }, + { + "name": "dev-coverage", + "binaryDir": "${sourceDir}/build/coverage", + "inherits": ["dev-mode", "coverage-linux", "conan"] + } + ], + "buildPresets": [ + { + "name": "dev", + "configurePreset": "dev", + "configuration": "Debug", + "jobs": 32 + } + ], + "testPresets": [ + { + "name": "dev", + "configurePreset": "dev", + "configuration": "Debug", + "output": { + "outputOnFailure": true + }, + "execution": { + "jobs": 32, + "noTestsAction": "error" + } + } + ] +} diff --git a/Makefile b/Makefile index 239dac0..e4c6fc8 100644 --- a/Makefile +++ b/Makefile @@ -1,26 +1,37 @@ -.PHONY: install test ci lint format unit integration +.PHONY: py-install py-test py-ci py-lint py-format py-unit py-integration cpp-deps cpp-init cpp-build -install: +py-install: poetry lock --no-update poetry install poetry env use python3.12 -test: lint unit +py-test: lint unit -ci: test integration +py-ci: test integration -lint: +py-lint: poetry run mypy . poetry run ruff check . poetry run ruff format --check -format: +py-format: poetry run ruff format poetry run ruff check --fix -unit: +py-unit: poetry run pytest src/pysrc/test/unit -integration: +py-integration: poetry run pytest src/pysrc/test/integration +cpp-deps: + conan install . -s build_type=Debug -b missing -pr cpp23 -pr:b cpp23 + +cpp-init: + cmake --preset=dev + +cpp-build: + cmake --build --preset=dev -j + +cpp-test: + ctest --preset=dev --timeout 1 diff --git a/cmake/dev-mode.cmake b/cmake/dev-mode.cmake new file mode 100644 index 0000000..f096cd8 --- /dev/null +++ b/cmake/dev-mode.cmake @@ -0,0 +1,18 @@ +include(cmake/folders.cmake) + +include(CTest) +if(BUILD_TESTING) + add_subdirectory(src/cppsrc/test) +endif() + +add_custom_target( + run-exe + COMMAND desk_monorepo_exe + VERBATIM +) +add_dependencies(run-exe desk_monorepo_exe) + +include(cmake/lint-targets.cmake) +include(cmake/spell-targets.cmake) + +add_folders(Project) diff --git a/cmake/folders.cmake b/cmake/folders.cmake new file mode 100644 index 0000000..da7bd33 --- /dev/null +++ b/cmake/folders.cmake @@ -0,0 +1,21 @@ +set_property(GLOBAL PROPERTY USE_FOLDERS YES) + +# Call this function at the end of a directory scope to assign a folder to +# targets created in that directory. Utility targets will be assigned to the +# UtilityTargets folder, otherwise to the ${name}Targets folder. If a target +# already has a folder assigned, then that target will be skipped. +function(add_folders name) + get_property(targets DIRECTORY PROPERTY BUILDSYSTEM_TARGETS) + foreach(target IN LISTS targets) + get_property(folder TARGET "${target}" PROPERTY FOLDER) + if(DEFINED folder) + continue() + endif() + set(folder Utility) + get_property(type TARGET "${target}" PROPERTY TYPE) + if(NOT type STREQUAL "UTILITY") + set(folder "${name}") + endif() + set_property(TARGET "${target}" PROPERTY FOLDER "${folder}Targets") + endforeach() +endfunction() diff --git a/cmake/install-rules.cmake b/cmake/install-rules.cmake new file mode 100644 index 0000000..60d2dc4 --- /dev/null +++ b/cmake/install-rules.cmake @@ -0,0 +1,8 @@ +install( + TARGETS desk_monorepo_exe + RUNTIME COMPONENT desk_monorepo_Runtime +) + +if(PROJECT_IS_TOP_LEVEL) + include(CPack) +endif() diff --git a/cmake/lint-targets.cmake b/cmake/lint-targets.cmake new file mode 100644 index 0000000..4caa363 --- /dev/null +++ b/cmake/lint-targets.cmake @@ -0,0 +1,33 @@ +set( + FORMAT_PATTERNS + src/cppsrc/src/*.cpp src/cppsrc/src/*.hpp + include/*.hpp + src/cppsrc/test/*.cpp src/cppsrc/test/*.hpp + CACHE STRING + "; separated patterns relative to the project source dir to format" +) + +set(FORMAT_COMMAND clang-format CACHE STRING "Formatter to use") + +add_custom_target( + format-check + COMMAND "${CMAKE_COMMAND}" + -D "FORMAT_COMMAND=${FORMAT_COMMAND}" + -D "PATTERNS=${FORMAT_PATTERNS}" + -P "${PROJECT_SOURCE_DIR}/cmake/lint.cmake" + WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}" + COMMENT "Linting the code" + VERBATIM +) + +add_custom_target( + format-fix + COMMAND "${CMAKE_COMMAND}" + -D "FORMAT_COMMAND=${FORMAT_COMMAND}" + -D "PATTERNS=${FORMAT_PATTERNS}" + -D FIX=YES + -P "${PROJECT_SOURCE_DIR}/cmake/lint.cmake" + WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}" + COMMENT "Fixing the code" + VERBATIM +) diff --git a/cmake/lint.cmake b/cmake/lint.cmake new file mode 100644 index 0000000..42a89aa --- /dev/null +++ b/cmake/lint.cmake @@ -0,0 +1,51 @@ +cmake_minimum_required(VERSION 3.14) + +macro(default name) + if(NOT DEFINED "${name}") + set("${name}" "${ARGN}") + endif() +endmacro() + +default(FORMAT_COMMAND clang-format) +default( + PATTERNS + src/cppsrc/src/*.cpp src/cppsrc/src/*.hpp + include/*.hpp + src/cppsrc/test/*.cpp src/cppsrc/test/*.hpp +) +default(FIX NO) + +set(flag --output-replacements-xml) +set(args OUTPUT_VARIABLE output) +if(FIX) + set(flag -i) + set(args "") +endif() + +file(GLOB_RECURSE files ${PATTERNS}) +set(badly_formatted "") +set(output "") +string(LENGTH "${CMAKE_SOURCE_DIR}/" path_prefix_length) + +foreach(file IN LISTS files) + execute_process( + COMMAND "${FORMAT_COMMAND}" --style=file "${flag}" "${file}" + WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" + RESULT_VARIABLE result + ${args} + ) + if(NOT result EQUAL "0") + message(FATAL_ERROR "'${file}': formatter returned with ${result}") + endif() + if(NOT FIX AND output MATCHES "\n + +library::library() + : name {fmt::format("{}", "desk_monorepo")} +{ +} diff --git a/src/cppsrc/src/lib.hpp b/src/cppsrc/src/lib.hpp new file mode 100644 index 0000000..70c8478 --- /dev/null +++ b/src/cppsrc/src/lib.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include + +/** + * @brief The core implementation of the executable + * + * This class makes up the library part of the executable, which means that the + * main logic is implemented here. This kind of separation makes it easy to + * test the implementation for the executable, because the logic is nicely + * separated from the command-line logic implemented in the main function. + */ +struct library +{ + /** + * @brief Simply initializes the name member to the name of the project + */ + library(); + + std::string name; +}; diff --git a/src/cppsrc/src/main.cpp b/src/cppsrc/src/main.cpp new file mode 100644 index 0000000..e002b9a --- /dev/null +++ b/src/cppsrc/src/main.cpp @@ -0,0 +1,12 @@ +#include +#include + +#include "lib.hpp" + +auto main() -> int +{ + auto const lib = library {}; + auto const message = "Hello from " + lib.name + "!"; + std::cout << message << '\n'; + return 0; +} diff --git a/src/cppsrc/test/CMakeLists.txt b/src/cppsrc/test/CMakeLists.txt new file mode 100644 index 0000000..90f0069 --- /dev/null +++ b/src/cppsrc/test/CMakeLists.txt @@ -0,0 +1,26 @@ +# Parent project does not export its library target, so this CML implicitly +# depends on being added from it, i.e. the testing is done only from the build +# tree and is not feasible from an install location + +project(desk_monorepoTests LANGUAGES CXX) + +# ---- Dependencies ---- + +find_package(Catch2 REQUIRED) +include(Catch) + +# ---- Tests ---- + +add_executable(desk_monorepo_test src/desk_monorepo_test.cpp) +target_link_libraries( + desk_monorepo_test PRIVATE + desk_monorepo_lib + Catch2::Catch2WithMain +) +target_compile_features(desk_monorepo_test PRIVATE cxx_std_20) + +catch_discover_tests(desk_monorepo_test) + +# ---- End-of-file commands ---- + +add_folders(Test) diff --git a/src/cppsrc/test/src/desk_monorepo_test.cpp b/src/cppsrc/test/src/desk_monorepo_test.cpp new file mode 100644 index 0000000..af9eff0 --- /dev/null +++ b/src/cppsrc/test/src/desk_monorepo_test.cpp @@ -0,0 +1,9 @@ +#include + +#include "lib.hpp" + +TEST_CASE("Name is desk_monorepo", "[library]") +{ + auto const lib = library {}; + REQUIRE(lib.name == "desk_monorepo"); +}