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

Overview

Project Status: Active – The project has reached a stable, usable state and is being actively developed. Build Status Build status Coverage Status codecov Codacy Badge Language grade: C/C++ Total alerts license Lines of Code Average time to resolve an issue Percentage of issues still open

Boiler plate for C++ projects

This is a boiler plate for C++ projects. What you get:

Demo of usage

Structure

.
├── CMakeLists.txt
├── app
│   └── main.cpp
├── include
│   ├── example.h
│   └── exampleConfig.h.in
├── src
│   └── example.cpp
└── tests
    ├── dummy.cpp
    └── main.cpp

Sources go in src/, header files in include/, main programs in app/, and tests go in tests/ (compiled to unit_tests by default).

If you add a new executable, say app/hello.cpp, you only need to add the following two lines to CMakeLists.txt:

add_executable(main app/main.cpp)   # Name of exec. and location of file.
target_link_libraries(main PRIVATE ${LIBRARY_NAME})  # Link the executable to lib built from src/*.cpp (if it uses it).

You can find the example source code that builds the main executable in app/main.cpp under the Build section in CMakeLists.txt. If the executable you made does not use the library in src/, then only the first line is needed.

Building

Build by making a build directory (i.e. build/), run cmake in that dir, and then use make to build the desired target.

Example:

> mkdir build && cd build
> cmake .. -DCMAKE_BUILD_TYPE=[Debug | Coverage | Release]
> make
> ./main
> make test      # Makes and runs the tests.
> make coverage  # Generate a coverage report.
> make doc       # Generate html documentation.

.gitignore

The .gitignore file is a copy of the Github C++.gitignore file, with the addition of ignoring the build directory (build/).

Services

If the repository is activated with Travis-CI, then unit tests will be built and executed on each commit. The same is true if the repository is activated with Appveyor.

If the repository is activated with Coveralls/Codecov, then deployment to Travis will also calculate code coverage and upload this to Coveralls.io and/or Codecov.io

Setup

Using the GitHub template

Click the Use this template button to make a new repository from this template.

From command line

When starting a new project, you probably don't want the history of this repository. To start fresh you can use the setup script as follows:

> git clone https://github.com/bsamseth/cpp-project  # Or use ssh-link if you like.
> cd cpp-project
> bash setup.sh

The result is a fresh Git repository with one commit adding all files from the boiler plate.

Comments
  • Typos in CMakeLists.txt

    Typos in CMakeLists.txt

    In CMakeLists.txt file, line 12 should be set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -g") instead of set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS} -Wall -g"), I found this out after I tried to debug main.cpp , breakpoints could not be set because flag -g was not set.

    Same with line 17, should be set(CMAKE_CXX_FLAGS "-Wall -O2")

    Also, after you pull googletest, all paths to googletest need one more segment googletest, For example {PROJECT_SOURCE_DIR}/external/googletest should become {PROJECT_SOURCE_DIR}/external/googletest/googletest and so on. Great boilerplate repo, very useful.

    opened by kabasakalis 5
  • cmake error on a clean build

    cmake error on a clean build

    Thx a lot for sharing the repo! I have been trying to find a repo template for cpp with support for CI and your repo is a great template for my project.

    However, I was unable to run cmake .. -DCMAKE_BUILD_TYPE=coverage after following the steps.

    The error is as follow

    -- The CXX compiler identification is GNU 7.5.0
    -- Check for working CXX compiler: /usr/bin/c++
    -- Check for working CXX compiler: /usr/bin/c++ -- works
    -- Detecting CXX compiler ABI info
    -- Detecting CXX compiler ABI info - done
    -- Detecting CXX compile features
    -- Detecting CXX compile features - done-- Found Doxygen: /usr/bin/doxygen (found version "1.8.13") found components:  doxygen dot 
    -- IPO is supported
    CMake Error at CMakeLists.txt:58 (target_link_libraries):
      Object library target "example" may not link to anything.
    
    
    -- Configuring incomplete, errors occurred!
    See also "/workspaces/PoissonDiscSampling/build/CMakeFiles/CMakeOutput.log".
    [email protected]:/workspaces/PoissonDiscSampling/build# mkdir build && cd build && cmake .. -DCMAKE_BUILD_TYPE=coverage^C
    [email protected]:/workspaces/PoissonDiscSampling/build# cd ../^C
    [email protected]:/workspaces/PoissonDiscSampling/build# rm -rf ./*
    [email protected]:/workspaces/PoissonDiscSampling/build# mkdir build && cd build && cmake .. -DCMAKE_BUILD_TYPE=coverage -DENABLE_DOCTESTS=OFF
    CMake Error: The source directory "/workspaces/PoissonDiscSampling/build" does not appear to contain CMakeLists.txt.
    Specify --help for usage, or press the help button on the CMake GUI.
    [email protected]:/workspaces/PoissonDiscSampling/build/build# cd ..
    [email protected]:/workspaces/PoissonDiscSampling/build# rm -rf ./*
    [email protected]:/workspaces/PoissonDiscSampling/build# cmake .. -DCMAKE_BUILD_TYPE=coverage -DENABLE_DOCTESTS=OFF
    -- The CXX compiler identification is GNU 7.5.0
    -- Check for working CXX compiler: /usr/bin/c++
    -- Check for working CXX compiler: /usr/bin/c++ -- works
    -- Detecting CXX compiler ABI info
    -- Detecting CXX compiler ABI info - done
    -- Detecting CXX compile features
    -- Detecting CXX compile features - done
    -- Found Doxygen: /usr/bin/doxygen (found version "1.8.13") found components:  doxygen dot 
    -- IPO is supported
    CMake Error at CMakeLists.txt:58 (target_link_libraries):
      Object library target "engine" may not link to anything.
    
    
    -- Configuring incomplete, errors occurred!
    

    Thought it might be related to the git submodule status, I try using git submodule add to manually add doctest but still no luck.

    code to reproduce (cmake version 3.10.2):

    git clone https://github.com/bsamseth/cpp-project.git
    cd cpp-project
    sh setup.sh
    mkdir build && cd build
    cmake .. -DCMAKE_BUILD_TYPE=coverage
    

    Github Action would also return failure during build step, see here

    opened by wyq977 4
  • add Page Views

    add Page Views

    When we add this service, it will count every hit of this repo. And this will guide us more about the visitors each day and will indicate the total views. For me, this is very helpful both for us and for those will view this repo seeing this page views. If there is the website built from this repo, it can be simply added there too.

    Screenshot (1642)

    opened by jdevstatic 3
  • Error: with linker (template class)

    Error: with linker (template class)

    i have this file in include/abin.hpp

    #ifndef ABIN_VEC_HPP
    #define ABIN_VEC_HPP
    namespace Vectorial
    {
    
    const int NODO_NULO = -1;
    
    template <typename T>
    class Abin
    {
    public:
      typedef int nodo;
      explicit Abin(int max);
      Abin(const Abin<T> &a);
      Abin<T> &operator=(const Abin<T> &a);
      void insertarRaiz(const T &e);
      void eliminarRaiz();
      void insertarHijoIzquierdo(nodo n, const T &e);
      void insertarHijoDerecho(nodo n, const T &e);
      void eliminarHijoIzquierdo(nodo n);
      void eliminarHijoDerecho(nodo n);
      bool vacio() const { return size == 0; }
      const T &elemento(nodo n) const;
      T &elemento(nodo n);
      nodo raiz() { return (size > 0) ? 0 : NODO_NULO; }
      nodo padre(nodo n) const;
      nodo hijoIzquierdo(nodo n) const;
      nodo hijoDerecho(nodo n) const;
      ~Abin() { delete[] nodos; }
    
    private:
      int max_size;
      int size;
      class celda
      {
      public:
        T elemento;
        nodo padre, h_izq, h_dch;
        celda(const T &elto, nodo p = NODO_NULO, nodo h_d = NODO_NULO, nodo h_i = NODO_NULO) : elemento{elto}, padre{p}, h_izq{h_i}, h_dch{h_d} {}
        celda(const celda &) = default;
        celda &operator=(const celda &) = default;
      };
      celda *nodos;
    };
    } // namespace Vectorial
    #endif
    

    and this one in src/abin.cpp

    #include "abin.hpp"
    #include <algorithm>
    #include <cassert>
    template <typename T>
    Vectorial::Abin<T>::Abin(int max) : max_size{max}, size{0}, nodos{new celda[max]} {}
    
    template <typename T>
    Vectorial::Abin<T>::Abin(const Abin<T> &a) : nodos{new celda[a.max_size]}, max_size{a.max_size}, size{a.size}
    {
        std::copy(a.nodos, a.nodos + (a.size - 1), nodos);
    }
    
    template <typename T>
    void Vectorial::Abin<T>::insertarRaiz(const T &e)
    {
        assert(size == 0);
        nodos[size++] = celda(e);
    }
    
    template <typename T>
    void Vectorial::Abin<T>::insertarHijoIzquierdo(nodo n, const T &e)
    {
        assert(n >= 0 && n < size);
        assert(nodos[n].h_izq == NODO_NULO);
        assert(size < max_size);
        nodos[n].h_izq = size;
        nodos[size++] = celda(e, n);
    }
    
    template <typename T>
    void Vectorial::Abin<T>::insertarHijoDerecho(nodo n, const T &e)
    {
        assert(n >= 0 && n < size);
        assert(nodos[n].h_dch == NODO_NULO);
        assert(size < max_size);
        nodos[n].h_dch = size;
        nodos[size++] = celda(e, n);
    }
    
    template <typename T>
    void Vectorial::Abin<T>::eliminarHijoIzquierdo(nodo n)
    {
        auto h_izq = nodos[n].h_izq;
        assert(n >= 0 && n < size);
        assert(h_izq != NODO_NULO);
        assert(nodos[h_izq].h_izq == NODO_NULO &&
               nodos[h_izq].h_dch == NODO_NULO);
        if (h_izq != size - 1)
        {
            nodos[h_izq] = nodos[size - 1];
            if (nodos[nodos[h_izq].padre].h_izq == size - 1)
                nodos[nodos[h_izq].padre].h_izq = h_izq;
            else
                nodos[nodos[h_izq].padre].h_dch = h_izq;
            if (nodos[h_izq].h_izq != NODO_NULO)
                nodos[nodos[h_izq].h_izq].padre = h_izq;
            if (nodos[h_izq].h_dch != NODO_NULO)
                nodos[nodos[h_izq].h_dch].padre = h_izq;
        }
        nodos[h_izq] = NODO_NULO;
        --size;
    }
    
    template <typename T>
    void Vectorial::Abin<T>::eliminarHijoDerecho(nodo n)
    {
        auto h_dch = nodos[n].h_dch;
        assert(n >= 0 && n < size);
        assert(h_dch != NODO_NULO);
        assert(nodos[h_dch].h_dch == NODO_NULO &&
               nodos[h_dch].h_izq == NODO_NULO);
        if (h_dch != size - 1)
        {
            nodos[h_dch] = nodos[size - 1];
            if (nodos[nodos[h_dch].padre].h_dch == size - 1)
                nodos[nodos[h_dch].padre].h_dch = h_dch;
            else
                nodos[nodos[h_dch].padre].h_izq = h_dch;
            if (nodos[h_dch].h_izq != NODO_NULO)
                nodos[nodos[h_dch].h_izq].padre = h_dch;
            if (nodos[h_dch].h_dch != NODO_NULO)
                nodos[nodos[h_dch].h_dch].padre = h_dch;
        }
        nodos[h_dch] = NODO_NULO;
        --size;
    }
    
    template <typename T>
    inline void Vectorial::Abin<T>::eliminarRaiz()
    {
        assert(size == 1);
        size = 0;
    }
    
    template <typename T>
    inline const T &Vectorial::Abin<T>::elemento(nodo n) const
    {
        assert(n >= 0 && n < size);
        return nodos[n].elemento;
    }
    
    template <typename T>
    inline T &Vectorial::Abin<T>::elemento(nodo n)
    {
        assert(n >= 0 && n < size);
        return nodos[n].elemento;
    }
    
    template <typename T>
    inline typename Vectorial::Abin<T>::nodo Vectorial::Abin<T>::padre(nodo n) const
    {
        assert(n >= 0 && n < size);
        return nodos[n].padre;
    }
    
    template <typename T>
    inline typename Vectorial::Abin<T>::nodo Vectorial::Abin<T>::hijoIzquierdo(nodo n) const
    {
        assert(n >= 0 && n < size);
        return nodos[n].h_izq;
    }
    
    template <typename T>
    inline typename Vectorial::Abin<T>::nodo Vectorial::Abin<T>::hijoDerecho(nodo n) const
    {
        assert(n >= 0 && n < size);
        return nodos[n].h_dch;
    }
    
    template <typename T>
    Vectorial::Abin<T> &Vectorial::Abin<T>::operator=(const Abin<T> &a)
    {
        if (this != &a)
        {
            if (max_size < a.max_size)
            {
                delete[] nodos;
                max_size = a.max_size;
                nodos = new celda[max_size];
            }
            size = a.size;
            std::copy(a.nodos, a.nodos + (a.size - 1), nodos);
        }
        return *this;
    }
    

    When i call the constructor i getting this error:

    [build] FAILED: main.x 
    [build] : && /usr/bin/clang++  -Wall -Wextra -g -O0 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk -Wl,-search_paths_first -Wl,-headerpad_max_install_names  CMakeFiles/main.x.dir/app/main.cpp.o  -o main.x  libengine.a && :
    [build] Undefined symbols for architecture x86_64:
    [build]   "Vectorial::Abin<int>::Abin(int)", referenced from:
    [build]       _main in main.cpp.o
    [build] ld: symbol(s) not found for architecture x86_64
    [build] clang: error: linker command failed with exit code 1 (use -v to see invocation)
    [build] ninja: build stopped: subcommand failed.
    [build] Build finished with exit code 1
    

    and my app/main.cpp

    #include <iostream>
    #include "abin.hpp"
    using namespace Vectorial;
    int main()
    {
      Abin<int> A(2);
      std::cout << A.vacio() << std::endl;
    }
    
    opened by KROSF 3
  • Allow multiple configurations on Windows

    Allow multiple configurations on Windows

    The current CI workflow fails if one attempts to specify any configuration other than Debug on Windows. The reason is that windows configuration happens at build time, not cmake generation time, and different output folders are produced (e.g. build\Debug and build\Release). Since Debug is the default configuration, a debug build is always be produced and an example failure would be that of "a test workflow unable to find the release executables".

    Solution is to use the --config option on the build command, which works for linux and mac as well. The template could also provide both Debug and Release configurations in the strategy matrix by default, but that depends on the maintainer's intentions.

    source

    opened by picanumber 2
  • Use FetchContent and add googletest

    Use FetchContent and add googletest

    Use FetchContent to download doctest and googletest. Thus, remove submodules. https://bewagner.net/programming/2020/05/02/cmake-fetchcontent/

    Let user decide which testing framework to use

    opened by doruirimescu 2
  • fatal error: doctest.h: No such file or directory

    fatal error: doctest.h: No such file or directory

    Hi bsamseth,

    First of all, thank you for this boilerplate which gives me a good idea on how to organise folder and cmake, however i have an issue when following your steps, when running the command: make i get this error

    [ 16%] Building CXX object CMakeFiles/test.dir/src/example.cpp.o In file included from /home/tom/Projects/test/src/example.cpp:1: /home/tom/Projects/test/include/example.h:22:10: fatal error: doctest.h: No such file or directory 22 | #include "doctest.h" | ^~~~~~~~~~~ compilation terminated. make[2]: *** [CMakeFiles/test.dir/build.make:63: CMakeFiles/test.dir/src/example.cpp.o] Error 1 make[1]: *** [CMakeFiles/Makefile2:452: CMakeFiles/test.dir/all] Error 2 make: *** [Makefile:95: all] Error 2

    Any idea what is happening here?

    opened by ThomasP1988 2
  • Clarify the need to clone submodules before build

    Clarify the need to clone submodules before build

    Issue #21 highlights a potential issue, in that it is not made clear that you need to pull down the submodules before building. This updates the README to make this a little more clear.

    Also, seems the setup.sh script had a potential bug, where the syntax used is not supported by all versions of sh (double brackets [[). So the default executable is changed to bash, and for good measure the submodule stuff is done first, just in case.

    Closes #21.

    opened by bsamseth 2
  • CMake renovation & move to doctest

    CMake renovation & move to doctest

    • Move from Google Test to Doctest
      • I just like it better, feels more lightweight, with the possibility of adding in-source documentation
    • Substantially shrink the main CMakeLists.txt file
      • Moved stable (i.e. things that don't need editing) stuff out of there, and now make more use of helpful scripts
    opened by bsamseth 2
  • mvcc and icc support? Visual studio support

    mvcc and icc support? Visual studio support

    Hi!

    Very interesting and very helpful repository! Thank you for sharing it!

    Do you plan to add support for different compilers and examples of usage for Windows users?

    Thank you!

    help wanted need feedback 
    opened by GillianGrayson 2
  • Fix the code coverage failure in Mac OS #7

    Fix the code coverage failure in Mac OS #7

    The reason is that the default c++ compiler identification in MacOs is 'AppleClang'. So when checking the compiler name, replace 'Clang' with '.*Clang'.

    opened by HenryRLee 2
  • C++20 modules

    C++20 modules

    I'd like to have a parallel branch with a setup using C++20 modules instead of header files. At some later point, this would be merged to master.

    As I don't personally have experience with modules in C++ yet, this would be great to get help with as a pull request.

    help wanted 
    opened by bsamseth 0
Owner
Bendik Samseth
MSc Computational Physics and Data Scientist
Bendik Samseth
Tool that generates unit test by C/C++ source code, trying to reach all branches and maximize code coverage

What is UTBotCpp? UTBotCpp generates test cases by code, trying to cover maximum statements and execution paths. We treat source code as source of tru

null 52 Jan 8, 2023
Flexible and fast Z-shell plugin manager that will allow installing everything from GitHub and other sites.

ZINIT News Zinit Wiki Quick Start Install Automatic Installation (Recommended) Manual Installation Usage Introduction Plugins and snippets Upgrade Zin

z-shell 26 Nov 15, 2022
A small self-contained alternative to readline and libedit that supports UTF-8 and Windows and is BSD licensed.

Linenoise Next Generation A small, portable GNU readline replacement for Linux, Windows and MacOS which is capable of handling UTF-8 characters. Unlik

ArangoDB 340 Dec 6, 2022
A readline and libedit replacement that supports UTF-8, syntax highlighting, hints and Windows and is BSD licensed.

Read Evaluate Print Loop ++ A small, portable GNU readline replacement for Linux, Windows and MacOS which is capable of handling UTF-8 characters. Unl

Marcin Konarski 604 Jan 6, 2023
A simple header-only C++ argument parser library. Supposed to be flexible and powerful, and attempts to be compatible with the functionality of the Python standard argparse library (though not necessarily the API).

args Note that this library is essentially in maintenance mode. I haven't had the time to work on it or give it the love that it deserves. I'm not add

Taylor C. Richberger 1.1k Jan 4, 2023
CLI11 is a command line parser for C++11 and beyond that provides a rich feature set with a simple and intuitive interface.

CLI11: Command line parser for C++11 What's new • Documentation • API Reference CLI11 is a command line parser for C++11 and beyond that provides a ri

null 2.4k Dec 30, 2022
A (relatively) small node library to clone and pull git repositories in a standalone manner thanks to libgit2, powered by WebAssembly and Emscripten

simple-git-wasm A (relatively) small node library to clone and pull git repositories in a standalone manner thanks to libgit2, powered by WebAssembly

Powercord 21 Oct 16, 2022
A simple header-only C++ argument parser library. Supposed to be flexible and powerful, and attempts to be compatible with the functionality of the Python standard argparse library (though not necessarily the API).

args Note that this library is essentially in maintenance mode. I haven't had the time to work on it or give it the love that it deserves. I'm not add

Taylor C. Richberger 896 Aug 31, 2021
Yori is a CMD replacement shell that supports backquotes, job control, and improves tab completion, file matching, aliases, command history, and more.

Yori is a CMD replacement shell that supports backquotes, job control, and improves tab completion, file matching, aliases, command history, and more.

Malcolm Smith 1.1k Dec 30, 2022
Free open-source modern C++17 / C++20 framework to create console, forms (GUI like WinForms) and unit test applications on Microsoft Windows, Apple macOS and Linux.

xtd Modern C++17/20 framework to create console (CLI), forms (GUI like WinForms) and tunit (unit tests like Microsoft Unit Testing Framework) applicat

Gammasoft 434 Dec 30, 2022
2021 Fall Comp2012h Final Project. A Plant-Vs-Zombie style desktop game with beautiful graphics and sound effects. Developer: thomas914, mitester and tiliuau.

Underperforming Students vs Teachers Table of Contents Underperforming Students vs Teachers Table of Contents Authors Code Conventions Workflow Class

null 3 Apr 14, 2022
Google's common Java, C++ and JavaScript library for parsing, formatting, and validating international phone numbers.

What is it? Google's common Java, C++ and JavaScript library for parsing, formatting, and validating international phone numbers. The Java version is

Google 14.5k Dec 30, 2022
A CLI program that helps you find classes and plan pre-requisites. Written in C++ and Python.

CourseHelper A CLI program created to help you prepare for course registration. Note: At the moment, this project is built specifically for other UCLA

Kyle Chui 0 Dec 13, 2022
A simple to use, composable, command line parser for C++ 11 and beyond

Clara v1.1.5 !! This repository is unmaintained. Go here for a fork that is somewhat maintained. !! A simple to use, composable, command line parser f

Catch Org 648 Dec 27, 2022
A small self-contained alternative to readline and libedit

Linenoise A minimal, zero-config, BSD licensed, readline replacement used in Redis, MongoDB, and Android. Single and multi line editing mode with the

Salvatore Sanfilippo 3.1k Jan 2, 2023
A simple to use, composable, command line parser for C++ 11 and beyond

Lyra A simple to use, composing, header only, command line arguments parser for C++ 11 and beyond. Obtain License Standards Stats Tests License Distri

Build Frameworks Group 388 Dec 22, 2022
Terminal calculator made for programmers working with multiple number representations, sizes, and overall close to the bits

Programmer calculator The programmer calculator is a simple terminal tool designed to give maximum efficiency and flexibility to the programmer workin

romes 183 Dec 24, 2022
A single header C++ library for parsing command line arguments and options with minimal amount of code

Quick Arg Parser Tired of unwieldy tools like getopt or argp? Quick Arg Parser is a single header C++ library for parsing command line arguments

null 47 Dec 21, 2022
The new Windows Terminal and the original Windows console host, all in the same place!

The new Windows Terminal and the original Windows console host, all in the same place!

Microsoft 86.8k Dec 29, 2022