C++ development setup in 2024

By Danny van Kooten on on Permalink.

I've been doing a lot of C and C++ programming lately. After trying a myriad of editors and related tooling, it seems I've finally settled on a satisfactory set-up that is both performant, reliable and powerful.

This post is mostly me praising a set of tools but also showcasing some of their capabilities.

Editor: Sublime Text

The two most popular options right now are probably VSCode and CLion, yet I found neither of them performant or reliable enough for my taste. Instead, I am using good ol' Sublime Text 4 in combination with their Language Server Protocol implementation and Clangd.

Sublime Text Editor in dark mode with Clangd as language server

Why Sublime, you ask?

The slight bummer is that it's not open source. Still, I really like how a small team from Australia can sit down and build a small but profitable business around a code editor.

The community for plugins is not as vibrant or active as it once was, but for me personally, everything I need is there.

Configuring Clangd

While Clangd works with Sublime Text through LSP-clangd out of the box, we do want to configure a thing or two.

First, enable background indexing explicitly.

  1. Go to Preferences > Package Settings > LSP > Servers > clangd
  2. Ensure initializationOptions["clangd"]["background-index"] is set to true:
    // Settings in here override those in "LSP-clangd/LSP-clangd.sublime-settings"
    {
      "initializationOptions": {
        "clangd.background-index": true,
      }
    }
    

To let Clangd know how to build your project, there exist several methods:

Compiler (flags)

As my workstation is running Debian, I tend to compile the C and C++ projects that I work on using whatever version of GCC and Clang is in the official package repositories.

Currently, this means gcc 12 and clang 14, both of which have near complete support for -std=c++20 1 2.

When a newer compiler is needed, there's always building GCC from source or LLVM's APT repositories.

Both GCC and Clang are conservative with warnings, so we should enable (some of) them explicitly. The group of warnings from -Wall and -Wextra is what I always enable as a baseline 3 4.

In terms of compilation profiles, I tend to use just three:

Development

Development mode cares mostly about fast compilation times. The LDFLAGS environment value is set to instruct our compiler to use mold for the linking stage, which is usually an order of magnitude faster than ld.

CFLAGS="-std=c11 -Wall -Wextra -Wvla -Wformat -Wformat=2 -Wconversion"
CXXFLAGS="-std=c++20 -Wall -Wextra"
LDFLAGS="-fuse-ld=mold"

Debug

In debug mode we want debug symbols, stack traces and runtime checks from both Address Sanitizer and Undefined Behavior Sanitizer.

CFLAGS="-g -fsanitize=address,undefined -fno-omit-frame-pointer"
CXXFLAGS="-g -fsanitize=address,undefined -D_GLIBCXX_ASSERTIONS -fno-omit-frame-pointer"
ASAN_OPTIONS="strict_string_checks=1:strict_memcmp=1:quarantine_size_mb=512:detect_stack_use_after_return=1:check_initialization_order=1"
UBSAN_OPTIONS="print_stacktrace=1"

-D_GLIBCXX_ASSERTIONS adds run-time bound checks for C++ containers from the STL. There is also -D_FORTIFY_SOURCE=2 which adds run-time buffer overflow detection for a collection of functions from the glibc, but it requires an optimization level of 1 or higher (-O1).

ASAN_OPTIONS is used to configure Address Sanitizer to allow it to use more memory for detecting use-after-free errors and perform some of its stricter checks which are disabled by default.

UBSAN_OPTIONS is used alongside -fno-omit-frame-pointer to configure Undefined Behavior Sanitizer to print a symbolized strack trace for each error report.

Release

In release mode we want the compiler to produce the fastest code possible at the cost of longer compilation times.

CFLAGS="-O3"
CXXFLAGS="-O3"

If you don't care about portability and want to target your specific CPU, you could add -march=native and -mtune=native.

Diagnostics: clang-tidy

Since we are using Clangd as our Language Server, we can instruct it to emit all sorts of diagnostics (besides just compiler warnings) through clang-tidy.

clang-tidy diagnostics in Sublime Text

clang-tidy is disabled by default, but we can enable it by modifying the settings for the LSP-clangd plugin.

  1. Go to Preferences > Package Settings > LSP > Servers > Clangd.
  2. Ensure initialiationOptions.clangd["clang-tidy"] is set to true:
    // Settings in here override those in "LSP-clangd/LSP-clangd.sublime-settings"
    {
      "initializationOptions": {
        "clangd.clang-tidy": true,
        "clangd.background-index": true,
        "clangd.header-insertion": "iwyu",
        "clangd.completion-style": "detailed",
      }
    }
    
  3. You can configure clang-tidy by creating a .clangd YAML file In your project root. In it, you can add or remove the clang-tidy checks you want. I mostly stick to the ones from performance-* and cppcoreguidelines-*.
    Diagnostics:
      ClangTidy:
        Add:
        	- performance-*
        	- cppcoreguidelines-*
        Remove:
        	- cppcoreguidelines-avoid-magic-numbers
    

The LLVM suite also contains a run-clang-tidy command which you can use to run a single check against your source directory:

run-clang-tidy -checks='-*,performance-unnecessary-value-param' src/

Formatter: clang-format

We can use clang-format through Sublime's LSP-clangd plugin.

Go to Preferences > Package Settings > LSP > Settings and ensure lsp_format_on_save is set to true.

Your code style can be configured through a .clang-format YAML file in your project root.

Profiling: perf

To find performance bottlenecks, I've not come across anything that beats perf + flamegraph.pl.

The author of the latter tool has a great post on his blog with many language specific tips on how to best create flamegraphs from a perf report.


  1. https://gcc.gnu.org/projects/cxx-status.html#cxx20 ↩︎

  2. https://clang.llvm.org/cxx_status.html ↩︎

  3. https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html ↩︎

  4. https://clang.llvm.org/docs/DiagnosticsReference.html#w-warnings ↩︎


Comments are welcome. You can email me at hi @ this domain.