Leitfaden für Betreuer

In diesem Dokument werden Vorgaben, Richtlinien und bewährte Praktiken beschrieben, die beim Beitragen zu vcpkg befolgt werden sollen.

Sie dient der gleichen Rolle wie:

Kuratierte Registerdesignziele

Ports müssen gleichzeitig installiert werden

Ein port, der in der kuratierten Registrierung enthalten ist, muss erfolgreich in Anwesenheit aller anderen Ports in der Registrierung erstellt werden. Die gesamte Kombination von Ports wird regelmäßig von der automatisierten CI von vcpkg getestet.

Ein Port darf keines der folgenden Aktionen ausführen:

Ausnahmen werden gemacht für:

  • Ports, die einen anderen Port in offizieller Funktion ersetzen. Dies schließt Fälle ein, in denen:
    • Dasselbe Projekt veröffentlicht eine Nachfolgerkomponente.
    • Ein weiteres Projekt übernimmt die Wartung einer aufgegebenen Komponente, einschließlich durch einen Fork.
    • Ein weiteres Projekt veröffentlicht eine Nachfolgerkomponente.
  • Ports, in denen keine Plattformüberlappung vorhanden ist. Beispielsweise ein Windows-only-Ersatz für eine Linux-Komponente, der Windows nicht unterstützt.
  • Ports, die dieser Richtlinie vorangehen und eine deutlich signifikante Anzahl von Benutzern und Mitwirkenden haben.

vcpkg-Betreuer bewerten Bestandsschutz-Ausnahmen fallweise. Beispielsweise wurde boringssl hinzugefügt, bevor benutzerdefinierte Registrys verfügbar waren, und verbleibt im kuratierten Registry, da es weiterhin relevante Nutzer hat, obwohl openssl der Canonical-Provider für die OpenSSL-Fork-Familie ist. Die vorherige Annahme allein garantiert keine Ausnahmeregelung.

Ports, die dieser Richtlinie nicht entsprechen, können nicht in die kuratierte Registrierung aufgenommen werden.

Tipp

Wenn Ihr Port nicht in die kuratierte Registrierung aufgenommen werden kann, können Sie eine benutzerdefinierte Registrierung veröffentlichen oder einen Überlagerungsport verwenden.

Ports müssen in mindestens einem offiziellen Triplet getestet werden

Alle Ports in der kuratierten Registrierung müssen im Rahmen der Continuous Integration (CI) für mindestens ein offizielles Triplet getestet werden.

Ausnahmen werden gemacht für:

  • Temporäre Umstände, z. B.:
    • Der Port wird nicht ohne eine Aktualisierung der CI-Infrastruktur erstellt.
    • Der Port wird nicht gebaut, weil es kürzlich eine kritische Änderung in einer Upstream-Abhängigkeit gab, und es wird gerade daran gearbeitet, die Situation zu lösen.
  • Ports, die dieser Richtlinie vorangehen und eine deutlich signifikante Anzahl von Benutzern und Mitwirkenden haben.

Neue Ports, die nicht in mindestens einem offiziellen Triplet getestet werden können, werden nicht in die kuratierte Registrierung aufgenommen. Vorhandene Ports, die dieser Richtlinie nicht mehr entsprechen und sich nicht für eine oben aufgeführte Ausnahme qualifizieren, werden aus dem Register entfernt. Wenn z. B. CI-Tests für jedes offizielle Triplet deaktiviert wurden, das ein Port unterstützt, und keine Ausnahme zutrifft, wird der Port delistet.

Tipp

Wenn Ihr Port nicht in die kuratierte Registrierung aufgenommen werden kann, können Sie eine benutzerdefinierte Registrierung veröffentlichen oder einen Überlagerungsport verwenden.

Verpackte Komponenten sollten stabil und aktiv gepflegt werden

Komponenten, die im kuratierten Registry verpackt sind, müssen aktiv gewartet werden. Ports für inaktive Komponenten können aus der Liste entfernt werden.

Eine Komponente wird als inaktiv betrachtet, wenn:

  • Die Wartungsbetreuer haben die Komponente als aufgegeben erklärt.
  • Das Quell-Repository ist archiviert oder akzeptiert keine Beiträge mehr.
  • Maintainer antworten nicht oder sind nicht erreichbar.
  • Es wurden lange keine sinnvollen Änderungen vorgenommen.

Ausnahmen werden für grundlegende Komponenten vorgenommen, die als reif und stabil betrachtet werden und nicht oft geändert werden. Beispiel: zlib.

Verpackte Komponenten sollten ausgereift sein

In der kuratierten Registry verpackte Komponenten müssen reif sein und für den Verbrauch durch Benutzer von vcpkg vorgesehen sein. Komponenten, die für den persönlichen Gebrauch vorgesehen sind, sollten in benutzerdefinierten Registries veröffentlicht werden.

Eine Komponente wird als reif genug für das kuratierte Register betrachtet, wenn eine dieser Aussagen zutrifft:

  • Die Komponente verfügt über ein Release, das mindestens sechs Monate alt ist.
  • Die Komponente weist mindestens sechs Monate aktiver öffentlicher Entwicklung auf.
  • Die Komponente ist ein offizieller Teil eines Projekts mit mindestens sechs Monaten Veröffentlichungen oder aktiver öffentlicher Entwicklung. Beispiel: eine neue Boost-Bibliothek oder Qt-Komponente.
  • Die Komponente zeigt einen äquivalenten Reifegrad zu den vorherigen Anforderungen in anderer Hinsicht.

Einige Indikatoren für die Unreife von Komponenten sind:

  • Die Komponente wird in Suchmaschinen nicht angezeigt.
  • Die Komponente wird häufig umbenannt.
  • Konflikte mit anderen Bibliotheken.

Tipp

Wenn Ihr Port nicht in die kuratierte Registrierung aufgenommen werden kann, können Sie eine benutzerdefinierte Registrierung veröffentlichen oder einen Überlagerungsport verwenden.

PR-Struktur

Erstellen separater Pullanforderungen pro Port

Kleinere Pullanforderungen (PRs) sind einfacher zu überprüfen. Pullanforderungen sollten Änderungen an einem einzelnen Port vornehmen. Dadurch werden auch die Wartezeiten für die Ergebnisse der kontinuierlichen Integration (CI) reduziert.

Das Einschränken von PRs auf einen einzelnen Port ist in einigen Fällen möglicherweise nicht möglich. Wenn Sie beispielsweise einen Port ändern, müssen nachgeschaltete Verbraucher aktualisiert oder gepatcht werden.

Vermeiden Sie irrelevante kosmetische Änderungen

Nehmen Sie keine sachfremden kosmetischen Änderungen an einem andernfalls unveränderten Port vor, z. B. Neuformatierung, Umbenennen von Variablen oder Beheben von Tippfehlern. Diese Änderungen verbrauchen die Berechnungszeit, die an anderer Stelle besser verwendet wird. Änderungen, die die Buildkorrektur, Kompatibilität, Zuverlässigkeit oder Reproduzierbarkeit verbessern, werden nicht als trivial betrachtet, nur weil die installierten Dateien unverändert bleiben.

Verwenden von unverwechselbaren Portnamen

Der Name eines Hafens sollte auf seinen Inhalt hinweisen.

Das Durchsuchen des Portnamens in einer Suchmaschine oder in spezialisierten Paketbrowsern wie Repology sollte zu der entsprechenden Komponente führen.

Ports mit kurzen oder allgemeinen Namen erfordern eine Klärung. Dies gilt nur für den Namen des Ports in der kuratierten Registrierung, der Name der verpackten Komponente und deren Inhalte sind nicht erforderlich, um dieser Richtlinie zu entsprechen.

Ausnahmen werden für Ports vorgenommen, die eine Komponente mit einer starken Zuordnung zum Namen des Ports enthalten. Zum Beispiel: libpng, openssl, oder zlib.

Um dieser Richtlinie zu entsprechen, können neue Ports mit mehrdeutigen Namen ein Präfix verwenden, z. B.:

  • Besitzer, Benutzername oder Organisation des Repositorys. Beispiel: google-cloud-cpp. Für Ports von Komponenten, die auf GitHub gehostet werden, ist der GitHub Besitzer ein akzeptables eindeutiges Präfix<github owner>-<repository name>.
  • Der Name einer Suite, zu der das Paket gehört: boost-dll. Nur wenn das Paket eine offizielle Komponente einer solchen Suite ist.

Beispiel: Mehrdeutiger Portname

Ein Port mit dem Namen ip wird als mehrdeutig angesehen, da:

  • der Name ist zu kurz,
  • Der Name ist ein gängiges Wort und
  • der Name ist keiner einzelnen Komponente stark zugeordnet.

Um festzustellen, ob ein Name mehrdeutig ist, entfernen Sie die folgenden allgemeinen Präfixe und Suffixe, die von C++- und Open-Source-Komponenten verwendet werden, aus dem Portnamen:

  • cpp
  • free
  • lib
  • open
  • Ziffern

Beispiel: ip-cpp, libip und ip5 sind mehrdeutig, weil sie auf denselben Stamm ip reduziert werden.

Portbenennungen einschränken

Um Verwirrung für Benutzer zu vermeiden, darf ein Port nicht mehr als einmal in einem zeitraum von 12 Monaten umbenannt werden.

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.

Ein vcpkg-Maintainer kann Ihre PR während des Überprüfungsprozesses in einen Entwurf umwandeln, in der Regel beim Anfordern von Änderungen oder beim Hinterlassen von Kommentaren, die darauf hinweisen, wann die PR als zur Überprüfung bereit markiert werden soll.

Inaktive PRs schließen

Ein vcpkg-Wartungsbetreuer kann eine PR schließen, nachdem er seit mehr als 60 Tagen auf eine Reaktion des Mitwirkenden wartet. Der Inaktivitäts-Countdown wird nur ausgeführt, während eine Aktion des Mitwirkenden erforderlich ist. Sie wird nicht ausgeführt, während die PR auf die Überprüfung des Buildlabors wartet oder von einem vcpkg-Betreuer überprüft wird.

Eine PR befindet sich in einem überprüfbaren Zustand, wenn sie:

  • Hat keine fehlerhaften PR-Überprüfungen, oder der Mitwirkende bittet um Hilfe oder rechtfertigt den Grund für die Fehler.
  • Keine offenen Änderungsanfragen oder Klarstellungen von einem vcpkg-Wartungsbetreuer.
  • Es gibt keine Zusammenführungskonflikte.

Der Countdown beginnt, wenn die PR in einen Zustand eintritt, der eine Aktion des Mitwirkenden erfordert. Dies kann passieren, wenn eine PR mit Problemen geöffnet wird, die der Mitwirkende beheben muss, oder wenn ein vcpkg-Betreuer Änderungen oder Klarstellungen anfordert. Ein vcpkg-Betreuer kann die PR als Entwurf markieren, wenn ein Mitwirkender zum Handeln aufgefordert wird.

Eine substantielle Antwort des Mitwirkenden setzt den Countdown zurück. Wenn die Antwort alle ausstehenden Anfragen löst und die PR zur Überprüfung bereit ist, wird der Countdown angehalten, bis die Mitwirkendenaktion erneut erforderlich ist. Wenn der Mitwirkende nicht innerhalb von 60 Tagen reagiert, während eine Aktion erforderlich ist, gilt die PR als veraltet und kann nach Ermessen eines vcpkg-Betreuers geschlossen werden.

Portfiles

Vermeiden veralteter Hilfsfunktionen

Derzeit sind die folgenden Hilfsmittel veraltet:

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.

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 der scripts/vcpkg-tools.json Datei.
  • Andere Stellen, an denen die Schreibweise der hexadezimalen Zeichenfolge keine Rolle spielt.

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 einem anderen Port 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 das unofficial-brotli Paket, das Ziel unofficial::brotli::brotlierzeugt.

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 Komponenten 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 lediglich verwendet werden, um die Parität mit unabhängigen Komponenten 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 gilt, 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_cmake_configure(
  SOURCE_PATH "${SOURCE_PATH}"
  OPTIONS
    ${FEATURE_OPTIONS}
  MAYBE_UNUSED_VARIABLES
    WINDOWS_OPTION # Applies only on Windows
)

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, libzipopen62541 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 über opencv2, 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 ein public-preview Feature auf.
  • imgui verfügt über ein experimental-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

Hinweis

Ein feature, das standardmäßig vom Upstream-Buildsystem aktiviert ist, bedeutet nicht, dass das Feature den default-features Einträgen hinzugefügt werden soll. Da der beabsichtigte Zweck von default-features nicht darin besteht, die Entscheidungen von Upstream zu modellieren, sondern den Komfort für Benutzer des klassischen Modus zu bieten.

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.

Hier zählen zu den Kunden sowohl Benutzerprojekte, die den Paketgraph nutzen, als auch nachgeschaltete Ports innerhalb dieses Graphen. Beide drücken ihre Abhängigkeitsanforderungen über die gleiche Featureschnittstelle aus.

Überlegen Sie sorgfältig, ob ein Feature standardmäßig aktiviert sein soll, da das Deaktivieren von Standardfeatures komplex ist.

So deaktivieren Sie standardfeatures für eine transitive Abhängigkeit:

  • Jeder Kunde, der vom Port abhängt, muss seine Standardfeatures in seiner Abhängigkeitsdeklaration unter Verwendung von "default-features": false deaktivieren.
  • Das Projekt auf oberster Ebene muss auch die transitive Abhängigkeit direkt benennen, entweder im Manifest mit "default-features": false, oder in der vcpkg install Befehlszeile mit [core].

Das Deaktivieren von Standardfeatures verhindert nicht, dass ein anderer Kunde explizit eine dieser Features anfordert.

Für diese Richtlinie ist eine API eine beliebige Schnittstelle, die Nutzern verfügbar gemacht wird, einschließlich Bibliotheksschnittstellen, ausführbaren Befehlszeilenschnittstellen und anderen binären Schnittstellen. Ein Feature kann standardmäßig aktiviert werden, wenn einer vorhandenen API Verhalten hinzugefügt wird, z. B. Unterstützung für zusätzliche Komprimierungsalgorithmen über eine vorhandene generische Schnittstelle.

Wenn ein Feature eine API hinzufügt, muss es in der kuratierten Registrierung von vcpkg 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, um const wchar_t* anstelle von const 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:

  1. bei Aktivierung des Feature die Polyfills in Aliase der Polyfill-Entität umgewandelt werden.
  2. der Zustand des Polyfills in den installierten Header integriert ist, sodass die Wahrscheinlichkeit von „unmöglichen“ Laufzeitfehlern aufgrund eines ABI-Konflikts gering ist.
  3. 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] ändert absl::string_view in einen Ersatz oder std::string_view; der Patch implementiert die Baking-Anforderung.

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

Bevorzugen Sie es, Abhängigkeiten separat zu verpacken, damit Benutzer sie über vcpkg auswählen und aktualisieren können. Mitgelieferte Abhängigkeiten bringen mehrere Herausforderungen mit sich:

  • Probleme beim Aktualisieren: Eingebundene Abhängigkeiten sind schwieriger zu verfolgen und zu aktualisieren, einschließlich der Anwendung von Sicherheitsupdates.
  • Symbolkonflikte: Eine eingebundene Abhängigkeit kann dieselben Symbole wie eine andere Version der Abhängigkeit definieren, wodurch Laufzeitfehler oder undefiniertes Verhalten verursacht werden.
  • Lizenzkonformität: Mitgelieferte Abhängigkeiten können Lizenzanforderungen verdecken oder Lizenzkompatibilitätsprobleme verursachen.
  • Erhöhte Wartung: Die Synchronisierung von mitgelieferten Abhängigkeiten mit ihren Upstream-Versionen erhöht den Wartungsaufwand und kann Arbeit über mehrere Ports hinweg duplizieren.

Aus diesen Gründen lösen Sie Abhängigkeiten vom Anbieter, wann immer praktikabel. Mitgelieferte Abhängigkeiten dürfen nicht gegenüber der Link-Domäne eines Benutzers offengelegt werden.

Eine Linkdomäne ist die Menge von Symbolen, die zur Laufzeit gegeneinander aufgelöst werden können. Auf Windows verfügt jede DLL im Allgemeinen über eine eigene Linkdomäne. Auf Plattformen mit einer prozessweiten Symboltabelle umfasst die Linkdomäne im Allgemeinen den gesamten Prozess.

Wenn eine Komponente eine mitgelieferte Abhängigkeit für dieselbe Link-Domäne wie eine über vcpkg ausgewählte Abhängigkeit verfügbar macht, können beide Kopien dieselben Symbole definieren. Dies verstößt gegen die One Definition Rule und kann Laufzeitfehler oder nicht definiertes Verhalten verursachen. Das Problem kann nur auftreten, wenn die beiden Versionen unterschiedlich genug sind, um inkompatibel zu sein.

Eine gebündelte Abhängigkeit ist nur zulässig, wenn sie vollständig von Link-Domänen isoliert ist, die von nachgeschalteten Ports und Benutzeranwendungen verwendet werden. Ein nur für den Host bestimmtes Build-Tool kann beispielsweise eine statisch verknüpfte Abhängigkeit enthalten, wenn nachgeschaltete Binärdateien nicht gegen das Tool gelinkt werden und die Symbole der Abhängigkeit nicht ihre Verknüpfungsdomänen eingeben können.

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)

Ersetzen Sie die install(TARGETS) Zeile durch einen bedingten Block, der auch das unerwünschte Ziel vom Standardbuild ausschließt:

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.

Eine Linker-Eingabedatei, die in lib oder debug/lib, z. B. einer .lib, .a, .so oder .dylib Datei, installiert ist, gilt als konfliktbehaftet, wenn sie eine der folgenden Aktionen ausführt:

  • Definiert main.
  • Definiert malloc.
  • Definiert Symbole, die auch in anderen Bibliotheken definiert sind.

Einige Linkereingabedateien bieten absichtlich eng begrenzte Ersetzungen für Symbole, die Konsumenten sonst an anderer Stelle definieren oder anderweitig beziehen würden. Beispielsweise stellt Google Test gtest-main.lib ein main für Testausführungsdateien bereit, deren Autoren sich dafür entscheiden, es zu verwenden, anstatt ihren eigenen Einstiegspunkt zu definieren.

Platzieren Sie widersprüchliche Linker-Eingabedateien in lib/manual-link oder debug/lib/manual-link ab, sodass Buildsysteme, die Dateien automatisch aus dem Bibliotheksverzeichnis verknüpfen, sie nicht auswählen. Windows DLLs verbleiben in bin oder debug/bin; platzieren Sie ihre Importbibliotheken in manual-link, wenn eine explizite Verknüpfung erforderlich ist. Verbraucher müssen dem Verknüpfen dieser Dateien ausdrücklich zustimmen und sind dafür verantwortlich, widersprüchliche Definitionen zu vermeiden. Diese Ausnahme stellt keinen allgemeinen Mechanismus dar, um alternative Anbieter einer anderen Komponente zu bündeln; zudem führt das Verschieben einer Linker-Eingabedatei in manual-link nicht dazu, dass deren Symbole vom Link-Bereich des Konsumenten isoliert werden.

Installieren vordefinierter Binärdateien

Ports, die vorgefertigte Artefakte (nur binär) installieren, sind zulässig, werden jedoch dringend nicht empfohlen, vorausgesetzt, die Artefakte hindern Benutzer nicht daran, Abhängigkeiten über vcpkg auszuwählen oder zu aktualisieren. Das Erstellen aus der Quelle wird bevorzugt, da vcpkg-Einstellungen berücksichtigt werden, die den Compiler und die Flags steuern.

Wir lehnen Ports ab, die alle folgenden Bedingungen erfüllen:

  1. Installieren Sie vorgefertigte Binärdateien, anstatt aus dem Quellcode zu erstellen, und
  2. Diese Binärdateien enthalten oder erfordern abhängigkeiten zur Laufzeit, die von anderen Ports in der kuratierten Registrierung bereitgestellt werden, und
  3. Die installierten Artefakte machen diese Abhängigkeiten einer Linkdomäne verfügbar, die auch Versionen enthalten kann, die über vcpkg ausgewählt wurden.

Diese Kombination sperrt den Abhängigkeitsgraphen effektiv auf die Versionen, die beim Erstellen des vorgefertigten Upstream-Artefakts verwendet wurden. Wenn vcpkg eine Abhängigkeit wie zlib z. B. oder opensslaktualisiert, können die vordefinierten und vom Benutzer ausgewählten Versionen in der gleichen Linkdomäne inkompatible Symbole definieren. Dies kann zu Verstößen gegen die One Definition Rule, ABI-Inkompatibilitäten oder verpassten Sicherheitsupdates führen.

Ein Artefakt legt eine Abhängigkeit offen, wenn diese Abhängigkeit Teil der Link-Domäne eines Benutzers ist, unabhängig davon, ob upstream sie offenlegen möchte. Dazu gehören:

  • Für Verbraucher verknüpfbare .lib, .a, .so, .dylib oder Importbibliotheken, die die Abhängigkeit in die Link-Domäne des Benutzers bringen.
  • Installierte Header, die auf Symbole, Typen oder Makros von anderen vcpkg-Ports verweisen (direkt oder über Inline-/Vorlagencode).
  • Installierte CMake-config- oder pkg-config-Dateien, die find_dependency() oder Requires: für andere vcpkg-Ports aufrufen.

Zulässige (aber dennoch abgeratene) Szenarien:

  • Hilfswerkzeuge, die ausschließlich auf dem Host-System während des Bauvorgangs eingesetzt werden; ihre Ausgaben werden zwar genutzt, aber abhängige Ports linken nicht gegen sie – vorausgesetzt, sie kapseln mitgelieferte Abhängigkeiten oder greifen ausschließlich auf allgegenwärtige System-Laufzeitbibliotheken zurück.
  • Vordefinierte Bibliotheken, deren gebündelte Abhängigkeiten vollständig in separaten Linkdomänen verbleiben und nicht in installierten Headern oder exportierten Schnittstellen erscheinen. Statische Verknüpfung allein isoliert keine Abhängigkeit von der Linkdomäne eines Benutzers.
  • Nur Daten-, Firmware- oder Objektpakete, die nicht mit Benutzercode verknüpft sind.

Verbotene Beispiele:

  • Eine vordefinierte Bibliothek, die eine private Kopie von zlib statisch linkt und ihre Symbole für eine Linkdomäne verfügbar macht, die auch die über vcpkg ausgewählte zlib-Version enthalten kann.
  • Eine vorgefertigte libfoo, die lib/libfoo.lib sowie Header-Dateien, einschließlich <zlib.h>, installiert und mit einer bestimmten zlib Version kompiliert wurde. Anwender verknüpfen dann mit libfoo in Erwartung der Kompatibilität.
  • Ein vordefiniertes SDK, das eine CMake-Paketdatei installiert find_dependency(OpenSSL), während die Binärdatei mit einer älteren OpenSSL-Veröffentlichung kompiliert wurde.

Entschärfungen / Alternativen:

  • Erstellen Sie einen Quellbuild mit Upstream-Skripten oder fügen Sie einen dünnen CMake-Wrapper hinzu.
  • Bitte die Upstream-Entwickler darum, ein quellcodebasiertes Release oder Anleitungen für einen reproduzierbaren Build zu veröffentlichen; verlinke das entsprechende Upstream-Issue bzw. den Pull Request in einem Kommentar in portfile.cmake oder vcpkg.json.
  • Verwenden Sie einen Overlay-Port oder eine private Registry für organisationsspezifische vorgefertigte Komponenten, die diese Regeln nicht erfüllen können.

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 Sie das "port-version"-Feld für jeden geänderten Port

Jede PR, die einen Port ändert, muss eine neue Version dieses Ports erstellen. PRs werden per Squash-Merge zusammengeführt, daher aktualisieren Sie die Version der einzelnen geänderten Ports einmal pro PR, nicht einmal pro Commit oder Review-Revision.

Wenn die upstream-Version nicht geändert wurde, erhöhen Sie das "port-version" Feld. Wenn sich die Upstreamversion geändert hat, setzen Sie "port-version" auf null zurück, indem Sie das Feld entfernen oder es auf 0 setzen.

Beispiel:

  • Die Paketversion von Zlib ist zurzeit 1.2.1, mit keinem expliziten "port-version" (entspricht einem "port-version" von 0).
  • 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 auf 1 aktualisieren.

Weitere Informationen finden Sie in der Versionsverwaltungsdokumentation .

Aktualisieren Sie die Versionsdateien in versions/ für jeden geänderten Port

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

Aktualisieren Sie für jeden geänderten Port in einer PR die Versionsdateien, um die endgültige Git-Struktur aufzuzeichnen. Wenn Sie während der Überprüfung weitere Änderungen vornehmen, führen Sie vcpkg x-add-version <port-name> --overwrite-version aus, um den nicht zusammengeführten Versionseintrag zu aktualisieren.

ohne "port-version" erneut zu inkrementieren.

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.

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

Benachrichtigungen im Upstream und Wartezeiten

Upstream-Besitzer sind die endgültige Entscheidungsinstanz für das Verhalten ihrer Komponente. vcpkg-Betreuer verlangen eine Benachrichtigung an Upstream für upstream-relevante Patches und für Fehler, die von KI-Codeüberprüfungstools in neuen Portübermittlungen identifiziert wurden.

Upstream-relevante Patches

Wenn ein Patch möglicherweise für Upstream nützlich sein könnte, müssen die Upstream-Verantwortlichen ü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 nicht mit dem Patch einverstanden ist, warten vcpkg-Betreuer mindestens 30 Tage nach der Upstream-Benachrichtigung, bevor solche Patches angewendet werden.

vcpkg-Betreuer überspringen diesen Wartezeitszeitraum, wenn sie 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 #includes 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.

KI-identifizierte Fehler in neuen Ports

Die kuratierte Registry zielt darauf ab, keinen bekanntermaßen ausnutzbaren Code auszuliefern, aber vcpkg-Betreuer können den Quellcode jeder Komponente nicht umfassend prüfen. Die Ergebnisse der KI-Codeüberprüfung sind für sich genommen keine abschließende Feststellung, dass Upstream-Code anfällig ist.

Wenn KI-Codeüberprüfungstools während der Überprüfung einer neuen Portübermittlung einen Fehler identifizieren, fordern die vcpkg-Betreuer, dass der Fehler an Upstream gemeldet wird, unter Befolgung des Sicherheitsmeldeprozesses des Projekts für potenziell ausnutzbare Fehler. Diese Anforderung gilt auch dann, wenn der Befund Upstreamcode betrifft, der vom Port nicht gepatcht wird.

  • Wenn upstream feststellt, dass das gemeldete Verhalten kein Fehler ist, akzeptieren vcpkg-Betreuer diese Entscheidung als endgültig und lehnen die neue Portübermittlung nicht auf der Grundlage dieser Feststellung ab.
  • Wenn Upstream den Fehler behebt, akzeptieren die vcpkg-Betreuer die korrigierte Version oder einen von Upstream genehmigten Patch, vorbehaltlich der Patchingrichtlinie und der anderen Anforderungen für neue Ports.
  • Wenn upstream nicht innerhalb von 30 Tagen nach der Meldung des Fehlers reagiert, werden vcpkg-Betreuer standardmäßig den KI-Befund als ausnutzbares Problem behandeln und die neue Port-Einreichung schließen.

Die Ausnahmen mit hoher Sicherheit für den Patch-Wartezeitraum verzichten nicht auf diese Anforderung zur Fehlerberichterstattung oder auf die Notwendigkeit einer Upstream-Antwort.

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") oder option(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 der FORCE Parameter an set() übergeben wird. Weitere Informationen finden Sie in der CMake-Dokumentation set

Download genehmigter Patches bevorzugen, statt sie in den Port einzuchecken

Wenn ein genehmigter oder zusammengeführter Patch aus einem Upstream-Commit abgerufen werden kann, laden Sie ihn herunter, und wenden Sie ihn an, anstatt ihn in den Port einzuchecken. Dieser Prozess wird aus folgenden Gründen bevorzugt:

  • Bestätigt, dass upstream die Patchänderungen akzeptiert hat.
  • Vereinfacht den Überprüfungsprozess, indem die Verantwortung in frühere Phasen verlagert wird.
  • Reduziert die Größe des vcpkg-Repositorys für Benutzer, die den Patch nicht verwenden.
  • Verhindert Lizenzkonflikte mit dem vcpkg-Repository.

Laden Sie Patches nur von URLs herunter, die an eine vollständige Commit-ID angeheftet sind, nicht von Pull-Request- oder Merge-Request-Diff-URLs, deren Inhalt sich ändern kann. Fügen Sie beim Herunterladen eines Commit-Patches von GitHub oder GitLab ?full_index=1 an die URL an. Dieser Parameter fordert vollständige Objekt-IDs im Diff an; sie macht keine änderbare URL unveränderlich.

Beispiele:

https://github.com/linux-audit/audit-userspace/commit/f8e9bc5914d715cdacb2edc938ab339d5094d017.patch?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 vcpkgVariablen 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.txts 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 .