Title: ferdiOS C++ Coding Standard Date: 2026-07-24 Author: Viktor “Vik” Bugov Section: Technology Summary: A public service announcement Navigation: true ## Foreword C++ is the worst programming language of all time ([proof](https://www.youtube.com/watch?v=7fGB-hjc2Gc)), and that is a good thing™, however please follow this document to keep things manageable. In general, ferdiOS prefers simple, readable code over complex but faster code. Typically, you should not worry about if something is heap, or stack allocated, move semantics. We are software developers, not computer scientists. > An idiot admires complexity, a genius admires simplicity. > > - Terry A. Davis, Game Developer ## Terminology - MUST - hard requirement - SHOULD - recommendation ### Coding style The software MUST have the following [.clang-format](/assets/.clang-format) file in the root of the project. The software MUST use space indentation, either 2 or 4 spaces. Kindly refrain from whatever this is: ```cpp // wrong int some_test = 5; bool foo = true; std::string = "bar"; // good int some_test = 5; bool foo = true; std::string = "bar"; ``` The software MUST use snake case. ```cpp // wrong void doSomething() { // good void do_something() { ``` The software MUST use an opening curly brace on the same line as the function statement. ```cpp // wrong void test() { // good void test() { ``` As mentioned, refer to [.clang-format](/assets/.clang-format). ### Project layout The software MUST place source/header files under `src/`, except `main.cpp` which SHOULD be in either the root directory OR in e.g. `src/`. If present, directory `thirdparty` SHOULD be placed in the root directory. The software MUST NOT place header files in a separate directory, e.g. `include/`. Such a public interface shall be properly defined in CMake, thus CMake will know how to install the headers correctly. ### CMake The software MUST use CMake. > Rational: While we also like Meson, or Scons, it is best if the ferdiOS > ecosystem only uses one build system across the board. CMake is an industry standard. The software MUST place `CMakeLists.txt` in the root directory. The software MUST enforce a minimum version in `CMakeLists.txt` via `cmake_minimum_required(VERSION 3.18)`. The software SHOULD use `target_include_directories()` over `include_directories`. In other words, the software SHOULD explicitly use `target_*` - also referred as 'modern CMake'. The software MUST use ccache to speed up (re)compilation. ```cmake find_program(CCACHE_PROGRAM ccache) if(CCACHE_PROGRAM) set(CMAKE_C_COMPILER_LAUNCHER "${CCACHE_PROGRAM}") set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_PROGRAM}") endif() ``` The software SHOULD consider NOT creating multiple `CMakeLists.txt`, instead have one large `CMakeLists.txt` that covers the whole project. The software MUST place CMake related files under `cmake/`, activated by `list(INSERT CMAKE_MODULE_PATH 0 "${CMAKE_SOURCE_DIR}/cmake")` set at the top of the `CMakeLists.txt`. The software MUST define a project with a version ```cmake project(EXAMPLE VERSION 0.9.0 LANGUAGES CXX) ``` ### Templates The software SHOULD NOT define templates, unless absolutely necessary. The sofware SHOULD NOT define aliases for language keywords. > Rational: readability disaster, compilation time disaster, complexity disaster. ### Macros The software SHOULD NOT define macros, unless absolutely necessary. ### Auto The software MUST use `auto` wherever possible. > Rational: An IDE typically provides additional information about the underlying type. ### Const The software MUST use `const` wherever possible. ### Filenames The software MUST use C++ header files that are suffixed with `.h`. Not `.hh`, or `.hpp`. The software MUST use C++ source files that are suffixed with `.cpp`. not `.cxx` or `.cc`, or `.c++`. ### Classes The software SHOULD mark base classes as final. The software MUST prefix private member variables with `m_` OR suffix them with `_`. ### Namespaces The software MUST use at least one namespace. The software MUST NOT define nested namespaces. > Rational: symbol lookup + scopes = possible headaches. The software MUST use the full namespace identifiers for external namespaces that are not under our control. ```cpp // bad using namespace std; string foo = "bar"; // good std::string foo = "bar"; ``` ### Pragma The software MUST use `#pragma once` instead of include guards in header files. > Rational: it is all too easy to copy and paste a header file to another header file, modify it to suit ones needs, and forget to change the name of the include guard. Once both are included, it takes you a while to track down the error, as the error messages aren't necessarily clear. ### Pointers The software SHOULD NOT use `new`, instead `std::make_shared` & friends. The software SHOULD pick the right smart pointer that is appropriate for the situation in question, however this is not enforced. Using smart pointers in general is already an improvement over raw pointers. ### Paths The software MUST NOT use `std::string` to represent a path, prefer `std::filesystem::path`, or file descriptor handles. ### Argparse The software MUST use `CLI11` for argument parsing, except for Qt apps where argument parsing is built-in. ### Linking and Vendoring The software SHOULD make an effort to vendor dependencies where possible. The software SHOULD place such vendored dependencies in a folder called `thirdparty`, or `external`. > Rational: vendoring dependencies makes software easier to compile, as well as produce binaries > that do not depend on a certain system state The software MUST NOT link against, or vendor a library if it creates a license conflict. The software SHOULD link against static libraries where possible. The software SHOULD NOT statically link against the following 'foundational' libraries: Qt, openssl, libsodium, (and more). The software MUST NOT link against the following libraries: - Boost - GTK ### Dbus The software SHOULD not use DBus, unless absolute necessary. The software SHOULD use fbus instead. ### Git The software MUST use semantic versioning. > Example: `0.0.1` The repository MUST use git tags that follow this same semantic versioning for releases. > Example: `0.0.1`, not `v0.0.1` The repository MUST NOT use git submodules. > Rational: Git submodules suffer from poor UX, and quirks. The repository MUST use the `master` branch as primary. > Example: not `main` The commit message MUST NOT contain emojis. > Rational: We are not the Javascript community The repository `README.md` SHOULD NOT contain emojis. > Rational: We are not the PHP community ### Precompiled headers The software SHOULD use precompiled headers when compilation times are get out of hand. The software MUST not include headers whose symbols are not used in subsequent code (unused headers). ### Code editor We suggest CLion as an IDE for ferdiOS C++ programming. It integrates nicely with CMake, supports remote debugging, and has various other useful features. CLion is free under non-commercial use.