๐Ÿš€ Kick-start your C++! A template for modern C++ projects using CMake, CI, code coverage, clang-format, reproducible dependency management and much more.

Actions Status Actions Status Actions Status Actions Status Actions Status codecov

ModernCppStarter

Setting up a new C++ project usually requires a significant amount of preparation and boilerplate code, even more so for modern C++ projects with tests, executables and continuous integration. This template is the result of learnings from many previous projects and should help reduce the work required to setup up a modern C++ project.

Features

Usage

Adjust the template to your needs

  • Use this repo as a template.
  • Replace all occurrences of "Greeter" in the relevant CMakeLists.txt with the name of your project
    • Capitalization matters here: Greeter means the name of the project, while greeter is used in file names.
    • Remember to rename the include/greeter directory to use your project's lowercase name and update all relevant #includes accordingly.
  • Replace the source files with your own
  • For header-only libraries: see the comments in CMakeLists.txt
  • Add your project's codecov token to your project's github secrets under CODECOV_TOKEN
  • Happy coding!

Eventually, you can remove any unused files, such as the standalone directory or irrelevant github workflows for your project. Feel free to replace the License with one suited for your project.

To cleanly separate the library and subproject code, the outer CMakeList.txt only defines the library itself while the tests and other subprojects are self-contained in their own directories. During development it is usually convenient to build all subprojects at once.

Build and run the standalone target

Use the following command to build and run the executable target.

cmake -Hstandalone -Bbuild/standalone
cmake --build build/standalone
./build/standalone/Greeter --help

Build and run test suite

Use the following commands from the project's root directory to run the test suite.

cmake -Htest -Bbuild/test
cmake --build build/test
CTEST_OUTPUT_ON_FAILURE=1 cmake --build build/test --target test

# or simply call the executable: 
./build/test/GreeterTests

To collect code coverage information, run CMake with the -DENABLE_TEST_COVERAGE=1 option.

Run clang-format

Use the following commands from the project's root directory to check and fix C++ and CMake source style. This requires clang-format, cmake-format and pyyaml to be installed on the current system.

cmake -Htest -Bbuild/test

# view changes
cmake --build build/test --target format

# apply changes
cmake --build build/test --target fix-format

See Format.cmake for details.

Build the documentation

The documentation is automatically built and published whenever a GitHub Release is created. To manually build documentation, call the following command.

cmake -Hdocumentation -Bbuild/doc
cmake --build build/doc --target GenerateDocs
# view the docs
open build/doc/doxygen/html/index.html

To build the documentation locally, you will need Doxygen, jinja2 and Pygments on installed your system.

Build everything at once

The project also includes an all directory that allows building all targets at the same time. This is useful during development, as it exposes all subprojects to your IDE and avoids redundant builds of the library.

cmake -Hall -Bbuild
cmake --build build

# run tests
./build/test/GreeterTests
# format code
cmake --build build --target fix-format
# run standalone
./build/standalone/Greeter --help
# build docs
cmake --build build --target GenerateDocs

Additional tools

The test and standalone subprojects include the tools.cmake file which is used to import additional tools on-demand through CMake configuration arguments. The following are currently supported.

Sanitizers

Sanitizers can be enabled by configuring CMake with -DUSE_SANITIZER=<Address | Memory | MemoryWithOrigins | Undefined | Thread | Leak | 'Address;Undefined'>.

Static Analyzers

Static Analyzers can be enabled by setting -DUSE_STATIC_ANALYZER=<clang-tidy | iwyu | cppcheck>, or a combination of those in quotation marks, separated by semicolons. By default, analyzers will automatically find configuration files such as .clang-format. Additional arguments can be passed to the analyzers by setting the CLANG_TIDY_ARGS, IWYU_ARGS or CPPCHECK_ARGS variables.

Ccache

Ccache can be enabled by configuring with -DUSE_CCACHE=<ON | OFF>.

FAQ

Can I use this for header-only libraries?

Yes, however you will need to change the library type to an INTERFACE library as documented in the CMakeLists.txt. See here for an example header-only library based on the template.

I don't need a standalone target / documentation. How can I get rid of it?

Simply remove the standalone / documentation directory and according github workflow file.

Can I build the standalone and tests at the same time? / How can I tell my IDE about all subprojects?

To keep the template modular, all subprojects derived from the library have been separated into their own CMake modules. This approach makes it trivial for third-party projects to re-use the projects library code. To allow IDEs to see the full scope of the project, the template includes the all directory that will create a single build for all subprojects. Use this as the main directory for best IDE support.

I see you are using GLOB to add source files in CMakeLists.txt. Isn't that evil?

Glob is considered bad because any changes to the source file structure might not be automatically caught by CMake's builders and you will need to manually invoke CMake on changes. I personally prefer the GLOB solution for its simplicity, but feel free to change it to explicitly listing sources.

I want create additional targets that depend on my library. Should I modify the main CMakeLists to include them?

Avoid including derived projects from the libraries CMakeLists (even though it is a common sight in the C++ world), as this effectively inverts the dependency tree and makes the build system hard to reason about. Instead, create a new directory or project with a CMakeLists that adds the library as a dependency (e.g. like the standalone directory). Depending type it might make sense move these components into a separate repositories and reference a specific commit or version of the library. This has the advantage that individual libraries and components can be improved and updated independently.

You recommend to add external dependencies using CPM.cmake. Will this force users of my library to use CPM as well?

CPM.cmake should be invisible to library users as it's a self-contained CMake Script. If problems do arise, users can always opt-out by defining CPM_USE_LOCAL_PACKAGES, which will override all calls to CPMAddPackage with find_package. Alternatively, you could use CPMFindPackage instead of CPMAddPackage, which will try to use find_package before calling CPMAddPackage as a fallback. Both approaches should be compatible with common C++ package managers without modifications, however come with the cost of reproducible builds.

Can I configure and build my project offline?

Using CPM, all missing dependencies are downloaded at configure time. To avoid redundant downloads, it's recommended to set a CPM cache directory, e.g.: export CPM_SOURCE_CACHE=$HOME/.cache/CPM. This will also allow offline configurations if all dependencies are present. No internet connection is required for building.

Can I use CPack to create a package installer for my project?

As there are a lot of possible options and configurations, this is not (yet) in the scope of this template. See the CPack documentation for more information on setting up CPack installers.

This is too much, I just want to play with C++ code and test some libraries.

Perhaps the MiniCppStarter is something for you!

Coming soon

  • Script to automatically adjust the template for new projects
Owner
Lars Melchior
I'm a physicist, founder and full stack developer based in Berlin. Let's change the world together!
Lars Melchior
Comments
  • Compile options and warnings for standalone?

    Compile options and warnings for standalone?

    Similar to how it's done in this other starter attempt, I feel like those options and warnings could be beneficial.

    I would like to get some input on how the IPO (LTO) optimization should be done before making a PR.
    In that other project it seems to be a global option whether LTO is on or off. Is that right?

  • Implemented Docker and Docker Compose support

    Implemented Docker and Docker Compose support

    Docker Support

    Implemented support to build, running, and testing with Docker containers and docker-compose.

    All instructions are included in README.md.

  • Adding 3rd party libs to target_include_directories

    Adding 3rd party libs to target_include_directories

    How to properly add other local third-party libraries inside the main package? the main package is not a single header libarary.

    issue_project
    โ”œโ”€โ”€ include
    โ”‚ย ย  โ”œโ”€โ”€ main_lib1
    โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ mainlib.h
    โ”‚ย ย  โ”œโ”€โ”€ main_lib2
    โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ mainlib2.h
    โ”‚ย ย  โ””โ”€โ”€ main_project.h
    โ””โ”€โ”€ thirdparty
        โ”œโ”€โ”€ lib1
        โ”‚ย ย  โ””โ”€โ”€ lib1.h
        โ””โ”€โ”€ lib2
            โ””โ”€โ”€ lib2.h
    

    I tried this

    target_include_directories(
      Greeter PUBLIC "$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include;${THIRD_PARTY_LIBRARY}">
                     $<INSTALL_INTERFACE:include/${PROJECT_NAME}-${PROJECT_VERSION}>
    )
    

    But with an error that the header file not found. However, if I tried to put "include_directories(${THIRD_PARTY_LIBRARY})" it will build the main Cmake but the test's Cmake will fail due to the following error:

    #include <xx/x.h> No such file or directory
    

    If I was not clear enough, I will create a simplified project to reproduce the issue.

    Thanks,

  • add a package for a interface(or not executable) library

    add a package for a interface(or not executable) library

    I noticed the CMakeList.txt file at the top level of your project, the line 55

    # Link dependencies
    target_link_libraries(Greeter PRIVATE fmt::fmt)
    

    Use target_link_libraries to link an external library which add by

    CPMAddPackage(
      NAME fmt
      GIT_TAG 7.1.3
      GITHUB_REPOSITORY fmtlib/fmt
      OPTIONS "FMT_INSTALL YES" # create an installable target
    )
    

    I am puzzled why this can be done, as far as I know, this will remind me of an error on my IDE (CLion).

    Cannot specify link libraries for target "PROJECT_NAME" which is not built by this project.

    This is the structure of my project:

    cmake |--- CPM.cmake

    exec |--- main.cpp |--- CMakeList.txt

    include |--- *.hpp

    src |--- *.cpp

    CMakeList.txt

    The content of CMakeList.txt in top level:

    cmake_minimum_required(VERSION 2.8.12...3.17)
    project(
    		foo
    		VERSION 0.0.1
    		LANGUAGES CXX
    )
    
    include(cmake/CPM.cmake)
    CPMAddPackage("gh:TheLartians/PackageProject.cmake#master")
    
    file(GLOB_RECURSE fooHeader CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp")
    file(GLOB_RECURSE fooSource CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
    
    add_library(
    		${PROJECT_NAME}
    		${fooHeader}
    		${fooSource}
    )
    
    set_target_properties(
    		${PROJECT_NAME} PROPERTIES
    		LINKER_LANGUAGE CXX
    		CXX_STANDARD 17
    )
    
    # being a cross-platform target, we enforce standards conformance on MSVC
    target_compile_options(${PROJECT_NAME} PUBLIC "$<$<BOOL:${MSVC}>:/permissive->")
    
    # MARK1
    # CPMAddPackage("gh:jarro2783/cxxopts#master")
    # set(CXXOPTS_BUILD_EXAMPLES off)
    # set(CXXOPTS_BUILD_TESTS off)
    # target_link_libraries(${PROJECT_NAME} cxxopts)
    
    target_include_directories(
    		${PROJECT_NAME}
    		PUBLIC
    		$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
    		$<INSTALL_INTERFACE:include/${PROJECT_NAME}-${PROJECT_VERSION}>
    )
    
    string(TOLOWER ${PROJECT_NAME}/version.h VERSION_HEADER_LOCATION)
    
    packageProject(
    		NAME ${PROJECT_NAME}
    		VERSION ${PROJECT_VERSION}
    		NAMESPACE ${PROJECT_NAME}
    		BINARY_DIR ${PROJECT_BINARY_DIR}
    		INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include
    		INCLUDE_DESTINATION include/${PROJECT_NAME}-${PROJECT_VERSION}
    		VERSION_HEADER "${VERSION_HEADER_LOCATION}"
    		DEPENDENCIES "foo"
    )
    

    The content of CMakeList.txt in exec:

    cmake_minimum_required(VERSION 2.8.12...3.17)
    
    project(
    		fooExec
    		LANGUAGES CXX
    )
    
    include(../cmake/CPM.cmake)
    
    CPMAddPackage(
    		NAME foo
    		SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/..
    )
    
    add_executable(
    		${PROJECT_NAME}
    		main.cpp
    )
    
    set_target_properties(
    		${PROJECT_NAME}
    		PROPERTIES CXX_STANDARD 17
    		OUTPUT_NAME "fooExec"
    )
    
    # MARK2
    CPMAddPackage("gh:jarro2783/cxxopts#master")
    set(CXXOPTS_BUILD_EXAMPLES off)
    set(CXXOPTS_BUILD_TESTS off)
    target_link_libraries(
    		${PROJECT_NAME}
    		PRIVATE
    		foo::foo
    )
    

    You may have noticed that I have a mark in each of the two files.

    At the beginning, I wrote the code that needs cxxopts in the exec folder (the same directory as main.cpp) and the exec folder's structure is similar to the top level (also has include and src folders), I use

    target_link_libraries(
    		${PROJECT_NAME}
    		PRIVATE
    		foo::foo
    		cxxopts
    )
    

    everything work well

    // and if I write
    #include <cxx
    
    // It immediately reminds me whether to write
    #include <cxxopts.hpp>
    
    // Yes, IDE knows that there is a file called cxxopts.hpp
    

    But soon I discovered that there are some problems with the design of this structure. I need to move the code that uses cxxopts to the include and src folders at the top level. So I tried to delete the cxxopts at MARK2 to

    target_link_libraries(
    		${PROJECT_NAME}
    		PRIVATE
    		foo::foo
    )
    

    And added the code at MARK1 (they didn't exist at the beginning).

    CPMAddPackage("gh:jarro2783/cxxopts#master")
    set(CXXOPTS_BUILD_EXAMPLES off)
    set(CXXOPTS_BUILD_TESTS off)
    
    # the code below is also not exist now
    # target_link_libraries(${PROJECT_NAME} cxxopts)
    

    then

    ```c++
    // and if I write
    #include <cxx
    
    // It reminds me nothing
    #include <cxxopts.hpp>
    
    // Yes, IDE does not knows that there is a file called cxxopts.hpp and it tells me file not found
    

    After this, I came back here, I use target_link_libraries like you

    CPMAddPackage("gh:jarro2783/cxxopts#master")
    set(CXXOPTS_BUILD_EXAMPLES off)
    set(CXXOPTS_BUILD_TESTS off)
    target_link_libraries(${PROJECT_NAME} cxxopts)
    

    What I didnโ€™t expect was that the error this time was not

    Cannot specify link libraries for target "PROJECT_NAME" which is not built by this project.

    It output

    CMake Error: install(EXPORT "fooTargets" ...) includes target "foo" which requires target "cxxopts" that is not in any export set.

    What I didn't expect again is

    // and if I write
    #include <cxx
    
    // It immediately reminds me whether to write
    #include <cxxopts.hpp>
    
    // Yes, IDE knows that there is a file called cxxopts.hpp again!!!
    

    I don't know what to do.

  • Use m.css for generating doxygen docs

    Use m.css for generating doxygen docs

    Here is the output: http://moderncppstarter-mcss-docs.surge.sh/index.html

    Addresses https://github.com/TheLartians/ModernCppStarter/issues/47 (although a bit indirectly).

    Also, note that right now, these are pending:

    • [x] The Pages and Files tabs have empty content, as m.css does not include undocumented entities by default in the output. We need to fix this by adding related documentation.
    • [x] Previously Doxygen was filled using env variables, ex: @[email protected], but now they have to be hardcoded. Maybe this can be improved.
  • How to Debug configuration with GreeterStandalone in CLion

    How to Debug configuration with GreeterStandalone in CLion

    As I opened starter with CLion, I can't find binary in configuration. CLion Settings: CMake: CMake options: -Hall -Bbuild Build directory: build.

    Only Greeter and fmt shows in Debug configuration, How to configure to debug the binary module๏ผŸ

  • Distinguish

    Distinguish "Greeter" as the name of the CMake project and as the name of files/directories/classes

    Hi TheLartians

    First of all thanks for this great project; it really simplifies things quite a bit.

    One thing might be confusing for beginners though: the name "Greeter" is used both as the name of the CMake project and as the name of several files/directories/classes. Although you can technically distinguish these two by the capitalization of the first letter it still opens possibilities for mistakes.

    One side effect in renaming the project name is also missing from the README: one needs to change #include <greeter/version.h> to #include <NewProjName/version.h> in .cpp files as well.

    Do you think changing the project name to something like "YourProject" is better? I can make the PR.

  • Use ${PROJECT_NAME} instead of writing projectname multiple times

    Use ${PROJECT_NAME} instead of writing projectname multiple times

    Is there a reason ${PROJECT_NAME} is not used? I thought this is the recommended way to go about it? Also it makes it easier to do the initial setup with your template.

    Example: Instead of:

    project(
      Greeter
      VERSION 1.0
      LANGUAGES CXX
    )
    
    add_library(Greeter ${headers} ${sources})
    
    set_target_properties(Greeter PROPERTIES CXX_STANDARD 17)
    
    target_compile_options(Greeter PUBLIC "$<$<COMPILE_LANG_AND_ID:CXX,MSVC>:/permissive->")
    
    target_link_libraries(Greeter PRIVATE fmt::fmt)
    

    use :

    project(
      Greeter
      VERSION 1.0
      LANGUAGES CXX
    )
    
    add_library(${PROJECT_NAME}${headers} ${sources})
    
    set_target_properties(${PROJECT_NAME}PROPERTIES CXX_STANDARD 17)
    
    target_compile_options(${PROJECT_NAME}PUBLIC "$<$<COMPILE_LANG_AND_ID:CXX,MSVC>:/permissive->")
    
    target_link_libraries(${PROJECT_NAME}PRIVATE fmt::fmt)
    
  • CMake Error: install(EXPORT

    CMake Error: install(EXPORT "GreeterTargets" ...) includes target "Greeter" which requires target "fmt-header-only" that is not in any export set.

    after adding a new build dependency I get this error:

    Claus-iMac:ModernCppStarter clausklein$ !rm
    rm -rf build/
    Claus-iMac:ModernCppStarter clausklein$ cmake -G Ninja -B build -S standalone/
    -- The CXX compiler identification is AppleClang 12.0.0.12000032
    -- Detecting CXX compiler ABI info
    -- Detecting CXX compiler ABI info - done
    -- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ - skipped
    -- Detecting CXX compile features
    -- Detecting CXX compile features - done
    -- Downloading CPM.cmake to /Users/clausklein/Workspace/cpp/ModernCppStarter/build/cmake/CPM_0.28.2.cmake
    -- CPM: adding package [email protected] (v1.2.2)
    -- Using ccache: /usr/local/bin/ccache
    -- CPM: adding package [email protected] (v2.2.0)
    -- cxxopts version 2.2.0
    -- The C compiler identification is AppleClang 12.0.0.12000032
    -- Detecting C compiler ABI info
    -- Detecting C compiler ABI info - done
    -- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc - skipped
    -- Detecting C compile features
    -- Detecting C compile features - done
    -- CPM: adding package [email protected] (/Users/clausklein/Workspace/cpp/ModernCppStarter/standalone/..)
    -- CPM: Greeter: adding package [email protected] (v1.4)
    -- CPM: Greeter: adding package [email protected] (7.1.3)
    -- Version: 7.1.3
    -- Build type: 
    -- CXX_STANDARD: 17
    -- Performing Test has_std_17_flag
    -- Performing Test has_std_17_flag - Success
    -- Performing Test has_std_1z_flag
    -- Performing Test has_std_1z_flag - Success
    -- Performing Test SUPPORTS_USER_DEFINED_LITERALS
    -- Performing Test SUPPORTS_USER_DEFINED_LITERALS - Success
    -- Performing Test FMT_HAS_VARIANT
    -- Performing Test FMT_HAS_VARIANT - Success
    -- Required features: cxx_variadic_templates
    -- Performing Test HAS_NULLPTR_WARNING
    -- Performing Test HAS_NULLPTR_WARNING - Success
    -- Looking for strtod_l
    -- Looking for strtod_l - found
    -- Configuring done
    CMake Error: install(EXPORT "GreeterTargets" ...) includes target "Greeter" which requires target "fmt-header-only" that is not in any export set.
    -- Generating done
    CMake Generate step failed.  Build files cannot be regenerated correctly.
    Claus-iMac:ModernCppStarter clausklein$ 
    
  • Starter with CLion

    Starter with CLion

    I would like to use this starter with Clion (from jetbrains).

    I can't find out how to setup all. In FAQ you said that is possible to make folder for example 'All' with single build (standalone/tests). Can you make a little sample?

  • Documentation build failure due to empty MCSS_SOURCE_DIR

    Documentation build failure due to empty MCSS_SOURCE_DIR

    On 4212173c2fed1703f1e68a7585c074fa55578be0 when I follow the directions for building the documentation, I get the following:

    [I] [email protected] ~/r/ModernCppStarter (master)> cmake -Hdocumentation -Bbuild/doc
    -- The C compiler identification is GNU 10.2.0
    -- The CXX compiler identification is GNU 10.2.0
    -- Detecting C compiler ABI info
    -- Detecting C compiler ABI info - done
    -- Check for working C compiler: /usr/bin/cc - skipped
    -- Detecting C compile features
    -- Detecting C compile features - done
    -- Detecting CXX compiler ABI info
    -- Detecting CXX compiler ABI info - done
    -- Check for working CXX compiler: /usr/bin/c++ - skipped
    -- Detecting CXX compile features
    -- Detecting CXX compile features - done
    -- Downloading CPM.cmake to /home/luke/repos/ModernCppStarter/build/doc/cmake/CPM_0.31.1.cmake
    -- CPM: adding package [email protected] (42d4a9a48f31f5df6e246c948403b54b50574a2a)
    -- CPM: adding package [email protected] (/home/luke/repos/ModernCppStarter/documentation/..)
    -- CPM: Greeter: adding package [email protected] (v1.4.1)
    -- CPM: Greeter: adding package [email protected] (7.1.3)
    -- Version: 7.1.3
    -- Build type: 
    -- CXX_STANDARD: 11
    -- Performing Test has_std_11_flag
    -- Performing Test has_std_11_flag - Success
    -- Performing Test has_std_0x_flag
    -- Performing Test has_std_0x_flag - Success
    -- Performing Test SUPPORTS_USER_DEFINED_LITERALS
    -- Performing Test SUPPORTS_USER_DEFINED_LITERALS - Success
    -- Performing Test FMT_HAS_VARIANT
    -- Performing Test FMT_HAS_VARIANT - Success
    -- Required features: cxx_variadic_templates
    -- Looking for strtod_l
    -- Looking for strtod_l - not found
    -- Configuring done
    -- Generating done
    -- Build files have been written to: /home/luke/repos/ModernCppStarter/build/doc
    
    [I] [email protected] ~/r/ModernCppStarter (master)> cmake --build build/doc --target GenerateDocs
    [0/2] Re-checking globbed directories...
    [1/1] cd /home/luke/repos/ModernCppStarter/build/doc && /usr/bin/cmake -E make_directory /home/luke/repos/Moder...ernCppStarter/build/doc/conf.py && echo Docs\ written\ to:\ /home/luke/repos/ModernCppStarter/build/doc/doxygen
    FAILED: CMakeFiles/GenerateDocs 
    cd /home/luke/repos/ModernCppStarter/build/doc && /usr/bin/cmake -E make_directory /home/luke/repos/ModernCppStarter/build/doc/doxygen && /documentation/doxygen.py /home/luke/repos/ModernCppStarter/build/doc/conf.py && echo Docs\ written\ to:\ /home/luke/repos/ModernCppStarter/build/doc/doxygen
    /bin/sh: line 1: /documentation/doxygen.py: No such file or directory
    ninja: build stopped: subcommand failed.
    

    I have Doxygen, jinja2, and pygments installed:

    [I] [email protected] ~/r/ModernCppStarter (master)> doxygen --version
    1.9.1
                                                                                                                                                                                                          [ 0s008 | Mar 20 09:45AM ]
    [I] [email protected] ~/r/ModernCppStarter (master)> python -c "import jinja2; print(jinja2.__version__)"
    2.11.3
                                                                                                                                                                                                          [ 0s073 | Mar 20 09:45AM ]
    [I] [email protected] ~/r/ModernCppStarter (master)> python -c "import pygments; print(pygments.__version__)"                                                                                                                           
    2.8.1                                                                                                                                                                                                                            
                                                                                                                                                                                                          [ 0s023 | Mar 20 09:45AM ] 
    [I] [email protected] ~/r/ModernCppStarter (master)> python --version                                                                                                                                                                   
    Python 3.9.2                                    
    

    For some reason, the MCSS_SOURCE_DIR is empty and is causing the command of the GenerateDocs custom command to be just /documentation/doxygen.py.

  • add docker multistage build

    add docker multistage build

    When playing around with docker in another project, I wanted to to see what some best practices for using C++ and docker might look like and checked out this repo. Unfortunately, #63 seems to have died quite some time ago.

    This is more a discussion starter than a complete PR, but comes with my naive approach on how a multi-stage docker build could look like - assuming the greeter standalone executable would be our 'web-application' or 'server'.

    Some remarks.

    • I placed the dockerfile in subdirectory and explicitly typed out, which files to copy in the docker image. This helps to keep the root directory clean. However, I feel that having the Dockerfile in the root directory (along with a .dockerignore file) and justing using COPY . . would be more straight forward.
    • I used ubuntu:20.04 because it's a nice compromise between ease of use and size (assuming we want to deploy an actual application). Something like gcc:11.2 would be easier to set up but a lot heavier (78mb vs 1.1gb)
    • I am not sure, what would be the best way (and place) to run the tests in docker. We could run them on the builder image itself or make a different image (as used here). Running the tests with docker itself also feels somewhat redundant because we basically do the same in the GitHub CI actions. But then again, if it was some tiny trimmed-for-size docker image, tests on that platform might be essential.

    Feedback is greatly appreciated

  • Include errors

    Include errors

    I tried to add multiple libraries to this template project, but all my library includes seem to be failing (eg: #include <SDL.h> ). I am not sure if I did something wrong. Could you take a look for me? The other problem I had when I tried to use spdlog with the

    "SPDLOG_FMT_EXTERNAL YES"

    option, the spdlog was not able to find fmt which was downloaded by CPMAddPackage already. Here is my CMakeList.txt:

    cmake_minimum_required(VERSION 3.14 FATAL_ERROR)
    
    # ---- Project ----
    
    # Note: update this to your new project's name and version
    project(
      ArcaneLords
      VERSION 0.1
      LANGUAGES CXX
    )
    
    
    set(OpenGL_GL_PREFERENCE "GLVND")
    
    
    # ---- Include guards ----
    
    if(PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR)
      message(
        FATAL_ERROR
          "In-source builds not allowed. Please make a new directory (called a build directory) and run CMake from there."
      )
    endif()
    
    # ---- Add dependencies via CPM ----
    # see https://github.com/TheLartians/CPM.cmake for more info
    
    include(cmake/CPM.cmake)
    
    # PackageProject.cmake will be used to make our target installable
    CPMAddPackage("gh:TheLartians/[email protected]")
    
    CPMAddPackage(
      NAME fmt
      GIT_TAG 7.1.3
      GITHUB_REPOSITORY fmtlib/fmt
      OPTIONS "FMT_INSTALL YES" # create an installable target
    )
    CPMAddPackage(
      NAME SDL2
      VERSION 2.0.12
      URL https://libsdl.org/release/SDL2-2.0.16.zip
    )
    CPMAddPackage(
      NAME glm
      GITHUB_REPOSITORY g-truc/glm
      OPTIONS "GLM_STATIC_LIBRARY_ENABLE"
      GIT_TAG 0.9.9.8
    )
    
    CPMAddPackage(
      NAME spdlog
      GITHUB_REPOSITORY gabime/spdlog
      OPTIONS "SPDLOG_INSTALL YES"
      GIT_TAG v1.9.2
    )
    
    # GLFW
    CPMAddPackage(
      NAME glfw
      GITHUB_REPOSITORY glfw/glfw
      GIT_TAG 3.3.2
      OPTIONS
    	"GLFW_BUILD_TESTS Off"
    	"GLFW_BUILD_EXAMPLES Off"
    	"GLFW_BUILD_DOCS Off"
        "GLFW_INSTALL Off"
        "GLFW_USE_HYBRID_HPG On"
    )
    
    # ---- Add source files ----
    
    # Note: globbing sources is considered bad practice as CMake's generators may not detect new files
    # automatically. Keep that in mind when changing files, or explicitly mention them here.
    file(GLOB_RECURSE headers CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/include/*.h")
    file(GLOB_RECURSE sources CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/source/*.cpp")
    
    # ---- Create library ----
    
    # Note: for header-only libraries change all PUBLIC flags to INTERFACE and create an interface
    # target: add_library(ArcaneLords INTERFACE)
    add_library(ArcaneLords ${headers} ${sources})
    
    set_target_properties(ArcaneLords PROPERTIES CXX_STANDARD 17)
    
    # being a cross-platform target, we enforce standards conformance on MSVC
    target_compile_options(ArcaneLords PUBLIC "$<$<COMPILE_LANG_AND_ID:CXX,MSVC>:/permissive->")
    
    # Link dependencies
    target_link_libraries(ArcaneLords PRIVATE ${SDL2_LIBRARIES} ${GLEW_LIBRARIES} fmt::fmt OpenGL32 spdlog::spdlog)
    
    target_include_directories(
        ArcaneLords PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
                     $<INSTALL_INTERFACE:include/${PROJECT_NAME}-${PROJECT_VERSION}>
    )
    
    # ---- Create an installable target ----
    # this allows users to install and find the library via `find_package()`.
    
    # the location where the project's version header will be placed should match the project's regular
    # header paths
    string(TOLOWER ${PROJECT_NAME}}/version.h VERSION_HEADER_LOCATION)
    
    packageProject(
      NAME ${PROJECT_NAME}
      VERSION ${PROJECT_VERSION}
      NAMESPACE ${PROJECT_NAME}
      BINARY_DIR ${PROJECT_BINARY_DIR}
      INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include
      INCLUDE_DESTINATION include/${PROJECT_NAME}-${PROJECT_VERSION}
      VERSION_HEADER "${PROJECT_NAME}version.h"
      EXPORT_HEADER "${PROJECT_NAME}/source/export.h"
      COMPATIBILITY SameMajorVersion
      DEPENDENCIES "fmt 7.1.3"; "SDL2"; "glm"; "spdlog"
    )
    
  • Add cross-platform builder in github action

    Add cross-platform builder in github action

    Cross-platform builder in github action:

    • Dockcross : https://github.com/dockcross/dockcross
    • Support over 10 CPU architectures (x86, x86_64, ARMv5, ARMv6, ARMv7, ARMv8, RISCV32, RISCV64...)
    • Support 4 compilers (Clang, GCC and TinyCC, Emscripten...)
    • Support 3 OS (Linux, Android, Windows) and WebAssembly
    • Add dockcross + CMake (and Ninja) scripts
    • Complete support C++17 and partial C++20 (GCC 11 and LLVG/Clang 12)
    • CMake 3.21
  • `cmake --build build/docs --target GenerateDocs` not working

    `cmake --build build/docs --target GenerateDocs` not working

    Happens on both Ubuntu WSL and Windows:

    cmake --build build/docs --target GenerateDocs
    [0/2] Re-checking globbed directories...
    [1/1] cd /mnt/c/Users/u26i76/Projects/ModernCppStarterOrig...26i76/Projects/ModernCppStarterOriginal/build/docs/doxygen
    FAILED: CMakeFiles/GenerateDocs
    cd .../build/docs && /usr/bin/cmake -E make_directory .../build/docs/doxygen && .../.cache/CPM/m.css/ce3daea984872362c3a8ed1c3d8956adbc400a88/documentation/doxygen.py .../build/docs/conf.py && echo Docs\ written\ to:\ .../build/docs/doxygen
    Warning: libgs not found
    Traceback (most recent call last):
      File ".../.cache/CPM/m.css/ce3daea984872362c3a8ed1c3d8956adbc400a88/documentation/doxygen.py", line 3857, in <module>
        subprocess.run(["doxygen", doxyfile], cwd=os.path.dirname(doxyfile), check=True)
      File "/usr/lib/python3.8/subprocess.py", line 489, in run
        with Popen(*popenargs, **kwargs) as process:
      File "/usr/lib/python3.8/subprocess.py", line 854, in __init__
        self._execute_child(args, executable, preexec_fn, close_fds,
      File "/usr/lib/python3.8/subprocess.py", line 1702, in _execute_child
        raise child_exception_type(errno_num, err_msg, err_filename)
    FileNotFoundError: [Errno 2] No such file or directory: 'doxygen'
    ninja: build stopped: subcommand failed.
    
  • Use `code-coverage.cmake` from `cmake-scripts`

    Use `code-coverage.cmake` from `cmake-scripts`

    Currently, the template just applies -fprofile-arcs -ftest-coverage to the Greeter target from test. As far as I could tell, it doesn't really generate the code coverage data locally, and I think it'd be useful to be able to do that.

    The code-coverage.cmake script exposes targets that we can run if we want to generate the data locally too. It also does checks that the current ModernCppStarter solution doesn't.

A template CMake project to get you started with C++ and tooling
A template CMake project to get you started with C++ and tooling

cpp_starter_project Getting Started Use the Github template First, click the green Use this template button near the top of this page. This will take

Aug 11, 2022
Blitz++ is a C++ template class library which provides array objects for scientific computing

Blitz++ is a C++ template class library which provides array objects for scientific computing

Nov 22, 2020
A template for modern C++ projects using CMake, Clang-Format, CI, unit testing and more, with support for downstream inclusion.

Modern C++ Template A quick C++ template for modern CMake projects, aimed to be an easy to use starting point. This is my personal take on such a type

Aug 11, 2022
๐Ÿ“ฆ CMake's missing package manager. A small CMake script for setup-free, cross-platform, reproducible dependency management.
๐Ÿ“ฆ CMake's missing package manager. A small CMake script for setup-free, cross-platform, reproducible dependency management.

Setup-free CMake dependency management CPM.cmake is a CMake script that adds dependency management capabilities to CMake. It's built as a thin wrapper

Aug 8, 2022
๐Ÿ“ฆ CMake's missing package manager. A small CMake script for setup-free, cross-platform, reproducible dependency management.
๐Ÿ“ฆ CMake's missing package manager. A small CMake script for setup-free, cross-platform, reproducible dependency management.

Setup-free CMake dependency management CPM.cmake is a CMake script that adds dependency management capabilities to CMake. It's built as a thin wrapper

Aug 7, 2022
CMake module to enable code coverage easily and generate coverage reports with CMake targets.

CMake-codecov CMake module to enable code coverage easily and generate coverage reports with CMake targets. Include into your project To use Findcodec

Jul 3, 2022
Standardise code formating for cmake projects with git and clang-format

git-cmake-format This project aims to provide a quick and easy way to integrate clang-format into your CMake project hosted in a git repository, it co

Apr 14, 2022
Boiler plate template for C++ projects, with CMake, Doctest, Travis CI, Appveyor, Github Actions and coverage reports.
Boiler plate template for C++ projects, with CMake, Doctest, Travis CI, Appveyor, Github Actions and coverage reports.

Boiler plate for C++ projects This is a boiler plate for C++ projects. What you get: Sources, headers and mains separated in distinct folders Use of m

Aug 10, 2022
Non-intrusive CMake dependency management

cmodule Non-intrusive CMake dependency management. Normally CMake's find_package() looks for packages installed on host system (and compiled for host

Jun 16, 2022
Source code for the data dependency part of Jan Kossmann's PhD thesis "Unsupervised Database Optimization: Efficient Index Selection & Data Dependency-driven Query Optimization"

Unsupervised Database Optimization: Data Dependency-Driven Query Optimization Source code for the experiments presented in Chapter 8 of Jan Kossmann's

Apr 24, 2022
Open-source node system framework, to change your algorithmic code into useful tools to create much more complicated simulations!
Open-source node system framework, to change your algorithmic code into useful tools to create much more complicated simulations!

Open-source node system framework, to change your algorithmic code into useful tools to create much more complicated simulations!

Aug 10, 2022
ChowKick is a kick drum synthesizer plugin based on creative modelling of old-school drum machine circuits
ChowKick is a kick drum synthesizer plugin based on creative modelling of old-school drum machine circuits

ChowKick is a kick drum synthesizer plugin based on creative modelling of old-school drum machine circuits. MIDI input to the plugin triggers a pulse with a parameterized size and shape. The pulse is then passed into a resonant filter which can be tuned to a specific frequency, or matched to the frequency of the incoming MIDI notes.

Aug 6, 2022
Gaming meets modern C++ - a fast and reliable entity component system (ECS) and much more
Gaming meets modern C++ - a fast and reliable entity component system (ECS) and much more

EnTT is a header-only, tiny and easy to use library for game programming and much more written in modern C++. Among others, it's used in Minecraft by

Aug 9, 2022
Gaming meets modern C++ - a fast and reliable entity component system (ECS) and much more
Gaming meets modern C++ - a fast and reliable entity component system (ECS) and much more

EnTT is a header-only, tiny and easy to use library for game programming and much more written in modern C++. Among others, it's used in Minecraft by

Aug 16, 2022
Gaming meets modern C++ - a fast and reliable entity-component system (ECS) and much more
Gaming meets modern C++ - a fast and reliable entity-component system (ECS) and much more

EnTT is a header-only, tiny and easy to use entity-component system (and much more) written in modern C++. Among others, it's also used in Minecraft by Mojang and The Forge by Confetti.

Feb 16, 2021
This template provides a base structure to start developing a small raylib game in plain C
This template provides a base structure to start developing a small raylib game in plain C

This template provides a base structure to start developing a small raylib game in plain C. The repo is also pre-configured with a default LICENSE (zlib/libpng) and a README.md (this one) to be properly filled by users.

Aug 3, 2022
Just getting started with Data Structure and Algorithms? Make your first contribution here and start the journey of learning DSA.

Getting Started ! โœจ If you are just beginning with open source then let's make your first contribution in this repository ! Contributing Tutorial ?? P

Apr 18, 2022
OpenGL Template Engine - a C++ OpenGL graphics engine which aimed to be a simple startup template for 3D OpenGL projects.
OpenGL Template Engine - a C++ OpenGL graphics engine which aimed to be a simple startup template for 3D OpenGL projects.

OpenGL Template Engine is a C++ OpenGL graphics engine which aimed to be a simple startup template for 3D OpenGL projects. This is the template I personally use for my own projects and provides me with the general OpenGL 3D render setup with model import and UI.

May 16, 2022
A minimal CMake template for Qt 5 & 6 projects

Minimal CMake Template for Qt 6 Projects This project is updated for Qt 6. Visit qt5 branch if you are looking for the Qt 5 template. This is a minima

May 30, 2022