Setting up C++ (Without Visual Studio)
Tags: cpp, tutorial, devjournal
Published: 2023-10-08 04:33:41

Setting up the development for C++ (and C) is hard. Especially for beginners, even when you are coming from other languages.
I use windows, which can complicates things even further.

I could use Visual Studio, which would probably make my life easier, but I refuse to.

In this post I am going to share how I managed to finally create a development environment for C++ on windows which I am satisfied with.

# 1. Compiler
First we need a compiler that works on windows. Traditionally to do this, I used the mingw64 gcc tools. However setting up mingw can be rather complicated and confusing.

Since then, I've discovered clang. The clang compiler is actually a part of the llvm project. The good thing about clang is that it has windows binaries, which means I can basically install it directly without any of the mingw / msys nonsense.

I installed clang (and other llvm tools) through winget.
```shell
winget install -e --id LLVM.LLVM
```

Alternatively, you can get clang (and llvm) from their [github releases](https://github.com/llvm/llvm-project/releases) or website [here](https://releases.llvm.org) (which links to their github releases anyway) where you download the windows .exe installer.

Now you should verify that clang has been added to your path by running:
```shell
clang --version
```
If it gives some error like `clang is not recognized...`
It means that the llvm binaries (which includes clang) has not been added to your path.
So add the llvm installation which is normally at `C:\Program Files\LLVM\bin` to your path.

Now if we run `clang --version` again we should get an output like:
```output
clang version 17.0.1
Target: x86_64-pc-windows-msvc
Thread model: posix
InstalledDir: C:\Program Files\LLVM\bin
```
Congratulations, we now have a C++ compiler!
# Setting up CMake
Most projects use CMake to build the project.
As much as I want to avoid CMake, it is inevitable. You cannot runaway from it.
I will not go into much detail about how cmake works. I find this [website](https://cliutils.gitlab.io/modern-cmake/) is very useful for learning about CMake.

The website also tells you how you can install cmake.

In general, CMake can generate Makefiles, Visual Studio solutions or other stuff needed to compile the project.

## Ninja
CMake by default generates a Visual Studio solution. Because I am a avoiding Visual Studio like a plague, we will be using Ninja.

Why Ninja?
We can't really tell CMake to generate Makefiles because we are not using the gcc toolchain and hence we don't have gnu make.
Besides ninja claims to be faster and can be installed easily.

### Installing Ninja
There are many ways to install ninja:
1. Use your system package manager. See [here](https://github.com/ninja-build/ninja/wiki/Pre-built-Ninja-packages)
2. Download the binary from [here](https://github.com/ninja-build/ninja/releases)
3. Build from source.

[Check here for more details](https://ninja-build.org)

For me I installed using through pip: `pip install ninja`
(Technically I used [pipx](https://pypa.github.io/pipx/) but that doesn't really matter)

It does not matter what method you use, as long as ninja is added to path and accessible from the terminal.

## Using CMake with ninja
Now to build your CMake project with Ninja you simply do:
```shell
cmake -S <project root> -B build -G Ninja
```

# Managing dependencies with vcpkg
When you program stuff, we tend to use external libraries/packages  so we don't reinvent the wheel every time we need something.

In python we can simply use pip to install them.

In C# we can use nuget.

However in C++ (and C), we have to manually download the external library/package and add them to the project, or put it in the C drive (which clutters it up), or some other very not elegant solution.

vcpkg solves this. There are other solutions like conan but I find vcpkg to be the simplest.

## Installing and adding vcpkg
There are many ways of installing and adding vcpkg to your project.

I will be installing vcpkg as a git submodule.

In the project root folder, run:
```shell
git submodule add https://github.com/microsoft/vcpkg
```
Now add the following to project `CMakeLists.txt` before the first `project()` call.
```cmake
set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake CACHE STRING "Vcpkg toolchain file")
```
> This will still allow people to not use vcpkg, by passing the CMAKE_TOOLCHAIN_FILE directly, but it will make the configure-build step slightly easier.
from: https://github.com/microsoft/vcpkg#vcpkg-as-a-submodule-with-cmake

## Consuming dependencies
To start using packages from vcpkg, we have to first create a `vcpkg.json` file in the project root.
In `vcpkg.json` we declare our dependencies like so:
```json
{
  "dependencies": [
    "fmt", // example dependency
  ]
}
```
You can now add use dependencies in CMakeList.txt like:
```cmake
find_package(fmt CONFIG REQUIRED) // first find the package first
target_link_libraries(main PRIVATE fmt::fmt) // Add package to target
```
(Taken from https://learn.microsoft.com/en-gb/vcpkg/consume/manifest-mode?tabs=msbuild%2Cbuild-MSBuild)

Now if you build your project with cmake, vcpkg will automatically fetch the required packages and build them for you.

## Finding packages
You can go to https://vcpkg.io/en/packages to see available packages.

# TLDR
My C++ setup basically consists of:
1. llvm/clang
2. CMake
3. Ninja
4. vcpkg

# THE END