Versioning: Implementation details

The latest version of this documentation is available on GitHub.

Contents

Minimum versioning

Vcpkg uses a minimal selection approach to versioning, inspired by the one used by Go. But modified in some ways:

The minimal selection principle, however, stays the same. Given a set of constraints, vcpkg will use the "oldest" possible versions of packages that can satisfy all the constraints.

Using a minimum version approach has the following advantages: * Is predictable and easy to understand. * User controls when upgrades happen, as in, no upgrades are performed automatically when a new version is released. * Avoids using a SAT solver.

To give an example, consider the following package graph:

    (A 1.0) -> (B 1.0)

    (A 1.1) -> (B 1.0) 
            -> (C 3.0) 

    (A 1.2) -> (B 2.0)
            -> (C 3.0)

    (C 2.0)

And the following manifest:

{
    "name": "example",
    "version": "1.0.0",
    "dependencies": [ 
        { "name": "A", "version>=": "1.1" },
        { "name": "C", "version>=": "2.0" }
    ], 
    "builtin-baseline": "<some git commit with A's baseline at 1.0>"
}

After accounting for transitive dependencies we have the following set of constraints: * A >= 1.1 * B >= 1.0 * C >= 3.0 * C >= 2.0

Since vcpkg has to satisfy all the constraints, the set of installed packages becomes:

Constraint resolution

Given a manifest with a set of versioned dependencies, vcpkg will attempt to calculate a package installation plan that satisfies all the constraints.

Version constraints come in the following flavors: * Declared constraints: Constraints declared explicitly in the top-level manifest using version>=. * Baseline constraints: Constraints added implicitly by the builtin-baseline. * Transitive constraints: Constraints added indirectly by dependencies of your dependencies. * Overriden constraints: Constraints overriden in the top-level manifest using overrides declarations.

To compute an installation plan, vcpkg follows roughly these steps:

Acquiring port versions

Although the concept of package versions has always been present in vcpkg, the concept of version constraints has been not.

With the introduction of versioning constraints, it is now possible that a package depends on a port version that does not match the one available locally. This raises a problem as vcpkg needs to know how to acquire the port files for the requested version.

To solve this problem, a new set of metadata files was introduced. These files are located in the versions/ directory at the root level of the vcpkg repository.

The versions/ directory, will contain JSON files for each one of the ports available in the registry. Each file will list all the versions available for a package and contain a Git tree-ish object that vcpkg can check out to obtain that version’s portfiles.

Example: zlib.json

{
  "versions": [
    {
      "git-tree": "2dfc991c739ab9f2605c2ad91a58a7982eb15687",
      "version-string": "1.2.11",
      "port-version": 9
    },
    ...
    {
      "git-tree": "a516e5ee220c8250f21821077d0e3dd517f02631",
      "version-string": "1.2.10",
      "port-version": 0
    },
    {
      "git-tree": "3309ec82cd96d752ff890c441cb20ef49b52bf94",
      "version-string": "1.2.8",
      "port-version": 0
    }
  ]
}

For each port, its corresponding versions file should be located in versions/{first letter of port name}-/{port name}.json. For example, zlib’s version file will be located in versions/z-/zlib.json. Aside from port version files, the current baseline file is located in versions/baseline.json.