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 construímos e executamos nosso projeto com o CMake:
Crie o diretório de compilação para o projeto.
PS D:\versions-test> mkdir build PS D:\versions-test> cd build
Configure 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 ...
Compile o projeto.
PS D:\versions-test\build> cmake --build . [2/2] Linking CXX executable main.exe
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 portfiles no , vcpkg está fazendo check-out dos arquivos para cada versão no ports/
buildtrees/versioning/versions/
. Os arquivos em ports/
ainda são usados ao executar vcpkg no modo clássico.
Observação
A saída do vcpkg durante a configuração do CMake só está disponível ao usar a versão 3.18
do CMake ou mais recente. Se você estiver usando um CMake mais antigo, poderá verificar o vcpkg-manifest-install.log
arquivo no diretório de compilação.
Leia nossa postagem no blog de anúncio de manifestos para saber como usar manifestos com o MSBuild.
Alterações manifestas
Se você tiver usado manifestos antes, notará que há algumas novas propriedades JSON. Vamos rever essas alterações:
version
{
"name": "versions-test",
"version": "1.0.0"
}
Esta é a declaração de versão do seu projeto. Anteriormente, você só podia declarar versões para seus projetos usando a version-string
propriedade. Agora que o versionamento chegou, vcpkg está ciente de alguns novos esquemas de versionamento.
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 YYYY-MM-DD formato: 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 de versão mínimas, ela é permitida apenas como parte das "dependencies"
declarações. Em nosso exemplo, definimos uma restrição explícita na versão 7.1.3#1
do fmt
.
vcpkg tem permissão para atualizar essa restrição se uma dependência transitiva exigir uma versão mais recente. Por exemplo, se zlib
fosse declarar uma dependência da fmt
versão 7.1.4
, o vcpkg seria instalado 7.1.4
.
vcpkg usa uma abordagem de versão mínima, em nosso exemplo, mesmo fmt
se a versão fosse lançada, vcpkg ainda instalaria a versão, pois essa é a versão 8.0.0
7.1.3#1
mínima que satisfaz a restrição. As vantagens dessa abordagem são que você não obtém atualizações de dependência inesperadas quando atualiza o vcpkg e obtém compilações 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" }
Este 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 ports/
diretório. 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 para "builtin-baseline"
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 vai procurar em compromisso 3426db05b996481ca31e95fff3734cf23e0f51bc
para descobrir qual versão do zlib
era a mais recente naquele momento (no nosso caso foi 1.2.11#9
).
Durante a resolução de 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 assim:
{ "dependencies": [
{
"name": "fmt",
"version>=": "7.1.3#1"
},
{
"name": "zlib",
"version>=": "1.2.11#7"
}
] }
Observação
O valor 1.2.11#7
representa version , port version 7
1.2.11
.
Como a linha de base introduz uma restrição de versão mínima para at 1.2.11#9
e uma versão superior satisfaz a restrição de versão mínima para , vcpkg tem permissão para zlib
1.2.11#7
atualizá-la.
As linhas de base também são um mecanismo conveniente para atualizar várias versões ao mesmo tempo, por exemplo, se você quiser depender de várias boost
bibliotecas, é mais conveniente definir o baseline
once do que declarar uma restrição de versão em cada pacote.
Mas e se você quiser fixar uma versão mais antiga do 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 das versões além da linha de base.
O mecanismo que vcpkg prevê 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, vai obrigar vcpkg a usar a versão exata declarada, overrides
ponto final.
Vamos modificar nosso exemplo mais uma vez, desta vez para forçar vcpkg a usar a versão 6.0.0
do 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"
}
]
}
Reconstrua 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 corra!
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 é: 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 a versão contida nela. As razões são duas: (1) é consistente com o comportamento existente das portas de sobreposição de mascarar completamente a porta existente, e (2) as portas de sobreposição não fornecem (e não se espera que forneçam) informações suficientes para alimentar o recurso de controle de versão do vcpkg.
Se você quiser ter personalização de porta flexível junto com o controle de versão, você deve considerar fazer seu próprio registro personalizado.
Leitura adicional
Se você estiver interessado em se aprofundar nos detalhes de como o controle de versão funciona, recomendamos que você leia nossos conceitos de referência e controle de versão de versão.