Guida del manutentore
Questo documento elenca un set di criteri da applicare durante l'aggiunta o l'aggiornamento di una ricetta delle porte. È destinato a svolgere il ruolo di Manuale dei criteri di Debian, Linee guida per i gestori di Homebrew e il cookbook formula di Homebrew.
Obiettivi generali di progettazione del Registro di sistema
Le porte nella baseline corrente devono essere installabili contemporaneamente
Si vuole essere in grado di mostrare agli utenti downstream delle librerie nel Registro di sistema curato che la combinazione di librerie in una determinata baseline pubblicata è stata testata per lavorare insieme in almeno alcune configurazioni. Consentendo alle porte di escludersi l'una dall'altra, la possibilità di testare tali configurazioni, poiché il numero di compilazioni necessarie per tali test aumenta con l'aumento 2^number_of_such_cases
di . Inoltre, l'installazione di dipendenze aggiuntive è sempre considerata "sicura": non esiste alcun modo per una porta o un utente finale di affermare che una dipendenza non è installata nei propri requisiti.
Se si vuole rappresentare una situazione alternativa di questo tipo per gli utenti, valutare la possibilità di descrivere come un utente può creare una porta di sovrapposizione che implementi il modulo alternativo con un commento anziché portfile.cmake
provare ad aggiungere porte aggiuntive non compilate nell'integrazione continua del Registro di sistema curato. Ad esempio, vedere glad@0.1.36.
Prima dell'introduzione dei registri, sono state accettate diverse porte non testate come alternative, ad esempio boringssl
, che potrebbero semplificare la creazione di porte sovrapposte. Questa operazione non è più accettata perché i registri consentono la pubblicazione di queste porte non con test senza modificare il Registro di sistema curato.
Struttura della richiesta pull
Effettuare richieste pull separate per porta
Quando possibile, separare le modifiche in più richieste pull. Questo li rende notevolmente più facili da esaminare e impedisce problemi con un set di modifiche di mantenere ogni altra modifica.
Evitare modifiche semplici nei file non modificati
Ad esempio, evitare la riformattazione o la ridenominazione delle variabili nei file di porta che altrimenti non hanno alcun motivo di essere modificate per il problema. Tuttavia, se è necessario modificare il file per lo scopo principale della richiesta pull (aggiornamento della libreria), le modifiche ovviamente vantaggiose come la correzione degli errori di digitazioni sono apprezzate!
Controllare i nomi rispetto ad altri repository
I nomi delle porte devono tentare di essere ambigui su quale pacchetto viene installata la porta. Idealmente, la ricerca del nome della porta in un motore di ricerca dovrebbe portare rapidamente al progetto corrispondente. Un buon servizio per controllare molti nomi di pacchetti in più repository contemporaneamente è La topologia.
I progetti con nomi brevi o denominati dopo parole comuni possono richiedere la disambiguazione, specialmente quando non sono presenti progetti con un'associazione forte alla parola specificata. Ad esempio, una porta con il nome ip
non è accettabile perché è probabile che più progetti vengano denominati in modo analogo.
Esempi di buoni ambiguità sono:
- Nome utente o organizzazione del proprietario del repository:
google-cloud-cpp
. - Il nome di una suite di librerie del progetto fa parte di:
boost-dll
.
I prefissi e i suffissi comuni usati da C++ e i progetti open source non sono ambiguità validi, alcuni esempi includono, ma non sono limitati a:
cpp
,free
,lib
,open
,- aggiunti
Ad esempio, quando si confrontano i nomi di porta seguenti: ip-cpp
libip
e ip5
e rimuovendo gli ambiguità non validi, tutti vengono ridotti allo stesso stelo (ip
) e pertanto vengono considerati con lo stesso nome.
Viene fatta un'eccezione a questa linea guida per i nomi fortemente associati a un singolo progetto. Ad esempio: libpng
e openssl
zlib
.
Usare le richieste pull della bozza di 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 deve essere aperta come bozze e convertita in richieste pull normali dopo il passaggio dell'integrazione continua.
Per altre informazioni sulle richieste pull di GitHub Draft, vedere Introduzione alle richieste pull bozza.
Portfiles
Evitare funzioni helper deprecate
Al momento, gli helper seguenti sono deprecati:
vcpkg_extract_source_archive_ex()
deve essere sostituito dall'overload supportato divcpkg_extract_source_archive()
(conARCHIVE
)- L'overload deprecato di
vcpkg_extract_source_archive()
senzaARCHIVE
deve essere sostituito dall'overload supportato conARCHIVE
. vcpkg_apply_patches()
deve essere sostituito dagliPATCHES
argomenti degli helper "extract" (ad esempiovcpkg_from_github()
)vcpkg_build_msbuild()
deve essere sostituito davcpkg_install_msbuild()
vcpkg_copy_tool_dependencies()
deve essere sostituito davcpkg_copy_tools()
vcpkg_configure_cmake
deve essere sostituito davcpkg_cmake_configure()
dopo la rimozionePREFER_NINJA
vcpkg_build_cmake
deve essere sostituito davcpkg_cmake_build()
vcpkg_install_cmake
deve essere sostituito davcpkg_cmake_install()
vcpkg_fixup_cmake_targets
deve essere sostituito davcpkg_cmake_config_fixup
Alcune delle funzioni helper sostitutive si trovano in "porte degli strumenti" per consentire ai consumer di aggiungere il proprio comportamento a versioni specifiche, per consentire il blocco del comportamento degli helper in una determinata versione. 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
}
Evitare commenti eccessivi nei file di porta
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.
Le porte non devono essere dipendenti dal percorso
Le porte non devono modificare il comportamento in base alle porte già installate in un modulo che modifica il contenuto installato dalla porta. 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 una porta tenta di installare un file già fornito da un altro file, l'installazione avrà esito negativo. Se una porta vuole usare un nome estremamente comune per un'intestazione, ad esempio, deve 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 uno spazio dei nomi 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 a seconda di una libreria dal sistema e a seconda di 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 unofficial::<port>::
nomi .
Ciò significa che l'utente dovrebbe visualizzare:
find_package(unofficial-<port> CONFIG)
come modo per ottenere il pacchetto unique-to-vcpkgunofficial::<port>::<target>
come destinazione esportata da tale porta.
Esempi:
brotli
crea ilunofficial-brotli
pacchetto, producendo la destinazioneunofficial::brotli::brotli
.
Installare il file di copyright
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
in nuove porte, 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 progetti. 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 solo per mantenere la parità con i progetti indipendenti.
Funzionalità
Non usare le funzionalità per implementare alternative
Le funzionalità devono essere considerate come funzionalità aggiuntive. Se port[featureA]
installa e port[featureB]
installa, port[featureA,featureB]
è necessario installare . Inoltre, se una seconda porta dipende [featureA]
da 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 e gli utenti che desiderano un'impostazione diversa devono usare le porte di sovrimpressione 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
disponeopencv2
di ,opencv3
, 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 unapublic-preview
funzionalità. imgui
include unaexperimental-docking
funzionalità che coinvolge il ramo di ancoraggio di anteprima che usa un commit di merge collegato a ognuna delle versioni numerate pubbliche.
Le funzionalità predefinite non devono aggiungere API
Le funzionalità predefinite sono destinate a garantire l'installazione di una build ragionevolmente funzionale di una libreria per i clienti che non lo conoscono. 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à.
È necessario valutare attentamente se una funzionalità deve essere attivata per impostazione predefinita, perché la disabilitazione delle funzionalità predefinite è complessa.
La disabilitazione di una funzionalità predefinita come consumer "transitivo" richiede:
- Tutti i clienti disabilitano in modo esplicito le funzionalità predefinite tramite
"default-features": false
o incluso[core]
nell'elenco delle funzionalità nella riga di comando. - Denominazione della dipendenza transitiva dalla
vcpkg install
riga di comando o come dipendenza diretta nel manifesto di primo livello
Nel Registro di sistema curato di vcpkg, se la funzionalità aggiunge API aggiuntive, eseguibili o altri file binari, 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 consumer di una porta dipende solo dalla funzionalità principale di tale porta, con probabilità elevata non deve essere interrotta attivando la funzionalità. 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 accettareconst 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é:
- L'attivazione della funzionalità modifica i polifill in alias dell'entità polyfilled
- Lo stato del polyfill viene inserito nelle intestazioni installate, in modo che gli errori di runtime "impossibile" di ABI non corrispondenti siano improbabili
- È 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]
modificheabsl::string_view
a una sostituzione ostd::string_view
; la patch implementa il requisito di cottura.
Soluzioni consigliate
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 compilazione
Non usare le dipendenze fornitore
Non usare copie incorporate delle librerie. Tutte le dipendenze devono essere suddivise e in pacchetto separatamente in modo che possano essere aggiornate e gestite.
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 gestibile riscrivere i sistemi di compilazione alternativi in CMake usando file(GLOB)
direttive.
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 alternativi per configurare i parametri 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 esegue l'applicazione di patch a una libreria basata su CMake, può essere sufficiente aggiungere destinazioni indesiderate ed eseguire EXCLUDE_FROM_ALL
il wrapping della install(TARGETS ...)
chiamata in un oggetto 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)
È necessario applicare patch solo alla install(TARGETS)
riga.
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 fa distinzione tra maiuscole e minuscole. Per altre informazioni, vedere la CMAKE_DISABLE_FIND_PACKAGE_<PackageName>
documentazione e CMAKE_REQUIRE_FIND_PACKAGE_<PackageName>
.
Inserire librerie in conflitto in una manual-link
directory
Una libreria viene considerata in conflitto se esegue una delle operazioni seguenti:
- Definire
main
- Definire malloc
- Definire i simboli dichiarati anche in altre librerie
Le librerie in conflitto sono in genere per progettazione e non sono considerate difetti. Poiché alcuni sistemi di compilazione si collegano a tutti gli elementi nella directory lib, questi devono essere spostati in una sottodirectory denominata manual-link
.
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 non venga specificato un valore upstream diverso. Per una spiegazione completa delle convenzioni, vedere la documentazione sul controllo delle versioni.
Se upstream non ha pubblicato una versione in un periodo di tempo, non modificare lo schema version-date
di controllo delle versioni della porta in 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 nel file manifesto di tutte le porte modificate
vcpkg usa questo campo per determinare se una determinata porta non è aggiornata e deve essere modificata ogni volta che cambia il comportamento della porta.
La convenzione consiste nell'usare il "port-version"
campo per le modifiche alla porta che non modificano la versione upstream e per reimpostare il "port-version"
valore su zero quando viene eseguito un aggiornamento alla versione upstream.
Ad esempio:
- La versione del pacchetto di Zlib è attualmente
1.2.1
, senza alcun esplicito"port-version"
(equivalente a un"port-version"
di0
). - Si è scoperto che il file di copyright errato è stato distribuito e corretto nel file di porta.
- È necessario aggiornare il
"port-version"
campo nel file manifesto in1
.
Per altre informazioni, vedere la documentazione sul controllo delle versioni.
Aggiornare i file di versione in versions/
di tutte le porte modificate
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
Ci aspettiamo che ogni volta che si aggiorna una porta, si aggiornano anche i file di versione.
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.
Nota
Questi comandi richiedono di aver eseguito il commit delle modifiche alle porte prima di eseguirle. Il motivo è che git SHA della directory delle porte è necessario in questi file di versione. Ma non preoccuparti, il x-add-version
comando avvisa se sono presenti modifiche locali che non sono state sottoposte a commit.
Per altre informazioni, vedere Informazioni di riferimento sul controllo delle versioni e Creazione di 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 vulnerabilità o arresti anomali
- non è possibile gestire gli aggiornamenti delle versioni upstream
- sono sufficientemente grandi da causare l'entanglement delle licenze con il repository vcpkg stesso
Inviare una notifica ai proprietari upstream per le patch pertinenti a monte
Se una patch potrebbe essere utile da upstream, upstream deve ricevere una notifica del contenuto della patch. Le patch che applicano comportamenti specifici di vcpkg non correlati a upstream, ad esempio la necessità di una dipendenza, non richiedono una notifica.
Per evitare situazioni in cui upstream non è d'accordo con la patch, attenderemo almeno 30 giorni per applicare tali patch.
Questo periodo di attesa verrà ignorato se si ha una maggiore probabilità che la modifica sia corretta. Esempi di patch ad alta attendibilità includono, ad esempio:
- L'accettazione upstream come patch (ad esempio, il backporting di una modifica specifica da una richiesta pull upstream è stato unito).
- Aggiunta di s mancanti
#include
. - 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.
Preferire le opzioni rispetto all'applicazione di patch
È preferibile impostare le opzioni in una chiamata a vcpkg_configure_xyz()
tramite l'applicazione diretta di patch alle 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")
ooption(VAR "Documentation" "Default Value")
) possono essere sottoposte a override semplicemente passandole nella riga di comando come-DVAR:STRING=Foo
. Un'eccezione rilevante è se ilFORCE
parametro viene passato aset()
. Per altre informazioni, vedere la documentazione di CMakeset
Preferisce scaricare le patch approvate per controllarle nella porta
Se un file patch approvato o unito può essere ottenuto da upstream, le porte devono provare a scaricarle e applicarle anziché inserirle come parte dei file di porta. Questo processo è preferibile perché:
- Conferma che upstream ha accettato le modifiche della patch
- Semplifica il processo di revisione spostando l'upstream onus
- Riduce le dimensioni del repository vcpkg per gli utenti che non usano la patch
- Evitare conflitti di licenza con il repository vcpkg
Le patch devono essere scaricate da un endpoint stabile per evitare conflitti SHA.
Quando si scaricano i file patch da una richiesta pull o si esegue il commit da GitHub e GitLab, il ?full_index=1
parametro deve essere aggiunto all'URL di download.
Esempi:
https://github.com/google/farmhash/pull/40.diff?full_index=1
https://github.com/linux-audit/audit-userspace/commit/f8e9bc5914d715cdacb2edc938ab339d5094d017.patch?full_index=1
https://gitlab.kitware.com/paraview/paraview/-/merge_requests/6375.diff?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 vcpkg
delle toolchain predefinite funziona perché il valore di VCPKG_<LANG>_FLAGS
viene inoltrato alla variabile appropriata CMAKE_LANG_FLAGS
. Tuttavia, una toolchain personalizzata che non riconosce vcpkg
le variabili non li 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 o AND FALSE
&& 0
alla condizione piuttosto che eliminare ogni riga dell'condizionale. Se è necessario disabilitare un'area di grandi dimensioni, è più breve aggiungere o if(0)
#if 0
intorno 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 è implementare nuove funzionalità anziché seguire una procedura open source appropriata (invio di un problema/richiesta pull/ecc.).
Non compilare test/docs/examples per impostazione predefinita
Quando si invia una nuova porta, verificare la presenza di opzioni come BUILD_TESTS
o o WITH_TESTS
POCO_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 con vcpkg_check_linkage(ONLY_STATIC_LIBRARY)
.
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 eseguita tramite l'applicazione di patch alla compilazione di CMake invece di chiamare file(RENAME)
semplicemente sugli archivi di output/LIB.
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
Tripletta
Attualmente non si accettano richieste di aggiunta di triplette non della community. L'innalzamento di livello dalla community allo stato triplo completo si basa principalmente sul budget per l'hardware per testare tali triplette e sarà guidato dalle metriche inviate da vcpkg per massimizzare la probabilità che le persone effettivamente usano siano completamente testate.
Si aggiungeranno triplette della community se:
- Si è dimostrato che le persone useranno effettivamente quel triplo della comunità; e
- non sappiamo che un triplo è rotto.
Ad esempio, non è stato aggiunto un triplo in https://github.com/microsoft/vcpkg/pull/29034 perché l'autore stava solo provando a "completare il set" anziché indicare che effettivamente userebbero un elemento di questo tipo e non è stato aggiunto linux-dynamic fino a quando non è stata creata la soluzione patchelf per rendere i risultati rilozionabili.
Note utili sull'implementazione
I file porta vengono eseguiti in modalità script
Mentre portfile.cmake
's e CMakeLists.txt
's condividono una sintassi comune e core costrutti di linguaggio CMake (aka "Comandi di scripting"), i file di porta vengono eseguiti in "Modalità script", mentre CMakeLists.txt
i file 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_NAME
non saranno corretti.
I file di porta hanno accesso diretto alle variabili impostate nel file triplet, ma CMakeLists.txt
non (anche se è spesso presente una traduzione che avviene - 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.