Skip to content

Vcpkg Vs Conan: Best Package Manager For C++?

People often think that starting a C++ project can be difficult, especially when a project has many third-party dependencies. Luckily, there are package management tools that can make your life easier. In this post we will be analysing the two most popular package managers for C/C++: Conan and Vcpkg.

Conan Vs Vcpkg - Best C/C++ package manager
Conan Or Vcpkg? Which tool should you choose?

Package managers can abstract the manual work necessary in including third-party libraries in your project. Specifically, the list below covers some of the features a good package manager provides:

  • Pull and install dependencies specified by the project (build if necessary).
  • Resolve dependency versioning problems.
  • Easy integration with your build system (including and linking libraries).
  • Support for cross-compilation of dependencies.

In case you haven’t fully understood the list above, worry not, this post will explain each point and compare Conan and Vcpkg in the context of each mentioned aspect.

Installing Conan vs Vcpkg

Although both package managers are fairly easy to install, there are differences in the process due to how these managers have been written.

Conan, for example, is mainly written in Python, therefore it requires a modern Python interpreter to be installed in your system, as well as the pip package manager. For this reason, the Conan installation page recommends Python >= 3.5 installed with pip3. Check out the Conan installation guide if you’re interested in installing this package manager.

At first glance, from their Github repo, it seems that Vcpkg is mainly written in CMake scripts. However, by taking a look at their bootstrap scripts, we see that it builds the vcpkg tool from C++ source code. Therefore, the Vcpkg tool itself is written in C++. For more information on installing Vcpkg, check out their getting started with Vcpkg guide.

In conclusion, Conan has more installation dependencies than Vcpkg. In other words, if your dev environment already has CMake and C++ compilers, you may find it easier to install Vcpkg compared to Conan. Anyway, both tools are fairly straightforward to install and get started.

A Simple C++ Project – Setting The Context

In order to have a fair test, we will be using the same project with the two different package managers. Log story short, I’ve modified the simplest C++ program so it prints the text “Which tool is better? Conan or Vcpkg?”. However, the catch is that the strings “Conan” and “Vcpkg” are substituted in with fmt, a well-known C++ text formatting library.

#include <fmt/format.h>

#include <iostream>

int main()
{
  std::cout << fmt::format("Which tool is better: {} or {}?\n",
                           "Conan",
                           "Vcpkg");
}

Don’t worry about the <fmt/format.h> header that’s being included in the first line; this is what we will be pulling in with each package manager. After all, we need to pull at least one third-party dependency for this test.

Just before we jump into the usage of each package manager, the base CMakeLists.txt needed for this project is outlined below.

cmake_minimum_required(VERSION 3.16)
project(PackageManagers)

find_package(fmt REQUIRED)

add_executable(test_project main.cpp)

target_link_libraries(test_project PRIVATE
  fmt::fmt)

As you will see, each package manager has a different way of integrating the pulled packages into your CMake targets. Overall, the project tree is as follows.

test_project
  |- main.cpp         # cpp source
  |- CMakeLists.txt   # CMake configs

Pulling Dependencies With Conan

Perhaps the most important feature of Conan is using the “conanfile”. Whether you use the text or Python “conanfile”, they both provide ways of specifying which recipes (packages) your project depends on. In addition, Conan uses the “conanfile” to download the correct source files and/or prebuilt binaries for the libraries you have asked for.

For simplicity’s sake, I will be using the “conanfile.txt” version. According to Conan’s documentation on conanfile.txt, the following contents should be enough to pull fmt version 8.0.0 from conan.io (Conan recipe centre).

[requires]
fmt/8.0.0

[generators]
cmake_find_package

Each line under [requires] declares the libraries you intend to pull for your project. Similarly, under the [generators] section, you must provide the integration methods.

Since we’re using CMake, the cleanest generator option I found was “cmake_find_package”; it generates a CMake “find” file that can be used with the command find_package(...)– essentially, the find_package(fmt REQUIRED) call in the base CMakeLists.txt will integrate the libraries into your build.

If you are using another build system generator, check out the supported generator options for Conan.

Finally, actually building the project is as easy as executing the following commands, assuming you’re executing them from the “test_project” directory.

mkdir build && cd build

# Pulling the dependencies with conan
# and save Find*.cmake files in "build/"
conan install \
      -s compiler=gcc \
      -s compiler.version=9 \
      -s compiler.libcxx=libstdc++11 \
      --build=missing ..

# Configuring the CMake project, telling
# it where to find the Conan dependencies
# through the Find*.cmake files location
cmake -DCMAKE_MODULE_PATH:FILEPATH="$(pwd)" ..

# build the project
cmake --build .

Note the verbose conan install command. In my case, I’ve told Conan that my compiler is gcc, the version is 9 and I want the standard library implementation libstdc++11. Luckily, Conan “profiles” will help us with the settings, we’ll talk about them in the upcoming sections.


Pulling Dependencies With Vcpkg

Once you install Vcpkg in a directory of your system, navigate to that directory using the command line. For this particular test project, we need to install fmt with the following command.

./vcpkg install fmt
./vcpkg integrate install

With Vcpkg, we don’t need to provide a version for the package. I assume that Vcpkg downloads the latest, most stable version of the specified library.

Interestingly, this might not suit your needs, and it may cause problems if the version of the library Vcpkg pulls is not compatible with the version you have developed with!

Looking at the output of the last command, ./vcpkg integrate install, you should see something along the lines:

CMake projects should use: "-DCMAKE_TOOLCHAIN_FILE=${SOME_PATH_TO}/vcpkg/scripts/buildsystems/vcpkg.cmake"

The above output will be useful when building because Vcpkg integrates with CMake via the toolchain file. Summing up the purpose of this “toolchain file” can be quite difficult as it’s a very complex concept, but it basically defines properties about the compiler and some utility paths.

Building the project is then done with the following commands.

cmake -DCMAKE_TOOLCHAIN_FILE="${SOME_PATH_TO}/vcpkg/scripts/buildsystems/vcpkg.cmake" ..

cmake --build .

Finally, we now have the executable test_project. Note that you have to change the -DCMAKE_TOOLCHAIN_FILE=... bit with the ./vcpkg integrate install output we saw earlier.

Integrating Into Your Build: Vcpkg Or Conan?

As we’ve seen in the previous section, the recommended integration steps for both tools are fairly straightforward.

The simplest Conan setup requires creating the conanfile.txt, where we declare which libraries we depend on, as well as their versions. Following that, we need to provide CMake with the -DCMAKE_MODULE_PATH variable in the configuration command, so CMake knows where the Find*.cmake files are.

On the other hand, Vcpkg’s “get started” guide recommends using the command line to install a version of the libraries you want (may not be the version you need). Finally, integrating the libraries you built with Vcpkg only requires giving CMake the -DCMAKE_TOOLCHAIN_FILE option.

So in terms of “out of the box usability” for extremely easy projects, perhaps projects that only use very stable third-party libraries, Vcpkg wins.

Managing Dependency Versions

Although Vcpkg is slightly less cumbersome to use out of the box, you may have noticed that, with Conan, we have to provide the versions of the libraries you want to include in your project.

Dependency versioning is a very important concept in software development. Simply put, if the developers of a library are following a strict versioning system, such as semantic versioning, version 2.0.0 will not be compatible with 1.9.9. For this reason, specifying exactly which version of a library you want is essential.

By default, Conan offers this feature (in fact, it forces you to specify the version). Vcpkg, however, does not enforce this by default.

Fortunately, Vcpkg recently introduced version manifests – a json file contained in the root of your project, where you declare dependencies and versions, much like the Conan counterpart. The Vcpkg manifest seems to support more advanced declarations, such as “I want at least version X of a library Y”.

Taking the above points into consideration, I would say that both tools provide a good way to manage the versions of your dependencies. Due to Conan enforcing this practice, and due to Vcpkg’s manifests being a little more verbose than Conan’s conanfile.txt, Conan wins in this context.

Support For Cross Compilation

In the previous sections, we assumed that we’re building whatever executable/library for our own platforms. For example, the “test_project” mentioned in the previous sections were built for WSL 2 (Ubuntu), with the native GCC compiler.

However, let’s say you are a seasoned engineer developing your application with your developer machine (such as an x84-64 Windows or a Linux machine), and your code will be running on a different architecture (such as an arm64 RaspberryPi 4). In this example, you need to cross-compile your application so it generates binaries that can be executed on your RaspberryPi 4.

I won’t get into the nitty-gritty of setting up a cross-compilation toolchain, but this is generally achieved in CMake by writing a custom toolchain file that sets up the correct compiler flags and options.

Luckily, both Conan and Vcpkg support cross-compilation, each with their own methods for doing so.

Cross Compiling With Conan (Conan Profiles)

You may remember a faint mention of Conan “profiles” in previous sections. Going into more detail, a Conan profile tells Conan the settings of the platform you wish to build the libraries for. More specifically, you can define profiles for:

  • Build platform: the platform you are using to build the binaries (where the compiler will be called from).
  • Host platform: the environment where the built libraries will be executed on.

In the example I gave before, the “build platform” would be your x86-64 Windows machine, and the “host platform” would be the arm64 RaspberryPi 4.

Personally, I cross-compile applications on a daily basis for arm devices. For this reason, I use the conan profile command to generate said profiles for my build and host targets. Finally, in the conan instal command, I use the arguments --profile:host and --profile:build to specify each profile file.

Check out the documentation on Conan profiles to get started with cross-compilation with Conan! All you have to do is provide the correct compiler and architecture settings, Conan will do the rest.

Cross Compiling With Vcpkg (Triplet Files)

Similar to Conan, Vcpkg also supports cross-compilation of dependencies via “triplet files”.

A triplet file is a CMake file containing information about the host architecture and points to a CMake toolchain file. So essentially, once you have written a CMake toolchain file for your cross-compilation, you basically point Vcpkg to the toolchain file in the triplet file.

For more information, check out the documentation of Vcpkg triplet files.

Quality Of Packages And General Support

One thing to consider when dealing with package managers is the quality of the third-party dependency packages.

At the time of writing this post, Conan has over 900 official packages in the Conan index, while Vcpkg has over 1700 library ports. Unlike Conan, a Vcpkg “port” isn’t necessarily a library package – as @Bibi mentioned in the comments, some modularised libraries have many port scripts! However, Vcpkg’s website claims you can pick from over 1500 open source libraries.

It is clear that Vcpkg wins when it comes to the number of libraries available. But how does the quality compare?

Thoughts On Package Quality In Conan & Vcpkg

Needless to say, both Conan and Vcpkg packages should work fairly well for popular development platforms. More specifically, if you are developing for x86-64 Windows or Linux machines, you will have no trouble building the dependencies from the package recipes (or “ports”, as they are called in Vcpkg).

As part of my day job, I actually compile software for less-known systems on a daily basis. For this reason, I use Conan to do dependency management on my projects.

So far, Conan has not let me down when it comes to managing the third-party libraries in my cross-compilation projects. With the exception of Protobuf, where the “protoc” compiler needs to be build for the “build” machine, and the libraries for the “host” machine. Everything else builds just fine.

Vcpkg, however, has let me down a few times. Precisely, I’ve had a few issues where the package “port” scripts fail to build for the RPi 4 & Rpi Pico. So I’d say that even the official packages still need some more testing on different platforms.

There seems to be a little more momentum in the Vcpkg’s Github repo. So it’s just a matter of time until the quality picks up in my opinion.

Binary Caching – No Need To Build From Source Every Time!

Conan supports pushing the libraries and binaries you build to an upstream. For this reason, if someone with the same profile settings as you pushes their prebuild libraries to the upstrem (Conan centre, for example), Conan will simply download the prebuilt libraries instead of building from the source code.

This means that, on average, your project’s build time will drop massively. It’s quite a handy feature for CI/CD pipelines as your jobs will take significantly less time to complete, and money will be saved!

As far as I am aware, Vcpkg does not have this feature yet, but they are planning on implementing it. So unfortunately, it builds all the libraries you pull from source.

Conan also provides the ability to host your own package remote. This essentially means you can have your own recipes and binaries stored in a server that’s accessible to you and your company. Very useful if you are creating custom recipes.

TL;DR – Conan or Vcpkg?

Both Conan and Vcpkg are fairly easy to install. Conan requires a recent version of Python to be installed in addition to the usual C++ development stack tools.

Conan requires the “conanfile” to be written by the user by default, where they will declare the libraries and versions to pull. Vcpkg installs dependencies through the command-line (unversioned), but also has support for versioned dependencies through the json manifest file.

Both tools theoretically support cross-compilation toolchains. I’ve had very few issues with Conan when compiling for arm systems. Vcpkg can be a hit or miss depending on the package you are building – I’ve personally had issues with pulling & building SDL for RPi4.

Conan has less oficial packages compared to Vcpkg, but overall quality and support of Conan package is better, in my opinion. In addition, Vcpkg has more momentum, so it’s just a matter of time until the quality picks up (over 1000 contributors, Conan has about 300 at the time of writing this post).

Conan has binary caching features, but Vcpkg does not yet. Reducing the build time is the main advantage of binary caching.

Which one to go for? Conan Or Vcpkg?

I’d say that, it depends on the type of your project. If you are developing for a popular architecture, and you will be using some obscure, not well known libraries, you are more likely to succeed with Vcpkg.

If you are working on a multi-platform project, and require stability and better supported packages, then I’d go with Conan.

Obviously, I think both tools are a very good addition to your tool set. They will massively improve in including third-party libraries in your project and allow you to focus on the most important aspect of software engineering: writing your code!

Did I miss anything? Do you have any useful feedback/criticism? Feel free to comment below!

Published inCPP

Be First to Comment

Leave a Reply

Your email address will not be published.