how I try to make C++ more managable

2023-09-01 - 3 minutes to read

When I started to make Project Diggy , I thought long and hard about what tools to use to create it. I went back and forth between Rust, Godot and C++.

C++ is currently the language I am most familiar and comfortable, as I've used it almost every day for the last 5 years, so that is what I ended up with in the end.

That doesn't mean that it's nice to use, so while I'm desperately learning Rust and Zig, and hoping that the libraries I need get ported to those languages, I'm trying to make my time with C++ as managable as possible.

To do this I have some key things set up.

cmake

Like it or not, CMake is currently the default choice for setting up your C++ project. I like that it has the most support, so that's what I went with.

I do have some special things set up to make things a little nicer though.

template

Modern CPP Starter is a great template for getting things set up. It was a great starter for changing things by myself later.

cpm

One of the coolest things that I saw in CPP starter was CPM, a wrapper for FetchContent, which is basically a package manager built into CMake. This turned package management from the worst thing about C/C++ into something I barely have to think about. For some libraries you have to input some manual stuff, but most of the time you just link the git repo, and it handles everything automagically.

Example (The current dependencies of Diggy):

CPMAddPackage("gh:raysan5/raylib#4.5.0")
CPMAddPackage("gh:catchorg/Catch2#v3.4.0")
CPMAddPackage("gh:fraillt/bitsery#v5.2.3")
CPMAddPackage(
  NAME EnTT
  VERSION 3.12.2
  GITHUB_REPOSITORY skypjack/entt
  # EnTT's CMakeLists screws with configuration options
  DOWNLOAD_ONLY True
)

if(EnTT_ADDED)
  add_library(EnTT INTERFACE)
  target_include_directories(EnTT SYSTEM INTERFACE ${EnTT_SOURCE_DIR}/src)
endif()

CPMAddPackage(
  NAME enet
  VERSION 1.3.17
  GIT_TAG 4f8e9bdc4ce6d1f61a6274b0e557065a38190952
  GITHUB_REPOSITORY lsalzman/enet
  DOWNLOAD_ONLY True
)

You just have to remember to link it to your project (with

target_link_libraries(${PROJECT_NAME} PRIVATE raylib)

), and you're ready to go!

clang-tidy && include-what-you-use

There are so many little things that are easy to forget when you are programming in C++, so these tools are like having a mini-rust nagging at you which is very helpful. I do think they can be a bit much when you just added them though, but that says more about me than the tools ^^

catch2

Last, and currently least is Catch2, the testing library I added. I haven't set up that many tests yet, but I have big plans.

the big plans

I want to set up some serious unit testing for my game, as I am planning on moving to Rust or Zig very soon, and there I will have to port or remake some of the libraries I'm currently using. The biggest one being bitsery, a cool serialization library with support for bitpacking, a feature I haven't found yet in Rust or Zig.

So if I need to create these things myself I want to have good tests set up, so I can make sure that serializing and such works the way I expect them to.

I'll probably just follow Gaffer On Games guide, that I used https://github.com/Risgrynsgrot/NetworkLib a few years ago to try to implement similar things myself.

I also want to have a look at setting up some CI/CD with Jenkins, to get some cross-compilation up and running, and also running tests.