diff --git a/.clang-format b/.clang-format index ffd5aa94..a96759cf 100644 --- a/.clang-format +++ b/.clang-format @@ -1,98 +1,47 @@ -AccessModifierOffset: -2 -AlignAfterOpenBracket: DontAlign -AlignConsecutiveAssignments: false -AlignConsecutiveDeclarations: false +# yaml-language-server: $schema=https://raw.githubusercontent.com/grizzie17/clang-format-schema/master/clang-format-schema.json + +# Reference: https://clang.llvm.org/docs/ClangFormatStyleOptions.html + +AlignArrayOfStructures: Left +AlignConsecutiveAssignments: + AlignCompound: true + Enabled: true +AlignConsecutiveBitFields: + Enabled: true +AlignConsecutiveDeclarations: + Enabled: true +AlignConsecutiveMacros: + Enabled: true AlignEscapedNewlines: Left -AlignOperands: true -AlignTrailingComments: false +AlignOperands: AlignAfterOperator +AllowAllArgumentsOnNextLine: false AllowAllParametersOfDeclarationOnNextLine: false -AllowShortBlocksOnASingleLine: true -AllowShortCaseLabelsOnASingleLine: false -AllowShortFunctionsOnASingleLine: All -AllowShortIfStatementsOnASingleLine: true -AllowShortLoopsOnASingleLine: true -AlwaysBreakAfterDefinitionReturnType: None -AlwaysBreakAfterReturnType: None -AlwaysBreakBeforeMultilineStrings: true -AlwaysBreakTemplateDeclarations: false +AllowShortBlocksOnASingleLine: Empty +AllowShortEnumsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Empty +AllowShortIfStatementsOnASingleLine: WithoutElse +AllowShortLambdasOnASingleLine: Empty +AlwaysBreakTemplateDeclarations: Yes BinPackArguments: false BinPackParameters: false -BraceWrapping: - AfterClass: true - AfterControlStatement: false - AfterEnum: false - AfterFunction: true - AfterNamespace: false - AfterObjCDeclaration: false - AfterStruct: true - AfterUnion: false - BeforeCatch: false - BeforeElse: false - IndentBraces: false - SplitEmptyFunction: false - SplitEmptyNamespace: true - SplitEmptyRecord: true -BreakAfterJavaFieldAnnotations: true BreakBeforeBinaryOperators: NonAssignment -BreakBeforeBraces: Custom -BreakBeforeInheritanceComma: true -BreakBeforeTernaryOperators: true -BreakConstructorInitializers: BeforeColon -BreakConstructorInitializersBeforeComma: false -BreakStringLiterals: true +BreakConstructorInitializers: AfterColon +BreakInheritanceList: AfterColon ColumnLimit: 120 -CommentPragmas: '^ IWYU pragma:' -CompactNamespaces: false -ConstructorInitializerAllOnOneLineOrOnePerLine: false -ConstructorInitializerIndentWidth: 2 -ContinuationIndentWidth: 2 -Cpp11BracedListStyle: false -DerivePointerAlignment: false -DisableFormat: false +EmptyLineBeforeAccessModifier: Always ExperimentalAutoDetectBinPacking: true -FixNamespaceComments: true -ForEachMacros: -- foreach -- Q_FOREACH -- BOOST_FOREACH -IncludeCategories: -- Priority: 2 - Regex: ^"(llvm|llvm-c|clang|clang-c)/ -- Priority: 3 - Regex: ^(<|"(gtest|gmock|isl|json)/) -- Priority: 1 - Regex: .* -IncludeIsMainRegex: (Test)?$ -IndentCaseLabels: false -IndentWidth: 2 -IndentWrappedFunctionNames: true -JavaScriptQuotes: Leave -JavaScriptWrapImports: true -KeepEmptyLinesAtTheStartOfBlocks: true -Language: Cpp -MacroBlockBegin: '' -MacroBlockEnd: '' -MaxEmptyLinesToKeep: 2 -NamespaceIndentation: Inner -ObjCBlockIndentWidth: 7 -ObjCSpaceAfterProperty: true -ObjCSpaceBeforeProtocolList: false -PointerAlignment: Right -ReflowComments: true -SortIncludes: true -SortUsingDeclarations: false -SpaceAfterCStyleCast: false -SpaceAfterTemplateKeyword: false -SpaceBeforeAssignmentOperators: true -SpaceBeforeParens: ControlStatements -SpaceInEmptyParentheses: false -SpacesBeforeTrailingComments: 0 -SpacesInAngles: false -SpacesInCStyleCastParentheses: false -SpacesInContainerLiterals: true -SpacesInParentheses: false -SpacesInSquareBrackets: false -Standard: c++20 -TabWidth: 8 -UseTab: Never - +IncludeBlocks: Regroup +IndentCaseLabels: true +IndentExternBlock: Indent +IndentWidth: 4 +InsertBraces: true +InsertTrailingCommas: Wrapped +KeepEmptyLinesAtTheStartOfBlocks: false +NamespaceIndentation: All +PackConstructorInitializers: CurrentLine +QualifierAlignment: Left +RemoveSemicolon: true +RequiresClausePosition: SingleLine +SeparateDefinitionBlocks: Always +SortIncludes: CaseInsensitive +SortUsingDeclarations: LexicographicNumeric diff --git a/.clang-tidy b/.clang-tidy index cdfaf8b2..02b2417c 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,30 +1,20 @@ ---- Checks: "*, - -abseil-*, - -altera-*, - -android-*, - -fuchsia-*, - -google-*, - -llvm*, - -modernize-use-trailing-return-type, - -zircon-*, - -readability-else-after-return, - -readability-static-accessed-through-instance, - -readability-avoid-const-params-in-decls, - -cppcoreguidelines-non-private-member-variables-in-classes, - -misc-non-private-member-variables-in-classes, -" -WarningsAsErrors: '' -HeaderFilterRegex: '' -FormatStyle: none + -abseil-*, + -altera-*, + -android-*, + -fuchsia-*, + -google-*, + -llvm*, + -zircon-*, + -*-non-private-member-variables-in-classes, + " CheckOptions: - - key: readability-identifier-length.IgnoredVariableNames - value: 'x|y|z' - key: readability-identifier-length.IgnoredParameterNames - value: 'x|y|z' - - - - + value: "x|y|z" + - key: readability-identifier-length.IgnoredVariableNames + value: "x|y|z" +FormatStyle: none +HeaderFilterRegex: "" +WarningsAsErrors: "" diff --git a/.clangd.in b/.clangd.in new file mode 100644 index 00000000..16cb4c9b --- /dev/null +++ b/.clangd.in @@ -0,0 +1,2 @@ +CompileFlags: + CompilationDatabase: "@CMAKE_BINARY_DIR@" diff --git a/.cmake-format.json b/.cmake-format.json new file mode 100644 index 00000000..f5a47a70 --- /dev/null +++ b/.cmake-format.json @@ -0,0 +1,13 @@ +{ + "$schema": "https://raw.githubusercontent.com/voidei/cmake_format/master/cmakelang/vscode_extension/schema/cmake-format.schema.json", + "encode": {}, + "format": { + "autosort": true, + "dangle_parens": true, + "line_width": 120 + }, + "lint": {}, + "markup": {}, + "misc": {}, + "parse": {} +} diff --git a/.cmake-format.yaml b/.cmake-format.yaml deleted file mode 100644 index 33bfdae7..00000000 --- a/.cmake-format.yaml +++ /dev/null @@ -1,21 +0,0 @@ -additional_commands: - foo: - flags: - - BAR - - BAZ - kwargs: - DEPENDS: '*' - HEADERS: '*' - SOURCES: '*' -bullet_char: '*' -dangle_parens: false -enum_char: . -line_ending: unix -line_width: 120 -max_pargs_hwrap: 3 -separate_ctrl_name_with_space: false -separate_fn_name_with_space: false -tab_size: 2 - -markup: - enable_markup: false diff --git a/.devcontainer/.dockerignore b/.devcontainer/.dockerignore deleted file mode 100644 index de407478..00000000 --- a/.devcontainer/.dockerignore +++ /dev/null @@ -1,34 +0,0 @@ -# Build directories and binary files -build/ -out/ -cmake-build-*/ - -# User spesific settings -CMakeUserPresets.json - -# IDE files -.vs/ -.idea/ -.vscode/ -!.vscode/settings.json -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/extensions.json -*.swp -*~ -_ReSharper* -*.log - -# OS Generated Files -.DS_Store -.AppleDouble -.LSOverride -._* -.Spotlight-V100 -.Trashes -.Trash-* -$RECYCLE.BIN/ -.TemporaryItems -ehthumbs.db -Thumbs.db -Dockerfile \ No newline at end of file diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index e948180e..3925a7ac 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,120 +1,218 @@ -# [Choice] bionic (18.04), focal (20.04) -ARG VARIANT="focal" +# syntax=docker/dockerfile:1.5-labs + +# bionic[18.04], focal[20.04], jammy[22.04], kinetic[22.10], lunar[23.04] +ARG VARIANT="jammy" + FROM ubuntu:${VARIANT} -# Restate the variant to use it later on in the llvm and cmake installations -ARG VARIANT +ARG DEBIAN_FRONTEND="noninteractive" -# Install necessary packages available from standard repos -RUN apt-get update -qq && export DEBIAN_FRONTEND=noninteractive && \ - apt-get install -y --no-install-recommends \ - software-properties-common wget apt-utils file zip \ - openssh-client gpg-agent socat rsync \ - make ninja-build git \ - python3 python3-pip +# Some mirrors may require handshake -# Install conan -RUN python3 -m pip install --upgrade pip setuptools && \ - python3 -m pip install conan && \ - conan --version +RUN <> "${list_path}" + } + + . /etc/os-release + + add_apt_repository "deadsnakes-ubuntu-nightly-${VERSION_CODENAME}" "https://ppa.launchpadcontent.net/deadsnakes/nightly/ubuntu ${VERSION_CODENAME} main" "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0xf23c5a6cf475977595c89f51ba6932366a755776" + add_apt_repository "deadsnakes-ubuntu-ppa-${VERSION_CODENAME}" "https://ppa.launchpadcontent.net/deadsnakes/ppa/ubuntu ${VERSION_CODENAME} main" "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0xf23c5a6cf475977595c89f51ba6932366a755776" + add_apt_repository "kitware-archive-keyring" "https://apt.kitware.com/ubuntu ${VERSION_CODENAME} main" "https://apt.kitware.com/keys/kitware-archive-latest.asc" + add_apt_repository "kitware-archive-keyring" "https://apt.kitware.com/ubuntu ${VERSION_CODENAME}-rc main" "https://apt.kitware.com/keys/kitware-archive-latest.asc" + add_apt_repository "ubuntu-toolchain-r-ubuntu-ppa-${VERSION_CODENAME}" "https://ppa.launchpadcontent.net/ubuntu-toolchain-r/ppa/ubuntu ${VERSION_CODENAME} main" "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x60c317803a41ba51845e371a1e9377a2ba9ef27f" + add_apt_repository "ubuntu-toolchain-r-ubuntu-test-${VERSION_CODENAME}" "https://ppa.launchpadcontent.net/ubuntu-toolchain-r/test/ubuntu ${VERSION_CODENAME} main" "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x60c317803a41ba51845e371a1e9377a2ba9ef27f" +EOF + +# Setup locales and timezone + +ENV TZ="UTC" + +RUN </dev/null && \ - add-apt-repository -y "deb ${LLVM_URL} ${LLVM_PKG} main" && \ - apt-get update -qq && export DEBIAN_FRONTEND=noninteractive && \ - apt-get install -y --no-install-recommends \ - clang-${LLVM_VER} lldb-${LLVM_VER} lld-${LLVM_VER} clangd-${LLVM_VER} \ - llvm-${LLVM_VER}-dev libclang-${LLVM_VER}-dev clang-tidy-${LLVM_VER} - -# Set the default clang-tidy, so CMake can find it -RUN update-alternatives --install /usr/bin/clang-tidy clang-tidy $(which clang-tidy-${LLVM_VER}) 1 - -# Set clang-${LLVM_VER} as default clang -RUN update-alternatives --install /usr/bin/clang clang $(which clang-${LLVM_VER}) 100 -RUN update-alternatives --install /usr/bin/clang++ clang++ $(which clang++-${LLVM_VER}) 100 - -# Add current cmake/ccmake, from Kitware -ARG CMAKE_URL="https://apt.kitware.com/ubuntu/" -ARG CMAKE_PKG=${VARIANT} -RUN wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null \ - | gpg --dearmor - | tee /etc/apt/trusted.gpg.d/kitware.gpg >/dev/null && \ - apt-add-repository -y "deb ${CMAKE_URL} ${CMAKE_PKG} main" && \ - apt-get update -qq && export DEBIAN_FRONTEND=noninteractive && \ - apt-get install -y --no-install-recommends cmake cmake-curses-gui - -# Install editors -RUN apt-get update -qq && export DEBIAN_FRONTEND=noninteractive && \ - apt-get install -y --no-install-recommends \ - neovim emacs nano - -# Install optional dependecies -RUN apt-get update -qq && export DEBIAN_FRONTEND=noninteractive && \ - apt-get install -y --no-install-recommends \ - doxygen graphviz ccache cppcheck - -# Install include-what-you-use -ENV IWYU /home/iwyu -ENV IWYU_BUILD ${IWYU}/build -ENV IWYU_SRC ${IWYU}/include-what-you-use -RUN mkdir -p ${IWYU_BUILD} && \ - git clone --branch clang_${LLVM_VER} \ - https://github.com/include-what-you-use/include-what-you-use.git \ - ${IWYU_SRC} -RUN CC=clang-${LLVM_VER} CXX=clang++-${LLVM_VER} cmake -S ${IWYU_SRC} \ - -B ${IWYU_BUILD} \ - -G "Unix Makefiles" -DCMAKE_PREFIX_PATH=/usr/lib/llvm-${LLVM_VER} && \ - cmake --build ${IWYU_BUILD} -j && \ - cmake --install ${IWYU_BUILD} - -# Per https://github.com/include-what-you-use/include-what-you-use#how-to-install: -# `You need to copy the Clang include directory to the expected location before -# running (similarly, use include-what-you-use -print-resource-dir to learn -# exactly where IWYU wants the headers).` -RUN mkdir -p $(include-what-you-use -print-resource-dir 2>/dev/null) -RUN ln -s $(readlink -f /usr/lib/clang/${LLVM_VER}/include) \ - $(include-what-you-use -print-resource-dir 2>/dev/null)/include - -## Cleanup cached apt data we don't need anymore -RUN apt-get autoremove -y && apt-get clean && \ +ENV CONAN_SYSREQUIRES_MODE="enabled" +# By default, anything you run in Docker is done as superuser. +# Conan runs some install commands as superuser, and will prepend `sudo` to +# these commands, unless `CONAN_SYSREQUIRES_SUDO=0` is in your env variables. +ENV CONAN_SYSREQUIRES_SUDO="0" + +RUN <" run: | - cmake --build ./build --config ${{matrix.build_type}} + cmake --build ./build --config ${{ matrix.build_type }} - name: Unix - Test and coverage if: runner.os != 'Windows' - working-directory: ./build # Execute tests defined by the CMake configuration. # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail run: | - ctest -C ${{matrix.build_type}} - gcovr -j ${{env.nproc}} --delete --root ../ --print-summary --xml-pretty --xml coverage.xml . --gcov-executable '${{ matrix.gcov_executable }}' + ctest -C ${{ matrix.build_type }} + gcovr -j ${{ env.nproc }} --delete --root ../ --print-summary --xml-pretty --xml coverage.xml . --gcov-executable '${{ matrix.gcov_executable }}' + working-directory: ./build - name: Windows - Test and coverage if: runner.os == 'Windows' - working-directory: ./build run: | - OpenCppCoverage.exe --export_type cobertura:coverage.xml --cover_children -- ctest -C ${{matrix.build_type}} + OpenCppCoverage.exe --export_type cobertura:coverage.xml --cover_children -- ctest -C ${{ matrix.build_type }} + working-directory: ./build - name: CPack if: matrix.package_generator != '' - working-directory: ./build run: | - cpack -C ${{matrix.build_type}} -G ${{matrix.package_generator}} + cpack -C ${{ matrix.build_type }} -G ${{ matrix.package_generator }} + working-directory: ./build - name: Publish Tagged Release - uses: softprops/action-gh-release@v1 if: ${{ startsWith(github.ref, 'refs/tags/') && matrix.package_generator != '' }} + uses: softprops/action-gh-release@v1 with: files: | build/*-*${{ matrix.build_type }}*-*.* - - name: Publish to codecov uses: codecov/codecov-action@v2 with: + files: ./build/coverage.xml flags: ${{ runner.os }} name: ${{ runner.os }}-coverage - files: ./build/coverage.xml diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index e21dc29e..c3013bbc 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -8,23 +8,29 @@ # We have attempted to detect the languages in your repository. Please check # the `language` matrix defined below to confirm you have the correct set of # supported CodeQL languages. -# + name: "CodeQL" on: - push: - branches: [ main, develop ] pull_request: - # The branches below must be a subset of the branches above - branches: [ main, develop ] - schedule: - - cron: '38 0 * * 5' + # The branches below must be a subset of the `push` section + branches: + - develop + - main + push: + branches: + - develop + - main + + schedule: + - cron: "38 0 * * 5" jobs: analyze: name: Analyze runs-on: ubuntu-latest + permissions: actions: read contents: read @@ -33,75 +39,77 @@ jobs: strategy: fail-fast: false matrix: - language: [ 'cpp' ] - # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] - # Learn more about CodeQL language support at https://git.io/codeql-language-support + build_type: + - Debug compiler: # you can specify the version after `-` like "llvm-13.0.0". - gcc-11 generator: - "Ninja Multi-Config" - build_type: - - Debug + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] + # Learn more about CodeQL language support at https://git.io/codeql-language-support + language: + - cpp packaging_maintainer_mode: - ON - steps: - - uses: actions/checkout@v3 - - - name: Setup Cache - uses: ./.github/actions/setup_cache - with: - compiler: ${{ matrix.compiler }} - build_type: ${{ matrix.build_type }} - packaging_maintainer_mode: ${{ matrix.packaging_maintainer_mode }} - generator: ${{ matrix.generator }} - - - name: Project Name - uses: cardinalby/export-env-action@v2 - with: - envFile: '.github/constants.env' - - - - name: Setup Cpp - uses: aminya/setup-cpp@v1 - with: - compiler: ${{ matrix.compiler }} - vcvarsall: ${{ contains(matrix.os, 'windows' )}} - - cmake: true - ninja: true - vcpkg: false - ccache: true - clangtidy: false - - cppcheck: false - - gcovr: false - opencppcoverage: false - - # make sure coverage is only enabled for Debug builds, since it sets -O0 to make sure coverage - # has meaningful results - - name: Configure CMake - run: | - cmake -S . -B ./build -G "${{matrix.generator}}" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -D${{ env.PROJECT_NAME }}_PACKAGING_MAINTAINER_MODE:BOOL=${{matrix.packaging_maintainer_mode}} -D${{ env.PROJECT_NAME }}_ENABLE_COVERAGE:BOOL=${{ matrix.build_type == 'Debug' }} - - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v2 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - # queries: ./path/to/local/query, your-org/your-repo/queries@main - - - - name: Build - # Execute the build. You can specify a specific target with "--target " - run: | - cmake --build ./build --config ${{matrix.build_type}} - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + - name: Checkout repository + uses: actions/checkout@master + with: + fetch-depth: 1 + + - name: Setup Cache + uses: ./.github/actions/setup_cache + with: + build_type: ${{ matrix.build_type }} + compiler: ${{ matrix.compiler }} + generator: ${{ matrix.generator }} + packaging_maintainer_mode: ${{ matrix.packaging_maintainer_mode }} + + - name: Project Name + uses: cardinalby/export-env-action@v2 + with: + envFile: ".github/constants.env" + + - name: Setup Cpp + uses: aminya/setup-cpp@v1 + with: + ccache: true + clangtidy: false + cmake: true + compiler: ${{ matrix.compiler }} + cppcheck: false + gcovr: false + ninja: true + opencppcoverage: false + vcpkg: false + vcvarsall: ${{ contains(matrix.os, 'windows') }} + + # make sure coverage is only enabled for Debug builds, since it sets -O0 to make sure coverage + # has meaningful results + - name: Configure CMake + run: | + cmake -B ./build -S . \ + -D${{ env.PROJECT_NAME }}_ENABLE_COVERAGE:BOOL=${{ matrix.build_type == 'Debug' }} \ + -D${{ env.PROJECT_NAME }}_PACKAGING_MAINTAINER_MODE:BOOL=${{ matrix.packaging_maintainer_mode }} \ + -DCMAKE_BUILD_TYPE:STRING=${{ matrix.build_type }} \ + -G "${{ matrix.generator }}" + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + # queries: ./path/to/local/query, your-org/your-repo/queries@main + + - name: Build + # Execute the build. You can specify a specific target with "--target " + run: | + cmake --build ./build --config ${{ matrix.build_type }} + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/devcontainer.yml b/.github/workflows/devcontainer.yml new file mode 100644 index 00000000..4b460486 --- /dev/null +++ b/.github/workflows/devcontainer.yml @@ -0,0 +1,93 @@ +name: Devcontainer + +on: + pull_request: + paths: + - ".devcontainer/**" + + push: + paths: + - ".devcontainer/**" + +env: + registry: ghcr.io + +jobs: + push: + runs-on: ubuntu-latest + + permissions: + contents: read + packages: write + id-token: write + + strategy: + fail-fast: false + matrix: + include: + - directory: .devcontainer + dockerfile: Dockerfile + image_name: devcontainers/cpp + + steps: + - name: Checkout repository + uses: actions/checkout@master + with: + fetch-depth: 1 + + - name: Install Cosign + if: github.event_name != 'pull_request' + uses: sigstore/cosign-installer@main + + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + + - name: Setup Docker Buildx + uses: docker/setup-buildx-action@v2 + + - name: Log into registry ${{ env.registry }} + if: github.event_name != 'pull_request' + uses: docker/login-action@v2 + with: + password: ${{ secrets.GITHUB_TOKEN }} + registry: ${{ env.registry }} + username: ${{ github.actor }} + + - name: Extract Docker metadata + id: meta + uses: docker/metadata-action@v4 + with: + images: ${{ env.registry }}/${{ github.repository_owner }}/${{ matrix.image_name }} + tags: | + enable={{is_default_branch}},type=raw,value=latest + event=branch,type=ref + event=pr,type=ref + type=schedule + pattern={{major}},type=semver + pattern={{major}}.{{minor},type=semver + pattern={{version}},type=semver + format=long,type=sha + + - name: Build and push Docker image + id: build-and-push + uses: docker/build-push-action@v3 + with: + cache-from: type=gha + cache-to: mode=max,type=gha + context: ${{ matrix.directory }} + file: ${{ matrix.directory }}/${{ matrix.dockerfile }} + labels: ${{ steps.meta.outputs.labels }} + platforms: linux/amd64,linux/arm64 + tags: ${{ steps.meta.outputs.tags }} + push: ${{ github.event_name != 'pull_request' }} + + - name: Sign the published Docker image + if: github.event_name != 'pull_request' + env: + COSIGN_EXPERIMENTAL: "true" + run: | + cosign sign --yes \ + -a "ref=${{ github.sha }}" \ + -a "repo=${{ github.repository }}" \ + -a "workflow=${{ github.workflow }}" \ + "${{ env.registry }}/${{ github.repository_owner }}/${{ matrix.image_name }}@${{ steps.build-and-push.outputs.digest }}" diff --git a/.github/workflows/template-janitor.yml b/.github/workflows/template-janitor.yml index 071ead0b..94e3b298 100644 --- a/.github/workflows/template-janitor.yml +++ b/.github/workflows/template-janitor.yml @@ -4,59 +4,63 @@ name: Template Janitor on: pull_request: - release: - types: [published] + push: - tags: branches: - - main - develop + - main + + release: + types: + - published env: TEMPLATES_PATH: ".github/template" - jobs: - template-cleanup: name: Cleanup after create runs-on: ubuntu-latest + strategy: matrix: - compiler: - - gcc-11 - generator: - - "Unix Makefiles" build_type: - Debug + compiler: + - gcc-11 developer_mode: - OFF + generator: + - "Unix Makefiles" steps: - - uses: actions/checkout@v3 + - name: Checkout repository + uses: actions/checkout@master + with: + fetch-depth: 1 - name: Setup Cache uses: ./.github/actions/setup_cache with: - compiler: ${{ matrix.compiler }} build_type: ${{ matrix.build_type }} + compiler: ${{ matrix.compiler }} developer_mode: ${{ matrix.developer_mode }} generator: ${{ matrix.generator }} - - name: Get organization and project name + - name: Get organization and project name run: | echo "NEW_ORG=${{ github.repository_owner }}" >> $GITHUB_ENV echo "NEW_PROJECT=${{ github.event.repository.name }}" >> $GITHUB_ENV echo "NEW_URL=${{ github.repositoryUrl }}" >> $GITHUB_ENV - uses: octokit/request-action@v2.x + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} id: get_repo_meta with: - route: GET /repos/{owner}/{repo} owner: ${{ env.NEW_ORG }} repo: ${{ env.NEW_PROJECT }} - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + route: GET /repos/{owner}/{repo} - name: Use testing variables if still a template if: fromJson(steps.get_repo_meta.outputs.data).is_template == true @@ -68,7 +72,7 @@ jobs: run: | # hyphens and dots in c++ identifiers are forbidden. Use underscores instead. NEW_SAFE_PROJECT=$(echo ${{ env.NEW_PROJECT }} | sed "s/-/_/g" | sed "s/\./_/g" ) - echo "NEW_SAFE_PROJECT=$NEW_SAFE_PROJECT" >> $GITHUB_ENV + echo "NEW_SAFE_PROJECT=$NEW_SAFE_PROJECT" >> $GITHUB_ENV # Rename all cpp_starter_project occurences to current repository and remove this workflow - name: Insert new org and project @@ -109,104 +113,104 @@ jobs: - name: Setup Cpp uses: aminya/setup-cpp@v1 with: - compiler: ${{ matrix.compiler }} - - cmake: true - ninja: false - vcpkg: false ccache: false clangtidy: false - + cmake: true + compiler: ${{ matrix.compiler }} cppcheck: false - gcovr: false + ninja: false opencppcoverage: false + vcpkg: false - name: Project Name uses: cardinalby/export-env-action@v2 with: - envFile: '.github/constants.env' - - + envFile: ".github/constants.env" - name: Test simple configuration to make sure nothing broke run: | - cmake -S . -B ./build -G "${{ matrix.generator }}" -DCMAKE_BUILD_TYPE:STRING=${{ matrix.build_type }} -D${{ env.NEW_SAFE_PROJECT }}_PACKAGING_MAINTAINER_MODE:BOOL=ON + cmake -B ./build -S . \ + -D${{ env.NEW_SAFE_PROJECT }}_PACKAGING_MAINTAINER_MODE:BOOL=ON \ + -DCMAKE_BUILD_TYPE:STRING=${{ matrix.build_type }} \ + -G "${{ matrix.generator }}" + # Build it because we may have broken something in the cpp/hpp files cmake --build build - uses: EndBug/add-and-commit@v9 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # only commit and push if we are not a template project anymore! if: fromJson(steps.get_repo_meta.outputs.data).is_template != true with: add: -A - author_name: Template Janitor author_email: template.janitor@example.com - message: 'Cleanup template and initialize repository' + author_name: Template Janitor + message: "Cleanup template and initialize repository" pathspec_error_handling: exitImmediately - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - template-rename: name: Renames template when a new name is detected runs-on: ubuntu-latest + strategy: matrix: - compiler: - - gcc-11 - generator: - - "Unix Makefiles" build_type: - Debug + compiler: + - gcc-11 developer_mode: - OFF + generator: + - "Unix Makefiles" steps: - - uses: actions/checkout@v3 + - name: Checkout repository + uses: actions/checkout@master + with: + fetch-depth: 1 - name: Setup Cache uses: ./.github/actions/setup_cache with: - compiler: ${{ matrix.compiler }} build_type: ${{ matrix.build_type }} + compiler: ${{ matrix.compiler }} developer_mode: ${{ matrix.developer_mode }} generator: ${{ matrix.generator }} - - name: Get organization and project name + - name: Get organization and project name run: | - echo "TEST_RUN=false" >> $GITHUB_ENV echo "NEW_ORG=${{ github.repository_owner }}" >> $GITHUB_ENV echo "NEW_PROJECT=${{ github.event.repository.name }}" >> $GITHUB_ENV echo "NEW_REPOSITORY=${{ github.repository }}" >> $GITHUB_ENV echo "TEMPLATE_NAME=`cat ${{ env.TEMPLATES_PATH }}/template_name`" >> $GITHUB_ENV echo "TEMPLATE_REPOSITORY=`cat ${{ env.TEMPLATES_PATH }}/template_repository`" >> $GITHUB_ENV + echo "TEST_RUN=false" >> $GITHUB_ENV - uses: octokit/request-action@v2.x + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} id: get_repo_meta with: - route: GET /repos/{owner}/{repo} owner: ${{ env.NEW_ORG }} repo: ${{ env.NEW_PROJECT }} - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + route: GET /repos/{owner}/{repo} - name: Setup fake test org/project names if project didn't change if: env.TEMPLATE_NAME == env.NEW_PROJECT run: | - echo "TEST_RUN=true" >> $GITHUB_ENV echo "NEW_ORG=${{ github.repository_owner }}" >> $GITHUB_ENV echo "NEW_PROJECT=TEST_PROJECT" >> $GITHUB_ENV echo "NEW_REPOSITORY=TEST_REPOSITORY" >> $GITHUB_ENV - + echo "TEST_RUN=true" >> $GITHUB_ENV # Rename all cpp_starter_project occurrences to current repository and remove this workflow - name: Update repository to match new template information run: | - # Update the README and template files to match the new org / repository names - sed -i "s|${{ env.TEMPLATE_REPOSITORY }}|${{ env.NEW_REPOSITORY }}|g" README.md ${{ env.TEMPLATES_PATH }}/template_repository + # Update the README and template files to match the new org / repository names sed -i "s|${{ env.TEMPLATE_NAME }}|${{ env.NEW_PROJECT }}|g" README.md ${{ env.TEMPLATES_PATH }}/template_name + sed -i "s|${{ env.TEMPLATE_REPOSITORY }}|${{ env.NEW_REPOSITORY }}|g" README.md ${{ env.TEMPLATES_PATH }}/template_repository - name: Print diff after template name replacement run: | @@ -215,32 +219,31 @@ jobs: - name: Setup Cpp uses: aminya/setup-cpp@v1 with: - compiler: gcc - - cmake: true - ninja: false - vcpkg: false ccache: false clangtidy: false - + cmake: true + compiler: gcc cppcheck: false - gcovr: false + ninja: false opencppcoverage: false - + vcpkg: false - name: Test simple configuration to make sure nothing broke (default compiler,cmake,developer_mode OFF) run: | - cmake -S . -B ./build -G "${{ matrix.generator }}" -DCMAKE_BUILD_TYPE:STRING=${{ matrix.build_type }} -D${{ env.PROJECT_NAME }}_PACKAGING_MAINTAINER_MODE:BOOL=ON + cmake -B ./build -S . \ + -D${{ env.PROJECT_NAME }}_PACKAGING_MAINTAINER_MODE:BOOL=ON \ + -DCMAKE_BUILD_TYPE:STRING=${{ matrix.build_type }} \ + -G "${{ matrix.generator }}" - uses: EndBug/add-and-commit@v9 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # only commit and push if we are a template and project name has changed if: fromJson(steps.get_repo_meta.outputs.data).is_template == true && env.TEST_RUN == 'false' with: add: -A - author_name: Template Janitor author_email: template.janitor@example.com - message: 'Change Template Name' + author_name: Template Janitor + message: "Change Template Name" pathspec_error_handling: exitImmediately - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index a3f1df04..1cf77593 100644 --- a/.gitignore +++ b/.gitignore @@ -1,34 +1,20 @@ +# IDE files +.fleet/* +.idea/* +.vs/* + +.vscode/* +!.vscode/extensions.json +!.vscode/launch.json +!.vscode/settings.json +!.vscode/tasks.json + # Build directories and binary files +.clangd build/ -out/ cmake-build-*/ conan-cache/ +out/ # User spesific settings CMakeUserPresets.json - -# IDE files -.vs/ -.idea/ -.vscode/ -!.vscode/settings.json -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/extensions.json -*.swp -*~ -_ReSharper* -*.log - -# OS Generated Files -.DS_Store -.AppleDouble -.LSOverride -._* -.Spotlight-V100 -.Trashes -.Trash-* -$RECYCLE.BIN/ -.TemporaryItems -ehthumbs.db -Thumbs.db diff --git a/.lgtm.yml b/.lgtm.yml deleted file mode 100644 index 6b87f593..00000000 --- a/.lgtm.yml +++ /dev/null @@ -1,24 +0,0 @@ -# for full syntax documentation see: https://lgtm.com/help/lgtm/lgtm.yml-configuration-file -path_classifiers: - test: - - "*/fuzz_test/**/*" - - "*/test/**/*" -extraction: - cpp: - prepare: - packages: - - g++-10 - - ccache - script: - - mkdir ~/.conan - - cat /usr/local/share/ca-certificates/semmle-cache-ca/semmle-cache-ca.crt >> ~/.conan/cacert.pem - - python3 -m pip install --upgrade pip setuptools - - python3 -m pip install conan - - python3 -m pip install cmake - - source ~/.profile - configure: - command: - - mkdir build - - cmake -D OPT_ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug -D ENABLE_DEVELOPER_MODE:BOOL=FALSE -S . -B build - index: - build_command: cmake --build ./build -- -j2 diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 00000000..1b25851e --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,18 @@ +{ + "recommendations": [ + "cheshirekow.cmake-format", + "cschlosser.doxdocgen", + "eamodio.gitlens", + "editorconfig.editorconfig", + "esbenp.prettier-vscode", + "github.vscode-github-actions", + "github.vscode-pull-request-github", + "llvm-vs-code-extensions.vscode-clangd", + "ms-vscode.cpptools-extension-pack", + "ms-vscode.makefile-tools", + "ms-vscode.vscode-github-issue-notebooks", + "mutantdino.resourcemonitor", + "usernamehw.errorlens", + "vadimcn.vscode-lldb", + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..7fc6cf15 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,38 @@ +{ + /** c++ */ + "C_Cpp.intelliSenseEngine": "disabled", + "clangd.fallbackFlags": ["-I${workspaceFolder}", "-std=c++20"], + "cmake.configureOnOpen": false, + "cmakeFormat.args": [ + "--config-file", + "${workspaceFolder}/.cmake-format.json" + ], + /** formatting */ + "editor.formatOnSave": true, + "files.autoSave": "onFocusChange", + "[c][cpp]": { + "editor.defaultFormatter": "llvm-vs-code-extensions.vscode-clangd" + }, + "[dockercompose][json][jsonc][yaml]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + /** telemetry */ + "gitlens.telemetry.enabled": false, + "telemetry.telemetryLevel": "off", + /** ui */ + "editor.accessibilitySupport": "off", + "editor.fontLigatures": true, + "editor.inlayHints.enabled": "on", + "editor.inlineSuggest.enabled": true, + "editor.stickyScroll.enabled": true, + "explorer.confirmDelete": false, + "explorer.confirmDragAndDrop": false, + "explorer.openEditors.visible": 9, + "gitlens.views.searchAndCompare.files.layout": "tree", + "scm.defaultViewMode": "tree", + "workbench.colorTheme": "GitHub Dark Default", + "workbench.startupEditor": "none", + /** vsc */ + "git.autofetch": true, + "git.confirmSync": false +} diff --git a/CMakeLists.txt b/CMakeLists.txt index 45e19f03..b16d1fc7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,17 +1,15 @@ cmake_minimum_required(VERSION 3.21) -# This template attempts to be "fetch_content"-able -# so that it works well with tools like CPM or other -# manual dependency management +# This template attempts to be "fetch_content"-able so that it works well with tools like CPM or other manual dependency +# management # Only set the cxx_standard if it is not set by someone else -if (NOT DEFINED CMAKE_CXX_STANDARD) +if(NOT DEFINED CMAKE_CXX_STANDARD) set(CMAKE_CXX_STANDARD 20) endif() -# strongly encouraged to enable this globally to avoid conflicts between -# -Wpedantic being enabled and -std=c++20 and -std=gnu++20 for example -# when compiling with PCH enabled +# strongly encouraged to enable this globally to avoid conflicts between -Wpedantic being enabled and -std=c++20 and +# -std=gnu++20 for example when compiling with PCH enabled set(CMAKE_CXX_EXTENSIONS OFF) # Set the project name and language @@ -20,12 +18,12 @@ project( VERSION 0.0.1 DESCRIPTION "" HOMEPAGE_URL "%%myurl%%" - LANGUAGES CXX C) + LANGUAGES CXX C +) include(cmake/PreventInSourceBuilds.cmake) include(ProjectOptions.cmake) - myproject_setup_options() myproject_global_options() @@ -39,20 +37,17 @@ set(CMAKE_CXX_VISIBILITY_PRESET hidden) set(GIT_SHA "Unknown" - CACHE STRING "SHA this build was generated from") -string( - SUBSTRING "${GIT_SHA}" - 0 - 8 - GIT_SHORT_SHA) + CACHE STRING "SHA this build was generated from" +) +string(SUBSTRING "${GIT_SHA}" 0 8 GIT_SHORT_SHA) target_compile_features(myproject_options INTERFACE cxx_std_${CMAKE_CXX_STANDARD}) add_library(myproject::myproject_options ALIAS myproject_options) add_library(myproject::myproject_warnings ALIAS myproject_warnings) -#add_library(myproject::myproject_options INTERFACE IMPORTED) -#add_library(myproject::myproject_warnings INTERFACE IMPORTED) +# add_library(myproject::myproject_options INTERFACE IMPORTED) add_library(myproject::myproject_warnings INTERFACE +# IMPORTED) # configure files based on CMake configuration options add_subdirectory(configured_files) @@ -73,18 +68,17 @@ if(BUILD_TESTING) add_subdirectory(test) endif() - if(myproject_BUILD_FUZZ_TESTS) message(AUTHOR_WARNING "Building Fuzz Tests, using fuzzing sanitizer https://www.llvm.org/docs/LibFuzzer.html") - if (NOT myproject_ENABLE_ADDRESS_SANITIZER AND NOT myproject_ENABLE_THREAD_SANITIZER) + if(NOT myproject_ENABLE_ADDRESS_SANITIZER AND NOT myproject_ENABLE_THREAD_SANITIZER) message(WARNING "You need asan or tsan enabled for meaningful fuzz testing") endif() add_subdirectory(fuzz_test) endif() -# If MSVC is being used, and ASAN is enabled, we need to set the debugger environment -# so that it behaves well with MSVC's debugger, and we can run the target from visual studio +# If MSVC is being used, and ASAN is enabled, we need to set the debugger environment so that it behaves well with +# MSVC's debugger, and we can run the target from visual studio if(MSVC) get_all_installable_targets(all_targets) message("all_targets=${all_targets}") @@ -94,26 +88,24 @@ endif() # set the startup project for the "play" button in MSVC set_property(DIRECTORY PROPERTY VS_STARTUP_PROJECT intro) +# Temporary solution to let VSCode clangd extension correctly resolve dependencies. It does not affect compilation, but +# IDE experience. https://github.com/clangd/vscode-clangd/issues/48#issuecomment-987765846 +configure_file(.clangd.in ${CMAKE_SOURCE_DIR}/.clangd @ONLY) + if(CMAKE_SKIP_INSTALL_RULES) return() endif() include(cmake/PackageProject.cmake) -# Add other targets that you want installed here, by default we just package the one executable -# we know we want to ship +# Add other targets that you want installed here, by default we just package the one executable we know we want to ship myproject_package_project( - TARGETS - intro - myproject_options - myproject_warnings - # FIXME: this does not work! CK - # PRIVATE_DEPENDENCIES_CONFIGURED project_options project_warnings + TARGETS intro myproject_options myproject_warnings + # FIXME: this does not work! CK PRIVATE_DEPENDENCIES_CONFIGURED project_options project_warnings ) -# Experience shows that explicit package naming can help make it easier to sort -# out potential ABI related issues before they start, while helping you -# track a build to a specific GIT SHA +# Experience shows that explicit package naming can help make it easier to sort out potential ABI related issues before +# they start, while helping you track a build to a specific GIT SHA set(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${CMAKE_PROJECT_VERSION}-${GIT_SHORT_SHA}-${CMAKE_SYSTEM_NAME}-${CMAKE_BUILD_TYPE}-${CMAKE_CXX_COMPILER_ID}-${CMAKE_CXX_COMPILER_VERSION}" ) diff --git a/CMakePresets.json b/CMakePresets.json index 5871489e..4cfee7e8 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -1,254 +1,318 @@ { - "version": 3, - "cmakeMinimumRequired": { - "major": 3, - "minor": 21, - "patch": 0 - }, - "configurePresets": [ - { - "name": "conf-common", - "description": "General settings that apply to all configurations", - "hidden": true, - "generator": "Ninja", - "binaryDir": "${sourceDir}/out/build/${presetName}", - "installDir": "${sourceDir}/out/install/${presetName}" - }, - { - "name": "conf-windows-common", - "description": "Windows settings for MSBuild toolchain that apply to msvc and clang", - "hidden": true, - "inherits": "conf-common", - "condition": { - "type": "equals", - "lhs": "${hostSystemName}", - "rhs": "Windows" - }, - "architecture": { - "value": "x64", - "strategy": "external" - }, - "toolset": { - "value": "host=x64", - "strategy": "external" - }, - "cacheVariables": { - "ENABLE_CPPCHECK_DEFAULT": "FALSE", - "ENABLE_CLANG_TIDY_DEFAULT": "FALSE" - } - }, - { - "name": "conf-unixlike-common", - "description": "Unix-like OS settings for gcc and clang toolchains", - "hidden": true, - "inherits": "conf-common", - "condition": { - "type": "inList", - "string": "${hostSystemName}", - "list": [ - "Linux", - "Darwin" - ] - }, - "vendor": { - "microsoft.com/VisualStudioRemoteSettings/CMake/1.0": { - "sourceDir": "$env{HOME}/.vs/$ms{projectDirName}" - } - } - }, - { - "name": "windows-msvc-debug-developer-mode", - "displayName": "msvc Debug (Developer Mode)", - "description": "Target Windows with the msvc compiler, debug build type", - "inherits": "conf-windows-common", - "cacheVariables": { - "CMAKE_C_COMPILER": "cl", - "CMAKE_CXX_COMPILER": "cl", - "CMAKE_BUILD_TYPE": "Debug", - "ENABLE_DEVELOPER_MODE": "ON" - } - }, - { - "name": "windows-msvc-release-developer-mode", - "displayName": "msvc Release (Developer Mode)", - "description": "Target Windows with the msvc compiler, release build type", - "inherits": "conf-windows-common", - "cacheVariables": { - "CMAKE_C_COMPILER": "cl", - "CMAKE_CXX_COMPILER": "cl", - "CMAKE_BUILD_TYPE": "RelWithDebInfo", - "ENABLE_DEVELOPER_MODE": "ON" - } - }, - { - "name": "windows-msvc-debug-user-mode", - "displayName": "msvc Debug (User Mode)", - "description": "Target Windows with the msvc compiler, debug build type", - "inherits": "conf-windows-common", - "cacheVariables": { - "CMAKE_C_COMPILER": "cl", - "CMAKE_CXX_COMPILER": "cl", - "CMAKE_BUILD_TYPE": "Debug", - "ENABLE_DEVELOPER_MODE": "OFF" - } - }, - { - "name": "windows-msvc-release-user-mode", - "displayName": "msvc Release (User Mode)", - "description": "Target Windows with the msvc compiler, release build type", - "inherits": "conf-windows-common", - "cacheVariables": { - "CMAKE_C_COMPILER": "cl", - "CMAKE_CXX_COMPILER": "cl", - "CMAKE_BUILD_TYPE": "RelWithDebInfo", - "ENABLE_DEVELOPER_MODE": "OFF" - } - }, - { - "name": "windows-clang-debug", - "displayName": "clang Debug", - "description": "Target Windows with the clang compiler, debug build type", - "inherits": "conf-windows-common", - "cacheVariables": { - "CMAKE_C_COMPILER": "clang-cl", - "CMAKE_CXX_COMPILER": "clang-cl", - "CMAKE_BUILD_TYPE": "Debug" - }, - "vendor": { - "microsoft.com/VisualStudioSettings/CMake/1.0": { - "intelliSenseMode": "windows-clang-x64" - } - } - }, - { - "name": "windows-clang-release", - "displayName": "clang Release", - "description": "Target Windows with the clang compiler, release build type", - "inherits": "conf-windows-common", - "cacheVariables": { - "CMAKE_C_COMPILER": "clang-cl", - "CMAKE_CXX_COMPILER": "clang-cl", - "CMAKE_BUILD_TYPE": "RelWithDebInfo" - }, - "vendor": { - "microsoft.com/VisualStudioSettings/CMake/1.0": { - "intelliSenseMode": "windows-clang-x64" - } - } - }, - { - "name": "unixlike-gcc-debug", - "displayName": "gcc Debug", - "description": "Target Unix-like OS with the gcc compiler, debug build type", - "inherits": "conf-unixlike-common", - "cacheVariables": { - "CMAKE_C_COMPILER": "gcc", - "CMAKE_CXX_COMPILER": "g++", - "CMAKE_BUILD_TYPE": "Debug" - } - }, - { - "name": "unixlike-gcc-release", - "displayName": "gcc Release", - "description": "Target Unix-like OS with the gcc compiler, release build type", - "inherits": "conf-unixlike-common", - "cacheVariables": { - "CMAKE_C_COMPILER": "gcc", - "CMAKE_CXX_COMPILER": "g++", - "CMAKE_BUILD_TYPE": "RelWithDebInfo" - } - }, - { - "name": "unixlike-clang-debug", - "displayName": "clang Debug", - "description": "Target Unix-like OS with the clang compiler, debug build type", - "inherits": "conf-unixlike-common", - "cacheVariables": { - "CMAKE_C_COMPILER": "clang", - "CMAKE_CXX_COMPILER": "clang++", - "CMAKE_BUILD_TYPE": "Debug" - } - }, - { - "name": "unixlike-clang-release", - "displayName": "clang Release", - "description": "Target Unix-like OS with the clang compiler, release build type", - "inherits": "conf-unixlike-common", - "cacheVariables": { - "CMAKE_C_COMPILER": "clang", - "CMAKE_CXX_COMPILER": "clang++", - "CMAKE_BUILD_TYPE": "RelWithDebInfo" - } + "cmakeMinimumRequired": { + "major": 3, + "minor": 21, + "patch": 0 + }, + "version": 3, + "buildPresets": [ + { + "hidden": true, + "name": "build-base" + }, + { + "condition": { + "list": ["Darwin", "Linux"], + "string": "${hostSystemName}", + "type": "inList" + }, + "hidden": true, + "inherits": ["build-base"], + "name": "build-unix-base" + }, + { + "configurePreset": "unix-clang-debug", + "inherits": ["build-unix-base"], + "name": "unix-clang-debug" + }, + { + "configurePreset": "unix-clang-release", + "inherits": ["build-unix-base"], + "name": "unix-clang-release" + }, + { + "configurePreset": "unix-gcc-debug", + "inherits": ["build-unix-base"], + "name": "unix-gcc-debug" + }, + { + "configurePreset": "unix-gcc-release", + "inherits": ["build-unix-base"], + "name": "unix-gcc-release" + }, + { + "condition": { + "lhs": "${hostSystemName}", + "rhs": "Windows", + "type": "equals" + }, + "hidden": true, + "inherits": ["build-base"], + "name": "build-windows-base" + }, + { + "configurePreset": "windows-clang-debug", + "inherits": ["build-windows-base"], + "name": "windows-clang-debug" + }, + { + "configurePreset": "windows-clang-release", + "inherits": ["build-windows-base"], + "name": "windows-clang-release" + }, + { + "configurePreset": "windows-msvc-debug-developer-mode", + "inherits": ["build-windows-base"], + "name": "windows-msvc-debug-developer-mode" + }, + { + "configurePreset": "windows-msvc-debug-user-mode", + "inherits": ["build-windows-base"], + "name": "windows-msvc-debug-user-mode" + }, + { + "configurePreset": "windows-msvc-release-developer-mode", + "inherits": ["build-windows-base"], + "name": "windows-msvc-release-developer-mode" + }, + { + "configurePreset": "windows-msvc-release-user-mode", + "inherits": ["build-windows-base"], + "name": "windows-msvc-release-user-mode" + } + ], + "configurePresets": [ + { + "binaryDir": "${sourceDir}/out/build/${presetName}", + "generator": "Ninja", + "hidden": true, + "installDir": "${sourceDir}/out/install/${presetName}", + "name": "conf-base" + }, + { + "condition": { + "list": ["Darwin", "Linux"], + "string": "${hostSystemName}", + "type": "inList" + }, + "hidden": true, + "inherits": ["conf-base"], + "name": "conf-unix-base", + "vendor": { + "microsoft.com/VisualStudioRemoteSettings/CMake/1.0": { + "sourceDir": "$env{HOME}/.vs/$ms{projectDirName}" } - ], - "testPresets": [ - { - "name": "test-common", - "description": "Test CMake settings that apply to all configurations", - "hidden": true, - "output": { - "outputOnFailure": true - }, - "execution": { - "noTestsAction": "error", - "stopOnFailure": true - } - }, - { - "name": "test-windows-msvc-debug-developer-mode", - "displayName": "Strict", - "description": "Enable output and stop on failure", - "inherits": "test-common", - "configurePreset": "windows-msvc-debug-developer-mode" - }, - { - "name": "test-windows-msvc-release-developer-mode", - "displayName": "Strict", - "description": "Enable output and stop on failure", - "inherits": "test-common", - "configurePreset": "windows-msvc-release-developer-mode" - }, - { - "name": "test-windows-clang-debug", - "displayName": "Strict", - "description": "Enable output and stop on failure", - "inherits": "test-common", - "configurePreset": "windows-clang-debug" - }, - { - "name": "test-windows-clang-release", - "displayName": "Strict", - "description": "Enable output and stop on failure", - "inherits": "test-common", - "configurePreset": "windows-clang-release" - }, - { - "name": "test-unixlike-gcc-debug", - "displayName": "Strict", - "description": "Enable output and stop on failure", - "inherits": "test-common", - "configurePreset": "unixlike-gcc-debug" - }, - { - "name": "test-unixlike-gcc-release", - "displayName": "Strict", - "description": "Enable output and stop on failure", - "inherits": "test-common", - "configurePreset": "unixlike-gcc-release" - }, - { - "name": "test-unixlike-clang-debug", - "displayName": "Strict", - "description": "Enable output and stop on failure", - "inherits": "test-common", - "configurePreset": "unixlike-clang-debug" - }, - { - "name": "test-unixlike-clang-release", - "displayName": "Strict", - "description": "Enable output and stop on failure", - "inherits": "test-common", - "configurePreset": "unixlike-clang-release" + } + }, + { + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "CMAKE_C_COMPILER": "clang", + "CMAKE_CXX_COMPILER": "clang++" + }, + "inherits": ["conf-unix-base"], + "name": "unix-clang-debug" + }, + { + "cacheVariables": { + "CMAKE_BUILD_TYPE": "RelWithDebInfo", + "CMAKE_C_COMPILER": "clang", + "CMAKE_CXX_COMPILER": "clang++" + }, + "inherits": ["conf-unix-base"], + "name": "unix-clang-release" + }, + { + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "CMAKE_C_COMPILER": "gcc", + "CMAKE_CXX_COMPILER": "g++" + }, + "inherits": ["conf-unix-base"], + "name": "unix-gcc-debug" + }, + { + "cacheVariables": { + "CMAKE_BUILD_TYPE": "RelWithDebInfo", + "CMAKE_C_COMPILER": "gcc", + "CMAKE_CXX_COMPILER": "g++" + }, + "inherits": ["conf-unix-base"], + "name": "unix-gcc-release" + }, + { + "architecture": { + "strategy": "external", + "value": "x64" + }, + "cacheVariables": { + "CMAKE_SYSTEM_PROCESSOR": "AMD64", + "ENABLE_CLANG_TIDY_DEFAULT": "FALSE", + "ENABLE_CPPCHECK_DEFAULT": "FALSE" + }, + "condition": { + "lhs": "${hostSystemName}", + "rhs": "Windows", + "type": "equals" + }, + "hidden": true, + "inherits": ["conf-base"], + "name": "conf-windows-base", + "toolset": { + "strategy": "external", + "value": "host=x64" + } + }, + { + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "CMAKE_C_COMPILER": "clang-cl", + "CMAKE_CXX_COMPILER": "clang-cl" + }, + "inherits": ["conf-windows-base"], + "name": "windows-clang-debug", + "vendor": { + "microsoft.com/VisualStudioSettings/CMake/1.0": { + "intelliSenseMode": "windows-clang-x64" } - ] -} \ No newline at end of file + } + }, + { + "cacheVariables": { + "CMAKE_BUILD_TYPE": "RelWithDebInfo", + "CMAKE_C_COMPILER": "clang-cl", + "CMAKE_CXX_COMPILER": "clang-cl" + }, + "inherits": ["conf-windows-base"], + "name": "windows-clang-release", + "vendor": { + "microsoft.com/VisualStudioSettings/CMake/1.0": { + "intelliSenseMode": "windows-clang-x64" + } + } + }, + { + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "CMAKE_C_COMPILER": "cl", + "CMAKE_CXX_COMPILER": "cl", + "ENABLE_DEVELOPER_MODE": "ON" + }, + "inherits": ["conf-windows-base"], + "name": "windows-msvc-debug-developer-mode" + }, + { + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "CMAKE_C_COMPILER": "cl", + "CMAKE_CXX_COMPILER": "cl", + "ENABLE_DEVELOPER_MODE": "OFF" + }, + "inherits": ["conf-windows-base"], + "name": "windows-msvc-debug-user-mode" + }, + { + "cacheVariables": { + "CMAKE_BUILD_TYPE": "RelWithDebInfo", + "CMAKE_C_COMPILER": "cl", + "CMAKE_CXX_COMPILER": "cl", + "ENABLE_DEVELOPER_MODE": "ON" + }, + "inherits": ["conf-windows-base"], + "name": "windows-msvc-release-developer-mode" + }, + { + "cacheVariables": { + "CMAKE_BUILD_TYPE": "RelWithDebInfo", + "CMAKE_C_COMPILER": "cl", + "CMAKE_CXX_COMPILER": "cl", + "ENABLE_DEVELOPER_MODE": "OFF" + }, + "inherits": ["conf-windows-base"], + "name": "windows-msvc-release-user-mode" + } + ], + "testPresets": [ + { + "execution": { + "noTestsAction": "error", + "stopOnFailure": true + }, + "hidden": true, + "name": "test-base", + "output": { + "outputOnFailure": true + } + }, + { + "condition": { + "list": ["Darwin", "Linux"], + "string": "${hostSystemName}", + "type": "inList" + }, + "hidden": true, + "inherits": ["test-base"], + "name": "test-unix-base" + }, + { + "configurePreset": "unix-clang-debug", + "inherits": ["test-unix-base"], + "name": "unix-clang-debug" + }, + { + "configurePreset": "unix-clang-release", + "inherits": ["test-unix-base"], + "name": "unix-clang-release" + }, + { + "configurePreset": "unix-gcc-debug", + "inherits": ["test-unix-base"], + "name": "unix-gcc-debug" + }, + { + "configurePreset": "unix-gcc-release", + "inherits": ["test-unix-base"], + "name": "unix-gcc-release" + }, + { + "condition": { + "lhs": "${hostSystemName}", + "rhs": "Windows", + "type": "equals" + }, + "hidden": true, + "inherits": ["test-base"], + "name": "test-windows-base" + }, + { + "configurePreset": "windows-clang-debug", + "inherits": ["test-windows-base"], + "name": "windows-clang-debug" + }, + { + "configurePreset": "windows-clang-release", + "inherits": ["test-windows-base"], + "name": "windows-clang-release" + }, + { + "configurePreset": "windows-msvc-debug-developer-mode", + "inherits": ["test-windows-base"], + "name": "windows-msvc-debug-developer-mode" + }, + { + "configurePreset": "windows-msvc-debug-user-mode", + "inherits": ["test-windows-base"], + "name": "windows-msvc-debug-user-mode" + }, + { + "configurePreset": "windows-msvc-release-developer-mode", + "inherits": ["test-windows-base"], + "name": "windows-msvc-release-developer-mode" + }, + { + "configurePreset": "windows-msvc-release-user-mode", + "inherits": ["test-windows-base"], + "name": "windows-msvc-release-user-mode" + } + ] +} diff --git a/Dependencies.cmake b/Dependencies.cmake index a84378d2..1a548134 100644 --- a/Dependencies.cmake +++ b/Dependencies.cmake @@ -1,13 +1,8 @@ include(cmake/CPM.cmake) -# Done as a function so that updates to variables like -# CMAKE_CXX_FLAGS don't propagate out to other -# targets +# Done as a function so that updates to variables like CMAKE_CXX_FLAGS don't propagate out to other targets function(myproject_setup_dependencies) - - # For each dependency, see if it's - # already been provided to us by a parent project - + # For each dependency, see if it's already been provided to us by a parent project if(NOT TARGET fmtlib::fmtlib) cpmaddpackage("gh:fmtlib/fmt#9.1.0") endif() @@ -21,7 +16,8 @@ function(myproject_setup_dependencies) GITHUB_REPOSITORY "gabime/spdlog" OPTIONS - "SPDLOG_FMT_EXTERNAL ON") + "SPDLOG_FMT_EXTERNAL ON" + ) endif() if(NOT TARGET Catch2::Catch2WithMain) @@ -39,5 +35,4 @@ function(myproject_setup_dependencies) if(NOT TARGET tools::tools) cpmaddpackage("gh:lefticus/tools#update_build_system") endif() - endfunction() diff --git a/LICENSE b/LICENSE.md similarity index 100% rename from LICENSE rename to LICENSE.md diff --git a/ProjectOptions.cmake b/ProjectOptions.cmake index 2709aa1a..bb570b7d 100644 --- a/ProjectOptions.cmake +++ b/ProjectOptions.cmake @@ -3,7 +3,6 @@ include(cmake/LibFuzzer.cmake) include(CMakeDependentOption) include(CheckCXXCompilerFlag) - macro(myproject_supports_sanitizers) if((CMAKE_CXX_COMPILER_ID MATCHES ".*Clang.*" OR CMAKE_CXX_COMPILER_ID MATCHES ".*GNU.*") AND NOT WIN32) set(SUPPORTS_UBSAN ON) @@ -22,11 +21,9 @@ macro(myproject_setup_options) option(myproject_ENABLE_HARDENING "Enable hardening" ON) option(myproject_ENABLE_COVERAGE "Enable coverage reporting" OFF) cmake_dependent_option( - myproject_ENABLE_GLOBAL_HARDENING - "Attempt to push hardening options to built dependencies" - ON - myproject_ENABLE_HARDENING - OFF) + myproject_ENABLE_GLOBAL_HARDENING "Attempt to push hardening options to built dependencies" ON + myproject_ENABLE_HARDENING OFF + ) myproject_supports_sanitizers() @@ -75,11 +72,16 @@ macro(myproject_setup_options) myproject_ENABLE_CPPCHECK myproject_ENABLE_COVERAGE myproject_ENABLE_PCH - myproject_ENABLE_CACHE) + myproject_ENABLE_CACHE + ) endif() myproject_check_libfuzzer_support(LIBFUZZER_SUPPORTED) - if(LIBFUZZER_SUPPORTED AND (myproject_ENABLE_SANITIZER_ADDRESS OR myproject_ENABLE_SANITIZER_THREAD OR myproject_ENABLE_SANITIZER_UNDEFINED)) + if(LIBFUZZER_SUPPORTED + AND (myproject_ENABLE_SANITIZER_ADDRESS + OR myproject_ENABLE_SANITIZER_THREAD + OR myproject_ENABLE_SANITIZER_UNDEFINED) + ) set(DEFAULT_FUZZER ON) else() set(DEFAULT_FUZZER OFF) @@ -99,11 +101,12 @@ macro(myproject_global_options) if(myproject_ENABLE_HARDENING AND myproject_ENABLE_GLOBAL_HARDENING) include(cmake/Hardening.cmake) - if(NOT SUPPORTS_UBSAN + if(NOT SUPPORTS_UBSAN OR myproject_ENABLE_SANITIZER_UNDEFINED OR myproject_ENABLE_SANITIZER_ADDRESS OR myproject_ENABLE_SANITIZER_THREAD - OR myproject_ENABLE_SANITIZER_LEAK) + OR myproject_ENABLE_SANITIZER_LEAK + ) set(ENABLE_UBSAN_MINIMAL_RUNTIME FALSE) else() set(ENABLE_UBSAN_MINIMAL_RUNTIME TRUE) @@ -122,13 +125,7 @@ macro(myproject_local_options) add_library(myproject_options INTERFACE) include(cmake/CompilerWarnings.cmake) - myproject_set_project_warnings( - myproject_warnings - ${myproject_WARNINGS_AS_ERRORS} - "" - "" - "" - "") + myproject_set_project_warnings(myproject_warnings ${myproject_WARNINGS_AS_ERRORS} "" "" "" "") if(myproject_ENABLE_USER_LINKER) include(cmake/Linker.cmake) @@ -137,22 +134,14 @@ macro(myproject_local_options) include(cmake/Sanitizers.cmake) myproject_enable_sanitizers( - myproject_options - ${myproject_ENABLE_SANITIZER_ADDRESS} - ${myproject_ENABLE_SANITIZER_LEAK} - ${myproject_ENABLE_SANITIZER_UNDEFINED} - ${myproject_ENABLE_SANITIZER_THREAD} - ${myproject_ENABLE_SANITIZER_MEMORY}) + myproject_options ${myproject_ENABLE_SANITIZER_ADDRESS} ${myproject_ENABLE_SANITIZER_LEAK} + ${myproject_ENABLE_SANITIZER_UNDEFINED} ${myproject_ENABLE_SANITIZER_THREAD} ${myproject_ENABLE_SANITIZER_MEMORY} + ) set_target_properties(myproject_options PROPERTIES UNITY_BUILD ${myproject_ENABLE_UNITY_BUILD}) if(myproject_ENABLE_PCH) - target_precompile_headers( - myproject_options - INTERFACE - - - ) + target_precompile_headers(myproject_options INTERFACE ) endif() if(myproject_ENABLE_CACHE) @@ -178,23 +167,23 @@ macro(myproject_local_options) if(myproject_WARNINGS_AS_ERRORS) check_cxx_compiler_flag("-Wl,--fatal-warnings" LINKER_FATAL_WARNINGS) if(LINKER_FATAL_WARNINGS) - # This is not working consistently, so disabling for now - # target_link_options(myproject_options INTERFACE -Wl,--fatal-warnings) + # This is not working consistently, so disabling for now target_link_options(myproject_options INTERFACE + # -Wl,--fatal-warnings) endif() endif() if(myproject_ENABLE_HARDENING AND NOT myproject_ENABLE_GLOBAL_HARDENING) include(cmake/Hardening.cmake) - if(NOT SUPPORTS_UBSAN + if(NOT SUPPORTS_UBSAN OR myproject_ENABLE_SANITIZER_UNDEFINED OR myproject_ENABLE_SANITIZER_ADDRESS OR myproject_ENABLE_SANITIZER_THREAD - OR myproject_ENABLE_SANITIZER_LEAK) + OR myproject_ENABLE_SANITIZER_LEAK + ) set(ENABLE_UBSAN_MINIMAL_RUNTIME FALSE) else() set(ENABLE_UBSAN_MINIMAL_RUNTIME TRUE) endif() myproject_enable_hardening(myproject_options OFF ${ENABLE_UBSAN_MINIMAL_RUNTIME}) endif() - endmacro() diff --git a/README.md b/README.md index bc766ae4..93c4dc7f 100644 --- a/README.md +++ b/README.md @@ -9,53 +9,53 @@ **NOTE** This is undergoing a major overhaul on a new branch currently. - This is a C++ Best Practices GitHub template for getting up and running with C++ quickly. By default (collectively known as `ENABLE_DEVELOPER_MODE`) - * Address Sanitizer and Undefined Behavior Sanitizer enabled where possible - * Warnings as errors - * clang-tidy and cppcheck static analysis - * CPM for dependencies +- Address Sanitizer and Undefined Behavior Sanitizer enabled where possible +- Warnings as errors +- clang-tidy and cppcheck static analysis +- CPM for dependencies It includes - * a basic CLI example - * examples for fuzz, unit, and constexpr testing - * large github action testing matrix +- a basic CLI example +- examples for fuzz, unit, and constexpr testing +- large github action testing matrix It requires - * cmake - * a compiler - +- cmake +- a compiler This project gets you started with a simple example of using FTXUI, which happens to also be a game. - ## Getting Started ### Use the Github template + First, click the green `Use this template` button near the top of this page. This will take you to Github's ['Generate Repository'](https://github.com/cpp-best-practices/cmake_template/generate) page. Fill in a repository name and short description, and click 'Create repository from template'. This will allow you to create a new repository in your Github account, prepopulated with the contents of this project. -After creating the project please wait until the cleanup workflow has finished +After creating the project please wait until the cleanup workflow has finished setting up your project and commited the changes. Now you can clone the project locally and get to work! - git clone https://github.com//.git +```shell +git clone https://github.com//.git +``` ## More Details - * [Dependency Setup](README_dependencies.md) - * [Building Details](README_building.md) - * [Troubleshooting](README_troubleshooting.md) - * [Docker](README_docker.md) +- [Dependency Setup](README_dependencies.md) +- [Building Details](README_building.md) +- [Troubleshooting](README_troubleshooting.md) +- [Docker](README_docker.md) ## Testing @@ -64,5 +64,3 @@ See [Catch2 tutorial](https://github.com/catchorg/Catch2/blob/master/docs/tutori ## Fuzz testing See [libFuzzer Tutorial](https://github.com/google/fuzzing/blob/master/tutorial/libFuzzerTutorial.md) - - diff --git a/README_building.md b/README_building.md index 99ceacfc..3376346d 100644 --- a/README_building.md +++ b/README_building.md @@ -1,185 +1,194 @@ -## Build Instructions +# Build Instructions A full build has different steps: -1) Specifying the compiler using environment variables -2) Configuring the project -3) Building the project -For the subsequent builds, in case you change the source code, you only need to repeat the last step. +1. Specifying the compiler using environment variables +2. Configuring the project +3. Building the project -### (1) Specify the compiler using environment variables +For the subsequent builds, in case you change the source code, you only need to repeat the last step -By default (if you don't set environment variables `CC` and `CXX`), the system default compiler will be used. +## 1. Specify the compiler using environment variables -CMake uses the environment variables CC and CXX to decide which compiler to use. So to avoid the conflict issues only specify the compilers using these variables. +By default (if you don't set environment variables `CC` and `CXX`), +the system default compiler will be used. +CMake uses the environment variables CC and CXX to decide which compiler to use. +So to avoid the conflict issues only specify the compilers using these variables: -
-Commands for setting the compilers +- MacOS/Ubuntu -- Debian/Ubuntu/MacOS: + - Permanently - Set your desired compiler (`clang`, `gcc`, etc): + Open `~/.bashrc` using your text editor: - - Temporarily (only for the current shell) + ```shell + gedit ~/.bashrc + ``` - Run one of the followings in the terminal: + Add `CC` and `CXX` to point to the compilers: - - clang + ```shell + export CC="clang" + export CXX="clang++" + ``` - CC=clang CXX=clang++ + Save and close the file. - - gcc + - Temporarily - CC=gcc CXX=g++ + - Clang - - Permanent: + ```shell + CC="clang" CXX="clang++" + ``` - Open `~/.bashrc` using your text editor: + - GCC - gedit ~/.bashrc + ```shell + CC="gcc" CXX="g++" + ``` - Add `CC` and `CXX` to point to the compilers: +- Windows - export CC=clang - export CXX=clang++ + - Permanently - Save and close the file. + - Clang -- Windows: + ```powershell + [Environment]::SetEnvironmentVariable("CC", "clang.exe", "User") + [Environment]::SetEnvironmentVariable("CXX", "clang++.exe", "User") + refreshenv + ``` - - Permanent: + - GCC - Run one of the followings in PowerShell: + ```powershell + [Environment]::SetEnvironmentVariable("CC", "gcc.exe", "User") + [Environment]::SetEnvironmentVariable("CXX", "g++.exe", "User") + refreshenv + ``` - - Visual Studio generator and compiler (cl) + - MSVC - [Environment]::SetEnvironmentVariable("CC", "cl.exe", "User") - [Environment]::SetEnvironmentVariable("CXX", "cl.exe", "User") - refreshenv + ```powershell + [Environment]::SetEnvironmentVariable("CC", "cl.exe", "User") + [Environment]::SetEnvironmentVariable("CXX", "cl.exe", "User") + refreshenv + ``` - Set the architecture using [vcvarsall](https://docs.microsoft.com/en-us/cpp/build/building-on-the-command-line?view=vs-2019#vcvarsall-syntax): + Set the architecture using [vcvarsall](https://docs.microsoft.com/en-us/cpp/build/building-on-the-command-line?view=vs-2019#vcvarsall-syntax): - vcvarsall.bat x64 + ```powershell + vcvarsall.bat x64 + ``` - - clang + - Temporarily - [Environment]::SetEnvironmentVariable("CC", "clang.exe", "User") - [Environment]::SetEnvironmentVariable("CXX", "clang++.exe", "User") - refreshenv + ```powershell + $Env:CC="clang.exe" + $Env:CXX="clang++.exe" + ``` - - gcc +## 2. Configure your build - [Environment]::SetEnvironmentVariable("CC", "gcc.exe", "User") - [Environment]::SetEnvironmentVariable("CXX", "g++.exe", "User") - refreshenv +To configure the project, you could use `cmake`, or `ccmake` or `cmake-gui`. +Each of them are explained in the following: +- Configuring via cmake - - Temporarily (only for the current shell): + ```shell + cmake -B ./build -S . + ``` - $Env:CC="clang.exe" - $Env:CXX="clang++.exe" + Cmake will automatically create the `./build` folder if it does not exist, and it wil configure the project. -
+ Instead, if you have CMake version 3.21+, you can use one of the configuration presets that are listed in the CmakePresets.json file. -### (2) Configure your build + ```shell + cmake --preset . + cmake --build + ``` -To configure the project, you could use `cmake`, or `ccmake` or `cmake-gui`. Each of them are explained in the following: +- Configuring via ccmake -#### (2.a) Configuring via cmake: -With Cmake directly: + ```shell + ccmake -B ./build -S . + ``` - cmake -S . -B ./build + Once `ccmake` has finished setting up, press 'c' to configure the project, + press 'g' to generate, and 'q' to quit. -Cmake will automatically create the `./build` folder if it does not exist, and it wil configure the project. +- Configuring via cmake-gui -Instead, if you have CMake version 3.21+, you can use one of the configuration presets that are listed in the CmakePresets.json file. + - Open cmake-gui from the project directory - cmake . --preset - cmake --build + ```shell + cmake-gui . + ``` -#### (2.b) Configuring via ccmake: + - Set the build directory -With the Cmake Curses Dialog Command Line tool: + ![build_dir](https://user-images.githubusercontent.com/16418197/82524586-fa48e380-9af4-11ea-8514-4e18a063d8eb.jpg) - ccmake -S . -B ./build + - Configure the generator -Once `ccmake` has finished setting up, press 'c' to configure the project, -press 'g' to generate, and 'q' to quit. + In cmake-gui, from the upper menu select `Tools/Configure` -#### (2.c) Configuring via cmake-gui: + **Warning**: if you have set `CC` and `CXX` always choose the `use default native compilers` option. + This picks `CC` and `CXX`. Don't change the compiler at this stage! -To use the GUI of the cmake: + - Windows - MinGW Makefiles -2.c.1) Open cmake-gui from the project directory: -``` -cmake-gui . -``` -2.c.2) Set the build directory: - -![build_dir](https://user-images.githubusercontent.com/16418197/82524586-fa48e380-9af4-11ea-8514-4e18a063d8eb.jpg) - -2.c.3) Configure the generator: - -In cmake-gui, from the upper menu select `Tools/Configure`. - -**Warning**: if you have set `CC` and `CXX` always choose the `use default native compilers` option. This picks `CC` and `CXX`. Don't change the compiler at this stage! - -
-Windows - MinGW Makefiles - -Choose MinGW Makefiles as the generator: + Choose MinGW Makefiles as the generator -mingw + ![mingw](https://user-images.githubusercontent.com/16418197/82769479-616ade80-9dfa-11ea-899e-3a8c31d43032.png) -
+ - Windows - Visual Studio generator and compiler -
-Windows - Visual Studio generator and compiler + You should have already set `C` and `CXX` to `cl.exe` -You should have already set `C` and `CXX` to `cl.exe`. + Choose "Visual Studio 16 2019" as the generator -Choose "Visual Studio 16 2019" as the generator: + ![default_vs](https://user-images.githubusercontent.com/16418197/82524696-32502680-9af5-11ea-9697-a42000e900a6.jpg) -default_vs + - Windows - Visual Studio generator and Clang Compiler -
+ You should have already set `C` and `CXX` to `clang.exe` and `clang++.exe` -
+ Choose "Visual Studio 16 2019" as the generator -Windows - Visual Studio generator and Clang Compiler + To tell Visual studio to use `clang-cl.exe`: -You should have already set `C` and `CXX` to `clang.exe` and `clang++.exe`. + - If you use the LLVM that is shipped with Visual Studio: write `ClangCl` under "optional toolset to use" -Choose "Visual Studio 16 2019" as the generator. To tell Visual studio to use `clang-cl.exe`: -- If you use the LLVM that is shipped with Visual Studio: write `ClangCl` under "optional toolset to use". + ![visual_studio](https://user-images.githubusercontent.com/16418197/82781142-ae60ac00-9e1e-11ea-8c77-222b005a8f7e.png) -visual_studio + - If you use an external LLVM: write [`LLVM_v142`](https://github.com/zufuliu/llvm-utils#llvm-for-visual-studio-2017-and-2019) under "optional toolset to use". -- If you use an external LLVM: write [`LLVM_v142`](https://github.com/zufuliu/llvm-utils#llvm-for-visual-studio-2017-and-2019) - under "optional toolset to use". + ![visual_studio](https://user-images.githubusercontent.com/16418197/82769558-b3136900-9dfa-11ea-9f73-02ab8f9b0ca4.png) -visual_studio + - Choose the Cmake options and then generate -
-
+ ![generate](https://user-images.githubusercontent.com/16418197/82781591-c97feb80-9e1f-11ea-86c8-f2748b96f516.png) -2.c.4) Choose the Cmake options and then generate: +## 3. Build the project -![generate](https://user-images.githubusercontent.com/16418197/82781591-c97feb80-9e1f-11ea-86c8-f2748b96f516.png) +Once you have selected all the options you would like to use, +you can build the project (all targets): -### (3) Build the project -Once you have selected all the options you would like to use, you can build the -project (all targets): - - cmake --build ./build - -For Visual Studio, give the build configuration (Release, RelWithDeb, Debug, etc) like the following: +```shell +cmake --build ./build +``` - cmake --build ./build -- /p:configuration=Release +For Visual Studio, give the build configuration +(Release, RelWithDeb, Debug, etc) like the following: +```powershell +cmake --build ./build -- /p:configuration=Release +``` -### Running the tests +## Running the tests You can use the `ctest` command run the tests. @@ -188,5 +197,3 @@ cd ./build ctest -C Debug cd ../ ``` - - diff --git a/README_dependencies.md b/README_dependencies.md index 42e4dab0..16b36888 100644 --- a/README_dependencies.md +++ b/README_dependencies.md @@ -1,192 +1,201 @@ -## Dependencies +# Dependencies Note about install commands: -- for Windows, we use [choco](https://chocolatey.org/install). -- for MacOS, we use [brew](https://brew.sh/). -- In case of an error in cmake, make sure that the dependencies are on the PATH. +- for MacOS, we use [brew](https://brew.sh/) +- for Windows, we use [choco](https://chocolatey.org/install) +- In case of an error in cmake, make sure that the dependencies are on the PATH -### Too Long, Didn't Install +## Too Long, Didn't Install This is a really long list of dependencies, and it's easy to mess up. That's why: -#### Docker -We have a Docker image that's already set up for you. See the [Docker instructions](#docker-instructions). +- Docker -#### Setup-cpp + We have a Docker image that's already set up for you. See the [Docker instructions](#docker-instructions). -We have [setup-cpp](https://github.com/aminya/setup-cpp) that is a cross-platform tool to install all the compilers and dependencies on the system. +- Setup-cpp -Please check [the setup-cpp documentation](https://github.com/aminya/setup-cpp) for more information. + We have [setup-cpp](https://github.com/aminya/setup-cpp) that is a cross-platform tool to install all the compilers and dependencies on the system. -For example, on Windows, you can run the following to install llvm, cmake, ninja, ccache, and cppcheck. -```ps1 -# windows example (open shell as admin) -curl -LJO "https://github.com/aminya/setup-cpp/releases/download/v0.5.7/setup_cpp_windows.exe" -./setup_cpp_windows --compiler llvm --cmake true --ninja true --ccache true --cppcheck true + Please check [the setup-cpp documentation](https://github.com/aminya/setup-cpp) for more information. -RefreshEnv.cmd # reload the environment -``` + For example, on Windows, you can run the following to install llvm, cmake, ninja, ccache, and cppcheck. -### Necessary Dependencies -1. A C++ compiler that supports C++17. -See [cppreference.com](https://en.cppreference.com/w/cpp/compiler_support) -to see which features are supported by each compiler. -The following compilers should work: + ```powershell + curl -O "https://github.com/aminya/setup-cpp/releases/latest/download/setup-cpp-x64-windows.exe" + ./setup_cpp_windows --ccache true --cmake true --compiler llvm --cppcheck true --ninja true + RefreshEnv.cmd + ``` - * [gcc 7+](https://gcc.gnu.org/) -
- Install command +## Necessary Dependencies - - Debian/Ubuntu: +- A C++ compiler that supports C++17 + See [cppreference.com](https://en.cppreference.com/w/cpp/compiler_support) + to see which features are supported by each compiler. + The following compilers should work: - sudo apt install build-essential + - [Clang 6+](https://clang.llvm.org) - - Windows: + - MacOS - choco install mingw -y + ```shell + brew install llvm + ``` - - MacOS: + - Ubuntu - brew install gcc -
+ ```shell + bash -c "$(wget -O - )" + ``` - * [clang 6+](https://clang.llvm.org/) -
- Install command + - Windows - - Debian/Ubuntu: + Visual Studio 2019 ships with LLVM (see the Visual Studio section). However, to install LLVM separately: - bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" + ```powershell + choco install llvm -y + ``` - - Windows: + llvm-utils for using external LLVM with Visual Studio generator: - Visual Studio 2019 ships with LLVM (see the Visual Studio section). However, to install LLVM separately: + ```powershell + git clone + cd llvm-utils/VS2017 + .\install.bat + ``` - choco install llvm -y + - [GCC 7+](https://gcc.gnu.org/) - llvm-utils for using external LLVM with Visual Studio generator: + - MacOS - git clone https://github.com/zufuliu/llvm-utils.git - cd llvm-utils/VS2017 - .\install.bat + ```shell + brew install gcc + ``` - - MacOS: + - Ubuntu - brew install llvm -
+ ```shell + sudo apt install build-essential + ``` - * [Visual Studio 2019 or higher](https://visualstudio.microsoft.com/) -
- Install command + Environment setup + - Windows - On Windows, you need to install Visual Studio 2019 because of the SDK and libraries that ship with it. + ```powershell + choco install mingw -y + ``` - Visual Studio IDE - 2019 Community (installs Clang too): + - [MSVC 2019+](https://visualstudio.microsoft.com) - choco install -y visualstudio2019community --package-parameters "add Microsoft.VisualStudio.Workload.NativeDesktop --includeRecommended --includeOptional --passive --locale en-US" + On Windows, you need to install Visual Studio 2019 because of the SDK and libraries that ship with it. - Put MSVC compiler, Clang compiler, and vcvarsall.bat on the path: + ```powershell + choco install -y visualstudio2019community --package-parameters "add Microsoft.VisualStudio.Workload.NativeDesktop --includeRecommended --includeOptional --passive --locale en-US" + ``` - choco install vswhere -y - refreshenv + Put MSVC compiler, Clang compiler, and vcvarsall.bat on the path: - # change to x86 for 32bit - $clpath = vswhere -products * -latest -prerelease -find **/Hostx64/x64/* - $clangpath = vswhere -products * -latest -prerelease -find **/Llvm/bin/* - $vcvarsallpath = vswhere -products * -latest -prerelease -find **/Auxiliary/Build/* + ```powershell + choco install vswhere -y + refreshenv + ``` - $path = [System.Environment]::GetEnvironmentVariable("PATH", "User") - [Environment]::SetEnvironmentVariable("Path", $path + ";$clpath" + ";$clangpath" + ";$vcvarsallpath", "User") - refreshenv + Change to x86 for 32bit -
+ ```powershell + $clpath = vswhere -products *-latest -prerelease -find **/Hostx64/x64/* + $clangpath = vswhere -products * -latest -prerelease -find **/Llvm/bin/* + $vcvarsallpath = vswhere -products * -latest -prerelease -find **/Auxiliary/Build/* + $path = [System.Environment]::GetEnvironmentVariable("PATH", "User") + refreshenv + ``` -2. [CMake 3.15+](https://cmake.org/) -
- Install Command +- [Cmake 3.15+](https://cmake.org) - - Debian/Ubuntu: + - MacOS - sudo apt-get install cmake + ```shell + brew install cmake + ``` - - Windows: + - Ubuntu - choco install cmake -y + ```shell + sudo apt-get install cmake + ``` - - MacOS: + - Windows - brew install cmake + ```powershell + choco install cmake -y + ``` -
+## Optional Dependencies -### Optional Dependencies -#### C++ Tools - * [Doxygen](http://doxygen.nl/) -
- Install Command +- [ccache](https://ccache.dev) - - Debian/Ubuntu: + - MacOS - sudo apt-get install doxygen - sudo apt-get install graphviz + ```shell + brew install ccache + ``` - - Windows: + - Ubuntu - choco install doxygen.install -y - choco install graphviz -y + ```shell + sudo apt-get install ccache + ``` - - MacOS: + - Windows - brew install doxygen - brew install graphviz + ```powershell + choco install ccache -y + ``` -
+- [Cppcheck](http://cppcheck.sourceforge.net) + - MacOS - * [ccache](https://ccache.dev/) -
- Install Command + ```shell + brew install cppcheck + ``` - - Debian/Ubuntu: + - Ubuntu - sudo apt-get install ccache + ```shell + sudo apt-get install cppcheck + ``` - - Windows: + - Windows - choco install ccache -y + ```powershell + choco install cppcheck -y + ``` - - MacOS: +- [Doxygen](http://doxygen.nl) - brew install ccache + - MacOS -
+ ```shell + brew install doxygen + brew install graphviz + ``` + - Ubuntu - * [Cppcheck](http://cppcheck.sourceforge.net/) -
- Install Command + ```shell + sudo apt-get install doxygen + sudo apt-get install graphviz + ``` - - Debian/Ubuntu: + - Windows - sudo apt-get install cppcheck + ```powershell + choco install doxygen.install -y + choco install graphviz -y + ``` - - Windows: +- [include-what-you-use](https://include-what-you-use.org) - choco install cppcheck -y - - - MacOS: - - brew install cppcheck - -
- - - * [include-what-you-use](https://include-what-you-use.org/) -
- Install Command - - Follow instructions here: - https://github.com/include-what-you-use/include-what-you-use#how-to-install -
+ Follow instructions [here](https://github.com/include-what-you-use/include-what-you-use#how-to-install) diff --git a/README_docker.md b/README_docker.md index b1f5bf52..4bf4adcc 100644 --- a/README_docker.md +++ b/README_docker.md @@ -1,9 +1,9 @@ -## Docker Instructions +# Docker Instructions If you have [Docker](https://www.docker.com/) installed, you can run this in your terminal, when the Dockerfile is inside the `.devcontainer` directory: -```bash +```shell docker build -f ./.devcontainer/Dockerfile --tag=my_project:latest . docker run -it my_project:latest ``` @@ -16,16 +16,16 @@ versions of `g++` and `clang++`. If you want to build this container using some other versions of gcc and clang, you may do so with the `GCC_VER` and `LLVM_VER` arguments: -```bash -docker build --tag=myproject:latest --build-arg GCC_VER=10 --build-arg LLVM_VER=11 . +```shell +docker build --build-arg GCC_VER=10 --build-arg LLVM_VER=11 --tag=myproject:latest . ``` The CC and CXX environment variables are set to GCC version 11 by default. If you wish to use clang as your default CC and CXX environment variables, you may do so like this: -```bash -docker build --tag=my_project:latest --build-arg USE_CLANG=1 . +```shell +docker build --build-arg USE_CLANG=1 --tag=my_project:latest . ``` You will be logged in as root, so you will see the `#` symbol as your prompt. @@ -36,27 +36,29 @@ If you need to mount your local copy directly in the Docker image, see [Docker volumes docs](https://docs.docker.com/storage/volumes/). TLDR: -```bash +```shell docker run -it \ - -v absolute_path_on_host_machine:absolute_path_in_guest_container \ - my_project:latest + -v absolute_path_on_host_machine:absolute_path_in_guest_container \ + my_project:latest ``` You can configure and build [as directed above](#build) using these commands: -```bash -/starter_project# mkdir build -/starter_project# cmake -S . -B ./build -/starter_project# cmake --build ./build +```shell +cd ./starter_project +mkdir -p ./build +cmake -B ./build -S . +cmake --build ./build ``` You can configure and build using `clang-13`, without rebuilding the container, with these commands: -```bash -/starter_project# mkdir build -/starter_project# CC=clang CXX=clang++ cmake -S . -B ./build -/starter_project# cmake --build ./build +```shell +cd ./starter_project +mkdir -p ./build +CC=clang CXX=clang++ cmake -B ./build -S . +cmake --build ./build ``` The `ccmake` tool is also installed; you can substitute `ccmake` for `cmake` to @@ -68,4 +70,3 @@ run them separately. A script called `build_examples.sh` is provided to help you to build the example GUI projects in this container. - diff --git a/cmake/CPM.cmake b/cmake/CPM.cmake index a3086b79..ed6978ef 100644 --- a/cmake/CPM.cmake +++ b/cmake/CPM.cmake @@ -13,8 +13,7 @@ get_filename_component(CPM_DOWNLOAD_LOCATION ${CPM_DOWNLOAD_LOCATION} ABSOLUTE) function(download_cpm) message(STATUS "Downloading CPM.cmake to ${CPM_DOWNLOAD_LOCATION}") - file(DOWNLOAD - https://github.com/cpm-cmake/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake + file(DOWNLOAD https://github.com/cpm-cmake/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake ${CPM_DOWNLOAD_LOCATION} ) endfunction() diff --git a/cmake/Cache.cmake b/cmake/Cache.cmake index 2164c10d..cf19c9a6 100644 --- a/cmake/Cache.cmake +++ b/cmake/Cache.cmake @@ -1,20 +1,17 @@ # Enable cache if available + function(myproject_enable_cache) set(CACHE_OPTION "ccache" - CACHE STRING "Compiler cache to be used") + CACHE STRING "Compiler cache to be used" + ) set(CACHE_OPTION_VALUES "ccache" "sccache") set_property(CACHE CACHE_OPTION PROPERTY STRINGS ${CACHE_OPTION_VALUES}) - list( - FIND - CACHE_OPTION_VALUES - ${CACHE_OPTION} - CACHE_OPTION_INDEX) + list(FIND CACHE_OPTION_VALUES ${CACHE_OPTION} CACHE_OPTION_INDEX) if(${CACHE_OPTION_INDEX} EQUAL -1) - message( - STATUS - "Using custom compiler cache system: '${CACHE_OPTION}', explicitly supported entries are ${CACHE_OPTION_VALUES}" + message(STATUS "Using custom compiler cache system: '${CACHE_OPTION}', " + "explicitly supported entries are ${CACHE_OPTION_VALUES}" ) endif() @@ -23,10 +20,12 @@ function(myproject_enable_cache) message(STATUS "${CACHE_BINARY} found and enabled") set(CMAKE_CXX_COMPILER_LAUNCHER ${CACHE_BINARY} - CACHE FILEPATH "CXX compiler cache used") + CACHE FILEPATH "CXX compiler cache used" + ) set(CMAKE_C_COMPILER_LAUNCHER ${CACHE_BINARY} - CACHE FILEPATH "C compiler cache used") + CACHE FILEPATH "C compiler cache used" + ) else() message(WARNING "${CACHE_OPTION} is enabled but was not found. Not using it") endif() diff --git a/cmake/CompilerWarnings.cmake b/cmake/CompilerWarnings.cmake index 109297b3..a3f01bb2 100644 --- a/cmake/CompilerWarnings.cmake +++ b/cmake/CompilerWarnings.cmake @@ -1,6 +1,4 @@ -# from here: -# -# https://github.com/lefticus/cppbestpractices/blob/master/02-Use_the_Tools_Available.md +# Reference: https://github.com/lefticus/cppbestpractices/blob/master/02-Use_the_Tools_Available.md function( myproject_set_project_warnings @@ -9,15 +7,16 @@ function( MSVC_WARNINGS CLANG_WARNINGS GCC_WARNINGS - CUDA_WARNINGS) + CUDA_WARNINGS +) if("${MSVC_WARNINGS}" STREQUAL "") set(MSVC_WARNINGS /W4 # Baseline reasonable warnings /w14242 # 'identifier': conversion from 'type1' to 'type1', possible loss of data /w14254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data /w14263 # 'function': member function does not override any base class virtual member function - /w14265 # 'classname': class has virtual functions, but destructor is not virtual instances of this class may not - # be destructed correctly + /w14265 # 'classname': class has virtual functions, but destructor is not virtual instances of this class may + # not be destructed correctly /w14287 # 'operator': unsigned/negative constant mismatch /we4289 # nonstandard extension used: 'variable': loop control variable declared in the for-loop is used outside # the for-loop scope @@ -71,13 +70,8 @@ function( endif() if("${CUDA_WARNINGS}" STREQUAL "") - set(CUDA_WARNINGS - -Wall - -Wextra - -Wunused - -Wconversion - -Wshadow - # TODO add more Cuda warnings + set(CUDA_WARNINGS -Wall -Wextra -Wunused -Wconversion -Wshadow + # TODO add more Cuda warnings ) endif() @@ -111,5 +105,6 @@ function( # C warnings $<$:${PROJECT_WARNINGS_C}> # Cuda warnings - $<$:${PROJECT_WARNINGS_CUDA}>) + $<$:${PROJECT_WARNINGS_CUDA}> + ) endfunction() diff --git a/cmake/Cuda.cmake b/cmake/Cuda.cmake index d784a882..0a4b0707 100644 --- a/cmake/Cuda.cmake +++ b/cmake/Cuda.cmake @@ -1,21 +1,16 @@ -# ! target_link_cuda -# A function that links Cuda to the given target -# -# # Example +# target_link_cuda - a function that links Cuda to the given target, Example: + +# cmake-format: off # add_executable(main_cuda main.cu) # target_compile_features(main_cuda PRIVATE cxx_std_17) # target_link_libraries(main_cuda PRIVATE project_options project_warnings) # target_link_cuda(main_cuda) -# +# cmake-format: on + macro(myproject_target_link_cuda target) # optional named CUDA_WARNINGS set(oneValueArgs CUDA_WARNINGS) - cmake_parse_arguments( - _cuda_args - "" - "${oneValueArgs}" - "" - ${ARGN}) + cmake_parse_arguments(_cuda_args "" "${oneValueArgs}" "" ${ARGN}) # add CUDA to cmake language enable_language(CUDA) @@ -28,14 +23,13 @@ macro(myproject_target_link_cuda target) # -fPIC set_target_properties(${target} PROPERTIES POSITION_INDEPENDENT_CODE ON) - # We need to explicitly state that we need all CUDA files in the - # ${target} library to be built with -dc as the member functions - # could be called by other libraries and executables + # We need to explicitly state that we need all CUDA files in the ${target} library to be built with -dc as the member + # functions could be called by other libraries and executables set_target_properties(${target} PROPERTIES CUDA_SEPARABLE_COMPILATION ON) if(APPLE) - # We need to add the path to the driver (libcuda.dylib) as an rpath, - # so that the static cuda runtime can find it at runtime. + # We need to add the path to the driver (libcuda.dylib) as an rpath, so that the static cuda runtime can find it at + # runtime. set_property(TARGET ${target} PROPERTY BUILD_RPATH ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES}) endif() diff --git a/cmake/Doxygen.cmake b/cmake/Doxygen.cmake index ed90c566..3790305c 100644 --- a/cmake/Doxygen.cmake +++ b/cmake/Doxygen.cmake @@ -28,17 +28,18 @@ function(myproject_enable_doxygen DOXYGEN_THEME) endif() if("${DOXYGEN_THEME}" STREQUAL "awesome" OR "${DOXYGEN_THEME}" STREQUAL "awesome-sidebar") - # use a modern doxygen theme - # https://github.com/jothepro/doxygen-awesome-css v1.6.1 - FetchContent_Declare(_doxygen_theme - URL https://github.com/jothepro/doxygen-awesome-css/archive/refs/tags/v1.6.1.zip) + # use a modern doxygen theme https://github.com/jothepro/doxygen-awesome-css v1.6.1 + FetchContent_Declare( + _doxygen_theme URL https://github.com/jothepro/doxygen-awesome-css/archive/refs/tags/v1.6.1.zip + ) FetchContent_MakeAvailable(_doxygen_theme) if("${DOXYGEN_THEME}" STREQUAL "awesome" OR "${DOXYGEN_THEME}" STREQUAL "awesome-sidebar") set(DOXYGEN_HTML_EXTRA_STYLESHEET "${_doxygen_theme_SOURCE_DIR}/doxygen-awesome.css") endif() if("${DOXYGEN_THEME}" STREQUAL "awesome-sidebar") set(DOXYGEN_HTML_EXTRA_STYLESHEET ${DOXYGEN_HTML_EXTRA_STYLESHEET} - "${_doxygen_theme_SOURCE_DIR}/doxygen-awesome-sidebar-only.css") + "${_doxygen_theme_SOURCE_DIR}/doxygen-awesome-sidebar-only.css" + ) endif() else() # use the original doxygen theme @@ -49,6 +50,8 @@ function(myproject_enable_doxygen DOXYGEN_THEME) # add doxygen-docs target message(STATUS "Adding `doxygen-docs` target that builds the documentation.") - doxygen_add_docs(doxygen-docs ALL ${PROJECT_SOURCE_DIR} - COMMENT "Generating documentation - entry file: ${CMAKE_CURRENT_BINARY_DIR}/html/index.html") + doxygen_add_docs( + doxygen-docs ALL ${PROJECT_SOURCE_DIR} + COMMENT "Generating documentation - entry file: ${CMAKE_CURRENT_BINARY_DIR}/html/index.html" + ) endfunction() diff --git a/cmake/Hardening.cmake b/cmake/Hardening.cmake index 5f61d229..422bb627 100644 --- a/cmake/Hardening.cmake +++ b/cmake/Hardening.cmake @@ -1,11 +1,6 @@ include(CheckCXXCompilerFlag) -macro( - myproject_enable_hardening - target - global - ubsan_minimal_runtime) - +macro(myproject_enable_hardening target global ubsan_minimal_runtime) message(STATUS "** Enabling Hardening (Target ${target}) **") if(MSVC) @@ -20,15 +15,16 @@ macro( set(NEW_COMPILE_OPTIONS "${NEW_COMPILE_OPTIONS} -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=3") message(STATUS "*** g++/clang _FORTIFY_SOURCE=3 enabled") - # check_cxx_compiler_flag(-fpie PIE) - #if(PIE) - # set(NEW_COMPILE_OPTIONS ${NEW_COMPILE_OPTIONS} -fpie) - # set(NEW_LINK_OPTIONS ${NEW_LINK_OPTIONS} -pie) - # - # message(STATUS "*** g++/clang PIE mode enabled") - #else() - # message(STATUS "*** g++/clang PIE mode NOT enabled (not supported)") - #endif() + # cmake-format: off + # check_cxx_compiler_flag(-fpie PIE) + # if(PIE) + # set(NEW_COMPILE_OPTIONS ${NEW_COMPILE_OPTIONS} -fpie) + # set(NEW_LINK_OPTIONS ${NEW_LINK_OPTIONS} -pie) + # message(STATUS "*** g++/clang PIE mode enabled") + # else() + # message(STATUS "*** g++/clang PIE mode NOT enabled (not supported)") + # endif() + # cmake-format: on check_cxx_compiler_flag(-fstack-protector-strong STACK_PROTECTOR) if(STACK_PROTECTOR) @@ -60,8 +56,9 @@ macro( endif() if(${ubsan_minimal_runtime}) - check_cxx_compiler_flag("-fsanitize=undefined -fno-sanitize-recover=undefined -fsanitize-minimal-runtime" - MINIMAL_RUNTIME) + check_cxx_compiler_flag( + "-fsanitize=undefined -fno-sanitize-recover=undefined -fsanitize-minimal-runtime" MINIMAL_RUNTIME + ) if(MINIMAL_RUNTIME) set(NEW_COMPILE_OPTIONS "${NEW_COMPILE_OPTIONS} -fsanitize=undefined -fsanitize-minimal-runtime") set(NEW_LINK_OPTIONS "${NEW_LINK_OPTIONS} -fsanitize=undefined -fsanitize-minimal-runtime") diff --git a/cmake/LibFuzzer.cmake b/cmake/LibFuzzer.cmake index 7ab5eea0..d0c3c3bf 100644 --- a/cmake/LibFuzzer.cmake +++ b/cmake/LibFuzzer.cmake @@ -5,13 +5,12 @@ function(myproject_check_libfuzzer_support var_name) extern \"C\" int LLVMFuzzerTestOneInput(const std::uint8_t *data, std::size_t size) { return 0; -} - ") +}" + ) include(CheckCXXSourceCompiles) set(CMAKE_REQUIRED_FLAGS "-fsanitize=fuzzer") set(CMAKE_REQUIRED_LINK_OPTIONS "-fsanitize=fuzzer") check_cxx_source_compiles("${LibFuzzerTestSource}" ${var_name}) - endfunction() diff --git a/cmake/Linker.cmake b/cmake/Linker.cmake index 067aac68..2253e3b9 100644 --- a/cmake/Linker.cmake +++ b/cmake/Linker.cmake @@ -3,19 +3,17 @@ macro(myproject_configure_linker project_name) set(USER_LINKER_OPTION "lld" - CACHE STRING "Linker to be used") + CACHE STRING "Linker to be used" + ) set(USER_LINKER_OPTION_VALUES "lld" "gold" "bfd" "mold") set_property(CACHE USER_LINKER_OPTION PROPERTY STRINGS ${USER_LINKER_OPTION_VALUES}) - list( - FIND - USER_LINKER_OPTION_VALUES - ${USER_LINKER_OPTION} - USER_LINKER_OPTION_INDEX) + list(FIND USER_LINKER_OPTION_VALUES ${USER_LINKER_OPTION} USER_LINKER_OPTION_INDEX) if(${USER_LINKER_OPTION_INDEX} EQUAL -1) message( STATUS - "Using custom linker: '${USER_LINKER_OPTION}', explicitly supported entries are ${USER_LINKER_OPTION_VALUES}") + "Using custom linker: '${USER_LINKER_OPTION}', explicitly supported entries are ${USER_LINKER_OPTION_VALUES}" + ) endif() if(NOT ENABLE_USER_LINKER) diff --git a/cmake/PackageProject.cmake b/cmake/PackageProject.cmake index f8314268..e8d46afb 100644 --- a/cmake/PackageProject.cmake +++ b/cmake/PackageProject.cmake @@ -3,8 +3,7 @@ function(myproject_package_project) cmake_policy(SET CMP0103 NEW) # disallow multiple calls with the same NAME - set(_options ARCH_INDEPENDENT # default to false - ) + set(_options ARCH_INDEPENDENT) # default to false set(_oneValueArgs # default to the project_name: NAME @@ -16,7 +15,8 @@ function(myproject_package_project) # default to ${CMAKE_BINARY_DIR} CONFIG_EXPORT_DESTINATION # default to ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATADIR}/${NAME} suitable for vcpkg, etc. - CONFIG_INSTALL_DESTINATION) + CONFIG_INSTALL_DESTINATION + ) set(_multiValueArgs # recursively found for the current folder if not specified TARGETS @@ -24,20 +24,17 @@ function(myproject_package_project) PUBLIC_INCLUDES # the names of the INTERFACE/PUBLIC dependencies that are found using `CONFIG` PUBLIC_DEPENDENCIES_CONFIGURED - # the INTERFACE/PUBLIC dependencies that are found by any means using `find_dependency`. - # the arguments must be specified within double quotes (e.g. " 1.0.0 EXACT" or " CONFIG"). + # the INTERFACE/PUBLIC dependencies that are found by any means using `find_dependency`. the arguments must be + # specified within double quotes (e.g. " 1.0.0 EXACT" or " CONFIG"). PUBLIC_DEPENDENCIES - # the names of the PRIVATE dependencies that are found using `CONFIG`. Only included when BUILD_SHARED_LIBS is OFF. + # the names of the PRIVATE dependencies that are found using `CONFIG`. Only included when BUILD_SHARED_LIBS is + # OFF. PRIVATE_DEPENDENCIES_CONFIGURED # PRIVATE dependencies that are only included when BUILD_SHARED_LIBS is OFF - PRIVATE_DEPENDENCIES) + PRIVATE_DEPENDENCIES + ) - cmake_parse_arguments( - _PackageProject - "${_options}" - "${_oneValueArgs}" - "${_multiValueArgs}" - "${ARGN}") + cmake_parse_arguments(_PackageProject "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" "${ARGN}") # Set default options include(GNUInstallDirs) # Define GNU standard installation directories such as CMAKE_INSTALL_DATADIR @@ -81,10 +78,7 @@ function(myproject_package_project) set(_PackageProject_INSTALL_DESTINATION "${_PackageProject_CONFIG_INSTALL_DESTINATION}") # Installation of the public/interface includes - if(NOT - "${_PackageProject_PUBLIC_INCLUDES}" - STREQUAL - "") + if(NOT "${_PackageProject_PUBLIC_INCLUDES}" STREQUAL "") foreach(_INC ${_PackageProject_PUBLIC_INCLUDES}) # make include absolute if(NOT IS_ABSOLUTE ${_INC}) @@ -92,7 +86,9 @@ function(myproject_package_project) endif() # install include if(IS_DIRECTORY ${_INC}) - # the include directories are directly installed to the install destination. If you want an `include` folder in the install destination, name your include directory as `include` (or install it manually using `install()` command). + # the include directories are directly installed to the install destination. If you want an `include` folder in + # the install destination, name your include directory as `include` (or install it manually using `install()` + # command). install(DIRECTORY ${_INC} DESTINATION "./") else() install(FILES ${_INC} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") @@ -101,10 +97,7 @@ function(myproject_package_project) endif() # Append the configured public dependencies - if(NOT - "${_PackageProject_PUBLIC_DEPENDENCIES_CONFIGURED}" - STREQUAL - "") + if(NOT "${_PackageProject_PUBLIC_DEPENDENCIES_CONFIGURED}" STREQUAL "") set(_PUBLIC_DEPENDENCIES_CONFIG) foreach(DEP ${_PackageProject_PUBLIC_DEPENDENCIES_CONFIGURED}) list(APPEND _PUBLIC_DEPENDENCIES_CONFIG "${DEP} CONFIG") @@ -115,10 +108,7 @@ function(myproject_package_project) set(_PackageProject_DEPENDENCIES ${_PackageProject_PUBLIC_DEPENDENCIES}) # Append the configured private dependencies - if(NOT - "${_PackageProject_PRIVATE_DEPENDENCIES_CONFIGURED}" - STREQUAL - "") + if(NOT "${_PackageProject_PRIVATE_DEPENDENCIES_CONFIGURED}" STREQUAL "") set(_PRIVATE_DEPENDENCIES_CONFIG) foreach(DEP ${_PackageProject_PRIVATE_DEPENDENCIES_CONFIGURED}) list(APPEND _PRIVATE_DEPENDENCIES_CONFIG "${DEP} CONFIG") @@ -134,7 +124,8 @@ function(myproject_package_project) LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT shlib ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT lib RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT bin - PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${_PackageProject_NAME}" COMPONENT dev) + PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${_PackageProject_NAME}" COMPONENT dev + ) # install the usage file set(_targets_str "") @@ -145,19 +136,21 @@ function(myproject_package_project) "The package ${_PackageProject_NAME} provides CMake targets: find_package(${_PackageProject_NAME} CONFIG REQUIRED) - target_link_libraries(main PRIVATE ${_targets_str}) - ") + target_link_libraries(main PRIVATE ${_targets_str})" + ) install(CODE "MESSAGE(STATUS \"${USAGE_FILE_CONTENT}\")") file(WRITE "${_PackageProject_EXPORT_DESTINATION}/usage" "${USAGE_FILE_CONTENT}") install(FILES "${_PackageProject_EXPORT_DESTINATION}/usage" - DESTINATION "${_PackageProject_CONFIG_INSTALL_DESTINATION}") + DESTINATION "${_PackageProject_CONFIG_INSTALL_DESTINATION}" + ) unset(_PackageProject_TARGETS) # download ForwardArguments FetchContent_Declare( _fargs - URL https://github.com/polysquare/cmake-forward-arguments/archive/8c50d1f956172edb34e95efa52a2d5cb1f686ed2.zip) + URL https://github.com/polysquare/cmake-forward-arguments/archive/8c50d1f956172edb34e95efa52a2d5cb1f686ed2.zip + ) FetchContent_GetProperties(_fargs) if(NOT _fargs_POPULATED) FetchContent_Populate(_fargs) @@ -174,7 +167,8 @@ function(myproject_package_project) SINGLEVAR_ARGS "${_oneValueArgs};EXPORT_DESTINATION;INSTALL_DESTINATION;NAMESPACE;VARS_PREFIX;EXPORT" MULTIVAR_ARGS - "${_multiValueArgs};DEPENDENCIES;PRIVATE_DEPENDENCIES") + "${_multiValueArgs};DEPENDENCIES;PRIVATE_DEPENDENCIES" + ) # download ycm FetchContent_Declare(_ycm URL https://github.com/robotology/ycm/archive/refs/tags/v0.13.0.zip) diff --git a/cmake/PreventInSourceBuilds.cmake b/cmake/PreventInSourceBuilds.cmake index 302a0bae..6db8e196 100644 --- a/cmake/PreventInSourceBuilds.cmake +++ b/cmake/PreventInSourceBuilds.cmake @@ -1,6 +1,4 @@ -# # This function will prevent in-source builds -# function(myproject_assure_out_of_source_builds) # make sure the user doesn't play dirty with symlinks get_filename_component(srcdir "${CMAKE_SOURCE_DIR}" REALPATH) diff --git a/cmake/Sanitizers.cmake b/cmake/Sanitizers.cmake index e238fa21..330d204c 100644 --- a/cmake/Sanitizers.cmake +++ b/cmake/Sanitizers.cmake @@ -5,8 +5,8 @@ function( ENABLE_SANITIZER_LEAK ENABLE_SANITIZER_UNDEFINED_BEHAVIOR ENABLE_SANITIZER_THREAD - ENABLE_SANITIZER_MEMORY) - + ENABLE_SANITIZER_MEMORY +) if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") set(SANITIZERS "") @@ -37,7 +37,8 @@ function( ) if("address" IN_LIST SANITIZERS OR "thread" IN_LIST SANITIZERS - OR "leak" IN_LIST SANITIZERS) + OR "leak" IN_LIST SANITIZERS + ) message(WARNING "Memory sanitizer does not work with Address, Thread or Leak sanitizer enabled") else() list(APPEND SANITIZERS "memory") @@ -50,22 +51,16 @@ function( if(${ENABLE_SANITIZER_LEAK} OR ${ENABLE_SANITIZER_UNDEFINED_BEHAVIOR} OR ${ENABLE_SANITIZER_THREAD} - OR ${ENABLE_SANITIZER_MEMORY}) + OR ${ENABLE_SANITIZER_MEMORY} + ) message(WARNING "MSVC only supports address sanitizer") endif() endif() - list( - JOIN - SANITIZERS - "," - LIST_OF_SANITIZERS) + list(JOIN SANITIZERS "," LIST_OF_SANITIZERS) if(LIST_OF_SANITIZERS) - if(NOT - "${LIST_OF_SANITIZERS}" - STREQUAL - "") + if(NOT "${LIST_OF_SANITIZERS}" STREQUAL "") if(NOT MSVC) target_compile_options(${project_name} INTERFACE -fsanitize=${LIST_OF_SANITIZERS}) target_link_options(${project_name} INTERFACE -fsanitize=${LIST_OF_SANITIZERS}) @@ -83,8 +78,4 @@ function( endif() endif() endif() - endfunction() - - - diff --git a/cmake/StandardProjectSettings.cmake b/cmake/StandardProjectSettings.cmake index b9f4123e..a9cf88de 100644 --- a/cmake/StandardProjectSettings.cmake +++ b/cmake/StandardProjectSettings.cmake @@ -1,17 +1,13 @@ # Set a default build type if none was specified + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) message(STATUS "Setting build type to 'RelWithDebInfo' as none was specified.") set(CMAKE_BUILD_TYPE RelWithDebInfo - CACHE STRING "Choose the type of build." FORCE) + CACHE STRING "Choose the type of build." FORCE + ) # Set the possible values of build type for cmake-gui, ccmake - set_property( - CACHE CMAKE_BUILD_TYPE - PROPERTY STRINGS - "Debug" - "Release" - "MinSizeRel" - "RelWithDebInfo") + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo") endif() # Generate compile_commands.json to make it easier to work with clang based tools @@ -28,8 +24,9 @@ if(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") if(WIN32) # On Windows cuda nvcc uses cl and not gcc - add_compile_options($<$:-fdiagnostics-color=always> - $<$:-fdiagnostics-color=always>) + add_compile_options( + $<$:-fdiagnostics-color=always> $<$:-fdiagnostics-color=always> + ) else() add_compile_options(-fdiagnostics-color=always) endif() @@ -39,7 +36,6 @@ else() message(STATUS "No colored compiler diagnostic set for '${CMAKE_CXX_COMPILER_ID}' compiler.") endif() - # run vcvarsall when msvc is used include("${CMAKE_CURRENT_LIST_DIR}/VCEnvironment.cmake") run_vcvarsall() diff --git a/cmake/StaticAnalyzers.cmake b/cmake/StaticAnalyzers.cmake index eb3674e0..1efcad24 100644 --- a/cmake/StaticAnalyzers.cmake +++ b/cmake/StaticAnalyzers.cmake @@ -1,7 +1,6 @@ macro(myproject_enable_cppcheck WARNINGS_AS_ERRORS CPPCHECK_OPTIONS) find_program(CPPCHECK cppcheck) if(CPPCHECK) - if(CMAKE_GENERATOR MATCHES ".*Visual Studio.*") set(CPPCHECK_TEMPLATE "vs") else() @@ -9,8 +8,8 @@ macro(myproject_enable_cppcheck WARNINGS_AS_ERRORS CPPCHECK_OPTIONS) endif() if("${CPPCHECK_OPTIONS}" STREQUAL "") - # Enable all warnings that are actionable by the user of this toolset - # style should enable the other 3, but we'll be explicit just in case + # Enable all warnings that are actionable by the user of this toolset style should enable the other 3, but we'll + # be explicit just in case set(CMAKE_CXX_CPPCHECK ${CPPCHECK} --template=${CPPCHECK_TEMPLATE} @@ -26,16 +25,14 @@ macro(myproject_enable_cppcheck WARNINGS_AS_ERRORS CPPCHECK_OPTIONS) # ignores code that cppcheck thinks is invalid C++ --suppress=syntaxError --suppress=preprocessorErrorDirective - --inconclusive) + --inconclusive + ) else() # if the user provides a CPPCHECK_OPTIONS with a template specified, it will override this template set(CMAKE_CXX_CPPCHECK ${CPPCHECK} --template=${CPPCHECK_TEMPLATE} ${CPPCHECK_OPTIONS}) endif() - if(NOT - "${CMAKE_CXX_STANDARD}" - STREQUAL - "") + if(NOT "${CMAKE_CXX_STANDARD}" STREQUAL "") set(CMAKE_CXX_CPPCHECK ${CMAKE_CXX_CPPCHECK} --std=c++${CMAKE_CXX_STANDARD}) endif() if(${WARNINGS_AS_ERRORS}) @@ -47,13 +44,9 @@ macro(myproject_enable_cppcheck WARNINGS_AS_ERRORS CPPCHECK_OPTIONS) endmacro() macro(myproject_enable_clang_tidy target WARNINGS_AS_ERRORS) - find_program(CLANGTIDY clang-tidy) if(CLANGTIDY) - if(NOT - CMAKE_CXX_COMPILER_ID - MATCHES - ".*Clang") + if(NOT CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") get_target_property(TARGET_PCH ${target} INTERFACE_PRECOMPILE_HEADERS) @@ -64,22 +57,18 @@ macro(myproject_enable_clang_tidy target WARNINGS_AS_ERRORS) if(NOT ("${TARGET_PCH}" STREQUAL "TARGET_PCH-NOTFOUND")) message( SEND_ERROR - "clang-tidy cannot be enabled with non-clang compiler and PCH, clang-tidy fails to handle gcc's PCH file") + "clang-tidy cannot be enabled with non-clang compiler and PCH, clang-tidy fails to handle gcc's PCH file" + ) endif() endif() # construct the clang-tidy command line set(CLANG_TIDY_OPTIONS - ${CLANGTIDY} - -extra-arg=-Wno-unknown-warning-option - -extra-arg=-Wno-ignored-optimization-argument - -extra-arg=-Wno-unused-command-line-argument - -p) + ${CLANGTIDY} -extra-arg=-Wno-unknown-warning-option -extra-arg=-Wno-ignored-optimization-argument + -extra-arg=-Wno-unused-command-line-argument -p + ) # set standard - if(NOT - "${CMAKE_CXX_STANDARD}" - STREQUAL - "") + if(NOT "${CMAKE_CXX_STANDARD}" STREQUAL "") if("${CLANG_TIDY_OPTIONS_DRIVER_MODE}" STREQUAL "cl") set(CLANG_TIDY_OPTIONS ${CLANG_TIDY_OPTIONS} -extra-arg=/std:c++${CMAKE_CXX_STANDARD}) else() diff --git a/cmake/SystemLink.cmake b/cmake/SystemLink.cmake index 000a9ad1..bfb5e07e 100644 --- a/cmake/SystemLink.cmake +++ b/cmake/SystemLink.cmake @@ -1,46 +1,29 @@ -# Include a system directory (which suppresses its warnings). +# Include a system directory (which suppresses its warnings) function(target_include_system_directories target) set(multiValueArgs INTERFACE PUBLIC PRIVATE) - cmake_parse_arguments( - ARG - "" - "" - "${multiValueArgs}" - ${ARGN}) + cmake_parse_arguments(ARG "" "" "${multiValueArgs}" ${ARGN}) foreach(scope IN ITEMS INTERFACE PUBLIC PRIVATE) foreach(lib_include_dirs IN LISTS ARG_${scope}) if(NOT MSVC) - # system includes do not work in MSVC - # awaiting https://gitlab.kitware.com/cmake/cmake/-/issues/18272# - # awaiting https://gitlab.kitware.com/cmake/cmake/-/issues/17904 + # system includes do not work in MSVC awaiting https://gitlab.kitware.com/cmake/cmake/-/issues/18272# awaiting + # https://gitlab.kitware.com/cmake/cmake/-/issues/17904 set(_SYSTEM SYSTEM) endif() if(${scope} STREQUAL "INTERFACE" OR ${scope} STREQUAL "PUBLIC") target_include_directories( - ${target} - ${_SYSTEM} - ${scope} - "$" - "$") + ${target} ${_SYSTEM} ${scope} "$" + "$" + ) else() - target_include_directories( - ${target} - ${_SYSTEM} - ${scope} - ${lib_include_dirs}) + target_include_directories(${target} ${_SYSTEM} ${scope} ${lib_include_dirs}) endif() endforeach() endforeach() - endfunction() -# Include the directories of a library target as system directories (which suppresses their warnings). -function( - target_include_system_library - target - scope - lib) +# Include the directories of a library target as system directories (which suppresses their warnings) +function(target_include_system_library target scope lib) # check if this is a target if(TARGET ${lib}) get_target_property(lib_include_dirs ${lib} INTERFACE_INCLUDE_DIRECTORIES) @@ -53,11 +36,7 @@ function( endfunction() # Link a library target as a system library (which suppresses its warnings). -function( - target_link_system_library - target - scope - lib) +function(target_link_system_library target scope lib) # Include the directories in the library target_include_system_library(${target} ${scope} ${lib}) @@ -68,12 +47,7 @@ endfunction() # Link multiple library targets as system libraries (which suppresses their warnings). function(target_link_system_libraries target) set(multiValueArgs INTERFACE PUBLIC PRIVATE) - cmake_parse_arguments( - ARG - "" - "" - "${multiValueArgs}" - ${ARGN}) + cmake_parse_arguments(ARG "" "" "${multiValueArgs}" ${ARGN}) foreach(scope IN ITEMS INTERFACE PUBLIC PRIVATE) foreach(lib IN LISTS ARG_${scope}) diff --git a/cmake/Utilities.cmake b/cmake/Utilities.cmake index 6fa78b28..304621ae 100644 --- a/cmake/Utilities.cmake +++ b/cmake/Utilities.cmake @@ -1,9 +1,5 @@ -# find a subtring from a string by a given prefix such as VCVARSALL_ENV_START -function( - find_substring_by_prefix - output - prefix - input) +# Find a subtring from a string by a given prefix such as VCVARSALL_ENV_START +function(find_substring_by_prefix output prefix input) # find the prefix string(FIND "${input}" "${prefix}" prefix_index) if("${prefix_index}" STREQUAL "-1") @@ -13,64 +9,33 @@ function( string(LENGTH "${prefix}" prefix_length) math(EXPR start_index "${prefix_index} + ${prefix_length}") - string( - SUBSTRING "${input}" - "${start_index}" - "-1" - _output) + string(SUBSTRING "${input}" "${start_index}" "-1" _output) set("${output}" "${_output}" - PARENT_SCOPE) + PARENT_SCOPE + ) endfunction() # A function to set environment variables of CMake from the output of `cmd /c set` function(set_env_from_string env_string) # replace ; in paths with __sep__ so we can split on ; - string( - REGEX - REPLACE ";" - "__sep__" - env_string_sep_added - "${env_string}") + string(REGEX REPLACE ";" "__sep__" env_string_sep_added "${env_string}") # the variables are separated by \r?\n - string( - REGEX - REPLACE "\r?\n" - ";" - env_list - "${env_string_sep_added}") + string(REGEX REPLACE "\r?\n" ";" env_list "${env_string_sep_added}") foreach(env_var ${env_list}) # split by = - string( - REGEX - REPLACE "=" - ";" - env_parts - "${env_var}") + string(REGEX REPLACE "=" ";" env_parts "${env_var}") list(LENGTH env_parts env_parts_length) if("${env_parts_length}" EQUAL "2") # get the variable name and value - list( - GET - env_parts - 0 - env_name) - list( - GET - env_parts - 1 - env_value) + list(GET env_parts 0 env_name) + list(GET env_parts 1 env_value) # recover ; in paths - string( - REGEX - REPLACE "__sep__" - ";" - env_value - "${env_value}") + string(REGEX REPLACE "__sep__" ";" env_value "${env_value}") # set env_name to env_value set(ENV{${env_name}} "${env_value}") @@ -88,7 +53,8 @@ function(get_all_targets var) get_all_targets_recursive(targets ${CMAKE_CURRENT_SOURCE_DIR}) set(${var} ${targets} - PARENT_SCOPE) + PARENT_SCOPE + ) endfunction() function(get_all_installable_targets var) @@ -96,23 +62,22 @@ function(get_all_installable_targets var) get_all_targets(targets) foreach(_target ${targets}) get_target_property(_target_type ${_target} TYPE) - if(NOT - ${_target_type} - MATCHES - ".*LIBRARY|EXECUTABLE") + if(NOT ${_target_type} MATCHES ".*LIBRARY|EXECUTABLE") list(REMOVE_ITEM targets ${_target}) endif() endforeach() set(${var} ${targets} - PARENT_SCOPE) + PARENT_SCOPE + ) endfunction() macro(get_all_targets_recursive targets dir) get_property( subdirectories DIRECTORY ${dir} - PROPERTY SUBDIRECTORIES) + PROPERTY SUBDIRECTORIES + ) foreach(subdir ${subdirectories}) get_all_targets_recursive(${targets} ${subdir}) endforeach() @@ -120,20 +85,24 @@ macro(get_all_targets_recursive targets dir) get_property( current_targets DIRECTORY ${dir} - PROPERTY BUILDSYSTEM_TARGETS) + PROPERTY BUILDSYSTEM_TARGETS + ) list(APPEND ${targets} ${current_targets}) endmacro() function(is_verbose var) if("CMAKE_MESSAGE_LOG_LEVEL" STREQUAL "VERBOSE" OR "CMAKE_MESSAGE_LOG_LEVEL" STREQUAL "DEBUG" - OR "CMAKE_MESSAGE_LOG_LEVEL" STREQUAL "TRACE") + OR "CMAKE_MESSAGE_LOG_LEVEL" STREQUAL "TRACE" + ) set(${var} ON - PARENT_SCOPE) + PARENT_SCOPE + ) else() set(${var} OFF - PARENT_SCOPE) + PARENT_SCOPE + ) endif() endfunction() diff --git a/cmake/VCEnvironment.cmake b/cmake/VCEnvironment.cmake index a95cb467..62c1c4f2 100644 --- a/cmake/VCEnvironment.cmake +++ b/cmake/VCEnvironment.cmake @@ -8,7 +8,8 @@ macro(detect_architecture) elseif( CMAKE_SYSTEM_PROCESSOR_LOWER STREQUAL x64 OR CMAKE_SYSTEM_PROCESSOR_LOWER STREQUAL x86_64 - OR CMAKE_SYSTEM_PROCESSOR_LOWER STREQUAL amd64) + OR CMAKE_SYSTEM_PROCESSOR_LOWER STREQUAL amd64 + ) set(VCVARSALL_ARCH x64) elseif(CMAKE_SYSTEM_PROCESSOR_LOWER STREQUAL arm) set(VCVARSALL_ARCH arm) @@ -34,12 +35,10 @@ function(run_vcvarsall) find_file( VCVARSALL_FILE NAMES vcvarsall.bat - PATHS "${MSVC_DIR}" - "${MSVC_DIR}/.." - "${MSVC_DIR}/../.." - "${MSVC_DIR}/../../../../../../../.." + PATHS "${MSVC_DIR}" "${MSVC_DIR}/.." "${MSVC_DIR}/../.." "${MSVC_DIR}/../../../../../../../.." "${MSVC_DIR}/../../../../../../.." - PATH_SUFFIXES "VC/Auxiliary/Build" "Common7/Tools" "Tools") + PATH_SUFFIXES "VC/Auxiliary/Build" "Common7/Tools" "Tools" + ) if(EXISTS ${VCVARSALL_FILE}) # detect the architecture @@ -53,7 +52,8 @@ function(run_vcvarsall) "&&" "call" "echo" "VCVARSALL_ENV_START" # "&" "set" # OUTPUT_VARIABLE VCVARSALL_OUTPUT - OUTPUT_STRIP_TRAILING_WHITESPACE) + OUTPUT_STRIP_TRAILING_WHITESPACE + ) # parse the output and get the environment variables string find_substring_by_prefix(VCVARSALL_ENV "VCVARSALL_ENV_START" "${VCVARSALL_OUTPUT}") @@ -65,7 +65,8 @@ function(run_vcvarsall) message( WARNING "Could not find `vcvarsall.bat` for automatic MSVC environment preparation. Please manually open the MSVC command prompt and rebuild the project. - ") + " + ) endif() endif() endfunction() diff --git a/configured_files/CMakeLists.txt b/configured_files/CMakeLists.txt index 2bf896ee..d5a6be2e 100644 --- a/configured_files/CMakeLists.txt +++ b/configured_files/CMakeLists.txt @@ -1,7 +1,6 @@ +# A very simple example of a configured file that might need to be converted to one that is publicly installed in the +# case that you are developing a library -# A very simple example of a configured file that might need to be -# converted to one that is publicly installed in the case that -# you are developing a library -configure_file("config.hpp.in" "${CMAKE_BINARY_DIR}/configured_files/include/internal_use_only/config.hpp" ESCAPE_QUOTES) - - +configure_file( + "config.hpp.in" "${CMAKE_BINARY_DIR}/configured_files/include/internal_use_only/config.hpp" ESCAPE_QUOTES +) diff --git a/configured_files/config.hpp.in b/configured_files/config.hpp.in index 86d5cb38..1126fb0e 100644 --- a/configured_files/config.hpp.in +++ b/configured_files/config.hpp.in @@ -1,16 +1,22 @@ #ifndef MYPROJECT_CONFIG_HPP #define MYPROJECT_CONFIG_HPP -// this is a basic example of how a CMake configured file might look -// in this particular case, we are using it to set the version number of our executable +// this is a basic example of how a CMake configured file might look in this +// particular case, we are using it to set the version number of our executable + +#include + namespace myproject::cmake { -inline constexpr std::string_view project_name = "@PROJECT_NAME@"; -inline constexpr std::string_view project_version = "@PROJECT_VERSION@"; -inline constexpr int project_version_major { @PROJECT_VERSION_MAJOR@ }; -inline constexpr int project_version_minor { @PROJECT_VERSION_MINOR@ }; -inline constexpr int project_version_patch { @PROJECT_VERSION_PATCH@ }; -inline constexpr int project_version_tweak { @PROJECT_VERSION_TWEAK@ }; -inline constexpr std::string_view git_sha = "@GIT_SHA@"; -}// namespace myproject::cmake + inline constexpr std::string_view git_sha = "@GIT_SHA@"; + inline constexpr std::string_view project_name = "@PROJECT_NAME@"; + inline constexpr std::string_view project_version = "@PROJECT_VERSION@"; + + // clang-format off + inline constexpr int project_version_major { @PROJECT_VERSION_MAJOR@ }; + inline constexpr int project_version_minor { @PROJECT_VERSION_MINOR@ }; + inline constexpr int project_version_patch { @PROJECT_VERSION_PATCH@ }; + inline constexpr int project_version_tweak { @PROJECT_VERSION_TWEAK@ }; + // clang-format on +} // namespace myproject::cmake #endif diff --git a/fuzz_test/CMakeLists.txt b/fuzz_test/CMakeLists.txt index 7a392f57..344b8d0a 100644 --- a/fuzz_test/CMakeLists.txt +++ b/fuzz_test/CMakeLists.txt @@ -1,21 +1,15 @@ # A fuzz test runs until it finds an error. This particular one is going to rely on libFuzzer. -# find_package(fmt) add_executable(fuzz_tester fuzz_tester.cpp) -target_link_libraries( - fuzz_tester - PRIVATE myproject_options - myproject_warnings - fmt::fmt - -coverage - -fsanitize=fuzzer) +target_link_libraries(fuzz_tester PRIVATE myproject_options myproject_warnings fmt::fmt -coverage -fsanitize=fuzzer) target_compile_options(fuzz_tester PRIVATE -fsanitize=fuzzer) # Allow short runs during automated testing to see if something new breaks set(FUZZ_RUNTIME 10 - CACHE STRING "Number of seconds to run fuzz tests during ctest run") # Default of 10 seconds + CACHE STRING "Number of seconds to run fuzz tests during ctest run" +) # Default of 10 seconds add_test(NAME fuzz_tester_run COMMAND fuzz_tester -max_total_time=${FUZZ_RUNTIME}) diff --git a/fuzz_test/fuzz_tester.cpp b/fuzz_test/fuzz_tester.cpp index ed0fc4ce..12b4c463 100644 --- a/fuzz_test/fuzz_tester.cpp +++ b/fuzz_test/fuzz_tester.cpp @@ -2,21 +2,19 @@ #include #include -[[nodiscard]] auto sum_values(const uint8_t *Data, size_t Size) -{ - constexpr auto scale = 1000; - - int value = 0; - for (std::size_t offset = 0; offset < Size; ++offset) { - value += static_cast(*std::next(Data, static_cast(offset))) * scale; - } - return value; +[[nodiscard]] auto sum_values(const uint8_t *data, std::size_t size) -> int { + constexpr auto scale = 1000; + int value = 0; + for (std::size_t offset = 0; offset < size; ++offset) { + value += static_cast(*std::next(data, static_cast(offset))) * scale; + } + return value; } -// Fuzzer that attempts to invoke undefined behavior for signed integer overflow -// cppcheck-suppress unusedFunction symbolName=LLVMFuzzerTestOneInput -extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) -{ - fmt::print("Value sum: {}, len{}\n", sum_values(Data, Size), Size); - return 0; +extern "C" { + // Fuzzer that attempts to invoke undefined behavior for signed integer overflow + auto LLVMFuzzerTestOneInput(const uint8_t *data, std::size_t size) -> int { + fmt::print("Value sum: {}, len{}\n", sum_values(data, size), size); + return 0; + } } diff --git a/include/myproject/sample_library.hpp b/include/myproject/sample_library.hpp index 1b2b1772..72fa7fb2 100644 --- a/include/myproject/sample_library.hpp +++ b/include/myproject/sample_library.hpp @@ -3,13 +3,14 @@ #include -[[nodiscard]] SAMPLE_LIBRARY_EXPORT int factorial(int) noexcept; +[[nodiscard]] SAMPLE_LIBRARY_EXPORT auto factorial(int) noexcept -> int; -[[nodiscard]] constexpr int factorial_constexpr(int input) noexcept -{ - if (input == 0) { return 1; } +[[nodiscard]] constexpr auto factorial_constexpr(int input) noexcept -> int { + if (input == 0) { + return 1; + } - return input * factorial_constexpr(input - 1); + return input * factorial_constexpr(input - 1); } -#endif +#endif // SAMPLE_LIBRARY_HPP diff --git a/src/ftxui_sample/CMakeLists.txt b/src/ftxui_sample/CMakeLists.txt index fc5c65e2..da10439b 100644 --- a/src/ftxui_sample/CMakeLists.txt +++ b/src/ftxui_sample/CMakeLists.txt @@ -1,19 +1,17 @@ add_executable(intro main.cpp) -target_link_libraries( - intro - PRIVATE myproject::myproject_options - myproject::myproject_warnings) +target_link_libraries(intro PRIVATE myproject::myproject_options myproject::myproject_warnings) target_link_system_libraries( intro PRIVATE - CLI11::CLI11 - fmt::fmt - spdlog::spdlog - lefticus::tools - ftxui::screen - ftxui::dom - ftxui::component) + CLI11::CLI11 + fmt::fmt + spdlog::spdlog + lefticus::tools + ftxui::screen + ftxui::dom + ftxui::component +) target_include_directories(intro PRIVATE "${CMAKE_BINARY_DIR}/configured_files/include") diff --git a/src/ftxui_sample/main.cpp b/src/ftxui_sample/main.cpp index aa53beaf..4895279e 100644 --- a/src/ftxui_sample/main.cpp +++ b/src/ftxui_sample/main.cpp @@ -1,349 +1,363 @@ #include +#include +#include +#include +#include #include +#include #include +#include #include - #include - -#include -#include // for ftxui -#include // for Slider -#include // for ScreenInteractive #include -#include +template +class GameBoard { + public: + static constexpr std::size_t width = Width; + static constexpr std::size_t height = Height; -// This file will be generated automatically when cur_you run the CMake -// configuration step. It creates a namespace called `myproject`. You can modify -// the source template at `configured_files/config.hpp.in`. -#include + std::size_t move_count{0}; -template struct GameBoard -{ - static constexpr std::size_t width = Width; - static constexpr std::size_t height = Height; + private: + std::array, width> _strings; + std::array, width> _values{}; - std::array, width> strings; - std::array, width> values{}; - - std::size_t move_count{ 0 }; - - std::string &get_string(std::size_t cur_x, std::size_t cur_y) { return strings.at(cur_x).at(cur_y); } - - - void set(std::size_t cur_x, std::size_t cur_y, bool new_value) - { - get(cur_x, cur_y) = new_value; - - if (new_value) { - get_string(cur_x, cur_y) = " ON"; - } else { - get_string(cur_x, cur_y) = "OFF"; + public: + GameBoard() { + visit([](const auto cur_x, const auto cur_y, auto &gameboard) { + gameboard.set(cur_x, cur_y, true); + }); } - } - void visit(auto visitor) - { - for (std::size_t cur_x = 0; cur_x < width; ++cur_x) { - for (std::size_t cur_y = 0; cur_y < height; ++cur_y) { visitor(cur_x, cur_y, *this); } + [[nodiscard]] auto get(std::size_t cur_x, std::size_t cur_y) const -> bool { + return _values.at(cur_x).at(cur_y); } - } - - [[nodiscard]] bool get(std::size_t cur_x, std::size_t cur_y) const { return values.at(cur_x).at(cur_y); } - [[nodiscard]] bool &get(std::size_t cur_x, std::size_t cur_y) { return values.at(cur_x).at(cur_y); } - - GameBoard() - { - visit([](const auto cur_x, const auto cur_y, auto &gameboard) { gameboard.set(cur_x, cur_y, true); }); - } - - void update_strings() - { - for (std::size_t cur_x = 0; cur_x < width; ++cur_x) { - for (std::size_t cur_y = 0; cur_y < height; ++cur_y) { set(cur_x, cur_y, get(cur_x, cur_y)); } + [[nodiscard]] auto get(std::size_t cur_x, std::size_t cur_y) -> bool & { + return _values.at(cur_x).at(cur_y); } - } - - void toggle(std::size_t cur_x, std::size_t cur_y) { set(cur_x, cur_y, !get(cur_x, cur_y)); } - - void press(std::size_t cur_x, std::size_t cur_y) - { - ++move_count; - toggle(cur_x, cur_y); - if (cur_x > 0) { toggle(cur_x - 1, cur_y); } - if (cur_y > 0) { toggle(cur_x, cur_y - 1); } - if (cur_x < width - 1) { toggle(cur_x + 1, cur_y); } - if (cur_y < height - 1) { toggle(cur_x, cur_y + 1); } - } - - [[nodiscard]] bool solved() const - { - for (std::size_t cur_x = 0; cur_x < width; ++cur_x) { - for (std::size_t cur_y = 0; cur_y < height; ++cur_y) { - if (!get(cur_x, cur_y)) { return false; } - } - } - - return true; - } -}; - - -void consequence_game() -{ - auto screen = ftxui::ScreenInteractive::TerminalOutput(); - GameBoard<3, 3> game_board; + auto get_string(std::size_t cur_x, std::size_t cur_y) -> std::string & { + return _strings.at(cur_x).at(cur_y); + } - std::string quit_text; + auto press(std::size_t cur_x, std::size_t cur_y) -> void { + ++move_count; + toggle(cur_x, cur_y); + if (cur_x > 0) { + toggle(cur_x - 1, cur_y); + } + if (cur_y > 0) { + toggle(cur_x, cur_y - 1); + } + if (cur_x < width - 1) { + toggle(cur_x + 1, cur_y); + } + if (cur_y < height - 1) { + toggle(cur_x, cur_y + 1); + } + } - const auto update_quit_text = [&quit_text](const auto &game_board_param) { - quit_text = fmt::format("Quit ({} moves)", game_board_param.move_count); - if (game_board_param.solved()) { quit_text += " Solved!"; } - }; + auto set(std::size_t cur_x, std::size_t cur_y, bool new_value) -> void { + get(cur_x, cur_y) = new_value; + if (new_value) { + get_string(cur_x, cur_y) = " ON"; + } else { + get_string(cur_x, cur_y) = "OFF"; + } + } - const auto make_buttons = [&] { - std::vector buttons; - for (std::size_t cur_x = 0; cur_x < game_board.width; ++cur_x) { - for (std::size_t cur_y = 0; cur_y < game_board.height; ++cur_y) { - buttons.push_back(ftxui::Button(&game_board.get_string(cur_x, cur_y), [=, &game_board] { - if (!game_board.solved()) { game_board.press(cur_x, cur_y); } - update_quit_text(game_board); - })); - } + [[nodiscard]] auto solved() const -> bool { + for (std::size_t cur_x = 0; cur_x < width; ++cur_x) { + for (std::size_t cur_y = 0; cur_y < height; ++cur_y) { + if (!get(cur_x, cur_y)) { + return false; + } + } + } + return true; } - return buttons; - }; - auto buttons = make_buttons(); + auto toggle(std::size_t cur_x, std::size_t cur_y) -> void { + set(cur_x, cur_y, !get(cur_x, cur_y)); + } - auto quit_button = ftxui::Button(&quit_text, screen.ExitLoopClosure()); + auto update_strings() -> void { + for (std::size_t cur_x = 0; cur_x < width; ++cur_x) { + for (std::size_t cur_y = 0; cur_y < height; ++cur_y) { + set(cur_x, cur_y, get(cur_x, cur_y)); + } + } + } - auto make_layout = [&] { - std::vector rows; + auto visit(auto visitor) -> void { + for (std::size_t cur_x = 0; cur_x < width; ++cur_x) { + for (std::size_t cur_y = 0; cur_y < height; ++cur_y) { + visitor(cur_x, cur_y, *this); + } + } + } +}; - std::size_t idx = 0; +auto consequence_game() -> void { + GameBoard<3, 3> game_board; + std::string quit_text; - for (std::size_t cur_x = 0; cur_x < game_board.width; ++cur_x) { - std::vector row; - for (std::size_t cur_y = 0; cur_y < game_board.height; ++cur_y) { - row.push_back(buttons[idx]->Render()); - ++idx; - } - rows.push_back(ftxui::hbox(std::move(row))); - } + auto screen = ftxui::ScreenInteractive::TerminalOutput(); - rows.push_back(ftxui::hbox({ quit_button->Render() })); + const auto update_quit_text = [&quit_text](const auto &game_board_param) { + quit_text = fmt::format("Quit ({} moves)", game_board_param.move_count); + if (game_board_param.solved()) { + quit_text += " Solved!"; + } + }; - return ftxui::vbox(std::move(rows)); - }; + const auto make_buttons = [&] { + std::vector buttons; + for (std::size_t cur_x = 0; cur_x < decltype(game_board)::width; ++cur_x) { + for (std::size_t cur_y = 0; cur_y < decltype(game_board)::height; ++cur_y) { + buttons.push_back(ftxui::Button(&game_board.get_string(cur_x, cur_y), [=, &game_board] { + if (!game_board.solved()) { + game_board.press(cur_x, cur_y); + } + update_quit_text(game_board); + })); + } + } + return buttons; + }; + auto buttons = make_buttons(); + auto quit_button = ftxui::Button(&quit_text, screen.ExitLoopClosure()); - static constexpr int randomization_iterations = 100; - static constexpr int random_seed = 42; + auto make_layout = [&] { + std::vector rows; + std::size_t idx = 0; - std::mt19937 gen32{ random_seed };// NOLINT fixed seed + for (std::size_t cur_x = 0; cur_x < decltype(game_board)::width; ++cur_x) { + std::vector row; + for (std::size_t cur_y = 0; cur_y < decltype(game_board)::height; ++cur_y) { + row.push_back(buttons[idx]->Render()); + ++idx; + } + rows.push_back(ftxui::hbox(std::move(row))); + } - // NOLINTNEXTLINE This cannot be const - std::uniform_int_distribution cur_x(static_cast(0), game_board.width - 1); - // NOLINTNEXTLINE This cannot be const - std::uniform_int_distribution cur_y(static_cast(0), game_board.height - 1); + rows.push_back(ftxui::hbox({quit_button->Render()})); + return ftxui::vbox(std::move(rows)); + }; - for (int i = 0; i < randomization_iterations; ++i) { game_board.press(cur_x(gen32), cur_y(gen32)); } - game_board.move_count = 0; - update_quit_text(game_board); + static constexpr int randomization_iterations = 100; + static constexpr int random_seed = 42; - auto all_buttons = buttons; - all_buttons.push_back(quit_button); - auto container = ftxui::Container::Horizontal(all_buttons); + std::mt19937 gen32{random_seed}; // NOLINT(cert-msc32-c, cert-msc51-cpp) - auto renderer = ftxui::Renderer(container, make_layout); + // NOLINTBEGIN(misc-const-correctness) + std::uniform_int_distribution cur_x(static_cast(0), decltype(game_board)::width - 1); + std::uniform_int_distribution cur_y(static_cast(0), decltype(game_board)::height - 1); + // NOLINTEND(misc-const-correctness) - screen.Loop(renderer); + for (int i = 0; i < randomization_iterations; ++i) { + game_board.press(cur_x(gen32), cur_y(gen32)); + } + game_board.move_count = 0; + update_quit_text(game_board); + + auto all_buttons = buttons; + all_buttons.push_back(quit_button); + auto container = ftxui::Container::Horizontal(all_buttons); + auto renderer = ftxui::Renderer(container, make_layout); + screen.Loop(renderer); } -struct Color -{ - lefticus::tools::uint_np8_t R{ static_cast(0) }; - lefticus::tools::uint_np8_t G{ static_cast(0) }; - lefticus::tools::uint_np8_t B{ static_cast(0) }; +struct Color { + lefticus::tools::uint_np8_t R{static_cast(0)}; + lefticus::tools::uint_np8_t G{static_cast(0)}; + lefticus::tools::uint_np8_t B{static_cast(0)}; }; // A simple way of representing a bitmap on screen using only characters -struct Bitmap : ftxui::Node -{ - Bitmap(std::size_t width, std::size_t height)// NOLINT same typed parameters adjacent to each other - : width_(width), height_(height) - {} - - Color &at(std::size_t cur_x, std::size_t cur_y) { return pixels.at(width_ * cur_y + cur_x); } - - void ComputeRequirement() override - { - requirement_ = ftxui::Requirement{ - .min_x = static_cast(width_), .min_y = static_cast(height_ / 2), .selected_box{ 0, 0, 0, 0 } - }; - } - - void Render(ftxui::Screen &screen) override - { - for (std::size_t cur_x = 0; cur_x < width_; ++cur_x) { - for (std::size_t cur_y = 0; cur_y < height_ / 2; ++cur_y) { - auto &pixel = screen.PixelAt(box_.x_min + static_cast(cur_x), box_.y_min + static_cast(cur_y)); - pixel.character = "▄"; - const auto &top_color = at(cur_x, cur_y * 2); - const auto &bottom_color = at(cur_x, cur_y * 2 + 1); - pixel.background_color = ftxui::Color{ top_color.R.get(), top_color.G.get(), top_color.B.get() }; - pixel.foreground_color = ftxui::Color{ bottom_color.R.get(), bottom_color.G.get(), bottom_color.B.get() }; - } +struct Bitmap : ftxui::Node { + private: + std::size_t _width; + std::size_t _height; + std::vector _pixels = std::vector(_width * _height, Color{}); + + public: + Bitmap(std::size_t width, std::size_t height) : // NOLINT(bugprone-easily-swappable-parameters) + _width(width), + _height(height) {} + + auto at(std::size_t cur_x, std::size_t cur_y) -> Color & { + return _pixels.at(_width * cur_y + cur_x); } - } - - [[nodiscard]] auto width() const noexcept { return width_; } - - [[nodiscard]] auto height() const noexcept { return height_; } - - [[nodiscard]] auto &data() noexcept { return pixels; } - -private: - std::size_t width_; - std::size_t height_; - - std::vector pixels = std::vector(width_ * height_, Color{}); -}; - -void game_iteration_canvas() -{ - // this should probably have a `bitmap` helper function that does what cur_you expect - // similar to the other parts of FTXUI - auto bm = std::make_shared(50, 50);// NOLINT magic numbers - auto small_bm = std::make_shared(6, 6);// NOLINT magic numbers - - double fps = 0; - - std::size_t max_row = 0; - std::size_t max_col = 0; - // to do, add total game time clock also, not just current elapsed time - auto game_iteration = [&](const std::chrono::steady_clock::duration elapsed_time) { - // in here we simulate however much game time has elapsed. Update animations, - // run character AI, whatever, update stats, etc - - // this isn't actually timing based for now, it's just updating the display however fast it can - fps = 1.0 - / (static_cast(std::chrono::duration_cast(elapsed_time).count()) - / 1'000'000.0);// NOLINT magic numbers - - for (std::size_t row = 0; row < max_row; ++row) { - for (std::size_t col = 0; col < bm->width(); ++col) { ++(bm->at(col, row).R); } + [[nodiscard]] auto data() noexcept -> auto & { + return _pixels; } - for (std::size_t row = 0; row < bm->height(); ++row) { - for (std::size_t col = 0; col < max_col; ++col) { ++(bm->at(col, row).G); } + [[nodiscard]] auto height() const noexcept { + return _height; } - // for the fun of it, let's have a second window doing interesting things - auto &small_bm_pixel = - small_bm->data().at(static_cast(elapsed_time.count()) % small_bm->data().size()); - - switch (elapsed_time.count() % 3) { - case 0: - small_bm_pixel.R += 11;// NOLINT Magic Number - break; - case 1: - small_bm_pixel.G += 11;// NOLINT Magic Number - break; - case 2: - small_bm_pixel.B += 11;// NOLINT Magic Number - break; + [[nodiscard]] auto width() const noexcept { + return _width; } + auto ComputeRequirement() -> void override { + requirement_ = ftxui::Requirement{ + .min_x = static_cast(_width), + .min_y = static_cast(_height / 2), + .selected_box{0, 0, 0, 0} + }; + } - ++max_row; - if (max_row >= bm->height()) { max_row = 0; } - ++max_col; - if (max_col >= bm->width()) { max_col = 0; } - }; - - auto screen = ftxui::ScreenInteractive::TerminalOutput(); - - int counter = 0; - - auto last_time = std::chrono::steady_clock::now(); - - auto make_layout = [&] { - // This code actually processes the draw event - const auto new_time = std::chrono::steady_clock::now(); + auto Render(ftxui::Screen &screen) -> void override { + for (std::size_t cur_x = 0; cur_x < _width; ++cur_x) { + for (std::size_t cur_y = 0; cur_y < _height / 2; ++cur_y) { + auto &pixel = + screen.PixelAt(box_.x_min + static_cast(cur_x), box_.y_min + static_cast(cur_y)); + pixel.character = "▄"; - ++counter; - // we will dispatch to the game_iteration function, where the work happens - game_iteration(new_time - last_time); - last_time = new_time; + const auto &top_color = at(cur_x, cur_y * 2); + const auto &bottom_color = at(cur_x, cur_y * 2 + 1); - // now actually draw the game elements - return ftxui::hbox({ bm | ftxui::border, - ftxui::vbox({ ftxui::text("Frame: " + std::to_string(counter)), - ftxui::text("FPS: " + std::to_string(fps)), - small_bm | ftxui::border }) }); - }; + pixel.background_color = ftxui::Color{top_color.R.get(), top_color.G.get(), top_color.B.get()}; + pixel.foreground_color = ftxui::Color{bottom_color.R.get(), bottom_color.G.get(), bottom_color.B.get()}; + } + } + } +}; - auto renderer = ftxui::Renderer(make_layout); +auto game_iteration_canvas() -> void { + // this should probably have a `bitmap` helper function that does what cur_you + // expect similar to the other parts of FTXUI + + auto bitmap = std::make_shared(50, 50); // NOLINT(*-magic-numbers) + auto small_bitmap = std::make_shared(6, 6); // NOLINT(*-magic-numbers) + + double fps = 0; + std::size_t max_row = 0; + std::size_t max_col = 0; + + // TODO: add total game time clock also, not just current elapsed time + auto game_iteration = [&](const std::chrono::steady_clock::duration elapsed_time) { + // in here we simulate however much game time has elapsed. + // Update animations, run character AI, whatever, update stats, etc + + // this isn't actually timing based for now, + // it's just updating the display however fast it can + fps = 1.0 + / (static_cast(std::chrono::duration_cast(elapsed_time).count()) + / 1'000'000.0); // NOLINT(*-magic-numbers) + + for (std::size_t row = 0; row < max_row; ++row) { + for (std::size_t col = 0; col < bitmap->width(); ++col) { + ++(bitmap->at(col, row).R); + } + } + + for (std::size_t row = 0; row < bitmap->height(); ++row) { + for (std::size_t col = 0; col < max_col; ++col) { + ++(bitmap->at(col, row).G); + } + } + + // for the fun of it, let's have a second window doing interesting + // things + auto &small_bm_pixel = + small_bitmap->data().at(static_cast(elapsed_time.count()) % small_bitmap->data().size()); + + switch (elapsed_time.count() % 3) { + case 0: + small_bm_pixel.R += 11; // NOLINT(*-magic-numbers) + break; + case 1: + small_bm_pixel.G += 11; // NOLINT(*-magic-numbers) + break; + case 2: + small_bm_pixel.B += 11; // NOLINT(*-magic-numbers) + break; + } + + ++max_row; + if (max_row >= bitmap->height()) { + max_row = 0; + } + ++max_col; + if (max_col >= bitmap->width()) { + max_col = 0; + } + }; + auto last_time = std::chrono::steady_clock::now(); + auto screen = ftxui::ScreenInteractive::TerminalOutput(); + int counter = 0; - std::atomic refresh_ui_continue = true; + auto make_layout = [&] { + // This code actually processes the draw event + const auto new_time = std::chrono::steady_clock::now(); - // This thread exists to make sure that the event queue has an event to - // process at approximately a rate of 30 FPS - std::thread refresh_ui([&] { - while (refresh_ui_continue) { - using namespace std::chrono_literals; - std::this_thread::sleep_for(1.0s / 30.0);// NOLINT magic numbers - screen.PostEvent(ftxui::Event::Custom); - } - }); + ++counter; + // we will dispatch to the game_iteration function, where the work happens + game_iteration(new_time - last_time); + last_time = new_time; - screen.Loop(renderer); + // now actually draw the game elements + return ftxui::hbox({bitmap | ftxui::border, + ftxui::vbox({ftxui::text("Frame: " + std::to_string(counter)), + ftxui::text("FPS: " + std::to_string(fps)), + small_bitmap | ftxui::border})}); + }; - refresh_ui_continue = false; - refresh_ui.join(); + auto renderer = ftxui::Renderer(make_layout); + std::atomic refresh_ui_continue = true; + + // This thread exists to make sure that the event queue has an event to + // process at approximately a rate of 30 FPS + std::thread refresh_ui([&] { + while (refresh_ui_continue) { + using namespace std::chrono_literals; + std::this_thread::sleep_for(1.0s / 30.0); // NOLINT magic numbers + screen.PostEvent(ftxui::Event::Custom); + } + }); + + screen.Loop(renderer); + refresh_ui_continue = false; + refresh_ui.join(); } -// NOLINTNEXTLINE(bugprone-exception-escape) -int main(int argc, const char **argv) -{ - try { - CLI::App app{ fmt::format("{} version {}", myproject::cmake::project_name, myproject::cmake::project_version) }; +auto main([[maybe_unused]] int argc, [[maybe_unused]] const char **argv) -> int try { + CLI::App app{fmt::format("{} version {}", myproject::cmake::project_name, myproject::cmake::project_version)}; std::optional message; app.add_option("-m,--message", message, "A message to print back out"); bool show_version = false; app.add_flag("--version", show_version, "Show version information"); - bool is_turn_based = false; - auto *turn_based = app.add_flag("--turn_based", is_turn_based); + bool is_turn_based = false; + auto *turn_based = app.add_flag("--turn_based", is_turn_based); - bool is_loop_based = false; - auto *loop_based = app.add_flag("--loop_based", is_loop_based); + bool is_loop_based = false; + auto *loop_based = app.add_flag("--loop_based", is_loop_based); turn_based->excludes(loop_based); loop_based->excludes(turn_based); - CLI11_PARSE(app, argc, argv); if (show_version) { - fmt::print("{}\n", myproject::cmake::project_version); - return EXIT_SUCCESS; + fmt::print("{}\n", myproject::cmake::project_version); + return EXIT_SUCCESS; } if (is_turn_based) { - consequence_game(); + consequence_game(); } else { - game_iteration_canvas(); + game_iteration_canvas(); } - - } catch (const std::exception &e) { +} catch (const std::exception &e) { spdlog::error("Unhandled exception in main: {}", e.what()); - } } diff --git a/src/sample_library/CMakeLists.txt b/src/sample_library/CMakeLists.txt index b75fe637..22b07814 100644 --- a/src/sample_library/CMakeLists.txt +++ b/src/sample_library/CMakeLists.txt @@ -1,16 +1,15 @@ include(GenerateExportHeader) - add_library(sample_library sample_library.cpp) - - add_library(myproject::sample_library ALIAS sample_library) target_link_libraries(sample_library PRIVATE myproject_options myproject_warnings) -target_include_directories(sample_library ${WARNING_GUARD} PUBLIC $ - $) +target_include_directories( + sample_library ${WARNING_GUARD} PUBLIC $ + $ +) target_compile_features(sample_library PUBLIC cxx_std_20) @@ -18,9 +17,12 @@ set_target_properties( sample_library PROPERTIES VERSION ${PROJECT_VERSION} CXX_VISIBILITY_PRESET hidden - VISIBILITY_INLINES_HIDDEN YES) + VISIBILITY_INLINES_HIDDEN YES +) -generate_export_header(sample_library EXPORT_FILE_NAME ${PROJECT_BINARY_DIR}/include/myproject/sample_library_export.hpp) +generate_export_header( + sample_library EXPORT_FILE_NAME ${PROJECT_BINARY_DIR}/include/myproject/sample_library_export.hpp +) if(NOT BUILD_SHARED_LIBS) target_compile_definitions(sample_library PUBLIC SAMPLE_LIBRARY_STATIC_DEFINE) diff --git a/src/sample_library/sample_library.cpp b/src/sample_library/sample_library.cpp index 878deae2..e7fbf855 100644 --- a/src/sample_library/sample_library.cpp +++ b/src/sample_library/sample_library.cpp @@ -1,13 +1,10 @@ #include -int factorial(int input) noexcept -{ - int result = 1; - - while (input > 0) { - result *= input; - --input; - } - - return result; +auto factorial(int input) noexcept -> int { + int result = 1; + while (input > 0) { + result *= input; + --input; + } + return result; } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 0739f424..22f6a195 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -22,27 +22,25 @@ include(${Catch2_SOURCE_DIR}/extras/Catch.cmake) # Provide a simple smoke test to make sure that the CLI works and can display a --help message add_test(NAME cli.has_help COMMAND intro --help) -# Provide a test to verify that the version being reported from the application -# matches the version given to CMake. This will be important once you package -# your program. Real world shows that this is the kind of simple mistake that is easy +# Provide a test to verify that the version being reported from the application matches the version given to CMake. This +# will be important once you package your program. Real world shows that this is the kind of simple mistake that is easy # to make, but also easy to test for. add_test(NAME cli.version_matches COMMAND intro --version) set_tests_properties(cli.version_matches PROPERTIES PASS_REGULAR_EXPRESSION "${PROJECT_VERSION}") add_executable(tests tests.cpp) target_link_libraries( - tests - PRIVATE myproject::myproject_warnings - myproject::myproject_options - myproject::sample_library - Catch2::Catch2WithMain) + tests PRIVATE myproject::myproject_warnings myproject::myproject_options myproject::sample_library + Catch2::Catch2WithMain +) if(WIN32 AND BUILD_SHARED_LIBS) add_custom_command( TARGET tests PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy $ $ - COMMAND_EXPAND_LISTS) + COMMAND_EXPAND_LISTS + ) endif() # automatically discover tests that are defined in catch based test files you can modify the unittests. Set TEST_PREFIX @@ -58,16 +56,15 @@ catch_discover_tests( OUTPUT_PREFIX "unittests." OUTPUT_SUFFIX - .xml) + .xml +) # Add a file containing a set of constexpr tests add_executable(constexpr_tests constexpr_tests.cpp) target_link_libraries( - constexpr_tests - PRIVATE myproject::myproject_warnings - myproject::myproject_options - myproject::sample_library - Catch2::Catch2WithMain) + constexpr_tests PRIVATE myproject::myproject_warnings myproject::myproject_options myproject::sample_library + Catch2::Catch2WithMain +) catch_discover_tests( constexpr_tests @@ -80,17 +77,16 @@ catch_discover_tests( OUTPUT_PREFIX "constexpr." OUTPUT_SUFFIX - .xml) + .xml +) # Disable the constexpr portion of the test, and build again this allows us to have an executable that we can debug when # things go wrong with the constexpr testing add_executable(relaxed_constexpr_tests constexpr_tests.cpp) target_link_libraries( - relaxed_constexpr_tests - PRIVATE myproject::myproject_warnings - myproject::myproject_options - myproject::sample_library - Catch2::Catch2WithMain) + relaxed_constexpr_tests PRIVATE myproject::myproject_warnings myproject::myproject_options myproject::sample_library + Catch2::Catch2WithMain +) target_compile_definitions(relaxed_constexpr_tests PRIVATE -DCATCH_CONFIG_RUNTIME_STATIC_REQUIRE) catch_discover_tests( @@ -104,4 +100,5 @@ catch_discover_tests( OUTPUT_PREFIX "relaxed_constexpr." OUTPUT_SUFFIX - .xml) + .xml +) diff --git a/test/constexpr_tests.cpp b/test/constexpr_tests.cpp index fe36db5e..34490fda 100644 --- a/test/constexpr_tests.cpp +++ b/test/constexpr_tests.cpp @@ -1,12 +1,10 @@ #include - #include -TEST_CASE("Factorials are computed with constexpr", "[factorial]") -{ - STATIC_REQUIRE(factorial_constexpr(0) == 1); - STATIC_REQUIRE(factorial_constexpr(1) == 1); - STATIC_REQUIRE(factorial_constexpr(2) == 2); - STATIC_REQUIRE(factorial_constexpr(3) == 6); - STATIC_REQUIRE(factorial_constexpr(10) == 3628800); +TEST_CASE("Factorials are computed with constexpr", "[factorial]") { + STATIC_REQUIRE(factorial_constexpr(0) == 1); + STATIC_REQUIRE(factorial_constexpr(1) == 1); + STATIC_REQUIRE(factorial_constexpr(2) == 2); + STATIC_REQUIRE(factorial_constexpr(3) == 6); + STATIC_REQUIRE(factorial_constexpr(10) == 3628800); } diff --git a/test/tests.cpp b/test/tests.cpp index 5b632e2e..55a17c6a 100644 --- a/test/tests.cpp +++ b/test/tests.cpp @@ -1,14 +1,10 @@ #include - - #include - -TEST_CASE("Factorials are computed", "[factorial]") -{ - REQUIRE(factorial(0) == 1); - REQUIRE(factorial(1) == 1); - REQUIRE(factorial(2) == 2); - REQUIRE(factorial(3) == 6); - REQUIRE(factorial(10) == 3628800); +TEST_CASE("Factorials are computed", "[factorial]") { + REQUIRE(factorial(0) == 1); + REQUIRE(factorial(1) == 1); + REQUIRE(factorial(2) == 2); + REQUIRE(factorial(3) == 6); + REQUIRE(factorial(10) == 3628800); }