Guida del manutentore

Questo documento descrive criteri, linee guida e procedure consigliate da seguire quando si apportano contributi a vcpkg.

È destinato a svolgere lo stesso ruolo di:

Obiettivi di progettazione del registro selezionato.

Le porte devono essere installate contemporaneamente

Una porta inclusa nel Registro di sistema curato deve essere compilata correttamente in presenza di tutte le altre porte nel Registro di sistema. L'intero set di porte viene testato regolarmente dalla CI automatizzata di vcpkg.

Una porta non deve eseguire alcuna delle operazioni seguenti:

Le eccezioni vengono effettuate per:

  • Porte che sostituiscono ufficialmente un'altra porta. Sono inclusi i casi in cui:
    • Lo stesso progetto pubblica un componente successore.
    • Un altro progetto assume la manutenzione di un componente abbandonato, incluso tramite un fork.
    • Un altro progetto pubblica un componente successore.
  • Porte in cui non è presente alcuna sovrapposizione della piattaforma. Ad esempio, un sostituto solo per Windows di un componente Linux che non supporta Windows.
  • Porte che precedono questa politica e hanno un numero di utenti e collaboratori dimostrabilmente significativo.

I gestori di vcpkg valutano caso per caso le eccezioni di salvaguardia. Ad esempio, boringssl è stato aggiunto prima che i registri personalizzati fossero disponibili e rimane nel registro curato perché ha ancora utenti significativi, anche se openssl è il provider canonico per la famiglia di fork OpenSSL. L'accettazione precedente da sola non garantisce un'eccezione.

Le porte che non sono conformi a questo criterio non possono essere accettate nel registro curato.

Suggerimento

Se la porta non può essere inclusa nel Registro di sistema curato, è consigliabile pubblicare un registro personalizzato o usare una porta di sovrimpressione.

Porte devono essere testate in almeno un tripletto ufficiale

Tutte le porte nel registro curato devono essere testate in CI per almeno una terna ufficiale.

Le eccezioni vengono effettuate per:

  • Circostanze temporanee, ad esempio:
    • Il port non viene generato senza un aggiornamento dell'infrastruttura CI.
    • Il port non viene compilato a causa di un cambiamento significativo in una dipendenza a monte e stiamo lavorando per risolvere la situazione.
  • Porte che precedono questa politica e hanno un numero di utenti e collaboratori dimostrabilmente significativo.

Le nuove port che non possono essere testate in almeno una terna ufficiale non vengono accettate nell'archivio curato. I porti esistenti che non sono più conformi a questo criterio e non sono idonei per un'eccezione elencata in precedenza vengono rimossi dal registro. Ad esempio, se il test CI è stato disabilitato in ogni tripletta ufficiale supportata da una port e non viene applicata alcuna eccezione, la port viene rimossa dall'elenco.

Suggerimento

Se la porta non può essere inclusa nel Registro di sistema curato, è consigliabile pubblicare un registro personalizzato o usare una porta di sovrimpressione.

I componenti pacchettizzati devono essere stabili e gestiti attivamente

I componenti inseriti nel registro curato devono essere in fase di manutenzione attiva. È possibile che le porte per i componenti inattivi siano rimosse dall'elenco.

Un componente viene considerato inattivo se:

  • I gestori hanno dichiarato che il componente è stato abbandonato.
  • Il repository di origine è archiviato o non accetta più contributi.
  • I gestori non rispondono o non sono raggiungibili.
  • Non sono state apportate modifiche significative in molto tempo.

Sono previste eccezioni per i componenti fondamentali considerati maturi e stabili e che non subiscono modifiche frequenti. Ad esempio: zlib.

I componenti pacchettizzati devono essere maturi

I componenti inclusi nel registro curato devono essere maturi e destinati all'utilizzo da parte degli utenti di vcpkg. I componenti destinati all'uso personale devono essere pubblicati nei registry personalizzati.

Un componente è considerato abbastanza maturo per il registro curato, se una di queste affermazioni è vera:

  • Il componente ha una versione vecchia di almeno sei mesi.
  • Il componente ha mostrato almeno sei mesi di sviluppo pubblico attivo.
  • Il componente è una parte ufficiale di un progetto con almeno sei mesi di release o sviluppo pubblico attivo. Ad esempio, una nuova libreria Boost o un nuovo componente Qt.
  • Il componente dimostra una maturità equivalente ai requisiti precedenti sotto un altro aspetto.

Alcuni indicatori di immaturità dei componenti sono:

  • Il componente non viene visualizzato nei motori di ricerca.
  • Il componente ha frequenti ridenominazioni.
  • Conflitti con altre librerie.

Suggerimento

Se la porta non può essere inclusa nel Registro di sistema curato, è consigliabile pubblicare un registro personalizzato o usare una porta di sovrimpressione.

Struttura della richiesta pull

Effettuare richieste pull separate per porta

Le richieste pull più piccole sono più facili da esaminare. Le richieste pull devono apportare modifiche a una singola porta. In questo modo si riducono anche i tempi di attesa per i risultati dell'integrazione continua (CI).

Limitare i PR a una sola porta potrebbe non essere possibile in alcuni casi. Ad esempio, quando si modifica una porta, è necessario aggiornare o applicare patch ai consumer downstream.

Evitare modifiche cosmetiche non correlate

Non apportare modifiche cosmetiche non correlate a un port altrimenti non modificato, ad esempio la riformattazione, la ridenominazione delle variabili o la correzione di errori di digitazione. Queste modifiche consumano tempo di calcolo che sarebbe meglio impiegare altrove. Le modifiche che migliorano la correttezza della compilazione, la compatibilità, l'affidabilità o la riproducibilità non vengono considerate semplici solo perché i file installati rimangono invariati.

Usare nomi di porta distintivi

Il nome di una porta deve essere indicativo del relativo contenuto.

La ricerca del nome della porta in un motore di ricerca o in browser di pacchetti specializzati, ad esempio Repology, dovrebbe portare al componente corrispondente.

Le porte con nomi brevi o denominate dopo parole comuni richiedono la disambiguazione. Questo vale solo per il nome del port nel registro curato; il nome del componente in pacchetto e il relativo contenuto non devono necessariamente essere conformi a questo criterio.

Sono previste eccezioni per le porte che includono un componente con una forte associazione al nome della porta. Per esempio: libpng, openssl, o zlib.

Per conformarsi a questo criterio, le nuove porte con nomi ambigui possono usare un prefisso, ad esempio:

  • Proprietario, nome utente o organizzazione del repository. Esempio: google-cloud-cpp. Per i porting dei componenti ospitati su GitHub, il proprietario su GitHub è un prefisso <github owner>-<repository name>non ambiguo accettabile.
  • Nome di una suite a cui appartiene il pacchetto: boost-dll. Solo se il pacchetto è un componente ufficiale di tale suite.

Esempio: Nome porta ambiguo

Una porta con il nome ip è considerata ambigua perché:

  • il nome è troppo breve,
  • il nome è una parola comune e
  • il nome non è strettamente associato ad alcun componente singolare.

Per determinare se un nome è ambiguo, rimuovere i prefissi e i suffissi comuni seguenti usati da C++ e componenti open source dal nome della porta:

  • cpp
  • free
  • lib
  • open
  • numeri

Ad esempio: ip-cpp, libip e ip5, sono ambigui perché sono ridotti allo stesso ip stelo.

Limitare le ridenominazione delle porte

Per evitare confusione per gli utenti, una porta non deve essere rinominata più di una volta in un periodo di 12 mesi.

Utilizza le richieste pull di bozza su GitHub

Le richieste pull di GitHub Draft sono un ottimo modo per ottenere feedback ci o umano sul lavoro che non è ancora pronto per l'unione. La maggior parte delle nuove richieste pull devono essere aperte come bozze e convertite in richieste pull normali dopo il superamento dell'integrazione continua.

Per ulteriori informazioni sulle richieste pull di bozza di GitHub, vedere Introduzione alle richieste pull di bozza.

Un manutentore vcpkg può convertire la richiesta pull in bozza durante il processo di revisione, in genere quando si richiedono modifiche o si lasciano commenti che indicano quando contrassegnare la richiesta pull come pronta per la revisione.

Chiudere le richieste pull inattive

Un manutentore vcpkg può chiudere una PR dopo aver atteso un'azione da parte del collaboratore per più di 60 giorni. Il conto alla rovescia dell'inattività scorre solo quando è necessaria l'azione del collaboratore. Non viene eseguito durante l'attesa della richiesta pull per la verifica del lab di compilazione o la revisione da parte di un manutentore vcpkg.

Una richiesta pull è in uno stato verificabile quando:

  • Non ha controlli delle richieste pull non riuscite o il collaboratore richiede assistenza o giustifica il motivo degli errori.
  • Non ci sono richieste di modifiche o chiarimenti in sospeso da un manutentore di vcpkg.
  • Non sono presenti conflitti di fusione.

Il conto alla rovescia inizia quando la richiesta pull entra in uno stato che richiede un'azione di collaboratore. Ciò può verificarsi quando una richiesta pull viene aperta con problemi che il collaboratore deve affrontare o quando un manutentore vcpkg richiede modifiche o chiarimenti. Un manutentore vcpkg può contrassegnare la richiesta pull come bozza quando richiede un'azione al collaboratore.

Una risposta sostanziale del collaboratore reimposta il conto alla rovescia. Se la risposta risolve tutte le richieste in sospeso e la richiesta pull è pronta per la revisione, il conto alla rovescia si interrompe finché non è nuovamente richiesta l'azione del collaboratore. Se il collaboratore non risponde entro 60 giorni mentre è necessaria un'azione, la PR viene considerata non aggiornata e può essere chiusa a discrezione del gestore vcpkg.

Portfiles

Evitare funzioni di supporto deprecate

Al momento, gli helper seguenti sono obsoleti:

Alcune delle funzioni helper sostitutive si trovano nelle "porte degli strumenti software" per permettere agli utenti di fissare il comportamento a versioni specifiche, permettendo il blocco del comportamento degli helper in una versione particolare. Le porte degli strumenti devono essere aggiunte alla porta, "dependencies"come indicato di seguito:

{
  "name": "vcpkg-cmake",
  "host": true
},
{
  "name": "vcpkg-cmake-config",
  "host": true
}

Evita commenti eccessivi nei portfile

Idealmente, i file di porta devono essere brevi, semplici e dichiarativi il più possibile. Rimuovere i commenti della create piastra caldaia introdotti dal comando prima di inviare una richiesta pull.

Usare lettere minuscole per le stringhe di cifre esadecimali

Molte delle funzionalità di vcpkg si basano sul confronto di stringhe di cifre esadecimali. Alcuni esempi includono, ad esempio, hash SHA512, ID commit Git e hash degli oggetti albero.

Internamente, vcpkg usa la normalizzazione minuscola per i confronti di tali valori in cui la combinazione di maiuscole e minuscole è irrilevante. Tuttavia, gli strumenti basati sull'infrastruttura di vcpkg potrebbero non fare le stesse considerazioni. Per questo motivo, sono necessarie stringhe esadecimali

per la coerenza negli scenari seguenti:

  • Parametro SHA512 nelle funzioni helper vcpkg.
  • Parametro REF nelle funzioni helper vcpkg, quando il valore è una stringa esadecimale.
  • Oggetto git-tree nei file di database della versione.
  • Oggetto sha512 nel scripts/vcpkg-tools.json file.
  • Altre posizioni in cui la combinazione di maiuscole e minuscole della stringa esadecimale non è importante.

Le porte non devono essere dipendenti dal percorso

Le porte non devono cambiare comportamento in base a quali porte sono già installate in un modo che alteri i contenuti che quella porta installa. Si consideri ad esempio di avere una situazione simile alla seguente:

> vcpkg install a
> vcpkg install b
> vcpkg remove a

e

> vcpkg install b

I file installati da b devono essere gli stessi, indipendentemente dall'influenza dell'installazione precedente di a. Ciò significa che le porte non devono tentare di rilevare se un elemento viene fornito nell'albero installato da un'altra porta prima di eseguire alcune azioni. Una causa specifica e comune di questo comportamento "dipendente dal percorso" è descritta di seguito in "Quando si definiscono le funzionalità, controllare in modo esplicito le dipendenze".

Regola di attribuzione delle porte univoca

Nell'intero sistema vcpkg, nessuna delle due porte che un utente deve usare contemporaneamente potrebbe fornire lo stesso file. Se un port tenta di installare un file già fornito da un altro port, l'installazione avrà esito negativo. Se una porta vuole utilizzare un nome estremamente comune per un'intestazione, ad esempio, dovrebbe inserire tali intestazioni in una sottodirectory anziché in include.

Questa proprietà viene controllata regolarmente dalle esecuzioni di integrazione continua che tentano di installare tutte le porte nel Registro di sistema, che avranno esito negativo FILE_CONFLICTS se due porte forniscono lo stesso file.

Aggiungere esportazioni CMake in un namespace non ufficiale

Un core design ideale di vcpkg consiste nel non creare "lock-in" per gli utenti. Nel sistema di compilazione non dovrebbe esserci alcuna differenza tra fare affidamento su una libreria del sistema e fare affidamento su una libreria da vcpkg. A tale scopo, si evita di aggiungere esportazioni o destinazioni CMake alle librerie esistenti con "il nome ovvio", per consentire agli upstream di aggiungere esportazioni CMake ufficiali senza conflitti con vcpkg.

A tale scopo, tutte le configurazioni CMake esportate dalla porta, che non si trovano nella libreria upstream, devono avere unofficial- come prefisso. Eventuali destinazioni aggiuntive devono trovarsi nello spazio dei nomi unofficial::<port>::

Ciò significa che l'utente dovrebbe visualizzare:

  • find_package(unofficial-<port> CONFIG) come modo per ottenere il pacchetto specifico per vcpkg
  • unofficial::<port>::<target> come destinazione esportata da tale porta.

Esempi:

  • brotli crea il unofficial-brotli pacchetto, producendo la destinazione unofficial::brotli::brotli.

Ogni porta deve fornire un file denominato copyright nella cartella ${CURRENT_PACKAGES_DIR}/share/${PORT}. Se il contenuto della licenza di un pacchetto è disponibile all'interno dei file di origine, questo file deve essere creato da una chiamata a vcpkg_install_copyright(). vcpkg_install_copyright aggrega anche più file di copyright, se necessario.

vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE")

Un metodo precedente per creare manualmente questo file è con il comando incorporato file di CMake. Questo è sconsigliato a favore di vcpkg_install_copyright nelle nuove versioni, ma è ancora consentito.

file(INSTALL "${SOURCE_PATH}/LICENSE" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}" RENAME copyright)

Se il contenuto della licenza nei file di origine upstream non è in formato testo (ad esempio un file PDF), copyright deve contenere una spiegazione su come un utente può trovare i requisiti di licenza. Se possibile, deve includere anche un collegamento ai file di origine originali che indicano questo, in modo che gli utenti possano verificare se è aggiornato.

file(WRITE "${CURRENT_PACKAGES_DIR}/share/${PORT}/copyright" [[As of 2023-07-25, according to
https://github.com/GPUOpen-LibrariesAndSDKs/display-library/blob/master/Public-Documents/README.md#end-user-license-agreement
this software is bound by the "SOFTWARE DEVELOPMENT KIT LICENSE AGREEMENT" PDF located at
https://github.com/GPUOpen-LibrariesAndSDKs/display-library/blob/master/Public-Documents/ADL%20SDK%20EULA.pdf
]])

Vincoli di versione nelle porte

I vincoli di versione all'interno delle porte devono essere in genere evitati, in quanto possono ostacolare l'evoluzione indipendente dei componenti. L'aggiunta di tali vincoli è consentita solo quando esiste una giustificazione ben documentata, ad esempio incompatibilità comprovata con versioni precedenti specifiche. Questi vincoli non devono essere utilizzati semplicemente per mantenere la parità con i componenti indipendenti.

Le variabili in MAYBE_UNUSED_VARIABLES devono essere applicate ad almeno una configurazione

Quando si aggiunge una nuova variabile a MAYBE_UNUSED_VARIABLES per disattivare un avviso durante il passaggio di configurazione di CMake, è necessario aggiungere un commento che spiega il caso quando si applica la nuova variabile. Se una variabile non si applica in alcuna configurazione, è molto probabile che esista un bug sottostante (ad esempio, un nome di variabile con errori di ortografia) e che l'aggiunta della variabile non abbia alcun effetto effettivo sulla compilazione.

vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_OPTIONS
  FEATURES
    windowsfeature WINDOWS_OPTION
)

vcpkg_cmake_configure(
  SOURCE_PATH "${SOURCE_PATH}"
  OPTIONS
    ${FEATURE_OPTIONS}
  MAYBE_UNUSED_VARIABLES
    WINDOWS_OPTION # Applies only on Windows
)

Funzionalità

Non usare le funzionalità per implementare alternative

Le funzionalità devono essere considerate come funzionalità aggiuntive. Se port[featureA] installa e port[featureB] installa, allora port[featureA,featureB] deve essere installato. Inoltre, se una seconda porta dipende da [featureA] e una terza porta dipende da [featureB], l'installazione della seconda e della terza porta deve avere le relative dipendenze soddisfatte.

Le librerie in questa situazione devono scegliere una delle opzioni disponibili espresse in vcpkg, mentre gli utenti che desiderano una configurazione diversa devono utilizzare porte overlay in questo momento.

Gli esempi esistenti non verranno accettati oggi per garantire la compatibilità con le versioni precedenti:

  • libgit2, libzip, open62541 tutte hanno funzionalità per la selezione di un back-end TLS o di crittografia. curl dispone di diverse opzioni back-end di crittografia, ma consente di selezionarle in fase di esecuzione, ovvero la tenet precedente viene mantenuta.
  • darknet dispone di opencv2opencv3 funzionalità per controllare quale versione di OpenCV usare per le relative dipendenze.

Una funzionalità può coinvolgere la funzionalità di anteprima o beta

Nonostante quanto sopra riportato, se è presente un ramo di anteprima o simile in cui la funzionalità di anteprima ha una probabilità elevata di non interrompere la funzionalità non di anteprima (ad esempio, nessuna rimozione di API), una funzionalità è accettabile per modellare questa impostazione.

Esempi:

  • Gli SDK di Azure (nel formato azure-Xxx) hanno una public-preview funzionalità.
  • imgui dispone di una experimental-docking funzionalità che attiva il ramo di ancoraggio di anteprima e utilizza un commit di merge associato a ciascuna delle loro versioni numerate pubbliche.

Le funzionalità predefinite non devono aggiungere API

Annotazioni

Una funzionalità abilitata di default dal sistema di compilazione upstream non implica che la funzione debba essere aggiunta alle voci default-features. Poiché lo scopo previsto di non è quello di modellare le decisioni prese da upstream, ma di offrire convenienza agli utenti della modalità classica .

Le funzionalità predefinite sono destinate a garantire l'installazione di una build ragionevolmente funzionale di una libreria per i clienti che non sanno di utilizzarla. Se non sanno che usano una libreria, non possono sapere di elencare le funzionalità. Ad esempio, libarchive espone funzionalità che consentono algoritmi di compressione a un'interfaccia generica esistente. Se compilata senza tali funzionalità, la libreria potrebbe non avere utilità.

In questo caso, i clienti includono entrambi i progetti utente che usano il grafo dei pacchetti e i port downstream all'interno di tale grafo. Entrambi esprimono i requisiti di dipendenza tramite la stessa interfaccia della funzionalità.

Valutare attentamente se una funzionalità deve essere attivata per impostazione predefinita, perché la disabilitazione delle funzionalità predefinite è complessa.

Per disabilitare le funzionalità predefinite per una dipendenza transitiva:

  • Ogni modulo che dipende dal port deve disabilitare le proprie funzionalità predefinite nella dichiarazione di dipendenza usando "default-features": false.
  • Il progetto di primo livello deve anche denominare direttamente la dipendenza transitiva, nel relativo manifesto con "default-features": falseo nella vcpkg install riga di comando con [core].

La disabilitazione delle funzionalità predefinite non impedisce a un altro cliente di richiedere esplicitamente una qualsiasi di queste funzionalità.

Per questa regola, un'API è qualsiasi interfaccia esposta ai consumer, incluse interfacce di libreria, interfacce della riga di comando eseguibili e altre interfacce binarie. Una funzionalità può essere abilitata per impostazione predefinita quando aggiunge il comportamento dietro un'API esistente, ad esempio il supporto per algoritmi di compressione aggiuntivi tramite un'interfaccia generica esistente.

Nel registro curato di vcpkg, se una funzionalità aggiunge un'API, deve essere disattivata per impostazione predefinita. In caso di dubbi, non contrassegnare una funzionalità come predefinita.

Non usare le funzionalità per controllare le alternative nelle interfacce pubblicate

Se un consumatore di una porta dipende solo dalla funzionalità principale di tale porta, con alta probabilità non devono essere interrotti attivando la funzione. Ciò è ancora più importante quando l'alternativa non è controllata direttamente dal consumer, ma da impostazioni del compilatore come /std:c++17 / -std=c++17.

Gli esempi esistenti non verranno accettati oggi per garantire la compatibilità con le versioni precedenti:

  • redis-plus-plus[cxx17] controlla un polyfill ma non inserisce l'impostazione nell'albero installato.
  • ace[wchar] modifica tutte le API in modo da accettare const wchar_t* anziché const char*.

Una funzionalità può sostituire i polifill con gli alias forniti che la sostituzione viene inserita nell'albero installato

Nonostante quanto sopra riportato, le porte possono rimuovere i polifill con una funzionalità, purché:

  1. L'attivazione della funzionalità modifica i polifill in alias dell'entità polyfilled
  2. Lo stato del polyfill viene inserito nelle intestazioni installate, in modo che gli errori di runtime "impossibile" di ABI non corrispondenti siano improbabili
  3. È possibile che un consumer della porta scriva codice che funziona in entrambe le modalità, ad esempio usando un typedef che è polifillato o meno

Esempio:

  • abseil[cxx17] sostituisce absl::string_view con un'alternativa o std::string_view; la patch implementa il requisito di cottura.

Se è fondamentale esporre le alternative sottostanti, è consigliabile fornire messaggi in fase di compilazione per indicare all'utente come copiare la porta in una sovrimpressione privata:

set(USING_DOG 0)
message(STATUS "This version of LibContoso uses the Kittens backend. To use the Dog backend instead, create an overlay port of this with USING_DOG set to 1 and the `kittens` dependency replaced with `dog`.")
message(STATUS "This recipe is at ${CMAKE_CURRENT_LIST_DIR}")
message(STATUS "See the overlay ports documentation at https://github.com/microsoft/vcpkg/blob/master/docs/specifications/ports-overlay.md")

Tecniche di costruzione

Non usare le dipendenze fornitore

È preferibile creare un pacchetto di dipendenze separatamente in modo che gli utenti possano selezionarle e aggiornarle tramite vcpkg. Le dipendenze incluse nel vendor presentano diverse sfide:

  • Difficoltà di aggiornamento: Le dipendenze vendorizzate sono più difficili da monitorare e aggiornare, anche quando si applicano correzioni di sicurezza.
  • Conflitti di simboli: Una dipendenza incorporata può definire gli stessi simboli di un'altra versione della dipendenza, causando errori di runtime o comportamento non definito.
  • Conformità delle licenze: Le dipendenze incluse nel progetto possono nascondere i requisiti di licenza o creare problemi di compatibilità delle licenze.
  • Maggiore manutenzione: Mantenere sincronizzate le dipendenze vendorizzate con le versioni upstream aumenta il lavoro di manutenzione e può duplicare il lavoro tra i porting.

Per questi motivi, elimina le dipendenze dal fornitore ogni volta che è pratico. Le dipendenze incluse nel pacchetto non devono essere esposte al dominio di collegamento di un utente.

Un dominio di collegamento è il set di simboli che possono essere risolti tra loro in fase di esecuzione. In Windows, ogni DLL ha in genere un proprio dominio di collegamento. Nelle piattaforme con una tabella dei simboli a livello di processo, il dominio di collegamento include in genere l'intero processo.

Se un componente espone una dipendenza inclusa nel progetto allo stesso dominio di collegamento di una dipendenza selezionata tramite vcpkg, entrambe le copie possono definire gli stessi simboli. Ciò viola la regola di definizione singola e può causare errori di runtime o comportamento non definito. Il problema potrebbe verificarsi solo quando le due versioni differiscono abbastanza da essere incompatibili.

Una dipendenza inclusa nel progetto è consentita solo quando è completamente isolata dai domini di collegamento usati dai port downstream e dalle applicazioni utente. Ad esempio, uno strumento di build solo per host può contenere una dipendenza collegata staticamente se i file binari downstream non si collegano allo strumento e i simboli della dipendenza non possono entrare nei rispettivi domini di collegamento.

Preferire l'uso di CMake

Quando sono disponibili più sistemi di compilazione, preferire l'uso di CMake. Inoltre, quando appropriato, può essere più semplice e facile da mantenere riscrivere i sistemi di build alternativi in CMake usando direttive file(GLOB).

Esempi: abseil

Scegliere file binari statici o condivisi

Quando si compilano librerie CMake, vcpkg_cmake_configure() passerà il valore corretto per BUILD_SHARED_LIBS in base alla variante richiesta dall'utente.

È possibile calcolare parametri di configurazione alternativi usando string(COMPARE EQUAL "${VCPKG_LIBRARY_LINKAGE}" ...).

# portfile.cmake

string(COMPARE EQUAL "${VCPKG_LIBRARY_LINKAGE}" "static" KEYSTONE_BUILD_STATIC)
string(COMPARE EQUAL "${VCPKG_LIBRARY_LINKAGE}" "dynamic" KEYSTONE_BUILD_SHARED)

vcpkg_cmake_configure(
    SOURCE_PATH ${SOURCE_PATH}
    OPTIONS
        -DKEYSTONE_BUILD_STATIC=${KEYSTONE_BUILD_STATIC}
        -DKEYSTONE_BUILD_SHARED=${KEYSTONE_BUILD_SHARED}
)

Se una libreria non offre opzioni di configurazione per selezionare la variante di compilazione, è necessario applicare patch alla compilazione. Quando si esegue l'applicazione di patch a una compilazione, è consigliabile tentare sempre di massimizzare la manutenibilità futura della porta. In genere questo significa ridurre al minimo il numero di righe che devono essere toccate per risolvere il problema.

Esempio: Applicazione di patch a una libreria CMake per evitare la compilazione di varianti indesiderate

Ad esempio, quando si applica una patch a una libreria basata su CMake, può essere sufficiente aggiungere EXCLUDE_FROM_ALL ai target indesiderati e racchiudere la chiamata install(TARGETS ...) in un if(BUILD_SHARED_LIBS). Questo sarà più breve del wrapping o dell'eliminazione di ogni riga che menziona la variante indesiderata.

Per un progetto CMakeLists.txt con il contenuto seguente:

add_library(contoso SHARED contoso.c)
add_library(contoso_static STATIC contoso.c)

install(TARGETS contoso contoso_static EXPORT ContosoTargets)

install(EXPORT ContosoTargets
  FILE ContosoTargets
  NAMESPACE contoso::
  DESTINATION share/contoso)

Sostituire la install(TARGETS) riga con un blocco condizionale che esclude anche la destinazione indesiderata dalla compilazione predefinita:

add_library(contoso SHARED contoso.c)
add_library(contoso_static STATIC contoso.c)

if(BUILD_SHARED_LIBS)
  set_target_properties(contoso_static PROPERTIES EXCLUDE_FROM_ALL 1)
  install(TARGETS contoso EXPORT ContosoTargets)
else()
  set_target_properties(contoso PROPERTIES EXCLUDE_FROM_ALL 1)
  install(TARGETS contoso_static EXPORT ContosoTargets)
endif()

install(EXPORT ContosoTargets
  FILE ContosoTargets
  NAMESPACE contoso::
  DESTINATION share/contoso)

Quando si definiscono le funzionalità, controllare in modo esplicito le dipendenze

Quando si definisce una funzionalità che acquisisce una dipendenza facoltativa, assicurarsi che la dipendenza non venga usata accidentalmente quando la funzionalità non è abilitata in modo esplicito.

set(CMAKE_DISABLE_FIND_PACKAGE_ZLIB ON)
set(CMAKE_REQUIRE_FIND_PACKAGE_ZLIB OFF)
if ("zlib" IN_LIST FEATURES)
  set(CMAKE_DISABLE_FIND_PACKAGE_ZLIB OFF)
  set(CMAKE_REQUIRE_FIND_PACKAGE_ZLIB ON)
endif()

vcpkg_cmake_configure(
  SOURCE_PATH ${SOURCE_PATH}
  OPTIONS
    -DCMAKE_DISABLE_FIND_PACKAGE_ZLIB=${CMAKE_DISABLE_FIND_PACKAGE_ZLIB}
    -DCMAKE_REQUIRE_FIND_PACKAGE_ZLIB=${CMAKE_REQUIRE_FIND_PACKAGE_ZLIB}
)

Il frammento di codice seguente che usa vcpkg_check_features() è equivalente.

vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_OPTIONS
  FEATURES
    "zlib"    CMAKE_REQUIRE_FIND_PACKAGE_ZLIB
  INVERTED_FEATURES
    "zlib"    CMAKE_DISABLE_FIND_PACKAGE_ZLIB
)

vcpkg_cmake_configure(
    SOURCE_PATH ${SOURCE_PATH}
    OPTIONS
      ${FEATURE_OPTIONS}
)

ZLIB nel frammento è sensibile alle maiuscole e minuscole. Per ulteriori informazioni, vedere la documentazione CMAKE_DISABLE_FIND_PACKAGE_<PackageName> e CMAKE_REQUIRE_FIND_PACKAGE_<PackageName>.

Un file di input del linker installato in lib o debug/lib, ad esempio un .libfile , .a, .soo .dylib , viene considerato in conflitto se esegue una delle operazioni seguenti:

  • Definisce main.
  • Definisce malloc.
  • Definisce i simboli definiti anche in altre librerie.

Alcuni file di input del linker forniscono intenzionalmente sostituzioni con ambito limitato per i simboli che i consumer altrimenti definiscono o ottengono altrove. Ad esempio, l'gtest-main.lib di Google Test fornisce main per i file eseguibili di test i cui autori scelgono di usarlo invece di definire il proprio punto di ingresso.

Posizionare file di input del linker in conflitto in lib/manual-link o debug/lib/manual-link in modo che i sistemi di compilazione che collegano automaticamente i file dalla directory di libreria non li selezionino. Windows DLL rimangono in bin o debug/bin; posizionare le librerie di importazione in manual-link quando è necessario il collegamento esplicito. I consumer devono acconsentire esplicitamente al collegamento di questi file e sono responsabili di evitare definizioni in conflitto. Questa eccezione non è un meccanismo generale per la creazione di pacchetti di provider alternativi di un altro componente e lo spostamento di un file di input del linker in manual-link non isola i simboli dal dominio di linking del componente consumer.

Installazione di file binari predefiniti

Le port che installano artefatti predefiniti (solo binari) sono consentite ma fortemente sconsigliate, a condizione che gli artefatti non impediscano agli utenti di selezionare o aggiornare le dipendenze tramite vcpkg. La compilazione dall'origine è preferibile perché rispetta le impostazioni vcpkg che controllano il compilatore e i flag.

Le porte che soddisfano tutte le condizioni seguenti verranno rifiutate:

  1. Installare file binari predefiniti anziché crearli dall'origine e
  2. Tali file binari incorporano o richiedono dipendenze in fase di esecuzione fornite da altri port nel registro curato e
  3. Gli artefatti installati espongono tali dipendenze a un dominio di collegamento che può contenere anche versioni selezionate tramite vcpkg.

Questa combinazione blocca efficacemente il grafico delle dipendenze alle versioni usate quando è stata prodotta la prebuild upstream. Se vcpkg aggiorna una dipendenza, zlib ad esempio o openssl, le versioni precompilate e selezionate dall'utente possono definire simboli incompatibili nello stesso dominio di collegamento. Ciò può causare violazioni della One Definition Rule, incompatibilità ABI o aggiornamenti di sicurezza mancanti.

Un artefatto espone una dipendenza ogni volta che tale dipendenza partecipa al dominio di collegamento di un utente, indipendentemente dal fatto che upstream intenda esporla. Tra queste vi sono anche:

  • Librerie collegabili dal .libconsumer, .a, .so, .dylib, o librerie di importazione che portano la dipendenza nel dominio di collegamento dell'utente.
  • Intestazioni installate che fanno riferimento (direttamente o tramite codice inline/modello) a simboli, tipi o macro da altre porte vcpkg.
  • File di configurazione di CMake o pkg-config installati che richiamano find_dependency() o Requires: su altri port di vcpkg.

Scenari consentiti (ma comunque sconsigliati):

  • Strumenti di supporto solo host usati in fase di compilazione i cui output vengono utilizzati, ma che non vengono linkati dalle porte dipendenti, purché isolino le dipendenze in bundle o si basino solo su librerie di runtime di sistema onnipresenti.
  • Le librerie predefinite le cui dipendenze in bundle rimangono interamente in domini di collegamento separati e non compaiono negli header installati o nelle interfacce esportate. Il collegamento statico da solo non isola una dipendenza dal link domain di un utente.
  • Pacchetti di asset, firmware o solo dati non collegati al codice utente.

Esempi non consentiti:

  • Libreria predefinita che collega in modo statico una copia privata di zlib ed espone i relativi simboli a un dominio di collegamento che può contenere anche la zlib versione selezionata tramite vcpkg.
  • Precompilato libfoo che installa lib/libfoo.lib più intestazioni, tra cui <zlib.h>, e è stato compilato in base a una versione specifica di zlib. Gli utenti quindi si collegano con libfoo per la compatibilità prevista.
  • SDK predefinito che installa un file di pacchetto CMake che chiama find_dependency(OpenSSL) mentre il file binario è stato compilato in base a una versione precedente di OpenSSL.

Mitigazioni/alternative:

  • Fornire una compilazione dal codice sorgente utilizzando script upstream o aggiungere un wrapper sottile per CMake.
  • Chiedi a upstream di pubblicare una versione basata sul codice sorgente o istruzioni per una build riproducibile; collega il problema upstream o la richiesta pull in un commento in portfile.cmake o vcpkg.json.
  • Usare una porta overlay o un registro privato per componenti precompilati specifici dell'organizzazione che non possono soddisfare queste regole.

Controllo delle versioni

Seguire le convenzioni comuni per il "version" campo

Quando si crea una nuova porta, seguire la convenzione di controllo delle versioni usata dall'autore del pacchetto. Quando si aggiorna la porta, continuare a usare la stessa convenzione, a meno che upstream non dica il contrario. Per una spiegazione completa delle convenzioni, vedere la documentazione sul controllo delle versioni.

Se upstream non ha pubblicato una versione da un po' di tempo, non modificare lo schema di versionamento della porta per ottenere le modifiche più recenti. Questi commit possono includere modifiche non pronte per l'ambiente di produzione. Chiedere invece al repository upstream di pubblicare una nuova versione.

Aggiornare il "port-version" campo per ogni porta modificata

Ogni PR che modifica una porta deve produrre una nuova versione di tale porta. Le richieste pull vengono unite con squash merge, quindi aggiorna la versione di ogni porta modificata una sola volta per richiesta pull, non una volta per commit o revisione della review.

Se la versione upstream non è stata modificata, incrementare il "port-version" campo. Se la versione upstream è stata modificata, reimpostare "port-version" su zero rimuovendo il campo o impostandolo su 0.

Ad esempio:

  • La versione del pacchetto di Zlib è attualmente 1.2.1, senza alcun esplicito "port-version" (equivalente a un "port-version" di 0).
  • Hai scoperto che il file di copyright errato è stato distribuito e l'hai corretto nel portfile.
  • È necessario aggiornare il "port-version" campo nel file manifesto in 1.

Per altre informazioni, vedere la documentazione sul controllo delle versioni.

Aggiornare i file di versione in versions/ per ogni port modificato

vcpkg usa un set di file di metadati per potenziare la funzionalità di controllo delle versioni. Questi file si trovano nei percorsi seguenti:

  • ${VCPKG_ROOT}/versions/baseline.json, (questo file è comune a tutte le porte) e
  • ${VCPKG_ROOT}/versions/${first-letter-of-portname}-/${portname}.json (uno per porta).

Ad esempio, per zlib i file pertinenti sono:

  • ${VCPKG_ROOT}/versions/baseline.json
  • ${VCPKG_ROOT}/versions/z-/zlib.json

Per ogni porta modificata in una richiesta pull, aggiornare i file di versione per registrare l'albero Git finale. Se si apportano ulteriori modifiche durante la revisione, eseguire vcpkg x-add-version <port-name> --overwrite-version per aggiornare la voce della versione non unita

senza incrementare "port-version" di nuovo.

Il metodo consigliato per aggiornare questi file consiste nell'eseguire il x-add-version comando, ad esempio:

vcpkg x-add-version zlib

Se si aggiornano più porte contemporaneamente, è possibile eseguire:

vcpkg x-add-version --all

per aggiornare i file per tutte le porte modificate contemporaneamente.

Per ulteriori informazioni, consultare gli articoli di riferimento sul controllo delle versioni e registri .

Applicazione di patch

vcpkg è una soluzione di creazione di pacchetti, non i proprietari finali dei componenti distribuiti. In alcuni casi è necessario applicare patch per migliorare la compatibilità dei componenti con le piattaforme o la compatibilità dei componenti tra loro.

  • Si vogliono evitare patch che:
    • upstream non sarebbe d'accordo con
    • causare instabilità o crash
    • non è possibile gestire gli aggiornamenti delle versioni upstream
    • sono sufficientemente grandi da causare l'entanglement delle licenze con il repository vcpkg stesso

Notifiche upstream e periodi di attesa

I proprietari upstream sono gli arbitri finali del comportamento del componente. I gestori vcpkg richiedono una notifica upstream per le patch rilevanti per upstream e per i bug identificati dagli strumenti di revisione del codice basati sull'intelligenza artificiale nelle nuove submission di port.

Patch rilevanti di Upstream

Se una patch potrebbe essere utile da upstream, i gestori vcpkg richiedono che upstream venga informato del contenuto della patch. Le patch che applicano un comportamento specifico di vcpkg non relativo all'upstream, ad esempio la rimozione di una dipendenza incorporata, non richiedono una notifica.

Per evitare situazioni in cui upstream non è d'accordo con la patch, i gestori vcpkg attendono almeno 30 giorni dopo la notifica upstream prima di applicare tali patch.

I gestori di vcpkg ignorano questo periodo di attesa se hanno un’elevata sicurezza che la modifica sia corretta. Esempi di patch ad alta attendibilità includono, ad esempio:

  • L'accettazione di upstream come patch (ad esempio, il backporting di una modifica specifica da una richiesta pull che upstream ha unito).
  • Aggiunta di #include mancanti.
  • Correzioni di codice prodotto piccole e ovvie (ad esempio, inizializzazione di una variabile non inizializzata).
  • Disabilitazione di componenti irrilevanti in-vcpkg della compilazione, ad esempio test o esempi.

Bug identificati dall'intelligenza artificiale nei nuovi porting

Il registro curato mira a evitare di distribuire codice con vulnerabilità note sfruttabili, ma i gestori vcpkg non possono controllare in modo completo il codice sorgente di ogni componente. I risultati della revisione del codice tramite IA non sono, da soli, una determinazione finale che il codice upstream è vulnerabile.

Quando gli strumenti di revisione del codice basati sull'intelligenza artificiale identificano un bug durante la revisione di una nuova richiesta di port, i gestori di vcpkg richiedono che il bug venga segnalato a upstream, seguendo il processo di segnalazione di sicurezza del progetto per bug potenzialmente sfruttabili. Questo requisito si applica anche quando l'individuazione riguarda il codice upstream che il porting non corregge.

  • Se upstream determina che il comportamento segnalato non è un bug, i gestori vcpkg accettano tale determinazione come finale e non rifiutano la nuova proposta di port sulla base di tale conclusione.
  • Se upstream corregge il bug, i manutentori di vcpkg accettano la versione corretta o una patch approvata da upstream, nel rispetto della policy sulle patch e degli altri requisiti per le nuove port.
  • Se upstream non risponde entro 30 giorni dalla segnalazione del bug, per impostazione predefinita i gestori di vcpkg considerano la segnalazione dell'IA come un problema sfruttabile e chiudono la nuova proposta di port.

Le eccezioni ad alta affidabilità al periodo di attesa della patch non esonerano da questo requisito di segnalazione dei bug né dalla necessità di una risposta upstream.

Preferire le opzioni rispetto all'applicazione di patch

È preferibile impostare le opzioni in una chiamata a vcpkg_configure_xyz() piuttosto che modificare direttamente le impostazioni.

Opzioni comuni che consentono di evitare l'applicazione di patch:

  • [MSBUILD] <PropertyGroup> è possibile eseguire l'override delle impostazioni all'interno del file di progetto tramite /p: parametri
  • [CMAKE] Le chiamate a find_package(XYz) negli script CMake possono essere disabilitate tramite -DCMAKE_DISABLE_FIND_PACKAGE_XYz=ON
  • [CMAKE] Le variabili della cache (dichiarate come set(VAR "value" CACHE STRING "Documentation") o option(VAR "Documentation" "Default Value")) possono essere sottoposte a override semplicemente passandole nella riga di comando come -DVAR:STRING=Foo. Un'eccezione rilevante è se il FORCE parametro viene passato a set(). Per altre informazioni, vedere la documentazione di CMake set

Preferisce scaricare le patch approvate per controllarle nella porta

Se una patch approvata o unita può essere ottenuta da un commit upstream, scaricarla e applicarla invece di inserirla nel port. Questo processo è preferibile perché:

  • Conferma che upstream ha accettato le modifiche della patch.
  • Semplifica il processo di revisione spostando la responsabilità a monte.
  • Riduce le dimensioni del repository vcpkg per gli utenti che non usano la patch.
  • Evita conflitti di licenza con il repository vcpkg.

Scaricare le patch solo dagli URL vincolati a un ID commit completo, non dagli URL diff delle richieste pull o di merge il cui contenuto può cambiare. Quando si scarica una patch di commit da GitHub o GitLab, aggiungere ?full_index=1 all'URL. Questo parametro richiede ID oggetto completi nella diff; non rende immutabile un URL modificabile.

Ad esempio:

https://github.com/linux-audit/audit-userspace/commit/f8e9bc5914d715cdacb2edc938ab339d5094d017.patch?full_index=1

Preferire l'applicazione di patch rispetto all'override dei VCPKG_<VARIABLE> valori

Alcune variabili precedute da VCPKG_<VARIABLE> hanno un equivalente CMAKE_<VARIABLE>. Tuttavia, non tutti vengono passati alla compilazione interna del pacchetto (vedere implementazione: Toolchain di Windows).

Si consideri l'esempio seguente:

set(VCPKG_C_FLAGS "-O2 ${VCPKG_C_FLAGS}")
set(VCPKG_CXX_FLAGS "-O2 ${VCPKG_CXX_FLAGS}")

L'uso delle vcpkg toolchain predefinite funziona perché il valore di VCPKG_<LANG>_FLAGS viene inoltrato alla variabile CMAKE_<LANG>_FLAGS appropriata. Tuttavia, una toolchain personalizzata che non riconosce le variabili di vcpkg non le inoltra.

Per questo motivo, è preferibile applicare patch direttamente al sistema di compilazione quando si imposta CMAKE_<LANG>_FLAGS.

Ridurre al minimo le patch

Quando si apportano modifiche a una libreria, cercare di ridurre al minimo il diff finale. Ciò significa che non è consigliabile riformattare il codice sorgente upstream quando si apportano modifiche che interessano un'area. Quando si disabilita un'istruzione condizionale, è preferibile aggiungere un AND FALSE o un && 0 alla condizione piuttosto che eliminare ogni riga del condizionale. Se è necessario disabilitare un'area di grandi dimensioni, è più breve aggiungere un if(0) o un #if 0 attorno all'area anziché eliminare ogni riga nella patch.

Non aggiungere patch se la porta è obsoleta e l'aggiornamento della porta a una versione rilasciata più recente risolverebbe lo stesso problema. vcpkg preferisce aggiornare le porte rispetto all'applicazione di patch alle versioni obsolete.

Ciò consente di mantenere le dimensioni del repository vcpkg inattivo, nonché di migliorare la probabilità che la patch venga applicata alle versioni di codice future.

Non implementare funzionalità nelle patch

Lo scopo dell'applicazione di patch in vcpkg è abilitare la compatibilità con compilatori, librerie e piattaforme. Non serve ad implementare nuove funzionalità anziché seguire le corrette procedure di Open Source (invio di un Issue/PR/ecc.).

Non creare test/documentazione/esempi per impostazione predefinita

Quando si invia una nuova porta, verificare la presenza di opzioni come BUILD_TESTS o o WITH_TESTSPOCO_ENABLE_SAMPLES e assicurarsi che i file binari aggiuntivi siano disabilitati. Ciò riduce al minimo i tempi di compilazione e le dipendenze per l'utente medio.

Facoltativamente, è possibile aggiungere una test funzionalità che consente di compilare i test, ma non deve essere presente nell'elenco Default-Features .

Consentire agli utenti esistenti della libreria di passare a vcpkg

Non aggiungere CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS

A meno che l'autore della libreria non lo usi già, non è consigliabile usare questa funzionalità di CMake perché interagisce male con i modelli C++ e interrompe determinate funzionalità del compilatore. Le librerie che non forniscono un file con estensione def e non usano dichiarazioni __declspec() semplicemente non supportano le compilazioni condivise per Windows e devono essere contrassegnate come tali:

if(VCPKG_TARGET_IS_WINDOWS)
    vcpkg_check_linkage(ONLY_STATIC_LIBRARY)
endif()

Non rinominare i file binari all'esterno dei nomi forniti da upstream

Ciò significa che se la libreria upstream ha nomi diversi nella versione e nel debug (libx e libxd), la libreria di debug non deve essere rinominata in libx. Viceversa, se la libreria upstream ha lo stesso nome nel rilascio e nel debug, non è consigliabile introdurre un nuovo nome.

Avvertenza importante:

  • Le varianti statiche e condivise spesso devono essere rinominate in uno schema comune. In questo modo i consumer possono usare un nome comune ed essere ignoranti del collegamento downstream. Questo è sicuro perché ne facciamo una sola alla volta disponibile.

Se una libreria genera file di integrazione CMake (foo-config.cmake), la ridenominazione deve essere effettuata applicando patch direttamente alla build di CMake, invece di limitarsi a eseguire file(RENAME) semplicemente sugli archivi/LIB di output.

Infine, i file DLL in Windows non devono mai essere rinominati dopo la compilazione perché interrompe i DATABASE generati.

Manifesti

È necessario che il file manifesto sia formattato. Usare il comando seguente per formattare tutti i file manifesto:

> vcpkg format-manifest --all

Trigemini

Attualmente non si accettano richieste di aggiunta di triplette non della community. L'innalzamento di livello dalla community allo stato di triplette completo si basa principalmente sul budget per l'hardware necessario a testare tali componenti tripli e sarà guidato dalle metriche inviate da vcpkg per massimizzare la probabilità che ciò che le persone effettivamente usano sia completamente testato.

Si aggiungeranno triplette della community se:

  • Si è dimostrato che le persone utilizzeranno effettivamente quel gruppo della comunità; e
  • non sappiamo che una tripletta sia rotta.

Ad esempio, non è stato aggiunto un terzetto in https://github.com/microsoft/vcpkg/pull/29034 perché l'autore stava solo cercando di "completare il set" anziché indicare che avrebbero effettivamente utilizzato un elemento del genere e non è stato aggiunto linux-dynamic fino a quando non è stata creata la soluzione patchelf per rendere i risultati rilocabili.

Note utili sull'implementazione

I file porta vengono eseguiti in modalità script

Mentre portfile.cmake e CMakeLists.txt condividono una sintassi comune e i costrutti fondamentali del linguaggio CMake (aka "Comandi di scripting"), i portfile (file di porta) vengono eseguiti in "Modalità script", mentre i file CMakeLists.txt vengono eseguiti in "Modalità progetto". La differenza più importante tra queste due modalità è che "Modalità script" non ha i concetti di "Toolchain", "Language" e "Target". Eventuali comportamenti, inclusi i comandi di scripting, che dipendono da questi costrutti (ad esempio CMAKE_CXX_COMPILER, CMAKE_EXECUTABLE_SUFFIX, ) CMAKE_SYSTEM_NAMEnon saranno corretti.

I Portfile hanno accesso diretto alle variabili impostate nel file triplet, ma CMakeLists.txt non ce l'hanno (anche se spesso avviene una traduzione -- VCPKG_LIBRARY_LINKAGE rispetto a BUILD_SHARED_LIBS).

I file di porta e le compilazioni di Project richiamati dai file di porta vengono eseguiti in processi diversi. Concettualmente:

+----------------------------+       +------------------------------------+
| CMake.exe                  |       | CMake.exe                          |
+----------------------------+       +------------------------------------+
| Triplet file               | ====> | Toolchain file                     |
| (x64-windows.cmake)        |       | (scripts/buildsystems/vcpkg.cmake) |
+----------------------------+       +------------------------------------+
| Portfile                   | ====> | CMakeLists.txt                     |
| (ports/foo/portfile.cmake) |       | (buildtrees/../CMakeLists.txt)     |
+----------------------------+       +------------------------------------+

Per determinare l'host in un file di porta, le variabili CMake standard sono appropriate (CMAKE_HOST_WIN32).

Per determinare la destinazione in un file di porta, è necessario usare le variabili triplet vcpkg (VCPKG_CMAKE_SYSTEM_NAME).

Per un'enumerazione completa delle possibili impostazioni, vedere anche la documentazione del triplet.