Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Dieses Dokument listet eine Reihe von Richtlinien auf, die Sie beim Hinzufügen oder Aktualisieren eines Portrezepts anwenden sollten. Es ist beabsichtigt, die Rolle von Debians Richtlinienhandbuch, Homebrews Betreuerrichtlinien und Homebrews Formula Cookbook zu erfüllen.
Allgemeine Ziele des Registrierungsentwurfs
Ports im aktuellen Basisplan müssen gleichzeitig installiert werden können
Wir möchten den nachgelagerten Benutzer*innen von Bibliotheken in der kuratierten Registrierung zeigen, dass die Kombination von Bibliotheken in jeder von uns veröffentlichten Baseline getestet wurde, um zumindest in einigen Konfigurationen zusammenzuarbeiten. Durch das Zulassen, dass Ports voneinander ausgeschlossen werden, wird die Möglichkeit zum Testen solcher Konfigurationen unterbrochen, da die Anzahl der für solche Tests erforderlichen Builds größer wird.2^number_of_such_cases
Darüber hinaus gilt die Installation zusätzlicher Abhängigkeiten immer als "sicher": Es gibt keine Möglichkeit, dass ein Port oder Endbenutzer bestätigt, dass eine Abhängigkeit nicht in ihren Anforderungen installiert ist.
Wenn Sie eine solche alternative Situation für Benutzer darstellen möchten, sollten Sie beschreiben, wie jemand einen Überlagerungsport erstellen kann, der das alternative Formular mit einem Kommentar portfile.cmake
implementiert, anstatt zu versuchen, zusätzliche Ports hinzuzufügen, die niemals in die fortlaufende Integration der kuratierten Registrierung integriert wurden. Siehe z. B . glad@0.1.36.
Vor der Einführung von Registrierungen haben wir mehrere nicht getestete Alternativ-Ports wie boringssl
akzeptiert, die das Erstellen von Überlagerungs-Ports erleichtern könnten. Dies wird nicht mehr akzeptiert, da Registrierungen die Veröffentlichung dieser nicht getesteten Ports zulassen, ohne die kuratierte Registrierung zu ändern.
Verwenden von Kleinbuchstaben für hexadezimale Ziffernzeichenfolgen
Viele der Features in vcpkg basieren auf dem Vergleichen von Zeichenfolgen von Hexadezimalziffern. Einige Beispiele sind, ohne darauf beschränkt zu sein, SHA512-Hashes, Git-Commit-IDs und Baumobjekthashes.
Intern verwendet vcpkg eine Kleinbuchstaben-Normalisierung für Vergleiche von Werten, bei denen die Groß-/Kleinschreibung irrelevant ist. Tools, die auf der Infrastruktur von vcpkg basieren, machen jedoch möglicherweise nicht dieselben Überlegungen. Aus diesem Grund benötigen wir hexadezimale Zeichenfolgen.
aus Gründen der Konsistenz in den folgenden Szenarien kleinzuschreiben:
- Der
SHA512
Parameter in vcpkg-Hilfsfunktionen. - Der
REF
Parameter in vcpkg-Hilfsfunktionen, wenn der Wert eine hexadezimale Zeichenfolge ist. - Das
git-tree
Objekt in Versionsdatenbankdateien. - Das
sha512
Objekt in derscripts/vcpkg-tools.json
Datei. - Andere Stellen, an denen die Schreibweise der hexadezimalen Zeichenfolge keine Rolle spielt.
PR-Struktur
Erstellen separater Pullanforderungen pro Port
Wann immer möglich, sollten Sie Änderungen in mehrere Pull Requests aufteilen. Dies erleichtert die Überprüfung erheblich und verhindert, dass Probleme mit einer Änderungssatz alle anderen Änderungen aufhalten.
Vermeiden sie triviale Änderungen in unberührten Dateien
Vermeiden Sie beispielsweise das Neuformatieren oder Umbenennen von Variablen in Portdateien, die andernfalls keinen Grund haben, geändert zu werden, um das Problem zu lösen. Wenn Sie die Datei jedoch für den primären Zweck der PR (Aktualisieren der Bibliothek) ändern müssen, werden offensichtlich vorteilhafte Änderungen wie das Beheben von Tippfehlern geschätzt!
Namen gegen andere Repositorys überprüfen
Port-Namen sollten nach Möglichkeit eindeutig angeben, welches Paket der Port installiert. Idealerweise sollte das Durchsuchen des Portnamens in einer Suchmaschine Sie schnell zum entsprechenden Projekt führen. Ein guter Dienst, um viele Paketnamen in mehreren Repositorys gleichzeitig zu überprüfen, ist Repology.
Projekte mit Kurznamen oder benannt nach allgemeinen Wörtern erfordern möglicherweise eine Mehrdeutigkeit, insbesondere wenn keine Projekte mit einer starken Zuordnung zum angegebenen Wort vorhanden sind. Beispielsweise ist ein Port mit dem Namen ip
nicht akzeptabel, da wahrscheinlich mehrere Projekte ähnlich benannt werden.
Beispiele für gute Klärungshilfen sind:
- Der Besitzername oder die Organisation des Repositorys:
google-cloud-cpp
. - Der Name einer Suite von Bibliotheken, zu der das Projekt gehört:
boost-dll
.
Allgemeine Präfixe und Suffixe, die von C++- und Open Source-Projekten verwendet werden, sind keine gültigen Unterscheidungsmerkmale, einige Beispiele umfassen, aber sind nicht beschränkt auf:
-
cpp
, -
free
, -
lib
, -
open
, - Zahlen
Wenn Sie beispielsweise die folgenden Portnamen vergleichen: ip-cpp
und libip
, und dabei die ungültigen Mehrdeutigkeiten von ip5
entfernen, werden sie alle auf denselben Stamm (ip
) reduziert und daher als denselben Namen betrachtet.
Eine Ausnahme dieser Richtlinie ist für Namen, die stark mit einem einzelnen Projekt verknüpft sind. Beispiel: libpng
, openssl
und zlib
.
PR-Entwürfe auf GitHub verwenden
GitHub Draft PRs sind eine großartige Möglichkeit, CI- oder menschliches Feedback zu Arbeiten zu erhalten, die noch nicht zum Zusammenführen bereit sind. Die meisten neuen PRs sollten als Entwürfe erstellt und in normale PRs umgewandelt werden, sobald die CI erfolgreich abgeschlossen ist.
Weitere Informationen zu GitHub-Entwurfs-PRs finden Sie unter Einführung von Entwurfs-Pullanforderungen.
Portdateien
Vermeiden veralteter Hilfsfunktionen
Derzeit sind die folgenden Hilfsmittel veraltet:
-
vcpkg_extract_source_archive_ex()
sollte durch die unterstützte Überladung vonvcpkg_extract_source_archive()
(durchARCHIVE
) ersetzt werden - Die veraltete Überladung von
vcpkg_extract_source_archive()
ohneARCHIVE
sollte durch die unterstützte Überladung mitARCHIVE
ersetzt werden. -
vcpkg_apply_patches()
sollte durch die ArgumentePATCHES
der Hilfsfunktionen „extrahieren“ ersetzt werden (z. B.vcpkg_from_github()
) -
vcpkg_build_msbuild()
sollte durchvcpkg_install_msbuild()
ersetzt werden -
vcpkg_copy_tool_dependencies()
sollte durchvcpkg_copy_tools()
ersetzt werden - Nach dem Entfernen von
vcpkg_configure_cmake
solltevcpkg_cmake_configure()
durchPREFER_NINJA
ersetzt werden. -
vcpkg_build_cmake
sollte durchvcpkg_cmake_build()
ersetzt werden -
vcpkg_install_cmake
sollte durchvcpkg_cmake_install()
ersetzt werden -
vcpkg_fixup_cmake_targets
sollte durchvcpkg_cmake_config_fixup
ersetzt werden
Einige der Ersatzhilfsfunktionen befinden sich in „Tools-Ports“, damit Verbraucher*innen ihr Verhalten an bestimmte Versionen binden können, um das Verhalten der Hilfsprogramme an eine bestimmte Version zu binden. Tool-Ports müssen wie folgt zu den "dependencies"
Ihrer Ports hinzugefügt werden:
{
"name": "vcpkg-cmake",
"host": true
},
{
"name": "vcpkg-cmake-config",
"host": true
}
Vermeiden Sie übermäßige Kommentare in Portfiles
Im Idealfall sollten Portfiles kurz, einfach und so deklarativ wie möglich sein.
Entfernen Sie alle vom create
-Befehl eingeführten Textbausteinkommentare, bevor Sie einen PR übermitteln.
Ports dürfen nicht vom Pfad abhängig sein.
Ports dürfen ihr Verhalten nicht auf der Grundlage der bereits installierten Ports in einer Form ändern, die die von diesem Port installierten Inhalte verändern würde. Angenommen, dies liegt vor:
> vcpkg install a
> vcpkg install b
> vcpkg remove a
und
> vcpkg install b
Die durch b
installierten Dateien müssen identisch sein, unabhängig davon, ob sie von der vorherigen Installation von a
beeinflusst wurden. Dies bedeutet, dass Ports nicht versuchen müssen, zu erkennen, ob etwas in der installierten Struktur von einem anderen Port bereitgestellt wird, bevor sie eine Aktion ausführen. Eine bestimmte und häufige Ursache für ein solches "pfadabhängiges" Verhalten wird unten unter "Beim Definieren von Features, explizit Steuern von Abhängigkeiten" beschrieben.
Eindeutige Portzuordnungsregel
Im gesamten vcpkg-System dürfen keine zwei Ports, die von Benutzer*innen gleichzeitig verwendet werden, dieselbe Datei bereitstellen. Wenn ein Port versucht, eine Datei zu installieren, die bereits von einer anderen Datei bereitgestellt wurde, schlägt die Installation fehl. Wenn ein Port zum Beispiel einen sehr gebräuchlichen Namen für einen Header verwenden möchte, sollte dieser Header in einem Unterverzeichnis und nicht in include
platziert werden.
Diese Eigenschaft wird regelmäßig von kontinuierlichen Integrationsläufen überprüft, die versuchen, alle Ports in der Registrierung zu installieren, was mit FILE_CONFLICTS
fehlschlägt, wenn zwei Ports dieselbe Datei bereitstellen.
Hinzufügen von CMake-Exporten in einem inoffiziellen Namespace
Ein zentraler Designgrundsatz von vcpkg ist es, keine Abhängigkeiten für Benutzer zu schaffen. Im Build-System sollte es keinen Unterschied geben, ob man von einer Bibliothek des Systems oder von vcpkg abhängt. Zu diesem Zweck vermeiden wir es, CMake-Exporte oder -Ziele zu vorhandenen Bibliotheken mit dem „offensichtlichen Namen“ hinzuzufügen, um Upstreams zu ermöglichen, ihre eigenen offiziellen CMake-Exporte hinzuzufügen, ohne mit vcpkg in Konflikt zu geraten.
Aus diesem Grund sollten alle vom Port exportierten CMake-Konfigurationen, die sich nicht in der Upstream-Bibliothek befinden, als Präfix unofficial-
aufweisen. Alle zusätzlichen Ziele sollten sich im unofficial::<port>::
Namespace befinden.
Dies bedeutet, dass der Benutzer Folgendes sehen sollte:
-
find_package(unofficial-<port> CONFIG)
als Methode, um an das für vcpkg eindeutige Paket zu gelangen -
unofficial::<port>::<target>
als exportiertes Ziel aus diesem Port.
Beispiele:
-
brotli
erstellt dasunofficial-brotli
Paket, das Zielunofficial::brotli::brotli
erzeugt.
Copyrightdatei installieren
Jeder Port muss eine Datei mit dem Namen copyright
im Ordner ${CURRENT_PACKAGES_DIR}/share/${PORT}
bereitstellen. Wenn der Lizenzinhalt eines Pakets in seinen Quelldateien verfügbar ist, sollte diese Datei durch einen Aufruf vcpkg_install_copyright()
erstellt werden.
vcpkg_install_copyright
Bündelt bei Bedarf auch mehrere Copyright-Dateien.
vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE")
Eine ältere Methode zum manuellen Erstellen dieser Datei ist mit dem integrierten file
Befehl von CMake. Davon wird zugunsten von vcpkg_install_copyright
bei neuen Ports abgeraten, ist aber weiterhin zulässig.
file(INSTALL "${SOURCE_PATH}/LICENSE" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}" RENAME copyright)
Wenn sich der Lizenzinhalt in den Upstreamquelldateien nicht in Textform befindet (z. B. eine PDF-Datei), copyright
sollte eine Erläuterung enthalten, wie ein Benutzer die Lizenzanforderungen finden kann. Wenn möglich, sollte es auch einen Link zu den ursprünglichen Quelldateien enthalten, die dies angeben, damit Benutzer überprüfen können, ob es auf dem neuesten Stand ist.
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
]])
Versionsbeschränkungen in Ports
Versionsbeschränkungen innerhalb von Ports sollten im Allgemeinen vermieden werden, da sie die unabhängige Entwicklung von Projekten behindern können. Das Hinzufügen solcher Einschränkungen ist nur zulässig, wenn eine gut dokumentierte Begründung vorhanden ist, z. B. nachgewiesene Inkompatibilität mit bestimmten früheren Versionen. Diese Einschränkungen sollten nicht nur verwendet werden, um die Parität mit unabhängigen Projekten aufrechtzuerhalten.
Variablen in MAYBE_UNUSED_VARIABLES
müssen für mindestens eine Konfiguration gelten.
Beim Hinzufügen einer neuen Variablen zu MAYBE_UNUSED_VARIABLES
um eine Warnung während des CMake-Konfigurationsvorgangs zu unterdrücken, müssen Sie einen Kommentar hinzufügen, der den Fall erklärt, wann die neue Variable zur Anwendung kommt. Wenn eine Variable in keiner Konfiguration angewendet wird, ist es sehr wahrscheinlich, dass ein zugrunde liegender Fehler vorhanden ist (z. B. ein falsch geschriebener Variablenname), und das Hinzufügen hat keine tatsächliche Auswirkung auf den Build.
vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_OPTIONS
FEATURES
windowsfeature WINDOWS_OPTION
)
vcpkg_configure_cmake(
SOURCE_PATH "${SOURCE_PATH}"
OPTIONS
${FEATURE_OPTIONS}
MAYBE_UNUSED_VARIABLES
# Applies only on Windows
WINDOWS_OPTION
)
Funktionen
Verwenden Sie keine Features, um Alternativen zu implementieren
Features müssen als additive Funktionalität behandelt werden. Wenn port[featureA]
installiert und port[featureB]
installiert werden, muss port[featureA,featureB]
installiert werden. Wenn ein zweiter Port von [featureA]
abhängt und ein dritter Port von [featureB]
abhängt, sollten bei der Installation sowohl des zweiten als auch des dritten Ports ihre Abhängigkeiten erfüllt werden.
Bibliotheken in dieser Situation müssen eine der in vcpkg angegebenen verfügbaren Optionen auswählen, und Benutzer*innen, die eine andere Einstellung benötigen, müssen derzeit Überlagerungsports verwenden.
Vorhandene Beispiele, die wir heute nicht akzeptieren würden, werden aus Gründen der Abwärtskompatibilität beibehalten.
-
libgit2
,libzip
open62541
alle verfügen über Features zum Auswählen eines TLS- oder Krypto-Back-End.curl
hat verschiedene Krypto-Back-End-Optionen, ermöglicht aber die Auswahl zwischen ihnen zur Laufzeit, was bedeutet, dass der obige Tenet beibehalten wird. -
darknet
verfügt überopencv2
,opencv3
, Features, um zu steuern, welche Version von opencv für seine Abhängigkeiten verwendet werden soll.
Ein Feature kann vorschau- oder Betafunktionen aktivieren
Ungeachtet der obigen Ausführungen ist ein Feature zur Modellierung dieser Einstellung akzeptabel, wenn es einen Vorschaubranch oder Ähnliches gibt, bei dem die Vorschaufunktionalität eine hohe Wahrscheinlichkeit hat, die Nicht-Vorschaufunktionalität nicht zu stören (z. B. keine API-Entfernungen).
Beispiele:
- Die Azure-SDKs (des Formulars
azure-Xxx
) weisen einpublic-preview
Feature auf. -
imgui
verfügt über einexperimental-docking
-Feature, das seinen Vorschau-Dockingbranch einbindet, bei dem an allen öffentlichen nummerierten Releases ein Merge-Commit angefügt ist.
Standardfeatures dürfen keine APIs hinzufügen
Standardfeatures sollen sicherstellen, dass ein vernünftig funktionsfähiger Build einer Bibliothek für Kunden installiert wird, die nicht wissen, dass sie sie verwenden. Wenn sie nicht wissen, dass sie eine Bibliothek verwenden, können sie die Features nicht auflisten. Beispielsweise stellt libarchive
Funktionen bereit, die Komprimierungsalgorithmen für eine bestehende generische Schnittstelle ermöglichen. Wird die Bibliothek ohne eine dieser Funktionen erstellt, hat sie möglicherweise keinen Nutzen.
Man muss sorgfältig überlegen, ob ein Feature standardmäßig aktiviert sein soll, da das Deaktivieren von Standardfeatures komplex ist.
Das Deaktivieren eines Standardfeatures als „transitiver“ Consumer erfordert Folgendes:
- Alle Kund*innen deaktivieren die Standardfeatures explizit über
"default-features": false
oder schließen[core]
in die Funktionsliste in der Befehlszeile ein. - Benennung von transitiven Abhängigkeiten auf der
vcpkg install
Befehlszeile oder als direkte Abhängigkeit im Manifest der obersten Ebene
Wenn das Feature in der kuratierten Registrierung von vcpkg zusätzliche APIs, ausführbare Dateien oder andere Binärdateien hinzufügt, muss sie standardmäßig deaktiviert sein. Markieren Sie im Zweifelsfall kein Feature als Standard.
Verwenden Sie keine Features, um Alternativen in veröffentlichten Schnittstellen zu steuern
Wenn ein Verbraucher eines Ports nur von der Kernfunktionalität dieses Ports abhängt, dürfen sie mit hoher Wahrscheinlichkeit nicht durch Aktivieren des Features unterbrochen werden. Dies ist noch wichtiger, wenn die Alternative nicht direkt vom Verbraucher gesteuert wird, sondern durch Compilereinstellungen wie /std:c++17
/ -std=c++17
.
Vorhandene Beispiele, die wir heute nicht akzeptieren würden, werden aus Gründen der Abwärtskompatibilität beibehalten.
-
redis-plus-plus[cxx17]
steuert ein Polyfill, integriert die Einstellung aber nicht in die installierte Struktur. -
ace[wchar]
ändert alle APIs, umconst wchar_t*
anstelle vonconst char*
zu akzeptieren.
Ein Feature kann Polyfills durch Aliase ersetzen, sofern der Ersatz in die installierte Struktur integriert ist.
Ungeachtet der obigen Ausführungen können Ports Polyfills mit einem Feature entfernen, sofern:
- bei Aktivierung des Feature die Polyfills in Aliase der Polyfill-Entität umgewandelt werden.
- der Zustand des Polyfills in den installierten Header integriert ist, sodass die Wahrscheinlichkeit von „unmöglichen“ Laufzeitfehlern aufgrund eines ABI-Konflikts gering ist.
- es möglich ist, dass ein Consumer des Ports Code schreibt, der in beiden Modi funktioniert, z. B. durch Verwendung einer Typdef mit oder ohne Polyfill.
Beispiel:
-
abseil[cxx17]
ändertabsl::string_view
in einen Ersatz oderstd::string_view
; der Patch implementiert die Baking-Anforderung.
Empfohlene Lösungen
Wenn es wichtig ist, die zugrunde liegenden Alternativen offenzulegen, empfehlen wir, Nachrichten zur Build-Zeit bereitzustellen, um den Benutzer darüber zu informieren, wie der Port in eine private Überlagerung kopiert werden kann.
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")
Bautechniken
Keine anbieterbezogenen Abhängigkeiten verwenden
Verwenden Sie keine eingebetteten Kopien von Bibliotheken. Alle Abhängigkeiten sollten separat aufgeteilt und verpackt werden, damit sie aktualisiert und verwaltet werden können.
Anbieterabhängigkeiten bringen verschiedene Herausforderungen mit sich, die mit den vcpkg-Zielen eines zuverlässigen, konsistenten und wartungsfähigen Paketverwaltungssystems in Widerspruch stehen:
Schwierigkeit bei Updates: Eingebettete Kopien von Bibliotheken erschweren das Nachverfolgen und Anwenden von Updates, einschließlich Sicherheitspatches, aus den upstream-Projekten. Dies führt zu potenziellen Sicherheitsrisiken und veralteten Abhängigkeiten im Ökosystem.
Symbolkonflikte: Eingebundene Abhängigkeiten können zu Symbolkonflikten führen, wenn mehrere Pakete unterschiedliche Versionen derselben Bibliothek enthalten.
Beispiel: Wenn Paket A die Bibliothek X (Version 1) und Paket B die Bibliothek X (Version 2) bereitstellt, kann eine Anwendung, die beide Pakete verknüpft, Laufzeitfehler oder nicht definiertes Verhalten aufgrund von widersprüchlichen Symbolen aufweisen.
Durch das getrennte Verpacken von Abhängigkeiten stellt vcpkg sicher, dass eine einzelne Version einer Bibliothek in allen Paketen verwendet wird, wodurch solche Konflikte beseitigt werden.
Lizenzkonformität: Eingebundene Abhängigkeiten können die Lizenzierung der eingebetteten Bibliotheken verdecken, möglicherweise gegen deren Bedingungen verstoßen oder Kompatibilitätsprobleme verursachen.
Erhöhte Wartungslast: Die Synchronisierung von lieferantenbezogenen Abhängigkeiten mit ihren upstream-Versionen erfordert erhebliche manuelle Anstrengungen und führt häufig zu doppelter Arbeit über Pakete hinweg.
Verwendung von CMake bevorzugen
Wenn mehrere Buildsysteme verfügbar sind, verwenden Sie lieber CMake.
Darüber hinaus kann es bei Bedarf einfacher und benutzerfreundlicher sein, alternative Buildsysteme mithilfe von file(GLOB)
Direktiven in CMake umzuschreiben.
Beispiele: abseil
Auswählen von statischen oder freigegebenen Binärdateien
Beim Erstellen von CMake-Bibliotheken wird vcpkg_cmake_configure()
den richtigen Wert für BUILD_SHARED_LIBS
basierend auf der vom Benutzer angeforderten Variante übergeben.
Sie können alternative Konfigurationsparameter mithilfe von string(COMPARE EQUAL "${VCPKG_LIBRARY_LINKAGE}" ...)
berechnen.
# 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}
)
Wenn eine Bibliothek keine Konfigurationsoptionen zum Auswählen der Buildvariante bietet, muss der Build gepatcht werden. Beim Patchen eines Builds sollten Sie immer versuchen, die zukünftige Wartung des Ports zu maximieren. Dies bedeutet in der Regel, die Anzahl der Zeilen zu minimieren, die berührt werden müssen, um das Problem zu beheben.
Beispiel: Patchen einer CMake-Bibliothek, um unerwünschte Varianten zu vermeiden
Wenn Sie z. B. eine CMake-basierte Bibliothek patchen, reicht es möglicherweise aus, EXCLUDE_FROM_ALL
zu unerwünschten Zielen hinzuzufügen und den install(TARGETS ...)
-Aufruf in einem if(BUILD_SHARED_LIBS)
zu umschließen. Dies ist kürzer als das Umschließen oder Löschen jeder Zeile, die die unerwünschte Variante erwähnt.
Für ein Projekt CMakeLists.txt
mit folgendem Inhalt:
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)
Nur die install(TARGETS)
Linie muss gepatcht werden.
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)
Wenn Sie Features definieren, steuern Sie explizit Abhängigkeiten
Stellen Sie beim Definieren eines Features, das eine optionale Abhängigkeit erfasst, sicher, dass die Abhängigkeit nicht versehentlich verwendet wird, wenn das Feature nicht explizit aktiviert ist.
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}
)
Der unten verwendete vcpkg_check_features()
Codeausschnitt ist gleichwertig.
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
im Codeausschnitt unterscheidet zwischen Groß-/Kleinbuchstaben. Weitere Informationen finden Sie in der CMAKE_DISABLE_FIND_PACKAGE_<PackageName>
- und CMAKE_REQUIRE_FIND_PACKAGE_<PackageName>
-Dokumentation.
Platzieren von widersprüchlichen Libs in einem manual-link
Verzeichnis
Eine Bibliothek gilt in folgenden Fällen als widersprüchlich:
-
main
definieren - Malloc definieren
- Definieren von Symbolen, die auch in anderen Bibliotheken deklariert sind
Widersprüchliche Bibliotheken sind in der Regel gewollt und werden nicht als Fehler angesehen. Da einige Buildsysteme mit allem im Lib-Verzeichnis verknüpft sind, sollten diese in ein Unterverzeichnis mit dem Namen manual-link
verschoben werden.
Versionsverwaltung
Folgen Sie den allgemeinen Konventionen für das "version"
-Feld
Folgen Sie beim Erstellen eines neuen Ports der vom Paketautor verwendeten Versionsverwaltungskonvention. Wenn Sie den Port aktualisieren, verwenden Sie weiterhin dieselbe Konvention, es sei denn, der Upstream sagt etwas anderes. Eine vollständige Erläuterung unserer Konventionen finden Sie in unserer Versionsverwaltungsdokumentation.
Wenn Upstream seit einiger Zeit keine neue Version veröffentlicht hat, ändern Sie das Versionsverwaltungsschema des Ports nicht in version-date
, um die neuesten Änderungen abzurufen. Diese Commits können Änderungen enthalten, die nicht zur Produktion bereit sind. Bitten Sie stattdessen das Upstream-Repository, eine neue Version zu veröffentlichen.
Aktualisieren des Felds "port-version"
in der Manifestdatei aller geänderten Ports
vcpkg verwendet dieses Feld, um zu bestimmen, ob ein bestimmter Port veraltet ist und geändert werden sollte, wann immer sich das Verhalten des Ports ändert.
Unsere Konvention besteht darin, das "port-version"
-Feld für Änderungen am Port zu verwenden, die die Upstream-Version nicht ändern, und "port-version"
auf Null zurückzusetzen, wenn die Upstream-Version aktualisiert wird.
Beispiel:
- Die Paketversion von Zlib ist zurzeit
1.2.1
, mit keinem expliziten"port-version"
(entspricht einem"port-version"
von0
). - Sie haben festgestellt, dass die falsche Copyrightdatei bereitgestellt wurde und dies in der Portdatei behoben wurde.
- Sie sollten das Feld
"port-version"
in der Manifestdatei auf1
aktualisieren.
Weitere Informationen finden Sie in der Versionsverwaltungsdokumentation .
Aktualisieren der Versionsdateien in versions/
bei allen geänderten Ports
vcpkg verwendet eine Reihe von Metadatendateien, um die Versionsverwaltungsfunktion zu unterstützen. Diese Dateien befinden sich an den folgenden Speicherorten:
-
${VCPKG_ROOT}/versions/baseline.json
, (diese Datei ist für alle Ports üblich) und -
${VCPKG_ROOT}/versions/${first-letter-of-portname}-/${portname}.json
(eine pro Port).
Beispielsweise sind für zlib
die relevanten Dateien:
${VCPKG_ROOT}/versions/baseline.json
${VCPKG_ROOT}/versions/z-/zlib.json
Wir erwarten, dass Sie bei jeder Aktualisierung eines Ports auch die Versionsdateien aktualisieren.
Die empfohlene Methode zum Aktualisieren dieser Dateien besteht darin, den x-add-version
Befehl auszuführen, z. B.:
vcpkg x-add-version zlib
Wenn Sie mehrere Ports gleichzeitig aktualisieren, können Sie stattdessen Folgendes ausführen:
vcpkg x-add-version --all
um die Dateien für alle geänderten Ports gleichzeitig zu aktualisieren.
Hinweis
Diese Befehle setzen voraus, dass Sie Ihre Änderungen an den Ports vorgenommen haben, bevor Sie sie ausführen. Der Grund dafür ist, dass die Git SHA des Portverzeichnisses in diesen Versionsdateien erforderlich ist. Aber keine Sorge, der x-add-version
Befehl wird Sie warnen, wenn Sie lokale Änderungen haben, die nicht festgeschrieben wurden.
Weitere Informationen finden Sie in den Artikeln zur Versionsverwaltung und zu Registrierungen.
Patchen
vcpkg ist eine Verpackungslösung, nicht die ultimativen Besitzer der von uns bereitgestellten Komponenten. In einigen Fällen müssen Patches angewendet werden, um die Kompatibilität von Komponenten mit Plattformen oder die Kompatibilität von Komponenten miteinander zu verbessern.
- Wir möchten Patches vermeiden, die:
- Upstream würde dem widersprechen
- Sicherheitsrisiken oder Abstürze verursachen
- wir sind nicht in der Lage, über Upstream-Versionsupdates hinweg zu warten
- sind groß genug, um eine Lizenzverschränkung mit dem vcpkg-Repository selbst zu verursachen
Benachrichtigen von Upstream-Besitzer*innen für Upstream-relevante Patches
Wenn ein Patch für Upstream von Nutzen sein könnte, muss der Upstream über den Inhalt des Patches benachrichtigt werden. (Patches, die vcpkg-spezifisches Verhalten anwenden, das nicht mit dem Upstream verknüpft ist, wie z. B. das De-Vendoring einer Abhängigkeit, erfordern keine Benachrichtigung.)
Um Situationen zu vermeiden, in denen upstream mit dem Patch nicht einverstanden ist, warten wir mindestens 30 Tage, um solche Patches anzuwenden.
Wir überspringen diesen Wartezeitszeitraum, wenn wir ein hohes Vertrauen haben, dass die Änderung korrekt ist. Beispiele für Patches mit hoher Zuverlässigkeit sind unter anderem:
- Akzeptanz des Upstreams als Patch (z. B. die Rückportierung einer bestimmten Änderung aus einem Pull Request, den der Upstream zusammengeführt hat).
- Fehlende
#include
s hinzugefügt. - Kleine und offensichtliche Produktcode-Korrekturen (z. B. Initialisieren einer uninitialisierten Variablen).
- Deaktivieren von irrelevanten vcpkg-Komponenten des Builds, z. B. Tests oder Beispiele.
Optionen dem Patchen vorziehen
Es empfiehlt sich, Optionen in einem Aufruf auf vcpkg_configure_xyz()
festzulegen, statt die Einstellungen direkt zu patchen.
Allgemeine Optionen, mit denen Sie Patching vermeiden können:
- [MSBUILD]
<PropertyGroup>
-Einstellungen innerhalb der Projektdatei können über/p:
-Parameter überschrieben werden. - [CMAKE] Aufrufe von
find_package(XYz)
in CMake-Skripts können über-DCMAKE_DISABLE_FIND_PACKAGE_XYz=ON
deaktiviert werden. - [CMAKE] Cachevariablen (deklariert als
set(VAR "value" CACHE STRING "Documentation")
oderoption(VAR "Documentation" "Default Value")
) können überschrieben werden, indem sie einfach in der Befehlszeile als-DVAR:STRING=Foo
übergeben werden. Eine wichtige Ausnahme ist, wenn derFORCE
Parameter anset()
übergeben wird. Weitere Informationen finden Sie in der CMake-Dokumentationset
Download genehmigter Patches bevorzugen, statt sie in den Port einzuchecken
Wenn eine genehmigte oder zusammengeführte Patchdatei aus upstream abgerufen werden kann, sollten Ports versuchen, sie herunterzuladen und anzuwenden, anstatt sie als Teil der Portdateien zu verwenden. Dieser Prozess wird bevorzugt, da er:
- Bestätigt, dass upstream die Patchänderungen akzeptiert hat
- Vereinfacht den Überprüfungsprozess durch Verlagerung der Verantwortung in den früheren Ablauf
- Reduziert die Größe des vcpkg-Repositorys für Benutzer, die den Patch nicht verwenden.
- Vermeiden von Lizenzkonflikten mit dem vcpkg-Repository
Patches sollten von einem stabilen Endpunkt heruntergeladen werden, um SHA-Konflikte zu vermeiden.
Beim Herunterladen von Patchdateien aus einer Pullanforderung oder einem Commit von GitHub und GitLab sollte der ?full_index=1
Parameter an die Download-URL angefügt werden.
Beispiele:
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
Patchen gegenüber dem Überschreiben von VCPKG_<VARIABLE>
-Werten bevorzugen
Einige Variablen, die mit VCPKG_<VARIABLE>
versehen sind, haben ein Äquivalent CMAKE_<VARIABLE>
.
Allerdings werden nicht alle an den internen Paketbuild übergeben (siehe Implementierung: Windows-Toolkette).
Betrachten Sie das folgende Beispiel:
set(VCPKG_C_FLAGS "-O2 ${VCPKG_C_FLAGS}")
set(VCPKG_CXX_FLAGS "-O2 ${VCPKG_CXX_FLAGS}")
Die Verwendung der integrierten vcpkg
-Toolchains funktioniert, da der Wert der VCPKG_<LANG>_FLAGS
-Variable an die entsprechende CMAKE_LANG_FLAGS
-Variable weitergeleitet wird. Aber eine benutzerdefinierte Toolkette, die sich nicht der vcpkg
Variablen bewusst ist, leitet sie nicht weiter.
Aus diesem Grund empfiehlt es sich, das Build-System direkt zu patchen, wenn CMAKE_<LANG>_FLAGS
festgelegt wird.
Patches minimieren
Wenn Sie Änderungen an einer Bibliothek vornehmen, versuchen Sie, den endgültigen Diff zu minimieren. Dies bedeutet, dass Sie den upstream-Quellcode nicht neu formatieren sollten, wenn Sie Änderungen vornehmen, die sich auf eine Region auswirken. Wenn Sie eine Bedingung deaktivieren, empfiehlt es sich, der Bedingung ein AND FALSE
oder && 0
hinzuzufügen, anstatt jede Zeile der Bedingung zu löschen. Wenn ein großer Bereich deaktiviert werden muss, ist es kürzer, ein if(0)
oder #if 0
um den Bereich anzufügen, anstatt jede Zeile im Patch zu löschen.
Fügen Sie keine Patches hinzu, wenn der Port veraltet ist und das Aktualisieren des Ports auf eine neuere veröffentlichte Version dasselbe Problem lösen würde. vcpkg bevorzugt das Aktualisieren von Ports über das Patchen veralteter Versionen.
Dies hilft, die Größe des vcpkg-Repositorys nach unten zu halten und die Wahrscheinlichkeit zu verbessern, dass der Patch auf zukünftige Codeversionen angewendet wird.
Features in Patches nicht implementieren
Der Zweck des Patchings in vcpkg besteht darin, kompatibilität mit Compilern, Bibliotheken und Plattformen zu ermöglichen. Es soll keine neuen Features anstelle des ordnungsgemäßen Open-Source-Verfahrens implementieren (z. B. Einreichen eines Issues/PR/etc).
Keine Tests/Dokumente/Beispiele standardmäßig erstellen
Prüfen Sie beim Übermitteln eines neuen Ports, ob Optionen wie BUILD_TESTS
, WITH_TESTS
oder POCO_ENABLE_SAMPLES
vorhanden sind, und stellen Sie sicher, dass die zusätzlichen Binärdateien deaktiviert sind. Dadurch werden Die Erstellungszeiten und Abhängigkeiten für den durchschnittlichen Benutzer minimiert.
Optional können Sie ein test
Feature hinzufügen, das das Erstellen der Tests ermöglicht, dies sollte jedoch nicht in der Default-Features
Liste enthalten sein.
Aktivieren vorhandener Benutzer der Bibliothek zum Wechseln zu vcpkg
Fügen Sie nicht CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS
hinzu.
Sofern der Autor der Bibliothek die Bibliothek nicht bereits verwendet, sollten wir diese CMake-Funktion nicht verwenden, da sie schlecht mit C++-Vorlagen interagiert und bestimmte Compilerfeatures aufbricht. Bibliotheken, die keine DEF-Datei bereitstellen und keine __declspec() Deklarationen verwenden, unterstützen einfach keine freigegebenen Builds für Windows und sollten als solche gekennzeichnet werden:
if(VCPKG_TARGET_IS_WINDOWS)
vcpkg_check_linkage(ONLY_STATIC_LIBRARY)
endif()
Keine Binärdateien außerhalb der von upstream angegebenen Namen umbenennen
D. h., wenn die Release- und Debugversion (libx ggü. libxd) der Upstream-Bibliothek unterschiedliche Namen haben, sollte die Debug-Bibliothek nicht in libx
umbenannt werden. Umgekehrt, wenn die Upstreambibliothek denselben Namen in Release und Debug aufweist, sollten wir keinen neuen Namen einführen.
Wichtiger Vorbehalt:
- Statische und geteilte Varianten sollten oft in ein gemeinsames Schema umbenannt werden. Dies ermöglicht es den Verbrauchern, einen gemeinsamen Namen zu verwenden und die nachgeschaltete Verknüpfung nicht zu kennen. Dies ist sicher, da wir jeweils nur jeweils eins zur Verfügung stellen.
Wenn eine Bibliothek CMake-Integrationsdateien generiert (foo-config.cmake
), muss die Umbenennung über das Patchen des CMake-Builds selbst erfolgen, anstatt einfach die Ausgabearchive/LIBs aufzurufen file(RENAME)
.
Schließlich sollten DLL-Dateien unter Windows niemals nach dem Build umbenannt werden, da die generierten LIBs unterbrochen werden.
Manifeste
Es ist erforderlich, dass die Manifestdatei formatiert ist. Verwenden Sie den folgenden Befehl, um alle Manifestdateien zu formatieren:
> vcpkg format-manifest --all
Tripels
Wir akzeptieren derzeit keine Anfragen zum Hinzufügen von Nicht-Community-Triplets. Die Höherstufung vom Community- auf einen vollständigen Tripletstatus basiert hauptsächlich auf dem Budget für die Hardware zum Testen solcher Triplets und wird durch von vcpkg übermittelten Metriken gesteuert, um die Wahrscheinlichkeit zu maximieren, dass etwas, das tatsächlich genutzt wird, vollständig getestet ist.
Wir fügen Community-Triplets hinzu, wenn:
- nachgewiesen wird, dass dieses Community-Triplet tatsächlich genutzt wird; und
- wir nicht wissen, dass ein solches Triplet fehlerhaft ist.
Beispielsweise haben wir kein Triplet in https://github.com/microsoft/vcpkg/pull/29034 hinzugefügt, da der Autor einfach versucht hat, den Satz zu vervollständigen, anstatt anzugeben, dass er tatsächlich so etwas verwenden würde. Und wir haben linux-dynamic erst hinzugefügt, nachdem die Patchelf-Lösung geschaffen wurde, um die Ergebnisse relocatable zu machen.
Nützliche Implementierungshinweise
Portfiles werden im Skriptmodus ausgeführt
Während portfile.cmake
's und CMakeLists.txt
's eine gemeinsame Syntax und kernige CMake-Sprachkonstrukte (auch als "Skriptbefehle" bezeichnet) verwenden, werden Portdateien im "Skriptmodus" ausgeführt, während CMakeLists.txt
Dateien im "Projektmodus" ausgeführt werden. Der wichtigste Unterschied zwischen diesen beiden Modi besteht darin, dass "Skriptmodus" nicht über die Konzepte "Toolchain", "Language" und "Target" verfügt. Alle Verhaltensweisen, einschließlich Skriptbefehle, die von diesen Konstrukten abhängen (z. B. CMAKE_CXX_COMPILER
, CMAKE_EXECUTABLE_SUFFIX
, CMAKE_SYSTEM_NAME
), sind nicht korrekt.
Portfiles haben direkten Zugriff auf Variablen, die in der Tripletdatei festgelegt sind, aber CMakeLists.txt
s nicht (obwohl es häufig eine Übersetzung gibt, die geschieht -- VCPKG_LIBRARY_LINKAGE
im Vergleich BUILD_SHARED_LIBS
).
Portfiles und Project-Builds, die von Portfiles aufgerufen werden, werden in verschiedenen Prozessen ausgeführt. Begrifflich:
+----------------------------+ +------------------------------------+
| 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) |
+----------------------------+ +------------------------------------+
Um den Host in einer Portdatei zu ermitteln, sind die standardmäßigen CMake-Variablen in Ordnung (CMAKE_HOST_WIN32
).
Um das Ziel in einer Portdatei zu ermitteln, sollten die vcpkg-Tripletvariablen verwendet werden (VCPKG_CMAKE_SYSTEM_NAME
).
Eine vollständige Aufzählung möglicher Einstellungen finden Sie in unserer Triplet-Dokumentation .