P3.NET

Vcpkg – Package Management for C++

Are you a C++ developer? Have you heard about vcpkg? Vcpkg is a package manager for C++. The goal is to allow C++ developers to take advantage of packages like we have in other languages. Gone, in theory, are the days of downloading SDKs, setting up include and lib paths and copying binaries around. vcpkg is an open source solution that Microsoft is integrating into Visual Studio.

How It Works

The goal of vcpkg is to replace the need for you, the developer, to manage include and library paths. C++ developers are used to having to install SDKs, add the path(s) to header files and point the linker to library files. With vcpkg this problem goes away. You can read more about it here. As of May 2018 vcpkg has 900 packages for Windows and 350 for Linux/MacOS. Any library writer can add their own which means it is a growing package system. Assuming a package is available a developer would need only to download the package locally and then compile and run their code. vcpkg is responsible for ensuring that the correct include paths get added and that any required libraries are automatically linked. As a C++ developer this is an incredible useful feature.

So how dow it work? Unlike other package managers, such as NuGet, vcpkg isn’t downloading libraries and binaries but rather the source code. The code is then compiled on your local machine and a cached version stored for later use. This is an unusual process and is actually slow (at least the first time). But C++ has always had the issue that libraries are generally tied to the compiler that generated them. So trying to use a library generated from gcc in Visual Studio isn’t going to work. The only workaround is to compile the code based upon the compiler being used.

What if the library you need is not available in source format? vcpkg does have support for compiled binaries. In this scenario vcpkg will download the pre-built binaries instead. But remember that compatibility with other compilers is not going to work correctly. This is also how you can share your private libraries amongst your team.

Getting Started

Getting started with vcpkg isn’t hard but it requires a few steps. At this time Visual Studio doesn’t have integrated support for it.

  1. Download the code from Github.
  2. Run the bootstrapper command to compile and set up the vcpkg infrastructure. Note that this is going to require a C++ compiler such as Visual Studio.
  3. If you want to put vcpkg into a shared location that you can run it from later then copy the entire repo. If you copy only the binaries then you will be missing some critical folders and it won’t work.

Once vcpkg is “installed” you can begin using it. If you are using Visual Studio you probably want to integrate vcpkg with it. To do that you must run the following command.

vcpkg integrate install

This will allow Visual Studio to find the packages without you having to modify the project file(s). More importantly though it wires up the path to the vcpkg installation such that you do not need to muck around with include or library paths in your projects. Just reference them as though they are already included and vcpkg will find them.

#include "sfml/graphics.hpp"

Listing Packages

To find out what packages are available for vcpkg use the search command. There can be a lot of packages so search will do a wildcard search for matching packages and their versions.

vcpkg search sfml

This command returns (as of June 2018).

sfml 2.5.0  Simple and fast multimedia library
thor 2.0-1  Extends the multimedia library SFML with higher-level features

To get the list of packages already installed for the current instance use the list command.

vcpkg list

Example output might be.

bzip2:x86-windows    1.0.6-2   High-quality data compressor.
sfml:x86-windows     2.5.0     Simple and fast multimedia library

The packages that are installed are located in the packages folder next to vcpkg. Remember that there can be multiple instances of vcpkg and therefore different packaegs installed depending upon the instance. If you look in the packages folder you will basically see the same structure that you would expect to see if you had downloaded a zip file or installed an SDK. There is generally an include and lib folders. There is also generally a bin folder for libraries that generate dynamic libraries instead of static libraries.

There is also an installed folder. This folder is a merged structure of the packages that are installed but each package is a subfolder under the appropriate platform (e.g. x86-windows). For example SFML is a separate folder under the include folder. This is what allows your code to use a typical include path (e.g. sfml/windows.hpp) and it be found by the compiler when using vcpkg. vcpkg simply adds the root folders of the platform to the search paths.

Installing a Package

To use a package it has to be installed. Use the install command for that.

vcpkg install sfml

You may need to update the packages either because you have updated your compiler or there are newer versions available. The update command can be used to find the outdate packages.

vcpkg update

To recompile the libraries to a newer compiler then use the upgrade command.

vcpkg upgrade

Building Packages

You can build your own packages for your libraries. To do so use the create command.

vcpkg create mylib http://mycompany.com/mylib.zip mylib-1.0.0.zip

The first parameter is the name of the package. The second parameter is the zip file containing the source code. It must be a buildable repository. The last parameter is the name of the package file that will be created. After the command executes the basic package is set up but you still have to define the metadata and customize the CMake process. Once the data is setup up you can use the build command to build the package. For full instructions on how to do this refer to the documentation in Github.

At this time there are some limitations on building multiple versions of a package. Refer to the issue here to track that work.

Outstanding Questions and Issues

vcpkg is new and so there are a lot of rough edges. If you’re coming from a NuGet background then it may seem almost primitive. But from a C++ point of view it really is nice to be able to do this without depending upon any SDKs or having to downlaod any zip files.

Here’s some common questions you may have and issues you may run across.

Q: What happens when you switch to a new compiler? What if you need to support multiple compilers?

A: The recommended solution is to create a new vcpkg instance. If you’re using Visual Studio then register the new instance. You can have any number of vcpkg instances on your machine.

There is the concept of triplets which would let you specify which platform/target to use from the command line. This may or may not be useful in your situation.

Q: What about third party dependencies within a library?

A: At this time there isn’t a good way to handle dependencies the library may have that are not already in vcpkg. As an example SFML needs FreeType and a few other third party dependencies. These are not automatically detected by vcpkg. Instead you have to manually copy the files from the lib folder appropriate for your platform (e.g. x86-windows).
There is an issue tracking this for vcpkg.

Q: I need to run this on a build machine?

A: At this time vcpkg has to be installed before it can be used. You can install vcpkg per project but it still requires downloading and installing it. There is no documentation currently available for getting vcpkg working with build systems other than CMake.

Q: How do I determine the packages I’m using in a project?

A: At this time there isn’t a way to determine that. C++ doesn’t really distinguish between your code and libraries. Since vcpkg really just injects its path into the include and library directories at build time it isn’t tracking what libraries you are using either.

Q: What do I do if the same header/library names are used in multiple packages?

A: Provided each library is using a separate, unique folder name then you should be fine. Each package is generated in its own folder under the base include and lib folders.