Introduzione al controllo delle versioni

Uso di versioni con manifesti

Si inizierà con la creazione di un semplice progetto CMake che dipende da fmt e zlib.

Creare una cartella con i file seguenti:

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)

A questo momento si compila ed esegue il progetto con CMake:

  1. Creare la directory di compilazione per il progetto.

    PS D:\versions-test> mkdir build
    PS D:\versions-test> cd build
    
  2. Configurare 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. Compilare il progetto.

    PS D:\versions-test\build> cmake --build .
    [2/2] Linking CXX executable main.exe
    
  4. Eseguire l'app.

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

Esaminare l'output:

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

Anziché usare i file di porta in ports/, vcpkg estrae i file per ogni versione in buildtrees/versioning/versions/. I file in ports/ vengono ancora usati durante l'esecuzione di vcpkg in modalità classica.

Nota

L'output da vcpkg durante la configurazione di CMake è disponibile solo quando si usa la versione 3.18 di CMake o versione successiva. Se si usa un CMake precedente, è possibile controllare il vcpkg-manifest-install.log file nella directory di compilazione.

Per informazioni sull'uso dei manifesti con MSBuild, vedere il post di blog sugli annunci sui manifesti.

Modifiche al manifesto

Se sono stati usati manifesti prima di notare che sono presenti alcune nuove proprietà JSON. Esaminiamo le modifiche seguenti:

version

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

Questa è la dichiarazione di versione del progetto. In precedenza, è possibile dichiarare solo le versioni per i progetti usando la version-string proprietà . Ora che il controllo delle versioni è venuto in giro, vcpkg è a conoscenza di alcuni nuovi schemi di controllo delle versioni.

Schema di versione Descrizione
version Numeri delimitati da punti: 1.0.0.5.
version-semver Versioni semantiche conformi: 1.2.0 e 1.2.0-rc.
version-date Date in YYYY-MM-DD formato: 2021-01-01
version-string Stringhe arbitrarie: vista, candy.

version>=

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

Questa proprietà viene usata per esprimere vincoli di versione minima, ma è consentita solo come parte delle "dependencies" dichiarazioni. Nell'esempio viene impostato un vincolo esplicito sulla versione 7.1.3#1 di fmt.

vcpkg può aggiornare questo vincolo se una dipendenza transitiva richiede una versione più recente. Ad esempio, se zlib dovesse dichiarare una dipendenza dalla fmt versione 7.1.4 , vcpkg verrà installato 7.1.4 .

vcpkg usa un approccio di versione minima, in questo esempio, anche se fmt la versione 8.0.0 dovesse essere rilasciata, vcpkg installerebbe comunque la versione 7.1.3#1 perché corrisponde alla versione minima che soddisfa il vincolo. I vantaggi di questo approccio sono che non si ottengono aggiornamenti imprevisti delle dipendenze quando si aggiorna vcpkg e si ottengono build riproducibili (in termini di versione usata) purché si usi lo stesso manifesto.

Se si desidera aggiornare le dipendenze, è possibile aumentare il vincolo di versione minima o usare una baseline più recente.

builtin-baseline

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

Questo campo dichiara la linea di base di controllo delle versioni per tutte le porte. L'impostazione di una linea di base è necessaria per abilitare il controllo delle versioni. In caso contrario, si otterranno le versioni correnti nella ports/ directory. È possibile eseguire "git rev-parse HEAD" per ottenere il commit corrente di vcpkg e impostarlo come baseline predefinita. Per altre informazioni, vedere la "builtin-baseline" documentazione .

In questo esempio non viene dichiarato un vincolo di versione per zlib. La versione viene invece ricavata dalla linea di base. Internamente, vcpkg cercherà di eseguire il commit 3426db05b996481ca31e95fff3734cf23e0f51bc per scoprire quale versione di zlib era l'ultima in quel momento (in questo caso era 1.2.11#9).

Durante la risoluzione della versione, le versioni di base vengono considerate come vincoli di versione minima. Se si dichiara un vincolo esplicito inferiore a una versione di base, il vincolo esplicito verrà aggiornato alla versione di base.

Ad esempio, se le dipendenze sono state modificate come segue:

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

Nota

Il valore 1.2.11#7 rappresenta la versione 1.2.11, la versione della 7porta .

Poiché la baseline introduce un vincolo di versione minima per zlib at 1.2.11#9 e una versione successiva soddisfa il vincolo di versione minima per 1.2.11#7, vcpkg è autorizzato ad aggiornarlo.

Le linee di base sono anche un meccanismo pratico per aggiornare più versioni alla volta, ad esempio, se si vuole dipendere da più boost librerie, è più pratico impostare una baseline volta che dichiarare un vincolo di versione per ogni pacchetto.

Ma cosa succede se si vuole aggiungere una versione precedente alla baseline?

overrides

Poiché le linee di base stabiliscono un piano di versione per tutti i pacchetti e i vincoli espliciti vengono aggiornati quando sono inferiori alla baseline, è necessario un altro meccanismo per effettuare il downgrade delle versioni oltre la baseline.

Il meccanismo fornito da vcpkg per tale scenario è overrides. Quando un override viene dichiarato in un pacchetto, vcpkg ignorerà tutti gli altri vincoli di versione dichiarati direttamente nel manifesto o dalle dipendenze transitive. In breve, overrides forza vcpkg a usare la versione esatta dichiarata, periodo.

Si modificherà ora l'esempio per forzare vcpkg a usare la versione 6.0.0 di 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"
        }
    ]
}

Ricompilare il progetto:

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

Ed eseguilo!

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

Si noti che è fmt ora alla versione 6.0.0 proprio come volevamo.

Versioni e porte personalizzate

L'ultima cosa da discutere è come le porte di sovrimpressione interagiscono con la risoluzione del controllo delle versioni. La risposta è: non lo fanno.

Andando in dettaglio, quando si fornisce una sovrimpressione per una porta, vcpkg userà sempre la porta di sovrimpressione senza occuparsi di quale versione è contenuta. I motivi sono due volte: (1) è coerente con il comportamento esistente delle porte sovrapposte di mascherare completamente la porta esistente e (2) le porte di sovrimpressione non (e non sono previste) forniscono informazioni sufficienti per alimentare la funzionalità di controllo delle versioni di vcpkg.

Se si vuole avere una personalizzazione delle porte flessibile insieme al controllo delle versioni, è consigliabile creare un registro personalizzato.

Altre risorse

Se si è interessati a approfondire i dettagli sul funzionamento del controllo delle versioni, è consigliabile leggere i concetti di riferimento sul controllo delle versioni e sul controllo delle versioni.