Tutorial: Install a specific version of a package
Important
This feature is only available in manifest mode.
vcpkg allows you to control the precise versions of each dependency in your project.
In this tutorial, you will learn to:
Prerequisites
- A terminal
- A code editor
- vcpkg
- CMake
1 - Create a project with a manifest
In an empty folder, create the following project files:
A source file (main.cpp
):
#include <fmt/core.h>
#include <zlib.h>
int main()
{
fmt::print("fmt version is {}\n"
"zlib version is {}\n",
FMT_VERSION, ZLIB_VERSION);
return 0;
}
A CMake project file (CMakeLists.txt
):
cmake_minimum_required(VERSION 3.18)
project(versionstest CXX)
add_executable(main main.cpp)
find_package(ZLIB REQUIRED)
find_package(fmt CONFIG REQUIRED)
target_link_libraries(main PRIVATE ZLIB::ZLIB fmt::fmt)
A vcpkg manifest (vcpkg.json
):
{
"dependencies": [ "fmt", "zlib" ]
}
Build the project, replace %VCPKG_ROOT%
with your vcpkg installation path:
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=%VCPKG_ROOT%/scripts/buildsystems/vcpkg.cmake
cmake --build build
Run the program:
fmt version is 70103
zlib version is 1.2.11
It is likely, that when you run the program the versions of these libraries are different than the output above. In the next step, we show you how to lock the versions of these dependencies so that they stay consistent each time you build the project.
2 - Add version constraints using a baseline
A version baseline, establishes a minimum version floor for all the packages. Read the vcpkg concepts to learn about baselines.
To get the exact versions used in the previous step, modify the contents of vcpkg.json
to:
{
"dependencies": [
"fmt",
"zlib"
],
"builtin-baseline": "3426db05b996481ca31e95fff3734cf23e0f51bc"
}
Setting builtin-baseline
to a specific commit SHA
of the vcpkg repository instructs vcpkg to use the package versions at that specific commit as the minimum
version for all the packages.
You can use Git to examine the versions for that particular baseline:
git show 3426db05b996481ca31e95fff3734cf23e0f51bc:versions/baseline.json | Select-String -Pattern '"zlib"|"fmt"' -Context 0,3
The output should look similar to this:
"fmt": {
"baseline": "7.1.3",
"port-version": 1
},
--
"zlib": {
"baseline": "1.2.11",
"port-version": 9
},
3 - Update the baseline versions
Baselines offer a convenient mechanism to update the versions of all your dependencies at once. To update your baseline run the following command:
vcpkg x-update-baseline
The x-update-baseline
command modifies your manifest file to set
builtin-baseline
to the current Git commit of your
vcpkg instance.
You can use the --add-initial-baseline
option to add a builtin-baseline
to a manifest that does
not have one yet.
4 - Add a minimum version constraint
Baselines are not the only way to lock down a package's version. vcpkg also accepts minimum version
constraints in the form of version>=
.
Modify the contents of vcpkg.json
to:
{
"dependencies": [
{
"name": "fmt",
"version>=": "10.1.1"
},
"zlib"
],
"builtin-baseline": "3426db05b996481ca31e95fff3734cf23e0f51bc"
}
The manifest file above uses the dependency object
notation to set a minimum version constraint (version>=
) on fmt
. In order to satisfy the
dependencies vcpkg needs to satisfy two constraints, one coming from the baseline and one coming
from the minimum version constraint in the dependencies
list.
- Baseline constraint,
"version>=": "7.1.3"
. - Dependencies list constraint,
"version>=": "10.1.1"
.
Build and run the project, replace %VCPKG_ROOT%
with your vcpkg installation path:
rm -r build
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=%VCPKG_ROOT%/scripts/buildsystems/vcpkg.cmake
cmake --build build
./build/main
The output should look like this:
fmt version is 100100
zlib version is 1.2.11
In this case, version 10.1.1
of fmt
satisfies both constraints. Notice how zlib
gets its
baseline version 1.2.11
.
5 - Force a specific version
In some cases, you may want to force a specific version of a package, for example:
- To resolve version conflicts.
- To lock down versions older than the baseline.
- To lock down versions that are otherwise incomparable, for example:
vista
,xp
.
vcpkg allows you to solve these issues by using version overrides.
Modify the vcpkg.json
contents to:
{
"dependencies": [
{
"name": "fmt",
"version>=": "10.1.1"
},
"zlib"
],
"builtin-baseline": "3426db05b996481ca31e95fff3734cf23e0f51bc",
"overrides": [
{
"name": "zlib",
"version": "1.2.8"
}
]
}
Any package included in the "overrides"
list will use the specified version while ignoring all
other version constraints. In this example, the baseline 3426db05b996481ca31e95fff3734cf23e0f51bc
adds a minimum version constraint on zlib
of 1.2.11
but the override declaration forces version
1.2.8
instead.
Build and run the project, replace %VCPKG_ROOT%
with your vcpkg installation path:
rm -r build
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=%VCPKG_ROOT%/scripts/buildsystems/vcpkg.cmake
cmake --build build
./build/main
The output should look like this:
fmt version is 100100
zlib version is 1.2.8
Next steps
In this tutorial, you learned the different mechanisms that vcpkg offers to lock down specific package versions. Read the versioning concepts and reference to learn more about how vcpkg handles version resolution.
Here are some additional tasks to try next:
- Reuse binaries across Continuous Integration runs using binary caching
- Manage your private libraries using custom registries