Introduction

The setup of a new C++ project typically involves several decisions and, consequently, a considerable amount of setup code to be written to get the first line executed.

  • C++ standard
  • Compiler toolchain
  • Package management
  • Build system
  • Test framework
  • Code coverage
  • Static code analysis
  • Sanitizers

Additionally, sharing of useful components with other developers and projects is harder compared to other languages" ecosystems due to the huge range of configuration possibilities.

The project cpp-dev (short: cpd) is an attempt to bridge the perceived gap to other languages by providing a tool to accomplish the goals mentioned above.

Design Principle: Simplicity-over-Configurability

The C++ ecosystem provides an large set of tools to support and execute the software engineering process. cpp-dev follows the design principle to limit the configurability (e.g. supported tool chain, package manager, pre-defined project setup, etc.) to achieve a simplistic, but effective and efficient development process.

cpp-dev is designed as a tool around the following external tools:

  • Package Management: Conan2
  • Build System: Ninja
  • Toolchain: LLVM-based (clang, clang-format, clang-coverage, clang-sanitizer, clang-tidy)
  • Test framework: gtest and gmock
  • Code coverage: lcov

INFO: cpd-dev will initially support only Ubuntu 24.04 (LTS) as operating system. Later, once the proof-of-concept phase is over, additional operating systems and distributions will be supported.

Not Yet-Another-Dependency-Manager

There have been a lot of good attempts in the community to create feature-rich package managers for C++ with Conan2 being one of the most prominent ones. cpp-dev does not and will not introduce another package manager, but use Conan2 as a fundamental building block. All packages consumed by and created by cpp-dev are proper Conan packages stored in a proper Conan remote (e.g. JFrog Artifactory). Therefore, all cpp-dev packages may also be used outside of cpp-dev as well, for example with plain CMake projects, when combined with Conan, of course.

Workflow

A workflow using cpp-dev could look like:

  • Initialize project: cpd init <new-project> [--std c++20] [--version <major.minor.patch>]
  • Add external dependency: cpd add-dep <dep>@<version>
  • Update external dependencies: cpd update-dep [<dep>@<version>]
  • Build: cpd build [release | debug]
  • Execute: cpd execute [release | debug]
  • Check: cpd check
  • Format: cpd format
  • Test: cpd test [--show-coverage]
  • Tests with compiler sanitiziers: cpd test-sanitize
  • Packaging (incl. uploading): cpd package
  • List Packages: cpd list-packages

Package Structure

Simplification by convention is a common principle in the software engineering community. cpp-dev therefore provides and expects a common package structure convention:

<root>
|_ cpp-dev.yaml
|_ src
   |_ executables
      |_ exec.cpp
   |_ <package-name>.cpp
   |_ <package-name>.test.cpp
|_ include
   |_ <package-name>
      |_ <package-name>.hpp

The source files listed in the src/executables folder are assumed to be stand-alone executables. Each of these file gets converted into a dedicated executable, e.g. exec.cpp would become the executable with name exec. All other C++ files outside of the executables folder are assumed to be library sources and get compiled into the library lib<package-name>. Each cpp-dev package supports only a single library per package.

Header-Only

Header-only packages only provide header files in the top-level include folder. Tests are then stored in the top-level src folder.

Configuration File

The cpp-dev configuration file has the following structure (currently re-worked):

name: <package-name>
author: <author>
version: 0.1.0
license: <software-license>

std: 20

dependencies:
   - name: boost
     channel: official
     version: 1.83.2