├── .clang-format ├── .clang-tidy ├── .cmake-format.yaml ├── .devcontainer ├── .dockerignore ├── Dockerfile └── devcontainer.json ├── .gitattributes ├── .github ├── FUNDING.yml ├── actions │ └── setup_cache │ │ └── action.yml ├── template │ ├── README.md │ ├── removal-list │ ├── template_name │ └── template_repository └── workflows │ ├── auto-clang-format.yml │ ├── ci.yml │ ├── codeql-analysis.yml │ └── template-janitor.yml ├── .gitignore ├── .gitlab-ci.yml ├── .lgtm.yml ├── CMakeLists.txt ├── CMakePresets.json ├── LICENSE ├── README.md ├── README_building.md ├── README_dependencies.md ├── README_docker.md ├── README_troubleshooting.md ├── build_examples.sh ├── conanfile.txt ├── configured_files ├── CMakeLists.txt └── config.hpp.in ├── fuzz_test ├── CMakeLists.txt └── fuzz_tester.cpp ├── src ├── CMakeLists.txt └── main.cpp └── test ├── CMakeLists.txt ├── catch_main.cpp ├── constexpr_tests.cpp └── tests.cpp /.clang-format: -------------------------------------------------------------------------------- 1 | AccessModifierOffset: -2 2 | AlignAfterOpenBracket: DontAlign 3 | AlignConsecutiveAssignments: false 4 | AlignConsecutiveDeclarations: false 5 | AlignEscapedNewlines: Left 6 | AlignOperands: true 7 | AlignTrailingComments: false 8 | AllowAllParametersOfDeclarationOnNextLine: false 9 | AllowShortBlocksOnASingleLine: true 10 | AllowShortCaseLabelsOnASingleLine: false 11 | AllowShortFunctionsOnASingleLine: All 12 | AllowShortIfStatementsOnASingleLine: true 13 | AllowShortLoopsOnASingleLine: true 14 | AlwaysBreakAfterDefinitionReturnType: None 15 | AlwaysBreakAfterReturnType: None 16 | AlwaysBreakBeforeMultilineStrings: true 17 | AlwaysBreakTemplateDeclarations: false 18 | BinPackArguments: false 19 | BinPackParameters: false 20 | BraceWrapping: 21 | AfterClass: true 22 | AfterControlStatement: false 23 | AfterEnum: false 24 | AfterFunction: true 25 | AfterNamespace: false 26 | AfterObjCDeclaration: false 27 | AfterStruct: true 28 | AfterUnion: false 29 | BeforeCatch: false 30 | BeforeElse: false 31 | IndentBraces: false 32 | SplitEmptyFunction: false 33 | SplitEmptyNamespace: true 34 | SplitEmptyRecord: true 35 | BreakAfterJavaFieldAnnotations: true 36 | BreakBeforeBinaryOperators: NonAssignment 37 | BreakBeforeBraces: Custom 38 | BreakBeforeInheritanceComma: true 39 | BreakBeforeTernaryOperators: true 40 | BreakConstructorInitializers: BeforeColon 41 | BreakConstructorInitializersBeforeComma: false 42 | BreakStringLiterals: true 43 | ColumnLimit: 120 44 | CommentPragmas: '^ IWYU pragma:' 45 | CompactNamespaces: false 46 | ConstructorInitializerAllOnOneLineOrOnePerLine: false 47 | ConstructorInitializerIndentWidth: 2 48 | ContinuationIndentWidth: 2 49 | Cpp11BracedListStyle: false 50 | DerivePointerAlignment: false 51 | DisableFormat: false 52 | ExperimentalAutoDetectBinPacking: true 53 | FixNamespaceComments: true 54 | ForEachMacros: 55 | - foreach 56 | - Q_FOREACH 57 | - BOOST_FOREACH 58 | IncludeCategories: 59 | - Priority: 2 60 | Regex: ^"(llvm|llvm-c|clang|clang-c)/ 61 | - Priority: 3 62 | Regex: ^(<|"(gtest|gmock|isl|json)/) 63 | - Priority: 1 64 | Regex: .* 65 | IncludeIsMainRegex: (Test)?$ 66 | IndentCaseLabels: false 67 | IndentWidth: 2 68 | IndentWrappedFunctionNames: true 69 | JavaScriptQuotes: Leave 70 | JavaScriptWrapImports: true 71 | KeepEmptyLinesAtTheStartOfBlocks: true 72 | Language: Cpp 73 | MacroBlockBegin: '' 74 | MacroBlockEnd: '' 75 | MaxEmptyLinesToKeep: 2 76 | NamespaceIndentation: Inner 77 | ObjCBlockIndentWidth: 7 78 | ObjCSpaceAfterProperty: true 79 | ObjCSpaceBeforeProtocolList: false 80 | PointerAlignment: Right 81 | ReflowComments: true 82 | SortIncludes: true 83 | SortUsingDeclarations: false 84 | SpaceAfterCStyleCast: false 85 | SpaceAfterTemplateKeyword: false 86 | SpaceBeforeAssignmentOperators: true 87 | SpaceBeforeParens: ControlStatements 88 | SpaceInEmptyParentheses: false 89 | SpacesBeforeTrailingComments: 0 90 | SpacesInAngles: false 91 | SpacesInCStyleCastParentheses: false 92 | SpacesInContainerLiterals: true 93 | SpacesInParentheses: false 94 | SpacesInSquareBrackets: false 95 | Standard: c++20 96 | TabWidth: 8 97 | UseTab: Never 98 | 99 | -------------------------------------------------------------------------------- /.clang-tidy: -------------------------------------------------------------------------------- 1 | --- 2 | Checks: "*, 3 | -abseil-*, 4 | -altera-*, 5 | -android-*, 6 | -fuchsia-*, 7 | -google-*, 8 | -llvm*, 9 | -modernize-use-trailing-return-type, 10 | -zircon-*, 11 | -readability-else-after-return, 12 | -readability-static-accessed-through-instance, 13 | -readability-avoid-const-params-in-decls, 14 | -cppcoreguidelines-non-private-member-variables-in-classes, 15 | -misc-non-private-member-variables-in-classes, 16 | " 17 | WarningsAsErrors: '' 18 | HeaderFilterRegex: '' 19 | FormatStyle: none 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /.cmake-format.yaml: -------------------------------------------------------------------------------- 1 | additional_commands: 2 | foo: 3 | flags: 4 | - BAR 5 | - BAZ 6 | kwargs: 7 | DEPENDS: '*' 8 | HEADERS: '*' 9 | SOURCES: '*' 10 | bullet_char: '*' 11 | dangle_parens: false 12 | enum_char: . 13 | line_ending: unix 14 | line_width: 120 15 | max_pargs_hwrap: 3 16 | separate_ctrl_name_with_space: false 17 | separate_fn_name_with_space: false 18 | tab_size: 2 19 | 20 | markup: 21 | enable_markup: false 22 | -------------------------------------------------------------------------------- /.devcontainer/.dockerignore: -------------------------------------------------------------------------------- 1 | # Build directories and binary files 2 | build/ 3 | out/ 4 | cmake-build-*/ 5 | 6 | # User spesific settings 7 | CMakeUserPresets.json 8 | 9 | # IDE files 10 | .vs/ 11 | .idea/ 12 | .vscode/ 13 | !.vscode/settings.json 14 | !.vscode/tasks.json 15 | !.vscode/launch.json 16 | !.vscode/extensions.json 17 | *.swp 18 | *~ 19 | _ReSharper* 20 | *.log 21 | 22 | # OS Generated Files 23 | .DS_Store 24 | .AppleDouble 25 | .LSOverride 26 | ._* 27 | .Spotlight-V100 28 | .Trashes 29 | .Trash-* 30 | $RECYCLE.BIN/ 31 | .TemporaryItems 32 | ehthumbs.db 33 | Thumbs.db 34 | Dockerfile -------------------------------------------------------------------------------- /.devcontainer/Dockerfile: -------------------------------------------------------------------------------- 1 | # [Choice] bionic (18.04), focal (20.04) 2 | ARG VARIANT="focal" 3 | FROM ubuntu:${VARIANT} 4 | 5 | # Restate the variant to use it later on in the llvm and cmake installations 6 | ARG VARIANT 7 | 8 | # Install necessary packages available from standard repos 9 | RUN apt-get update -qq && export DEBIAN_FRONTEND=noninteractive && \ 10 | apt-get install -y --no-install-recommends \ 11 | software-properties-common wget apt-utils file zip \ 12 | openssh-client gpg-agent socat rsync \ 13 | make ninja-build git \ 14 | python3 python3-pip 15 | 16 | # Install conan 17 | RUN python3 -m pip install --upgrade pip setuptools && \ 18 | python3 -m pip install conan && \ 19 | conan --version 20 | 21 | # By default, anything you run in Docker is done as superuser. 22 | # Conan runs some install commands as superuser, and will prepend `sudo` to 23 | # these commands, unless `CONAN_SYSREQUIRES_SUDO=0` is in your env variables. 24 | ENV CONAN_SYSREQUIRES_SUDO 0 25 | # Some packages request that Conan use the system package manager to install 26 | # a few dependencies. This flag allows Conan to proceed with these installations; 27 | # leaving this flag undefined can cause some installation failures. 28 | ENV CONAN_SYSREQUIRES_MODE enabled 29 | 30 | # User-settable versions: 31 | # This Dockerfile should support gcc-[7, 8, 9, 10, 11] and clang-[10, 11, 12, 13] 32 | # Earlier versions of clang will require significant modifications to the IWYU section 33 | ARG GCC_VER="11" 34 | # Add gcc-${GCC_VER} 35 | RUN add-apt-repository -y ppa:ubuntu-toolchain-r/test && \ 36 | apt-get update -qq && export DEBIAN_FRONTEND=noninteractive && \ 37 | apt-get install -y --no-install-recommends \ 38 | gcc-${GCC_VER} g++-${GCC_VER} gdb 39 | 40 | # Set gcc-${GCC_VER} as default gcc 41 | RUN update-alternatives --install /usr/bin/gcc gcc $(which gcc-${GCC_VER}) 100 42 | RUN update-alternatives --install /usr/bin/g++ g++ $(which g++-${GCC_VER}) 100 43 | 44 | ARG LLVM_VER="13" 45 | # Add clang-${LLVM_VER} 46 | ARG LLVM_URL="http://apt.llvm.org/${VARIANT}/" 47 | ARG LLVM_PKG="llvm-toolchain-${VARIANT}-${LLVM_VER}" 48 | RUN wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - 2>/dev/null && \ 49 | add-apt-repository -y "deb ${LLVM_URL} ${LLVM_PKG} main" && \ 50 | apt-get update -qq && export DEBIAN_FRONTEND=noninteractive && \ 51 | apt-get install -y --no-install-recommends \ 52 | clang-${LLVM_VER} lldb-${LLVM_VER} lld-${LLVM_VER} clangd-${LLVM_VER} \ 53 | llvm-${LLVM_VER}-dev libclang-${LLVM_VER}-dev clang-tidy-${LLVM_VER} 54 | 55 | # Set the default clang-tidy, so CMake can find it 56 | RUN update-alternatives --install /usr/bin/clang-tidy clang-tidy $(which clang-tidy-${LLVM_VER}) 1 57 | 58 | # Set clang-${LLVM_VER} as default clang 59 | RUN update-alternatives --install /usr/bin/clang clang $(which clang-${LLVM_VER}) 100 60 | RUN update-alternatives --install /usr/bin/clang++ clang++ $(which clang++-${LLVM_VER}) 100 61 | 62 | # Add current cmake/ccmake, from Kitware 63 | ARG CMAKE_URL="https://apt.kitware.com/ubuntu/" 64 | ARG CMAKE_PKG=${VARIANT} 65 | RUN wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null \ 66 | | gpg --dearmor - | tee /etc/apt/trusted.gpg.d/kitware.gpg >/dev/null && \ 67 | apt-add-repository -y "deb ${CMAKE_URL} ${CMAKE_PKG} main" && \ 68 | apt-get update -qq && export DEBIAN_FRONTEND=noninteractive && \ 69 | apt-get install -y --no-install-recommends cmake cmake-curses-gui 70 | 71 | # Install editors 72 | RUN apt-get update -qq && export DEBIAN_FRONTEND=noninteractive && \ 73 | apt-get install -y --no-install-recommends \ 74 | neovim emacs nano 75 | 76 | # Install optional dependecies 77 | RUN apt-get update -qq && export DEBIAN_FRONTEND=noninteractive && \ 78 | apt-get install -y --no-install-recommends \ 79 | doxygen graphviz ccache cppcheck 80 | 81 | # Install include-what-you-use 82 | ENV IWYU /home/iwyu 83 | ENV IWYU_BUILD ${IWYU}/build 84 | ENV IWYU_SRC ${IWYU}/include-what-you-use 85 | RUN mkdir -p ${IWYU_BUILD} && \ 86 | git clone --branch clang_${LLVM_VER} \ 87 | https://github.com/include-what-you-use/include-what-you-use.git \ 88 | ${IWYU_SRC} 89 | RUN CC=clang-${LLVM_VER} CXX=clang++-${LLVM_VER} cmake -S ${IWYU_SRC} \ 90 | -B ${IWYU_BUILD} \ 91 | -G "Unix Makefiles" -DCMAKE_PREFIX_PATH=/usr/lib/llvm-${LLVM_VER} && \ 92 | cmake --build ${IWYU_BUILD} -j && \ 93 | cmake --install ${IWYU_BUILD} 94 | 95 | # Per https://github.com/include-what-you-use/include-what-you-use#how-to-install: 96 | # `You need to copy the Clang include directory to the expected location before 97 | # running (similarly, use include-what-you-use -print-resource-dir to learn 98 | # exactly where IWYU wants the headers).` 99 | RUN mkdir -p $(include-what-you-use -print-resource-dir 2>/dev/null) 100 | RUN ln -s $(readlink -f /usr/lib/clang/${LLVM_VER}/include) \ 101 | $(include-what-you-use -print-resource-dir 2>/dev/null)/include 102 | 103 | ## Cleanup cached apt data we don't need anymore 104 | RUN apt-get autoremove -y && apt-get clean && \ 105 | rm -rf /var/lib/apt/lists/* 106 | 107 | # Allow the user to set compiler defaults 108 | ARG USE_CLANG 109 | # if --build-arg USE_CLANG=1, set CC to 'clang' or set to null otherwise. 110 | ENV CC=${USE_CLANG:+"clang"} 111 | ENV CXX=${USE_CLANG:+"clang++"} 112 | # if CC is null, set it to 'gcc' (or leave as is otherwise). 113 | ENV CC=${CC:-"gcc"} 114 | ENV CXX=${CXX:-"g++"} 115 | 116 | # Include project 117 | #ADD . /workspaces/cpp_starter_project 118 | #WORKDIR /workspaces/cpp_starter_project 119 | 120 | CMD ["/bin/bash"] 121 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | // For format details, see https://aka.ms/devcontainer.json. For config options, see the README at: 2 | // https://github.com/microsoft/vscode-dev-containers/tree/v0.205.2/containers/cpp 3 | { 4 | "name": "C++", 5 | "build": { 6 | "dockerfile": "Dockerfile", 7 | // Update 'VARIANT' to pick an Ubuntu OS version. Options: [bionic, focal]. Default: focal 8 | // Update 'GCC_VER' to pick a gcc and g++ version. Options: [7, 8, 9, 10, 11]. Default: 11 9 | // Update 'LLVM_VER' to pick clang version. Options: [10, 11, 12, 13]. Default: 13 10 | // Update 'USE_CLANG' to set clang as the default C and C++ compiler. Options: [1, null]. Default null 11 | // "args": { 12 | // "VARIANT": "focal", 13 | // "GCC_VER": "11", 14 | // "LLVM_VER": "13" 15 | // } 16 | }, 17 | "runArgs": [ 18 | "--cap-add=SYS_PTRACE", 19 | "--security-opt", 20 | "seccomp=unconfined" 21 | ], 22 | // Set *default* container specific settings.json values on container create. 23 | "settings": { 24 | "cmake.configureOnOpen": true, 25 | "editor.formatOnSave": true 26 | }, 27 | // Add the IDs of extensions you want installed when the container is created. 28 | "extensions": [ 29 | "ms-vscode.cpptools", 30 | "ms-vscode.cmake-tools", 31 | "twxs.cmake", 32 | "ms-vscode.cpptools-themes", 33 | "cschlosser.doxdocgen", 34 | "eamodio.gitlens", 35 | "ms-python.python", 36 | "ms-python.vscode-pylance", 37 | "mutantdino.resourcemonitor" 38 | ], 39 | // Use 'forwardPorts' to make a list of ports inside the container available locally. 40 | // "forwardPorts": [], 41 | // Use 'postCreateCommand' to run commands after the container is created. 42 | //"postCreateCommand": "uname -a", 43 | // Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. 44 | //"remoteUser": "vscode", 45 | "workspaceMount": "source=${localWorkspaceFolder},target=/workspaces/${localWorkspaceFolderBasename},type=bind,consistency=delegated", 46 | "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}", 47 | "features": { 48 | "git": "latest", 49 | "git-lfs": "latest", 50 | "powershell": "latest" 51 | } 52 | } -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################### 2 | # Git Line Endings # 3 | ############################### 4 | 5 | * text=auto eol=lf 6 | *.{cmd,[cC][mM][dD]} text eol=crlf 7 | *.{bat,[bB][aA][tT]} text eol=crlf 8 | *.{vcxproj,vcxproj.filters} text eol=crlf 9 | 10 | ############################### 11 | # Git Large File System (LFS) # 12 | ############################### 13 | 14 | # Archives 15 | #*.7z filter=lfs diff=lfs merge=lfs -text 16 | #*.br filter=lfs diff=lfs merge=lfs -text 17 | #*.gz filter=lfs diff=lfs merge=lfs -text 18 | #*.tar filter=lfs diff=lfs merge=lfs -text 19 | #*.zip filter=lfs diff=lfs merge=lfs -text 20 | 21 | # Documents 22 | #*.pdf filter=lfs diff=lfs merge=lfs -text 23 | 24 | # Images 25 | #*.gif filter=lfs diff=lfs merge=lfs -text 26 | #*.ico filter=lfs diff=lfs merge=lfs -text 27 | #*.jpg filter=lfs diff=lfs merge=lfs -text 28 | #*.pdf filter=lfs diff=lfs merge=lfs -text 29 | #*.png filter=lfs diff=lfs merge=lfs -text 30 | #*.psd filter=lfs diff=lfs merge=lfs -text 31 | #*.webp filter=lfs diff=lfs merge=lfs -text 32 | 33 | # Fonts 34 | #*.woff2 filter=lfs diff=lfs merge=lfs -text 35 | 36 | # Other 37 | #*.exe filter=lfs diff=lfs merge=lfs -text -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: lefticus 4 | patreon: lefticus 5 | -------------------------------------------------------------------------------- /.github/actions/setup_cache/action.yml: -------------------------------------------------------------------------------- 1 | 2 | name: 'setup_cache' 3 | description: 'sets up the shared cache' 4 | inputs: 5 | compiler: 6 | required: true 7 | type: string 8 | build_type: 9 | required: true 10 | type: string 11 | generator: 12 | required: true 13 | type: string 14 | developer_mode: 15 | required: true 16 | type: string 17 | 18 | 19 | runs: 20 | using: "composite" 21 | steps: 22 | - name: Cache 23 | uses: actions/cache@v2 24 | with: 25 | # You might want to add .ccache to your cache configuration? 26 | path: | 27 | ~/vcpkg 28 | ./build/vcpkg_installed 29 | ${{ env.CONAN_USER_HOME }} 30 | ~/.cache/pip 31 | ${{ env.HOME }}/.cache/vcpkg/archives 32 | ${{ env.XDG_CACHE_HOME }}/vcpkg/archives 33 | ${{ env.LOCALAPPDATA }}\vcpkg\archives 34 | ${{ env.APPDATA }}\vcpkg\archives 35 | key: ${{ runner.os }}-${{ inputs.compiler }}-${{ inputs.build_type }}-${{ hashFiles('./conanfile.txt')}}-${{ inputs.generator }}-${{ inputs.developer_mode }}-${{ hashFiles('**/CMakeLists.txt') }}-${{ hashFiles('./vcpkg.json')}} 36 | restore-keys: | 37 | ${{ runner.os }}-${{ inputs.compiler }}-${{ inputs.build_type }}-${{ hashFiles('./conanfile.txt') }} 38 | 39 | -------------------------------------------------------------------------------- /.github/template/README.md: -------------------------------------------------------------------------------- 1 | # %%myproject%% 2 | 3 | [![ci](https://github.com/%%myorg%%/%%myproject%%/actions/workflows/ci.yml/badge.svg)](https://github.com/%%myorg%%/%%myproject%%/actions/workflows/ci.yml) 4 | [![codecov](https://codecov.io/gh/%%myorg%%/%%myproject%%/branch/main/graph/badge.svg)](https://codecov.io/gh/%%myorg%%/%%myproject%%) 5 | [![CodeQL](https://github.com/%%myorg%%/%%myproject%%/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/%%myorg%%/%%myproject%%/actions/workflows/codeql-analysis.yml) 6 | 7 | LGTM Has to be set up manually after template is created: 8 | 9 | [![Language grade: C++](https://img.shields.io/lgtm/grade/cpp/github/%%myorg%%/%%myproject%%)](https://lgtm.com/projects/g/%%myorg%%/%%myproject%%/context:cpp) 10 | 11 | ## About %%myproject%% 12 | %%description%% 13 | 14 | 15 | ## More Details 16 | 17 | * [Dependency Setup](README_dependencies.md) 18 | * [Building Details](README_building.md) 19 | * [Troubleshooting](README_troubleshooting.md) 20 | * [Docker](README_docker.md) 21 | -------------------------------------------------------------------------------- /.github/template/removal-list: -------------------------------------------------------------------------------- 1 | LICENSE 2 | .github/FUNDING.yml -------------------------------------------------------------------------------- /.github/template/template_name: -------------------------------------------------------------------------------- 1 | cmake_conan_boilerplate_template 2 | -------------------------------------------------------------------------------- /.github/template/template_repository: -------------------------------------------------------------------------------- 1 | cpp-best-practices/cmake_conan_boilerplate_template 2 | -------------------------------------------------------------------------------- /.github/workflows/auto-clang-format.yml: -------------------------------------------------------------------------------- 1 | name: auto-clang-format 2 | on: [pull_request] 3 | 4 | jobs: 5 | build: 6 | runs-on: ubuntu-latest 7 | 8 | steps: 9 | - uses: actions/checkout@v2 10 | - uses: DoozyX/clang-format-lint-action@v0.13 11 | with: 12 | source: '.' 13 | exclude: './third_party ./external' 14 | extensions: 'h,cpp,hpp' 15 | clangFormatVersion: 12 16 | inplace: True 17 | - uses: EndBug/add-and-commit@v4 18 | with: 19 | author_name: Clang Robot 20 | author_email: robot@example.com 21 | message: ':art: Committing clang-format changes' 22 | env: 23 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 24 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: ci 2 | on: 3 | pull_request: 4 | release: 5 | types: [published] 6 | push: 7 | tags: 8 | branches: 9 | - main 10 | - develop 11 | 12 | env: 13 | # Conan cache environment variables 14 | CONAN_SYSREQUIRES_MODE: enabled 15 | CONAN_USER_HOME: "${{ github.workspace }}/conan-cache" 16 | CONAN_USER_HOME_SHORT: "${{ github.workspace }}/conan-cache/short" 17 | CLANG_TIDY_VERSION: "13.0.0" 18 | 19 | jobs: 20 | Test: 21 | runs-on: ${{ matrix.os }} 22 | strategy: 23 | fail-fast: false 24 | 25 | # Recommendations: 26 | # * support at least 2 operating systems 27 | # * support at least 2 compilers 28 | # * make sure all supported configurations for your project are built 29 | # 30 | # Disable/enable builds in this list to meet the above recommendations 31 | # and your own projects needs 32 | matrix: 33 | os: 34 | - ubuntu-20.04 35 | - macos-10.15 36 | - windows-2019 37 | compiler: 38 | # you can specify the version after `-` like "llvm-13.0.0". 39 | - llvm-13.0.0 40 | - gcc-11 41 | generator: 42 | - "Ninja Multi-Config" 43 | build_type: 44 | - Release 45 | - Debug 46 | developer_mode: 47 | - ON 48 | - OFF 49 | 50 | exclude: 51 | # mingw is determined by this author to be too buggy to support 52 | - os: windows-2019 53 | compiler: gcc-11 54 | 55 | include: 56 | # Add appropriate variables for gcov version required. This will intentionally break 57 | # if you try to use a compiler that does not have gcov set 58 | - compiler: gcc-11 59 | gcov_executable: gcov 60 | - compiler: llvm-13.0.0 61 | gcov_executable: "llvm-cov gcov" 62 | 63 | # Set up preferred package generators, for given build configurations 64 | - build_type: Release 65 | developer_mode: OFF 66 | package_generator: TBZ2 67 | 68 | # This exists solely to make sure a non-multiconfig build works 69 | - os: ubuntu-20.04 70 | compiler: gcc-11 71 | generator: "Unix Makefiles" 72 | build_type: Debug 73 | gcov_executable: gcov 74 | developer_mode: On 75 | 76 | # Windows msvc builds 77 | - os: windows-2022 78 | compiler: msvc 79 | generator: "Visual Studio 17 2022" 80 | build_type: Debug 81 | developer_mode: On 82 | 83 | - os: windows-2022 84 | compiler: msvc 85 | generator: "Visual Studio 17 2022" 86 | build_type: Release 87 | developer_mode: On 88 | 89 | - os: windows-2022 90 | compiler: msvc 91 | generator: "Visual Studio 17 2022" 92 | build_type: Debug 93 | developer_mode: Off 94 | 95 | - os: windows-2022 96 | compiler: msvc 97 | generator: "Visual Studio 17 2022" 98 | build_type: Release 99 | developer_mode: Off 100 | package_generator: ZIP 101 | 102 | 103 | steps: 104 | - name: Check for llvm version mismatches 105 | if: ${{ contains(matrix.compiler, 'llvm') && !contains(matrix.compiler, env.CLANG_TIDY_VERSION) }} 106 | uses: actions/github-script@v3 107 | with: 108 | script: | 109 | core.setFailed('There is a mismatch between configured llvm compiler and clang-tidy version chosen') 110 | 111 | - uses: actions/checkout@v2 112 | 113 | - name: Setup Cache 114 | uses: ./.github/actions/setup_cache 115 | with: 116 | compiler: ${{ matrix.compiler }} 117 | build_type: ${{ matrix.build_type }} 118 | developer_mode: ${{ matrix.developer_mode }} 119 | generator: ${{ matrix.generator }} 120 | 121 | - name: Setup Cpp 122 | uses: aminya/setup-cpp@v1 123 | with: 124 | compiler: ${{ matrix.compiler }} 125 | vcvarsall: ${{ contains(matrix.os, 'windows' )}} 126 | 127 | cmake: true 128 | ninja: true 129 | conan: true 130 | vcpkg: false 131 | ccache: true 132 | clangtidy: ${{ env.CLANG_TIDY_VERSION }} 133 | 134 | 135 | cppcheck: true 136 | 137 | gcovr: true 138 | opencppcoverage: true 139 | 140 | - name: Cleanup Conan system packages (they are not properly cached) 141 | run: | 142 | conan remove -f '*/system' 143 | 144 | # make sure coverage is only enabled for Debug builds, since it sets -O0 to make sure coverage 145 | # has meaningful results 146 | - name: Configure CMake 147 | run: | 148 | cmake -S . -B ./build -G "${{matrix.generator}}" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DENABLE_DEVELOPER_MODE:BOOL=${{matrix.developer_mode}} -DOPT_ENABLE_COVERAGE:BOOL=${{ matrix.build_type == 'Debug' }} -DGIT_SHA:STRING=${{ github.sha }} 149 | 150 | - name: Build 151 | # Execute the build. You can specify a specific target with "--target " 152 | run: | 153 | cmake --build ./build --config ${{matrix.build_type}} 154 | 155 | - name: Unix - Test and coverage 156 | if: runner.os != 'Windows' 157 | working-directory: ./build 158 | # Execute tests defined by the CMake configuration. 159 | # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail 160 | run: | 161 | ctest -C ${{matrix.build_type}} 162 | gcovr -j ${{env.nproc}} --delete --root ../ --print-summary --xml-pretty --xml coverage.xml . --gcov-executable '${{ matrix.gcov_executable }}' 163 | 164 | - name: Windows - Test and coverage 165 | if: runner.os == 'Windows' 166 | working-directory: ./build 167 | run: | 168 | OpenCppCoverage.exe --export_type cobertura:coverage.xml --cover_children -- ctest -C ${{matrix.build_type}} 169 | 170 | - name: CPack 171 | if: matrix.package_generator != '' 172 | working-directory: ./build 173 | run: | 174 | cpack -C ${{matrix.build_type}} -G ${{matrix.package_generator}} 175 | 176 | - name: Publish Tagged Release 177 | uses: softprops/action-gh-release@v1 178 | if: ${{ startsWith(github.ref, 'refs/tags/') && matrix.package_generator != '' }} 179 | with: 180 | files: | 181 | build/*-*${{ matrix.build_type }}*-*.* 182 | 183 | 184 | - name: Publish to codecov 185 | uses: codecov/codecov-action@v2 186 | with: 187 | flags: ${{ runner.os }} 188 | name: ${{ runner.os }}-coverage 189 | files: ./build/coverage.xml 190 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ main, develop ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ main, develop ] 20 | schedule: 21 | - cron: '38 0 * * 5' 22 | 23 | env: 24 | # Conan cache environment variables 25 | CONAN_SYSREQUIRES_MODE: enabled 26 | CONAN_USER_HOME: "${{ github.workspace }}/conan-cache" 27 | CONAN_USER_HOME_SHORT: "${{ github.workspace }}/conan-cache/short" 28 | 29 | 30 | jobs: 31 | analyze: 32 | name: Analyze 33 | runs-on: ubuntu-latest 34 | permissions: 35 | actions: read 36 | contents: read 37 | security-events: write 38 | 39 | strategy: 40 | fail-fast: false 41 | matrix: 42 | language: [ 'cpp' ] 43 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] 44 | # Learn more about CodeQL language support at https://git.io/codeql-language-support 45 | compiler: 46 | # you can specify the version after `-` like "llvm-13.0.0". 47 | - gcc-11 48 | generator: 49 | - "Ninja Multi-Config" 50 | build_type: 51 | - Debug 52 | developer_mode: 53 | - OFF 54 | 55 | 56 | steps: 57 | - uses: actions/checkout@v2 58 | 59 | - name: Setup Cache 60 | uses: ./.github/actions/setup_cache 61 | with: 62 | compiler: ${{ matrix.compiler }} 63 | build_type: ${{ matrix.build_type }} 64 | developer_mode: ${{ matrix.developer_mode }} 65 | generator: ${{ matrix.generator }} 66 | 67 | 68 | - name: Setup Cpp 69 | uses: aminya/setup-cpp@v1 70 | with: 71 | compiler: ${{ matrix.compiler }} 72 | vcvarsall: ${{ contains(matrix.os, 'windows' )}} 73 | 74 | cmake: true 75 | ninja: true 76 | conan: true 77 | vcpkg: false 78 | ccache: true 79 | clangtidy: false 80 | 81 | cppcheck: false 82 | 83 | gcovr: false 84 | opencppcoverage: false 85 | 86 | - name: Cleanup Conan system packages (they are not properly cached) 87 | run: | 88 | conan remove -f '*/system' 89 | 90 | # make sure coverage is only enabled for Debug builds, since it sets -O0 to make sure coverage 91 | # has meaningful results 92 | - name: Configure CMake 93 | run: | 94 | cmake -S . -B ./build -G "${{matrix.generator}}" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DENABLE_DEVELOPER_MODE:BOOL=${{matrix.developer_mode}} -DOPT_ENABLE_COVERAGE:BOOL=${{ matrix.build_type == 'Debug' }} 95 | 96 | # Initializes the CodeQL tools for scanning. 97 | - name: Initialize CodeQL 98 | uses: github/codeql-action/init@v1 99 | with: 100 | languages: ${{ matrix.language }} 101 | # If you wish to specify custom queries, you can do so here or in a config file. 102 | # By default, queries listed here will override any specified in a config file. 103 | # Prefix the list here with "+" to use these queries and those in the config file. 104 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 105 | 106 | 107 | - name: Build 108 | # Execute the build. You can specify a specific target with "--target " 109 | run: | 110 | cmake --build ./build --config ${{matrix.build_type}} 111 | 112 | - name: Perform CodeQL Analysis 113 | uses: github/codeql-action/analyze@v1 114 | -------------------------------------------------------------------------------- /.github/workflows/template-janitor.yml: -------------------------------------------------------------------------------- 1 | # This workflow should cleanup everything unneeded from the template project 2 | 3 | name: Template Janitor 4 | 5 | on: 6 | pull_request: 7 | release: 8 | types: [published] 9 | push: 10 | tags: 11 | branches: 12 | - main 13 | - develop 14 | 15 | env: 16 | TEMPLATES_PATH: ".github/template" 17 | CONAN_SYSREQUIRES_MODE: enabled 18 | CONAN_USER_HOME: "${{ github.workspace }}/conan-cache" 19 | CONAN_USER_HOME_SHORT: "${{ github.workspace }}/conan-cache/short" 20 | 21 | 22 | jobs: 23 | 24 | template-cleanup: 25 | name: Cleanup after create 26 | runs-on: ubuntu-latest 27 | strategy: 28 | matrix: 29 | compiler: 30 | - gcc-11 31 | generator: 32 | - "Unix Makefiles" 33 | build_type: 34 | - Debug 35 | developer_mode: 36 | - OFF 37 | 38 | steps: 39 | - uses: actions/checkout@v2 40 | 41 | - name: Setup Cache 42 | uses: ./.github/actions/setup_cache 43 | with: 44 | compiler: ${{ matrix.compiler }} 45 | build_type: ${{ matrix.build_type }} 46 | developer_mode: ${{ matrix.developer_mode }} 47 | generator: ${{ matrix.generator }} 48 | 49 | - name: Get organization and project name 50 | run: | 51 | echo "NEW_ORG=${{ github.repository_owner }}" >> $GITHUB_ENV 52 | echo "NEW_PROJECT=${{ github.event.repository.name }}" >> $GITHUB_ENV 53 | echo "NEW_URL=${{ github.repositoryUrl }}" >> $GITHUB_ENV 54 | 55 | - uses: octokit/request-action@v2.x 56 | id: get_repo_meta 57 | with: 58 | route: GET /repos/{owner}/{repo} 59 | owner: ${{ env.NEW_ORG }} 60 | repo: ${{ env.NEW_PROJECT }} 61 | env: 62 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 63 | 64 | - name: Use testing variables if still a template 65 | if: fromJson(steps.get_repo_meta.outputs.data).is_template == true 66 | run: | 67 | # This name is unsafe because it is not a valid C++ identifier 68 | echo "NEW_PROJECT=my-unsafe.project" >> $GITHUB_ENV 69 | 70 | - name: Add safe replacement variable versions 71 | run: | 72 | # hyphens and dots in c++ identifiers are forbidden. Use underscores instead. 73 | NEW_SAFE_PROJECT=$(echo ${{ env.NEW_PROJECT }} | sed "s/-/_/g" | sed "s/\./_/g" ) 74 | echo "NEW_SAFE_PROJECT=$NEW_SAFE_PROJECT" >> $GITHUB_ENV 75 | 76 | # Rename all cpp_starter_project occurences to current repository and remove this workflow 77 | - name: Insert new org and project 78 | run: | 79 | # rename the CMake project to match the github project 80 | sed -i "s/myproject/${{ env.NEW_SAFE_PROJECT }}/gi" CMakeLists.txt configured_files/config.hpp.in src/main.cpp test/CMakeLists.txt fuzz_test/CMakeLists.txt 81 | 82 | # Update URL placeholders for project 83 | sed -i "s|%%myurl%%|${{ fromJson(steps.get_repo_meta.outputs.data).html_url }}|gi" CMakeLists.txt 84 | 85 | # fill in placeholders of readme and move it into place 86 | sed -i "s/%%myorg%%/${{ env.NEW_ORG }}/g" ${{ env.TEMPLATES_PATH }}/README.md 87 | sed -i "s/%%myproject%%/${{ env.NEW_PROJECT }}/g" ${{ env.TEMPLATES_PATH }}/README.md 88 | sed -i "s|%%description%%|${{ fromJson(steps.get_repo_meta.outputs.data).description }}|g" ${{ env.TEMPLATES_PATH }}/README.md 89 | cp ${{ env.TEMPLATES_PATH }}/README.md README.md 90 | 91 | - name: Print diff after replacement 92 | run: | 93 | # Exclude the README as that is checked separately! 94 | git diff ':!README.md' 95 | # following should not have any diffs 96 | diff ${{ env.TEMPLATES_PATH }}/README.md README.md 97 | 98 | - name: Remove unwanted files 99 | run: | 100 | # No tests needed as this will fail if any file from the list is missing/misspelled 101 | xargs rm -r < ${{ env.TEMPLATES_PATH }}/removal-list 102 | 103 | - name: Clean up before commit and push 104 | run: | 105 | rm -r ${{ env.TEMPLATES_PATH }} 106 | 107 | # Can we get that from a variable? 108 | # Remove this workflow as it has fulfilled its purpose 109 | rm .github/workflows/template-janitor.yml 110 | 111 | - name: Setup Cpp 112 | uses: aminya/setup-cpp@v1 113 | with: 114 | compiler: ${{ matrix.compiler }} 115 | 116 | cmake: true 117 | ninja: false 118 | conan: true 119 | vcpkg: false 120 | ccache: false 121 | clangtidy: false 122 | 123 | cppcheck: false 124 | 125 | gcovr: false 126 | opencppcoverage: false 127 | 128 | - name: Cleanup Conan system packages (they are not properly cached) 129 | run: | 130 | conan remove -f '*/system' 131 | 132 | - name: Test simple configuration to make sure nothing broke 133 | run: | 134 | cmake -S . -B ./build -G "${{ matrix.generator }}" -DCMAKE_BUILD_TYPE:STRING=${{ matrix.build_type }} -DENABLE_DEVELOPER_MODE:BOOL=${{ matrix.developer_mode }} -DOPT_ENABLE_COVERAGE:BOOL=OFF 135 | # Build it because we may have broken something in the cpp/hpp files 136 | cmake --build build 137 | 138 | - uses: EndBug/add-and-commit@v4 139 | # only commit and push if we are not a template project anymore! 140 | if: fromJson(steps.get_repo_meta.outputs.data).is_template != true 141 | with: 142 | author_name: Template Janitor 143 | author_email: template.janitor@example.com 144 | message: 'Cleanup template and initialize repository' 145 | env: 146 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 147 | 148 | 149 | 150 | template-rename: 151 | name: Renames template when a new name is detected 152 | runs-on: ubuntu-latest 153 | strategy: 154 | matrix: 155 | compiler: 156 | - gcc-11 157 | generator: 158 | - "Unix Makefiles" 159 | build_type: 160 | - Debug 161 | developer_mode: 162 | - OFF 163 | 164 | steps: 165 | - uses: actions/checkout@v2 166 | 167 | - name: Setup Cache 168 | uses: ./.github/actions/setup_cache 169 | with: 170 | compiler: ${{ matrix.compiler }} 171 | build_type: ${{ matrix.build_type }} 172 | developer_mode: ${{ matrix.developer_mode }} 173 | generator: ${{ matrix.generator }} 174 | 175 | - name: Get organization and project name 176 | run: | 177 | echo "TEST_RUN=false" >> $GITHUB_ENV 178 | echo "NEW_ORG=${{ github.repository_owner }}" >> $GITHUB_ENV 179 | echo "NEW_PROJECT=${{ github.event.repository.name }}" >> $GITHUB_ENV 180 | echo "NEW_REPOSITORY=${{ github.repository }}" >> $GITHUB_ENV 181 | echo "TEMPLATE_NAME=`cat ${{ env.TEMPLATES_PATH }}/template_name`" >> $GITHUB_ENV 182 | echo "TEMPLATE_REPOSITORY=`cat ${{ env.TEMPLATES_PATH }}/template_repository`" >> $GITHUB_ENV 183 | 184 | - uses: octokit/request-action@v2.x 185 | id: get_repo_meta 186 | with: 187 | route: GET /repos/{owner}/{repo} 188 | owner: ${{ env.NEW_ORG }} 189 | repo: ${{ env.NEW_PROJECT }} 190 | env: 191 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 192 | 193 | - name: Setup fake test org/project names if project didn't change 194 | if: env.TEMPLATE_NAME == env.NEW_PROJECT 195 | run: | 196 | echo "TEST_RUN=true" >> $GITHUB_ENV 197 | echo "NEW_ORG=${{ github.repository_owner }}" >> $GITHUB_ENV 198 | echo "NEW_PROJECT=TEST_PROJECT" >> $GITHUB_ENV 199 | echo "NEW_REPOSITORY=TEST_REPOSITORY" >> $GITHUB_ENV 200 | 201 | 202 | # Rename all cpp_starter_project occurrences to current repository and remove this workflow 203 | - name: Update repository to match new template information 204 | run: | 205 | # Update the README and template files to match the new org / repository names 206 | sed -i "s|${{ env.TEMPLATE_REPOSITORY }}|${{ env.NEW_REPOSITORY }}|g" README.md ${{ env.TEMPLATES_PATH }}/template_repository 207 | sed -i "s|${{ env.TEMPLATE_NAME }}|${{ env.NEW_PROJECT }}|g" README.md ${{ env.TEMPLATES_PATH }}/template_name 208 | 209 | - name: Print diff after template name replacement 210 | run: | 211 | git diff 212 | 213 | - name: Setup Cpp 214 | uses: aminya/setup-cpp@v1 215 | with: 216 | compiler: gcc 217 | 218 | cmake: true 219 | ninja: false 220 | conan: true 221 | vcpkg: false 222 | ccache: false 223 | clangtidy: false 224 | 225 | cppcheck: false 226 | 227 | gcovr: false 228 | opencppcoverage: false 229 | 230 | - name: Cleanup Conan system packages (they are not properly cached) 231 | run: | 232 | conan remove -f '*/system' 233 | 234 | - name: Test simple configuration to make sure nothing broke (default compiler,cmake,developer_mode OFF) 235 | run: | 236 | cmake -S . -B ./build -G "${{ matrix.generator }}" -DCMAKE_BUILD_TYPE:STRING=${{ matrix.build_type }} -DENABLE_DEVELOPER_MODE:BOOL=${{ matrix.developer_mode }} -DOPT_ENABLE_COVERAGE:BOOL=OFF 237 | 238 | - uses: EndBug/add-and-commit@v4 239 | # only commit and push if we are a template and project name has changed 240 | if: fromJson(steps.get_repo_meta.outputs.data).is_template == true && env.TEST_RUN == 'false' 241 | with: 242 | author_name: Template Janitor 243 | author_email: template.janitor@example.com 244 | message: 'Change Template Name' 245 | env: 246 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 247 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Build directories and binary files 2 | build/ 3 | out/ 4 | cmake-build-*/ 5 | conan-cache/ 6 | 7 | # User spesific settings 8 | CMakeUserPresets.json 9 | 10 | # IDE files 11 | .vs/ 12 | .idea/ 13 | .vscode/ 14 | !.vscode/settings.json 15 | !.vscode/tasks.json 16 | !.vscode/launch.json 17 | !.vscode/extensions.json 18 | *.swp 19 | *~ 20 | _ReSharper* 21 | *.log 22 | 23 | # OS Generated Files 24 | .DS_Store 25 | .AppleDouble 26 | .LSOverride 27 | ._* 28 | .Spotlight-V100 29 | .Trashes 30 | .Trash-* 31 | $RECYCLE.BIN/ 32 | .TemporaryItems 33 | ehthumbs.db 34 | Thumbs.db 35 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | image: ubuntu:latest 2 | 3 | stages: 4 | - test 5 | 6 | .setup_linux: &setup_linux | 7 | DEBIAN_FRONTEND=noninteractive 8 | 9 | # set time-zone 10 | TZ=Canada/Pacific 11 | ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone 12 | 13 | # for downloading 14 | apt-get update -qq 15 | apt-get install -y --no-install-recommends curl gnupg ca-certificates 16 | 17 | # keys used by apt 18 | apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 3B4FE6ACC0B21F32 19 | apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 40976EAF437D05B5 20 | apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 1E9377A2BA9EF27F 21 | 22 | .setup_cpp: &setup_cpp | 23 | curl -LJO "https://github.com/aminya/setup-cpp/releases/download/v0.10.0/setup_cpp_linux" 24 | chmod +x setup_cpp_linux 25 | ./setup_cpp_linux --compiler $compiler --cmake true --ninja true --conan true --ccache true --clangtidy true --clangformat true --cppcheck true 26 | source ~/.profile 27 | 28 | .test: &test | 29 | # Build and Test 30 | cmake -S . -B ./build -DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo 31 | cmake --build ./build --config RelWithDebInfo 32 | 33 | test_linux_llvm: 34 | stage: test 35 | variables: 36 | compiler: llvm 37 | script: 38 | - *setup_linux 39 | - *setup_cpp 40 | - *test 41 | 42 | test_linux_gcc: 43 | stage: test 44 | variables: 45 | compiler: gcc 46 | script: 47 | - *setup_linux 48 | - *setup_cpp 49 | - *test 50 | -------------------------------------------------------------------------------- /.lgtm.yml: -------------------------------------------------------------------------------- 1 | # for full syntax documentation see: https://lgtm.com/help/lgtm/lgtm.yml-configuration-file 2 | path_classifiers: 3 | test: 4 | - "*/fuzz_test/**/*" 5 | - "*/test/**/*" 6 | extraction: 7 | cpp: 8 | prepare: 9 | packages: 10 | - g++-10 11 | - ccache 12 | script: 13 | - mkdir ~/.conan 14 | - cat /usr/local/share/ca-certificates/semmle-cache-ca/semmle-cache-ca.crt >> ~/.conan/cacert.pem 15 | - python3 -m pip install --upgrade pip setuptools 16 | - python3 -m pip install conan 17 | - python3 -m pip install cmake 18 | - source ~/.profile 19 | configure: 20 | command: 21 | - mkdir build 22 | - cmake -D OPT_ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug -D ENABLE_DEVELOPER_MODE:BOOL=FALSE -S . -B build 23 | index: 24 | build_command: cmake --build ./build -- -j2 25 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16...3.23) 2 | 3 | # Not ideal to use this global variable, but necessary to make sure 4 | # that tooling and projects use the same version 5 | set(CMAKE_CXX_STANDARD 20) 6 | 7 | # strongly encouraged to enable this globally to avoid conflicts between 8 | # -Wpedantic being enabled and -std=c++20 and -std=gnu++20 for example 9 | # when compiling with PCH enabled 10 | set(CMAKE_CXX_EXTENSIONS OFF) 11 | 12 | # Note: by default ENABLE_DEVELOPER_MODE is True 13 | # This means that all analysis (sanitizers, static analysis) 14 | # is enabled and all warnings are treated as errors 15 | # if you want to switch this behavior, change TRUE to FALSE 16 | set(ENABLE_DEVELOPER_MODE 17 | TRUE 18 | CACHE BOOL "Enable 'developer mode'") 19 | 20 | # Change this to false if you want to disable warnings_as_errors in developer mode 21 | set(OPT_WARNINGS_AS_ERRORS_DEVELOPER_DEFAULT TRUE) 22 | 23 | # Add project_options v0.20.0 24 | # https://github.com/cpp-best-practices/project_options 25 | include(FetchContent) 26 | FetchContent_Declare(_project_options URL https://github.com/aminya/project_options/archive/refs/tags/v0.20.0.zip) 27 | FetchContent_MakeAvailable(_project_options) 28 | include(${_project_options_SOURCE_DIR}/Index.cmake) 29 | 30 | # uncomment to enable vcpkg: 31 | # # Setup vcpkg - should be called before defining project() 32 | # run_vcpkg() 33 | 34 | # Set the project name and language 35 | project( 36 | myproject 37 | VERSION 0.0.1 38 | DESCRIPTION "" 39 | HOMEPAGE_URL "%%myurl%%" 40 | LANGUAGES CXX C) 41 | 42 | # This variable is set by project() in CMake 3.21+ 43 | string( 44 | COMPARE EQUAL 45 | "${CMAKE_SOURCE_DIR}" 46 | "${PROJECT_SOURCE_DIR}" 47 | PROJECT_IS_TOP_LEVEL) 48 | if(PROJECT_IS_TOP_LEVEL) 49 | # Consider the CTest module, which creates targets and options! 50 | # Only needed if you want to enable submissions to a CDash server. 51 | include(CTest) 52 | endif() 53 | 54 | set(GIT_SHA 55 | "Unknown" 56 | CACHE STRING "SHA this build was generated from") 57 | string( 58 | SUBSTRING "${GIT_SHA}" 59 | 0 60 | 8 61 | GIT_SHORT_SHA) 62 | 63 | get_property(BUILDING_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) 64 | if(BUILDING_MULTI_CONFIG) 65 | if(NOT CMAKE_BUILD_TYPE) 66 | # Make sure that all supported configuration types have their 67 | # associated conan packages available. You can reduce this 68 | # list to only the configuration types you use, but only if one 69 | # is not forced-set on the command line for VS 70 | message(TRACE "Setting up multi-config build types") 71 | set(CMAKE_CONFIGURATION_TYPES 72 | Debug 73 | Release 74 | RelWithDebInfo 75 | MinSizeRel 76 | CACHE STRING "Enabled build types" FORCE) 77 | else() 78 | message(TRACE "User chose a specific build type, so we are using that") 79 | set(CMAKE_CONFIGURATION_TYPES 80 | ${CMAKE_BUILD_TYPE} 81 | CACHE STRING "Enabled build types" FORCE) 82 | endif() 83 | endif() 84 | 85 | include(${_project_options_SOURCE_DIR}/src/DynamicProjectOptions.cmake) 86 | 87 | # defaulted_project_options sets recommended defaults and provides user and developer 88 | # modes and full GUI support for choosing options at configure time 89 | 90 | # for more flexibility, look into project_options() macro 91 | 92 | # Any default can be overridden 93 | # set(_DEFAULT ) - set default for both user and developer modes 94 | # set(_DEVELOPER_DEFAULT ) - set default for developer mode 95 | # set(_USER_DEFAULT ) - set default for user mode 96 | 97 | # Initialize project_options variable related to this project 98 | # This overwrites `project_options` and sets `project_warnings` 99 | # uncomment the options to enable them: 100 | dynamic_project_options( 101 | # Note: PCH is disabled by default in developer mode because these headers become 102 | # globally included and they can mask other errors 103 | PCH_HEADERS 104 | 105 | # This is a list of headers to pre-compile, here are some common ones 106 | ENABLE_CONAN 107 | # CONAN_OPTIONS # Extra options to pass to conan 108 | # MSVC_WARNINGS # Override the defaults for the MSVC warnings 109 | # CLANG_WARNINGS # Override the defaults for the CLANG warnings 110 | # GCC_WARNINGS # Override the defaults for the GCC warnings 111 | CPPCHECK_OPTIONS 112 | --enable=style,performance,warning,portability 113 | --inline-suppr 114 | # We cannot act on a bug/missing feature of cppcheck 115 | --suppress=cppcheckError 116 | --suppress=internalAstError 117 | # if a file does not have an internalAstError, we get an unmatchedSuppression error 118 | --suppress=unmatchedSuppression 119 | --suppress=passedByValue 120 | --suppress=syntaxError 121 | --inconclusive 122 | ) 123 | 124 | target_compile_features(project_options INTERFACE cxx_std_${CMAKE_CXX_STANDARD}) 125 | # TODO: The INTERFACE library NAMESPACE ALIAS are missing! CK 126 | add_library(myproject::project_options INTERFACE IMPORTED) 127 | add_library(myproject::project_warnings INTERFACE IMPORTED) 128 | 129 | # configure files based on CMake configuration options 130 | add_subdirectory(configured_files) 131 | 132 | # Adding the src: 133 | add_subdirectory(src) 134 | 135 | # Adding the tests: 136 | option(ENABLE_TESTING "Enable the tests" ${PROJECT_IS_TOP_LEVEL}) 137 | if(ENABLE_TESTING) 138 | enable_testing() 139 | message(AUTHOR_WARNING "Building Tests. Be sure to check out test/constexpr_tests.cpp for constexpr testing") 140 | add_subdirectory(test) 141 | endif() 142 | 143 | option(ENABLE_FUZZING "Enable the fuzz tests" OFF) 144 | if(ENABLE_FUZZING) 145 | message(AUTHOR_WARNING "Building Fuzz Tests, using fuzzing sanitizer https://www.llvm.org/docs/LibFuzzer.html") 146 | add_subdirectory(fuzz_test) 147 | endif() 148 | 149 | # If MSVC is being used, and ASAN is enabled, we need to set the debugger environment 150 | # so that it behaves well with MSVC's debugger, and we can run the target from visual studio 151 | if(MSVC) 152 | get_all_installable_targets(all_targets) 153 | message("all_targets=${all_targets}") 154 | set_target_properties(${all_targets} PROPERTIES VS_DEBUGGER_ENVIRONMENT "PATH=$(VC_ExecutablePath_x64);%PATH%") 155 | endif() 156 | 157 | # set the startup project for the "play" button in MSVC 158 | set_property(DIRECTORY PROPERTY VS_STARTUP_PROJECT intro) 159 | 160 | if(CMAKE_SKIP_INSTALL_RULES) 161 | return() 162 | elseif(NOT PROJECT_IS_TOP_LEVEL) 163 | return() 164 | endif() 165 | 166 | # Add other targets that you want installed here, be default we just package the one executable 167 | # we know we want to ship 168 | package_project(TARGETS intro project_options project_warnings 169 | # FIXME: this does not work! CK 170 | # PRIVATE_DEPENDENCIES_CONFIGURED project_options project_warnings 171 | ) 172 | 173 | # Experience shows that explicit package naming can help make it easier to sort 174 | # out potential ABI related issues before they start, while helping you 175 | # track a build to a specific GIT SHA 176 | set(CPACK_PACKAGE_FILE_NAME 177 | "${CMAKE_PROJECT_NAME}-${CMAKE_PROJECT_VERSION}-${GIT_SHORT_SHA}-${CMAKE_SYSTEM_NAME}-${CMAKE_BUILD_TYPE}-${CMAKE_CXX_COMPILER_ID}-${CMAKE_CXX_COMPILER_VERSION}" 178 | ) 179 | 180 | include(CPack) 181 | -------------------------------------------------------------------------------- /CMakePresets.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "cmakeMinimumRequired": { 4 | "major": 3, 5 | "minor": 21, 6 | "patch": 0 7 | }, 8 | "configurePresets": [ 9 | { 10 | "name": "conf-common", 11 | "description": "General settings that apply to all configurations", 12 | "hidden": true, 13 | "generator": "Ninja", 14 | "binaryDir": "${sourceDir}/out/build/${presetName}", 15 | "installDir": "${sourceDir}/out/install/${presetName}" 16 | }, 17 | { 18 | "name": "conf-windows-common", 19 | "description": "Windows settings for MSBuild toolchain that apply to msvc and clang", 20 | "hidden": true, 21 | "inherits": "conf-common", 22 | "condition": { 23 | "type": "equals", 24 | "lhs": "${hostSystemName}", 25 | "rhs": "Windows" 26 | }, 27 | "architecture": { 28 | "value": "x64", 29 | "strategy": "external" 30 | }, 31 | "toolset": { 32 | "value": "host=x64", 33 | "strategy": "external" 34 | }, 35 | "cacheVariables": { 36 | "ENABLE_CPPCHECK_DEFAULT": "FALSE", 37 | "ENABLE_CLANG_TIDY_DEFAULT": "FALSE" 38 | } 39 | }, 40 | { 41 | "name": "conf-unixlike-common", 42 | "description": "Unix-like OS settings for gcc and clang toolchains", 43 | "hidden": true, 44 | "inherits": "conf-common", 45 | "condition": { 46 | "type": "inList", 47 | "string": "${hostSystemName}", 48 | "list": [ 49 | "Linux", 50 | "Darwin" 51 | ] 52 | }, 53 | "vendor": { 54 | "microsoft.com/VisualStudioRemoteSettings/CMake/1.0": { 55 | "sourceDir": "$env{HOME}/.vs/$ms{projectDirName}" 56 | } 57 | } 58 | }, 59 | { 60 | "name": "windows-msvc-debug-developer-mode", 61 | "displayName": "msvc Debug (Developer Mode)", 62 | "description": "Target Windows with the msvc compiler, debug build type", 63 | "inherits": "conf-windows-common", 64 | "cacheVariables": { 65 | "CMAKE_C_COMPILER": "cl", 66 | "CMAKE_CXX_COMPILER": "cl", 67 | "CMAKE_BUILD_TYPE": "Debug", 68 | "ENABLE_DEVELOPER_MODE": "ON" 69 | } 70 | }, 71 | { 72 | "name": "windows-msvc-release-developer-mode", 73 | "displayName": "msvc Release (Developer Mode)", 74 | "description": "Target Windows with the msvc compiler, release build type", 75 | "inherits": "conf-windows-common", 76 | "cacheVariables": { 77 | "CMAKE_C_COMPILER": "cl", 78 | "CMAKE_CXX_COMPILER": "cl", 79 | "CMAKE_BUILD_TYPE": "RelWithDebInfo", 80 | "ENABLE_DEVELOPER_MODE": "ON" 81 | } 82 | }, 83 | { 84 | "name": "windows-msvc-debug-user-mode", 85 | "displayName": "msvc Debug (User Mode)", 86 | "description": "Target Windows with the msvc compiler, debug build type", 87 | "inherits": "conf-windows-common", 88 | "cacheVariables": { 89 | "CMAKE_C_COMPILER": "cl", 90 | "CMAKE_CXX_COMPILER": "cl", 91 | "CMAKE_BUILD_TYPE": "Debug", 92 | "ENABLE_DEVELOPER_MODE": "OFF" 93 | } 94 | }, 95 | { 96 | "name": "windows-msvc-release-user-mode", 97 | "displayName": "msvc Release (User Mode)", 98 | "description": "Target Windows with the msvc compiler, release build type", 99 | "inherits": "conf-windows-common", 100 | "cacheVariables": { 101 | "CMAKE_C_COMPILER": "cl", 102 | "CMAKE_CXX_COMPILER": "cl", 103 | "CMAKE_BUILD_TYPE": "RelWithDebInfo", 104 | "ENABLE_DEVELOPER_MODE": "OFF" 105 | } 106 | }, 107 | { 108 | "name": "windows-clang-debug", 109 | "displayName": "clang Debug", 110 | "description": "Target Windows with the clang compiler, debug build type", 111 | "inherits": "conf-windows-common", 112 | "cacheVariables": { 113 | "CMAKE_C_COMPILER": "clang-cl", 114 | "CMAKE_CXX_COMPILER": "clang-cl", 115 | "CMAKE_BUILD_TYPE": "Debug" 116 | }, 117 | "vendor": { 118 | "microsoft.com/VisualStudioSettings/CMake/1.0": { 119 | "intelliSenseMode": "windows-clang-x64" 120 | } 121 | } 122 | }, 123 | { 124 | "name": "windows-clang-release", 125 | "displayName": "clang Release", 126 | "description": "Target Windows with the clang compiler, release build type", 127 | "inherits": "conf-windows-common", 128 | "cacheVariables": { 129 | "CMAKE_C_COMPILER": "clang-cl", 130 | "CMAKE_CXX_COMPILER": "clang-cl", 131 | "CMAKE_BUILD_TYPE": "RelWithDebInfo" 132 | }, 133 | "vendor": { 134 | "microsoft.com/VisualStudioSettings/CMake/1.0": { 135 | "intelliSenseMode": "windows-clang-x64" 136 | } 137 | } 138 | }, 139 | { 140 | "name": "unixlike-gcc-debug", 141 | "displayName": "gcc Debug", 142 | "description": "Target Unix-like OS with the gcc compiler, debug build type", 143 | "inherits": "conf-unixlike-common", 144 | "cacheVariables": { 145 | "CMAKE_C_COMPILER": "gcc", 146 | "CMAKE_CXX_COMPILER": "g++", 147 | "CMAKE_BUILD_TYPE": "Debug" 148 | } 149 | }, 150 | { 151 | "name": "unixlike-gcc-release", 152 | "displayName": "gcc Release", 153 | "description": "Target Unix-like OS with the gcc compiler, release build type", 154 | "inherits": "conf-unixlike-common", 155 | "cacheVariables": { 156 | "CMAKE_C_COMPILER": "gcc", 157 | "CMAKE_CXX_COMPILER": "g++", 158 | "CMAKE_BUILD_TYPE": "RelWithDebInfo" 159 | } 160 | }, 161 | { 162 | "name": "unixlike-clang-debug", 163 | "displayName": "clang Debug", 164 | "description": "Target Unix-like OS with the clang compiler, debug build type", 165 | "inherits": "conf-unixlike-common", 166 | "cacheVariables": { 167 | "CMAKE_C_COMPILER": "clang", 168 | "CMAKE_CXX_COMPILER": "clang++", 169 | "CMAKE_BUILD_TYPE": "Debug" 170 | } 171 | }, 172 | { 173 | "name": "unixlike-clang-release", 174 | "displayName": "clang Release", 175 | "description": "Target Unix-like OS with the clang compiler, release build type", 176 | "inherits": "conf-unixlike-common", 177 | "cacheVariables": { 178 | "CMAKE_C_COMPILER": "clang", 179 | "CMAKE_CXX_COMPILER": "clang++", 180 | "CMAKE_BUILD_TYPE": "RelWithDebInfo" 181 | } 182 | } 183 | ], 184 | "testPresets": [ 185 | { 186 | "name": "test-common", 187 | "description": "Test CMake settings that apply to all configurations", 188 | "hidden": true, 189 | "output": { 190 | "outputOnFailure": true 191 | }, 192 | "execution": { 193 | "noTestsAction": "error", 194 | "stopOnFailure": true 195 | } 196 | }, 197 | { 198 | "name": "test-windows-msvc-debug-developer-mode", 199 | "displayName": "Strict", 200 | "description": "Enable output and stop on failure", 201 | "inherits": "test-common", 202 | "configurePreset": "windows-msvc-debug-developer-mode" 203 | }, 204 | { 205 | "name": "test-windows-msvc-release-developer-mode", 206 | "displayName": "Strict", 207 | "description": "Enable output and stop on failure", 208 | "inherits": "test-common", 209 | "configurePreset": "windows-msvc-release-developer-mode" 210 | }, 211 | { 212 | "name": "test-windows-clang-debug", 213 | "displayName": "Strict", 214 | "description": "Enable output and stop on failure", 215 | "inherits": "test-common", 216 | "configurePreset": "windows-clang-debug" 217 | }, 218 | { 219 | "name": "test-windows-clang-release", 220 | "displayName": "Strict", 221 | "description": "Enable output and stop on failure", 222 | "inherits": "test-common", 223 | "configurePreset": "windows-clang-release" 224 | }, 225 | { 226 | "name": "test-unixlike-gcc-debug", 227 | "displayName": "Strict", 228 | "description": "Enable output and stop on failure", 229 | "inherits": "test-common", 230 | "configurePreset": "unixlike-gcc-debug" 231 | }, 232 | { 233 | "name": "test-unixlike-gcc-release", 234 | "displayName": "Strict", 235 | "description": "Enable output and stop on failure", 236 | "inherits": "test-common", 237 | "configurePreset": "unixlike-gcc-release" 238 | }, 239 | { 240 | "name": "test-unixlike-clang-debug", 241 | "displayName": "Strict", 242 | "description": "Enable output and stop on failure", 243 | "inherits": "test-common", 244 | "configurePreset": "unixlike-clang-debug" 245 | }, 246 | { 247 | "name": "test-unixlike-clang-release", 248 | "displayName": "Strict", 249 | "description": "Enable output and stop on failure", 250 | "inherits": "test-common", 251 | "configurePreset": "unixlike-clang-release" 252 | } 253 | ] 254 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NOTE: This Project Is Archived 2 | 3 | All efforts to maintain "Best Practices" CMake templates are being merged into https://github.com/cpp-best-practices/cmake_template 4 | 5 | ***Important*** the new cmake_template is simplified in many ways to make it more maintainable, and the goal will be to always keep it simple. 6 | 7 | 8 | # cmake_conan_boilerplate_template 9 | 10 | [![ci](https://github.com/cpp-best-practices/cmake_conan_boilerplate_template/actions/workflows/ci.yml/badge.svg)](https://github.com/cpp-best-practices/cmake_conan_boilerplate_template/actions/workflows/ci.yml) 11 | [![codecov](https://codecov.io/gh/cpp-best-practices/cmake_conan_boilerplate_template/branch/main/graph/badge.svg)](https://codecov.io/gh/cpp-best-practices/cmake_conan_boilerplate_template) 12 | [![Language grade: C++](https://img.shields.io/lgtm/grade/cpp/github/cpp-best-practices/cmake_conan_boilerplate_template)](https://lgtm.com/projects/g/cpp-best-practices/cmake_conan_boilerplate_template/context:cpp) 13 | [![CodeQL](https://github.com/cpp-best-practices/cmake_conan_boilerplate_template/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/cpp-best-practices/cmake_conan_boilerplate_template/actions/workflows/codeql-analysis.yml) 14 | 15 | ## About cmake_conan_boilerplate_template 16 | 17 | This is a C++ Best Practices GitHub template for getting up and running with C++ quickly. 18 | 19 | By default (collectively known as `ENABLE_DEVELOPER_MODE`) 20 | 21 | * Address Sanitizer and Undefined Behavior Sanitizer enabled where possible 22 | * Warnings as errors 23 | * clang-tidy and cppcheck static analysis 24 | * conan for dependencies 25 | 26 | It includes 27 | 28 | * a basic CLI example 29 | * examples for fuzz, unit, and constexpr testing 30 | * large github action testing matrix 31 | 32 | It requires 33 | 34 | * cmake 35 | * conan 36 | * a compiler 37 | 38 | If you want a more complex example project, check out the [cpp_starter_project](https://github.com/cpp-best-practices/cpp_starter_project). 39 | 40 | Ths Boilerplate project will merge new features first, then they will be merged (as appropriate) into cpp_starter_project. 41 | 42 | ## Getting Started 43 | 44 | ### Use the Github template 45 | First, click the green `Use this template` button near the top of this page. 46 | This will take you to Github's ['Generate Repository'](https://github.com/cpp-best-practices/cmake_conan_boilerplate_template/generate) page. 47 | Fill in a repository name and short description, and click 'Create repository from template'. 48 | This will allow you to create a new repository in your Github account, 49 | prepopulated with the contents of this project. 50 | 51 | After creating the project please wait until the cleanup workflow has finished 52 | setting up your project and commited the changes. 53 | 54 | Now you can clone the project locally and get to work! 55 | 56 | git clone https://github.com//.git 57 | 58 | ## More Details 59 | 60 | * [Dependency Setup](README_dependencies.md) 61 | * [Building Details](README_building.md) 62 | * [Troubleshooting](README_troubleshooting.md) 63 | * [Docker](README_docker.md) 64 | 65 | ## Testing 66 | 67 | See [Catch2 tutorial](https://github.com/catchorg/Catch2/blob/master/docs/tutorial.md) 68 | 69 | ## Fuzz testing 70 | 71 | See [libFuzzer Tutorial](https://github.com/google/fuzzing/blob/master/tutorial/libFuzzerTutorial.md) 72 | 73 | 74 | -------------------------------------------------------------------------------- /README_building.md: -------------------------------------------------------------------------------- 1 | ## Build Instructions 2 | 3 | A full build has different steps: 4 | 1) Specifying the compiler using environment variables 5 | 2) Configuring the project 6 | 3) Building the project 7 | 8 | For the subsequent builds, in case you change the source code, you only need to repeat the last step. 9 | 10 | ### (1) Specify the compiler using environment variables 11 | 12 | By default (if you don't set environment variables `CC` and `CXX`), the system default compiler will be used. 13 | 14 | Conan and CMake use 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. 15 | 16 | CMake will detect which compiler was used to build each of the Conan targets. If you build all of your Conan targets with one compiler, and then build your CMake targets with a different compiler, the project may fail to build. 17 | 18 |
19 | Commands for setting the compilers 20 | 21 | - Debian/Ubuntu/MacOS: 22 | 23 | Set your desired compiler (`clang`, `gcc`, etc): 24 | 25 | - Temporarily (only for the current shell) 26 | 27 | Run one of the followings in the terminal: 28 | 29 | - clang 30 | 31 | CC=clang CXX=clang++ 32 | 33 | - gcc 34 | 35 | CC=gcc CXX=g++ 36 | 37 | - Permanent: 38 | 39 | Open `~/.bashrc` using your text editor: 40 | 41 | gedit ~/.bashrc 42 | 43 | Add `CC` and `CXX` to point to the compilers: 44 | 45 | export CC=clang 46 | export CXX=clang++ 47 | 48 | Save and close the file. 49 | 50 | - Windows: 51 | 52 | - Permanent: 53 | 54 | Run one of the followings in PowerShell: 55 | 56 | - Visual Studio generator and compiler (cl) 57 | 58 | [Environment]::SetEnvironmentVariable("CC", "cl.exe", "User") 59 | [Environment]::SetEnvironmentVariable("CXX", "cl.exe", "User") 60 | refreshenv 61 | 62 | Set the architecture using [vcvarsall](https://docs.microsoft.com/en-us/cpp/build/building-on-the-command-line?view=vs-2019#vcvarsall-syntax): 63 | 64 | vcvarsall.bat x64 65 | 66 | - clang 67 | 68 | [Environment]::SetEnvironmentVariable("CC", "clang.exe", "User") 69 | [Environment]::SetEnvironmentVariable("CXX", "clang++.exe", "User") 70 | refreshenv 71 | 72 | - gcc 73 | 74 | [Environment]::SetEnvironmentVariable("CC", "gcc.exe", "User") 75 | [Environment]::SetEnvironmentVariable("CXX", "g++.exe", "User") 76 | refreshenv 77 | 78 | 79 | - Temporarily (only for the current shell): 80 | 81 | $Env:CC="clang.exe" 82 | $Env:CXX="clang++.exe" 83 | 84 |
85 | 86 | ### (2) Configure your build 87 | 88 | To configure the project, you could use `cmake`, or `ccmake` or `cmake-gui`. Each of them are explained in the following: 89 | 90 | #### (2.a) Configuring via cmake: 91 | With Cmake directly: 92 | 93 | cmake -S . -B ./build 94 | 95 | Cmake will automatically create the `./build` folder if it does not exist, and it wil configure the project. 96 | 97 | Instead, if you have CMake version 3.21+, you can use one of the configuration presets that are listed in the CmakePresets.json file. 98 | 99 | cmake . --preset 100 | cmake --build 101 | 102 | #### (2.b) Configuring via ccmake: 103 | 104 | With the Cmake Curses Dialog Command Line tool: 105 | 106 | ccmake -S . -B ./build 107 | 108 | Once `ccmake` has finished setting up, press 'c' to configure the project, 109 | press 'g' to generate, and 'q' to quit. 110 | 111 | #### (2.c) Configuring via cmake-gui: 112 | 113 | To use the GUI of the cmake: 114 | 115 | 2.c.1) Open cmake-gui from the project directory: 116 | ``` 117 | cmake-gui . 118 | ``` 119 | 2.c.2) Set the build directory: 120 | 121 | ![build_dir](https://user-images.githubusercontent.com/16418197/82524586-fa48e380-9af4-11ea-8514-4e18a063d8eb.jpg) 122 | 123 | 2.c.3) Configure the generator: 124 | 125 | In cmake-gui, from the upper menu select `Tools/Configure`. 126 | 127 | **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! 128 | 129 |
130 | Windows - MinGW Makefiles 131 | 132 | Choose MinGW Makefiles as the generator: 133 | 134 | mingw 135 | 136 |
137 | 138 |
139 | Windows - Visual Studio generator and compiler 140 | 141 | You should have already set `C` and `CXX` to `cl.exe`. 142 | 143 | Choose "Visual Studio 16 2019" as the generator: 144 | 145 | default_vs 146 | 147 |
148 | 149 |
150 | 151 | Windows - Visual Studio generator and Clang Compiler 152 | 153 | You should have already set `C` and `CXX` to `clang.exe` and `clang++.exe`. 154 | 155 | Choose "Visual Studio 16 2019" as the generator. To tell Visual studio to use `clang-cl.exe`: 156 | - If you use the LLVM that is shipped with Visual Studio: write `ClangCl` under "optional toolset to use". 157 | 158 | visual_studio 159 | 160 | - If you use an external LLVM: write [`LLVM_v142`](https://github.com/zufuliu/llvm-utils#llvm-for-visual-studio-2017-and-2019) 161 | under "optional toolset to use". 162 | 163 | visual_studio 164 | 165 |
166 |
167 | 168 | 2.c.4) Choose the Cmake options and then generate: 169 | 170 | ![generate](https://user-images.githubusercontent.com/16418197/82781591-c97feb80-9e1f-11ea-86c8-f2748b96f516.png) 171 | 172 | ### (3) Build the project 173 | Once you have selected all the options you would like to use, you can build the 174 | project (all targets): 175 | 176 | cmake --build ./build 177 | 178 | For Visual Studio, give the build configuration (Release, RelWithDeb, Debug, etc) like the following: 179 | 180 | cmake --build ./build -- /p:configuration=Release 181 | 182 | 183 | ### Running the tests 184 | 185 | You can use the `ctest` command run the tests. 186 | 187 | ```shell 188 | cd ./build 189 | ctest -C Debug 190 | cd ../ 191 | ``` 192 | 193 | 194 | -------------------------------------------------------------------------------- /README_dependencies.md: -------------------------------------------------------------------------------- 1 | ## Dependencies 2 | 3 | Note about install commands: 4 | - for Windows, we use [choco](https://chocolatey.org/install). 5 | - for MacOS, we use [brew](https://brew.sh/). 6 | - In case of an error in cmake, make sure that the dependencies are on the PATH. 7 | 8 | 9 | ### Too Long, Didn't Install 10 | 11 | This is a really long list of dependencies, and it's easy to mess up. That's why: 12 | 13 | #### Docker 14 | We have a Docker image that's already set up for you. See the [Docker instructions](#docker-instructions). 15 | 16 | #### Setup-cpp 17 | 18 | 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. 19 | 20 | Please check [the setup-cpp documentation](https://github.com/aminya/setup-cpp) for more information. 21 | 22 | For example, on Windows, you can run the following to install llvm, cmake, ninja, ccache, conan, and cppcheck. 23 | ```ps1 24 | # windows example (open shell as admin) 25 | curl -LJO "https://github.com/aminya/setup-cpp/releases/download/v0.5.7/setup_cpp_windows.exe" 26 | ./setup_cpp_windows --compiler llvm --cmake true --ninja true --ccache true --conan true --cppcheck true 27 | 28 | RefreshEnv.cmd # reload the environment 29 | ``` 30 | 31 | ### Necessary Dependencies 32 | 1. A C++ compiler that supports C++17. 33 | See [cppreference.com](https://en.cppreference.com/w/cpp/compiler_support) 34 | to see which features are supported by each compiler. 35 | The following compilers should work: 36 | 37 | * [gcc 7+](https://gcc.gnu.org/) 38 |
39 | Install command 40 | 41 | - Debian/Ubuntu: 42 | 43 | sudo apt install build-essential 44 | 45 | - Windows: 46 | 47 | choco install mingw -y 48 | 49 | - MacOS: 50 | 51 | brew install gcc 52 |
53 | 54 | * [clang 6+](https://clang.llvm.org/) 55 |
56 | Install command 57 | 58 | - Debian/Ubuntu: 59 | 60 | bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" 61 | 62 | - Windows: 63 | 64 | Visual Studio 2019 ships with LLVM (see the Visual Studio section). However, to install LLVM separately: 65 | 66 | choco install llvm -y 67 | 68 | llvm-utils for using external LLVM with Visual Studio generator: 69 | 70 | git clone https://github.com/zufuliu/llvm-utils.git 71 | cd llvm-utils/VS2017 72 | .\install.bat 73 | 74 | - MacOS: 75 | 76 | brew install llvm 77 |
78 | 79 | * [Visual Studio 2019 or higher](https://visualstudio.microsoft.com/) 80 |
81 | Install command + Environment setup 82 | 83 | On Windows, you need to install Visual Studio 2019 because of the SDK and libraries that ship with it. 84 | 85 | Visual Studio IDE - 2019 Community (installs Clang too): 86 | 87 | choco install -y visualstudio2019community --package-parameters "add Microsoft.VisualStudio.Workload.NativeDesktop --includeRecommended --includeOptional --passive --locale en-US" 88 | 89 | Put MSVC compiler, Clang compiler, and vcvarsall.bat on the path: 90 | 91 | choco install vswhere -y 92 | refreshenv 93 | 94 | # change to x86 for 32bit 95 | $clpath = vswhere -products * -latest -prerelease -find **/Hostx64/x64/* 96 | $clangpath = vswhere -products * -latest -prerelease -find **/Llvm/bin/* 97 | $vcvarsallpath = vswhere -products * -latest -prerelease -find **/Auxiliary/Build/* 98 | 99 | $path = [System.Environment]::GetEnvironmentVariable("PATH", "User") 100 | [Environment]::SetEnvironmentVariable("Path", $path + ";$clpath" + ";$clangpath" + ";$vcvarsallpath", "User") 101 | refreshenv 102 | 103 |
104 | 105 | 106 | 2. [Conan](https://conan.io/) 107 |
108 | Install Command 109 | 110 | - Via pip - https://docs.conan.io/en/latest/installation.html#install-with-pip-recommended 111 | 112 | pip install --user conan 113 | 114 | - Windows: 115 | 116 | choco install conan -y 117 | 118 | - MacOS: 119 | 120 | brew install conan 121 | 122 |
123 | 124 | 3. [CMake 3.15+](https://cmake.org/) 125 |
126 | Install Command 127 | 128 | - Debian/Ubuntu: 129 | 130 | sudo apt-get install cmake 131 | 132 | - Windows: 133 | 134 | choco install cmake -y 135 | 136 | - MacOS: 137 | 138 | brew install cmake 139 | 140 |
141 | 142 | ### Optional Dependencies 143 | #### C++ Tools 144 | * [Doxygen](http://doxygen.nl/) 145 |
146 | Install Command 147 | 148 | - Debian/Ubuntu: 149 | 150 | sudo apt-get install doxygen 151 | sudo apt-get install graphviz 152 | 153 | - Windows: 154 | 155 | choco install doxygen.install -y 156 | choco install graphviz -y 157 | 158 | - MacOS: 159 | 160 | brew install doxygen 161 | brew install graphviz 162 | 163 |
164 | 165 | 166 | * [ccache](https://ccache.dev/) 167 |
168 | Install Command 169 | 170 | - Debian/Ubuntu: 171 | 172 | sudo apt-get install ccache 173 | 174 | - Windows: 175 | 176 | choco install ccache -y 177 | 178 | - MacOS: 179 | 180 | brew install ccache 181 | 182 |
183 | 184 | 185 | * [Cppcheck](http://cppcheck.sourceforge.net/) 186 |
187 | Install Command 188 | 189 | - Debian/Ubuntu: 190 | 191 | sudo apt-get install cppcheck 192 | 193 | - Windows: 194 | 195 | choco install cppcheck -y 196 | 197 | - MacOS: 198 | 199 | brew install cppcheck 200 | 201 |
202 | 203 | 204 | * [include-what-you-use](https://include-what-you-use.org/) 205 |
206 | Install Command 207 | 208 | Follow instructions here: 209 | https://github.com/include-what-you-use/include-what-you-use#how-to-install 210 |
211 | 212 | #### GUI libraries 213 | This project can be made to work with several optional GUI frameworks. 214 | 215 | If desired, you should install the following optional dependencies as 216 | directed by their documentation, linked here: 217 | 218 | - [FLTK](https://www.fltk.org/doc-1.4/index.html) 219 | - [GTKMM](https://www.gtkmm.org/en/documentation.html) 220 | - [QT](https://doc.qt.io/) 221 | 222 | The following dependencies can be downloaded automatically by CMake and Conan. 223 | All you need to do to install them is to turn on a CMake flag during 224 | configuration. 225 | If you run into difficulty using them, please refer to their documentation, 226 | linked here: 227 | 228 | - [NANA](http://nanapro.org/en-us/documentation/) 229 | - [SDL](http://wiki.libsdl.org/FrontPage) 230 | - [IMGUI](https://github.com/ocornut/imgui/tree/master/docs): 231 | This framework depends on SFML, and if you are using Linux, you may need 232 | to install several of SFML's dependencies using your package manager. See 233 | [the SFML build tutorial](https://www.sfml-dev.org/tutorials/2.5/compile-with-cmake.php) 234 | for specifics. 235 | 236 | 237 | -------------------------------------------------------------------------------- /README_docker.md: -------------------------------------------------------------------------------- 1 | ## Docker Instructions 2 | 3 | If you have [Docker](https://www.docker.com/) installed, you can run this 4 | in your terminal, when the Dockerfile is inside the `.devcontainer` directory: 5 | 6 | ```bash 7 | docker build -f ./.devcontainer/Dockerfile --tag=my_project:latest . 8 | docker run -it my_project:latest 9 | ``` 10 | 11 | This command will put you in a `bash` session in a Ubuntu 20.04 Docker container, 12 | with all of the tools listed in the [Dependencies](#dependencies) section already installed. 13 | Additionally, you will have `g++-11` and `clang++-13` installed as the default 14 | versions of `g++` and `clang++`. 15 | 16 | If you want to build this container using some other versions of gcc and clang, 17 | you may do so with the `GCC_VER` and `LLVM_VER` arguments: 18 | 19 | ```bash 20 | docker build --tag=myproject:latest --build-arg GCC_VER=10 --build-arg LLVM_VER=11 . 21 | ``` 22 | 23 | The CC and CXX environment variables are set to GCC version 11 by default. 24 | If you wish to use clang as your default CC and CXX environment variables, you 25 | may do so like this: 26 | 27 | ```bash 28 | docker build --tag=my_project:latest --build-arg USE_CLANG=1 . 29 | ``` 30 | 31 | You will be logged in as root, so you will see the `#` symbol as your prompt. 32 | You will be in a directory that contains a copy of the `cpp_starter_project`; 33 | any changes you make to your local copy will not be updated in the Docker image 34 | until you rebuild it. 35 | If you need to mount your local copy directly in the Docker image, see 36 | [Docker volumes docs](https://docs.docker.com/storage/volumes/). 37 | TLDR: 38 | 39 | ```bash 40 | docker run -it \ 41 | -v absolute_path_on_host_machine:absolute_path_in_guest_container \ 42 | my_project:latest 43 | ``` 44 | 45 | You can configure and build [as directed above](#build) using these commands: 46 | 47 | ```bash 48 | /starter_project# mkdir build 49 | /starter_project# cmake -S . -B ./build 50 | /starter_project# cmake --build ./build 51 | ``` 52 | 53 | You can configure and build using `clang-13`, without rebuilding the container, 54 | with these commands: 55 | 56 | ```bash 57 | /starter_project# mkdir build 58 | /starter_project# CC=clang CXX=clang++ cmake -S . -B ./build 59 | /starter_project# cmake --build ./build 60 | ``` 61 | 62 | The `ccmake` tool is also installed; you can substitute `ccmake` for `cmake` to 63 | configure the project interactively. 64 | All of the tools this project supports are installed in the Docker image; 65 | enabling them is as simple as flipping a switch using the `ccmake` interface. 66 | Be aware that some of the sanitizers conflict with each other, so be sure to 67 | run them separately. 68 | 69 | A script called `build_examples.sh` is provided to help you to build the example 70 | GUI projects in this container. 71 | 72 | -------------------------------------------------------------------------------- /README_troubleshooting.md: -------------------------------------------------------------------------------- 1 | ## Troubleshooting 2 | 3 | ### Update Conan 4 | Many problems that users have can be resolved by updating Conan, so if you are 5 | having any trouble with this project, you should start by doing that. 6 | 7 | To update conan: 8 | 9 | pip install --user --upgrade conan 10 | 11 | You may need to use `pip3` instead of `pip` in this command, depending on your 12 | platform. 13 | 14 | ### Clear Conan cache 15 | If you continue to have trouble with your Conan dependencies, you can try 16 | clearing your Conan cache: 17 | 18 | conan remove -f '*' 19 | 20 | The next time you run `cmake` or `cmake --build`, your Conan dependencies will 21 | be rebuilt. If you aren't using your system's default compiler, don't forget to 22 | set the CC, CXX, CMAKE_C_COMPILER, and CMAKE_CXX_COMPILER variables, as 23 | described in the 'Build using an alternate compiler' section above. 24 | 25 | ### Identifying misconfiguration of Conan dependencies 26 | 27 | If you have a dependency 'A' that requires a specific version of another 28 | dependency 'B', and your project is trying to use the wrong version of 29 | dependency 'B', Conan will produce warnings about this configuration error 30 | when you run CMake. These warnings can easily get lost between a couple 31 | hundred or thousand lines of output, depending on the size of your project. 32 | 33 | If your project has a Conan configuration error, you can use `conan info` to 34 | find it. `conan info` displays information about the dependency graph of your 35 | project, with colorized output in some terminals. 36 | 37 | cd build 38 | conan info . 39 | 40 | In my terminal, the first couple lines of `conan info`'s output show all of the 41 | project's configuration warnings in a bright yellow font. 42 | 43 | For example, the package `spdlog/1.5.0` depends on the package `fmt/6.1.2`. 44 | If you were to modify the file `conanfile.py` so that it requires an 45 | earlier version of `fmt`, such as `fmt/6.0.0`, and then run: 46 | 47 | ```bash 48 | conan remove -f '*' # clear Conan cache 49 | rm -rf build # clear previous CMake build 50 | cmake -S . -B ./build # rebuild Conan dependencies 51 | conan info ./build 52 | ``` 53 | 54 | ...the first line of output would be a warning that `spdlog` needs a more recent 55 | version of `fmt`. 56 | 57 | 58 | -------------------------------------------------------------------------------- /build_examples.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # This script is intended to be run from an Ubuntu Docker image (or other Debian-derived distros). 4 | # It uses `apt-get` to install dependencies required by the examples, 5 | 6 | set -euo pipefail 7 | 8 | function install_fltk() { 9 | apt-get install -y --no-install-recommends libfltk1.3-dev libgl1-mesa-dev fluid 10 | } 11 | 12 | function install_gtkmm() { 13 | apt-get install -y --no-install-recommends pkg-config libgtkmm-3.0-dev 14 | } 15 | 16 | function install_imgui() { 17 | apt-get install -y --no-install-recommends pkg-config libgl1-mesa-dev 18 | } 19 | 20 | function install_nana() { 21 | # CMakeLists.txt is 'supposed' to install all of these automatically, but for 22 | # some reason it doesn't always work. Installing them manually does work. 23 | apt-get install -y --no-install-recommends libjpeg8-dev libpng-dev \ 24 | libasound2-dev alsa-utils alsa-oss libx11-dev libxft-dev libxcursor-dev 25 | # Note: Nana's headers trigger the -Wshadow warning, and cannot be compiled with -Werror. 26 | # Supposedly, this is fixed in the develop-1.8 branch, but I cannot confirm. 27 | } 28 | 29 | function install_qt() { 30 | apt-get install -y --no-install-recommends qt5-default qtbase5-dev 31 | } 32 | 33 | function install_sdl() { 34 | pip install mako 35 | } 36 | 37 | # call the above functions to install the required dependencies. As an example for qt: 38 | # install_qt 39 | 40 | # build with: 41 | cmake -S . -B "./build" 42 | cmake --build "./build" -------------------------------------------------------------------------------- /conanfile.txt: -------------------------------------------------------------------------------- 1 | # Docs at https://docs.conan.io/en/latest/reference/conanfile_txt.html 2 | 3 | [requires] 4 | catch2/2.13.9 5 | cli11/2.2.0 6 | spdlog/1.10.0 7 | 8 | [generators] 9 | cmake_find_package_multi 10 | -------------------------------------------------------------------------------- /configured_files/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | # A very simple example of a configured file that might need to be 3 | # converted to one that is publicly installed in the case that 4 | # you are developing a library 5 | configure_file("config.hpp.in" "${CMAKE_BINARY_DIR}/configured_files/include/internal_use_only/config.hpp" ESCAPE_QUOTES) 6 | 7 | 8 | -------------------------------------------------------------------------------- /configured_files/config.hpp.in: -------------------------------------------------------------------------------- 1 | #ifndef MYPROJECT_CONFIG_HPP 2 | #define MYPROJECT_CONFIG_HPP 3 | 4 | // this is a basic example of how a CMake configured file might look 5 | // in this particular case, we are using it to set the version number of our executable 6 | namespace myproject::cmake { 7 | static constexpr std::string_view project_name = "@PROJECT_NAME@"; 8 | static constexpr std::string_view project_version = "@PROJECT_VERSION@"; 9 | static constexpr int project_version_major { @PROJECT_VERSION_MAJOR@ }; 10 | static constexpr int project_version_minor { @PROJECT_VERSION_MINOR@ }; 11 | static constexpr int project_version_patch { @PROJECT_VERSION_PATCH@ }; 12 | static constexpr int project_version_tweak { @PROJECT_VERSION_TWEAK@ }; 13 | static constexpr std::string_view git_sha = "@GIT_SHA@"; 14 | }// namespace myproject::cmake 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /fuzz_test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # A fuzz test runs until it finds an error. This particular one is going to rely on libFuzzer. 2 | # 3 | 4 | find_package(fmt) 5 | 6 | add_executable(fuzz_tester fuzz_tester.cpp) 7 | target_link_libraries( 8 | fuzz_tester 9 | PRIVATE project_options 10 | project_warnings 11 | fmt::fmt 12 | -coverage 13 | -fsanitize=fuzzer,undefined,address) 14 | target_compile_options(fuzz_tester PRIVATE -fsanitize=fuzzer,undefined,address) 15 | 16 | # Allow short runs during automated testing to see if something new breaks 17 | set(FUZZ_RUNTIME 18 | 10 19 | CACHE STRING "Number of seconds to run fuzz tests during ctest run") # Default of 10 seconds 20 | 21 | add_test(NAME fuzz_tester_run COMMAND fuzz_tester -max_total_time=${FUZZ_RUNTIME}) 22 | -------------------------------------------------------------------------------- /fuzz_test/fuzz_tester.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | [[nodiscard]] auto sum_values(const uint8_t *Data, size_t Size) 6 | { 7 | constexpr auto scale = 1000; 8 | 9 | int value = 0; 10 | for (std::size_t offset = 0; offset < Size; ++offset) { 11 | value += static_cast(*std::next(Data, static_cast(offset))) * scale; 12 | } 13 | return value; 14 | } 15 | 16 | // Fuzzer that attempts to invoke undefined behavior for signed integer overflow 17 | // cppcheck-suppress unusedFunction symbolName=LLVMFuzzerTestOneInput 18 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) 19 | { 20 | fmt::print("Value sum: {}, len{}\n", sum_values(Data, Size), Size); 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | find_package(fmt CONFIG REQUIRED) 2 | find_package(spdlog CONFIG REQUIRED) 3 | find_package(CLI11 CONFIG REQUIRED) 4 | 5 | # Generic test that uses conan libs 6 | add_executable(intro main.cpp) 7 | target_link_libraries( 8 | intro 9 | PUBLIC project_options project_warnings 10 | PRIVATE CLI11::CLI11 fmt::fmt spdlog::spdlog) 11 | 12 | target_include_directories(intro PRIVATE "${CMAKE_BINARY_DIR}/configured_files/include") 13 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | // This file will be generated automatically when you run the CMake configuration step. 9 | // It creates a namespace called `myproject`. 10 | // You can modify the source template at `configured_files/config.hpp.in`. 11 | #include 12 | 13 | 14 | // NOLINTNEXTLINE(bugprone-exception-escape) 15 | int main(int argc, const char **argv) 16 | { 17 | try { 18 | CLI::App app{ fmt::format("{} version {}", myproject::cmake::project_name, myproject::cmake::project_version) }; 19 | 20 | std::optional message; 21 | app.add_option("-m,--message", message, "A message to print back out"); 22 | bool show_version = false; 23 | app.add_flag("--version", show_version, "Show version information"); 24 | 25 | CLI11_PARSE(app, argc, argv); 26 | 27 | if (show_version) { 28 | fmt::print("{}\n", myproject::cmake::project_version); 29 | return EXIT_SUCCESS; 30 | } 31 | 32 | // Use the default logger (stdout, multi-threaded, colored) 33 | spdlog::info("Hello, {}!", "World"); 34 | 35 | if (message) { 36 | fmt::print("Message: '{}'\n", *message); 37 | } else { 38 | fmt::print("No Message Provided :(\n"); 39 | } 40 | } catch (const std::exception &e) { 41 | spdlog::error("Unhandled exception in main: {}", e.what()); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15...3.23) 2 | 3 | project(CmakeConfigPackageTests LANGUAGES CXX) 4 | 5 | # ---- Test as standalone project the exported config package ---- 6 | 7 | if(PROJECT_IS_TOP_LEVEL OR TEST_INSTALLED_VERSION) 8 | enable_testing() 9 | 10 | find_package(myproject CONFIG REQUIRED) # for intro, project_options, ... 11 | 12 | if(NOT TARGET myproject::project_options) 13 | message(FATAL_ERROR "Requiered config package not found!") 14 | return() # be strictly paranoid for Template Janitor github action! CK 15 | endif() 16 | endif() 17 | 18 | # ---- Dependencies ---- 19 | 20 | find_package(Catch2 CONFIG REQUIRED) 21 | 22 | include(Catch) 23 | 24 | add_library(catch_main OBJECT catch_main.cpp) 25 | target_link_libraries(catch_main PUBLIC Catch2::Catch2) 26 | target_link_libraries(catch_main PRIVATE myproject::project_options) 27 | 28 | # Provide a simple smoke test to make sure that the CLI works and can display a --help message 29 | add_test(NAME cli.has_help COMMAND intro --help) 30 | 31 | # Provide a test to verify that the version being reported from the application 32 | # matches the version given to CMake. This will be important once you package 33 | # your program. Real world shows that this is the kind of simple mistake that is easy 34 | # to make, but also easy to test for. 35 | add_test(NAME cli.version_matches COMMAND intro --version) 36 | set_tests_properties(cli.version_matches PROPERTIES PASS_REGULAR_EXPRESSION "${PROJECT_VERSION}") 37 | 38 | add_executable(tests tests.cpp) 39 | target_link_libraries(tests PRIVATE myproject::project_warnings myproject::project_options catch_main) 40 | 41 | # automatically discover tests that are defined in catch based test files you can modify the unittests. Set TEST_PREFIX 42 | # to whatever you want, or use different for different binaries 43 | catch_discover_tests( 44 | tests 45 | TEST_PREFIX 46 | "unittests." 47 | REPORTER 48 | xml 49 | OUTPUT_DIR 50 | . 51 | OUTPUT_PREFIX 52 | "unittests." 53 | OUTPUT_SUFFIX 54 | .xml) 55 | 56 | # Add a file containing a set of constexpr tests 57 | add_executable(constexpr_tests constexpr_tests.cpp) 58 | target_link_libraries(constexpr_tests PRIVATE myproject::project_options myproject::project_warnings catch_main) 59 | 60 | catch_discover_tests( 61 | constexpr_tests 62 | TEST_PREFIX 63 | "constexpr." 64 | REPORTER 65 | xml 66 | OUTPUT_DIR 67 | . 68 | OUTPUT_PREFIX 69 | "constexpr." 70 | OUTPUT_SUFFIX 71 | .xml) 72 | 73 | # Disable the constexpr portion of the test, and build again this allows us to have an executable that we can debug when 74 | # things go wrong with the constexpr testing 75 | add_executable(relaxed_constexpr_tests constexpr_tests.cpp) 76 | target_link_libraries(relaxed_constexpr_tests PRIVATE myproject::project_options myproject::project_warnings catch_main) 77 | target_compile_definitions(relaxed_constexpr_tests PRIVATE -DCATCH_CONFIG_RUNTIME_STATIC_REQUIRE) 78 | 79 | catch_discover_tests( 80 | relaxed_constexpr_tests 81 | TEST_PREFIX 82 | "relaxed_constexpr." 83 | REPORTER 84 | xml 85 | OUTPUT_DIR 86 | . 87 | OUTPUT_PREFIX 88 | "relaxed_constexpr." 89 | OUTPUT_SUFFIX 90 | .xml) 91 | -------------------------------------------------------------------------------- /test/catch_main.cpp: -------------------------------------------------------------------------------- 1 | #define CATCH_CONFIG_MAIN// This tells the catch header to generate a main 2 | 3 | #include 4 | -------------------------------------------------------------------------------- /test/constexpr_tests.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | constexpr unsigned int Factorial(unsigned int number)// NOLINT(misc-no-recursion) 4 | { 5 | return number <= 1 ? number : Factorial(number - 1) * number; 6 | } 7 | 8 | TEST_CASE("Factorials are computed with constexpr", "[factorial]") 9 | { 10 | STATIC_REQUIRE(Factorial(1) == 1); 11 | STATIC_REQUIRE(Factorial(2) == 2); 12 | STATIC_REQUIRE(Factorial(3) == 6); 13 | STATIC_REQUIRE(Factorial(10) == 3628800); 14 | } 15 | -------------------------------------------------------------------------------- /test/tests.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | unsigned int Factorial(unsigned int number)// NOLINT(misc-no-recursion) 4 | { 5 | return number <= 1 ? number : Factorial(number - 1) * number; 6 | } 7 | 8 | TEST_CASE("Factorials are computed", "[factorial]") 9 | { 10 | REQUIRE(Factorial(1) == 1); 11 | REQUIRE(Factorial(2) == 2); 12 | REQUIRE(Factorial(3) == 6); 13 | REQUIRE(Factorial(10) == 3628800); 14 | } 15 | --------------------------------------------------------------------------------