Compartilhar via


Introdução ao controle de versão

Usando versões com manifestos

Vamos começar com a criação de um projeto CMake simples que depende de fmt e zlib.

Crie uma pasta com os seguintes arquivos:

vcpkg.json

{
    "name": "versions-test",
    "version": "1.0.0",
    "dependencies": [
        {
            "name": "fmt",
            "version>=": "7.1.3#1"
        }, 
        "zlib"
    ],
    "builtin-baseline": "3426db05b996481ca31e95fff3734cf23e0f51bc"
}

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;
}

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)

E agora compilamos e executamos nosso projeto com o CMake:

  1. Crie o diretório de build para o projeto.

    PS D:\versions-test> mkdir build
    PS D:\versions-test> cd build
    
  2. Configurar o CMake.

    PS D:\versions-test\build> cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=D:/vcpkg/scripts/buildsystems/vcpkg.cmake ..
    -- Running vcpkg install
    Detecting compiler hash for triplet x86-windows...
    The following packages will be built and installed:
        fmt[core]:x64-windows -> 7.1.3#1 -- D:\Work\viromer\vcpkg\buildtrees\versioning\versions\fmt\4f8427eb0bd40da1856d4e67bde39a4fda689d72
        vcpkg-cmake[core]:x64-windows -> 2021-02-26 -- D:\Work\viromer\vcpkg\buildtrees\versioning\versions\vcpkg-cmake\51896aa8073adb5c8450daa423d03eedf0dfc61f
        vcpkg-cmake-config[core]:x64-windows -> 2021-02-26 -- D:\Work\viromer\vcpkg\buildtrees\versioning\versions\vcpkg-cmake-config\d255b3d566a8861dcc99a958240463e678528066
        zlib[core]:x64-windows -> 1.2.11#9 -- D:\Work\viromer\vcpkg\buildtrees\versioning\versions\zlib\827111046e37c98153d9d82bb6fa4183b6d728e4
    ...
    
  3. Compile o projeto.

    PS D:\versions-test\build> cmake --build .
    [2/2] Linking CXX executable main.exe
    
  4. Execute-o!

    PS D:\versions-test\build> ./main.exe
    fmt version is 70103
    zlib version is 1.2.11
    

Dê uma olhada na saída:

fmt[core]:x86-windows -> 7.1.3#1 -- D:\vcpkg\buildtrees\versioning\versions\fmt\4f8427eb0bd40da1856d4e67bde39a4fda689d72
...
zlib[core]:x86-windows -> 1.2.11#9 -- D:\vcpkg\buildtrees\versioning\versions\zlib\827111046e37c98153d9d82bb6fa4183b6d728e4

Em vez de usar os arquivos de porta em ports/, vcpkg está verificando os arquivos de cada versão em buildtrees/versioning/versions/. Os arquivos em ports/ ainda são usados ao executar vcpkg no modo clássico.

Nota

A saída do vcpkg durante a configuração do CMake só está disponível ao usar a versão do CMake 3.18 ou mais recente. Se você estiver usando um CMake mais antigo, poderá verificar o arquivo vcpkg-manifest-install.log no diretório de build.

Leia nossa postagem no blog de anúncio de manifestos para saber como usar manifestos com o MSBuild.

Alterações de manifesto

Se você tiver usado manifestos antes, observará que há algumas novas propriedades JSON. Vamos examinar estas alterações:

version

{
    "name": "versions-test",
    "version": "1.0.0"
}

Esta é a declaração de versão do projeto. Anteriormente, você só podia declarar versões para seus projetos usando a propriedade version-string. Agora que o controle de versão surgiu, o vcpkg está ciente de alguns novos esquemas de controle de versão.

Esquema de versão Descrição
version Numéricos separados por pontos: 1.0.0.5.
version-semver Versões semânticas compatíveis: 1.2.0 e 1.2.0-rc.
version-date Datas no formato YYYY-MM-DD: 2021-01-01
version-string Cadeias de caracteres arbitrárias: vista, candy.

version>=

{
    "dependencies": [
        { "name": "fmt", "version>=": "7.1.3" },
        "zlib"
    ]
}

Essa propriedade é usada para expressar restrições mínimas de versão, ela é permitida apenas como parte das declarações de "dependencies". Em nosso exemplo, definimos uma restrição explícita no 7.1.3#1 de versão de fmt.

Vcpkg poderá atualizar essa restrição se uma dependência transitiva exigir uma versão mais recente. Por exemplo, se zlib declarassem uma dependência na versão fmt7.1.4, o vcpkg instalaria 7.1.4 em vez disso.

vcpkg usa uma abordagem de versão mínima, em nosso exemplo, mesmo que fmt versão 8.0.0 fosse lançada, vcpkg ainda instalaria a versão 7.1.3#1, pois essa é a versão mínima que atende à restrição. As vantagens dessa abordagem são que você não recebe atualizações de dependência inesperadas quando atualiza vcpkg e obtém builds reproduzíveis (em termos de versão usada), desde que use o mesmo manifesto.

Se você quiser atualizar suas dependências, poderá aumentar a restrição de versão mínima ou usar uma linha de base mais recente.

builtin-baseline

{ "builtin-baseline": "3426db05b996481ca31e95fff3734cf23e0f51bc" }

Esse campo declara a linha de base de controle de versão para todas as portas. A definição de uma linha de base é necessária para habilitar o controle de versão, caso contrário, você obterá as versões atuais no diretório ports/. Você pode executar 'git rev-parse HEAD' para obter a confirmação atual de vcpkg e defini-la como a linha de base interna. Consulte a documentação "builtin-baseline" para obter mais informações.

Em nosso exemplo, não declaramos uma restrição de versão para zlib; em vez disso, a versão é retirada da linha de base. Internamente, vcpkg procurará no commit 3426db05b996481ca31e95fff3734cf23e0f51bc para descobrir qual versão do zlib era a mais recente naquele momento (no nosso caso, era 1.2.11#9).

Durante a resolução da versão, as versões de linha de base são tratadas como restrições mínimas de versão. Se você declarar uma restrição explícita menor que uma versão de linha de base, a restrição explícita será atualizada para a versão de linha de base.

Por exemplo, se modificarmos nossas dependências como esta:

{ "dependencies": [
    {
        "name": "fmt",
        "version>=": "7.1.3#1"
    },
    {
        "name": "zlib",
        "version>=": "1.2.11#7"
    }
] }

Nota

O valor 1.2.11#7 representa 1.2.11de versão, versão da porta 7.

Como a linha de base introduz uma restrição de versão mínima para zlib em 1.2.11#9 e uma versão mais alta atende à restrição de versão mínima para 1.2.11#7, vcpkg tem permissão para atualizá-la.

As linhas de base também são um mecanismo conveniente para atualizar várias versões de cada vez, por exemplo, se você quiser depender de várias bibliotecas de boost, é mais conveniente definir o baseline uma vez do que declarar uma restrição de versão em cada pacote.

Mas e se você quiser fixar uma versão mais antiga que a linha de base?

overrides

Como as linhas de base estabelecem um piso de versão para todos os pacotes e as restrições explícitas são atualizadas quando são inferiores à linha de base, precisamos de outro mecanismo para fazer downgrade de versões após a linha de base.

O mecanismo que vcpkg fornece para esse cenário é overrides. Quando uma substituição é declarada em um pacote, vcpkg ignorará todas as outras restrições de versão declaradas diretamente no manifesto ou de dependências transitivas. Em suma, overrides forçará vcpkg a usar a versão exata declarada, ponto final.

Vamos modificar nosso exemplo mais uma vez, desta vez para forçar o vcpkg a usar 6.0.0 de versão de fmt.

{
    "name": "versions-test",
    "version": "1.0.0",
    "dependencies": [
        {
            "name": "fmt",
            "version>=": "7.1.3#1"
        },
        {
            "name": "zlib",
            "version>=": "1.2.11#7"
        }
    ],
    "builtin-baseline": "3426db05b996481ca31e95fff3734cf23e0f51bc",
    "overrides": [
        {
            "name": "fmt",
            "version": "6.0.0"
        }
    ]
}

Recompile nosso projeto:

PS D:\versions-test\build> rm ./CMakeCache.txt
PS D:\versions-test\build> rm -r ./vcpkg_installed
PS D:\versions-test\build> cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=D:/vcpkg/scripts/buildsystems/vcpkg.cmake ..
-- Running vcpkg install
Detecting compiler hash for triplet x86-windows...
The following packages will be built and installed:
    fmt[core]:x86-windows -> 6.0.0 -- D:\vcpkg\buildtrees\versioning\versions\fmt\d99b6a35e1406ba6b6e09d719bebd086f83ed5f3
    zlib[core]:x86-windows -> 1.2.11#9 -- D:\vcpkg\buildtrees\versioning\versions\zlib\827111046e37c98153d9d82bb6fa4183b6d728e4
...
PS D:\versions-test\build> cmake --build .
[2/2] Linking CXX executable main.exe

E execute-o!

PS D:\versions-test\build> .\main.exe
fmt version is 60000
zlib version is 1.2.11

Observe como o fmt está agora na versão 6.0.0 exatamente como queríamos.

Versões e portas personalizadas

A última coisa a discutir é como as portas de sobreposição interagem com a resolução de controle de versão. A resposta é: eles não.

Entrando em mais detalhes, quando você fornece uma sobreposição para uma porta, vcpkg sempre usará a porta de sobreposição sem se importar com qual versão está contida nela. Os motivos são duplos: (1) ele é consistente com o comportamento existente de portas de sobreposição de mascarar completamente a porta existente e (2) portas de sobreposição não fornecem (e não são esperadas) informações suficientes para alimentar o recurso de controle de versão do vcpkg.

Se você quiser ter a personalização de porta flexível junto com o controle de versão, considere fazer seu próprio registro personalizado.

Leitura adicional

Se você estiver interessado em se aprofundar nos detalhes de como funciona o controle de versão, recomendamos que você leia nosso de referência de controle de versão e conceitos de controle de versão.