Handleiding voor onderhoud
Dit document bevat een set beleidsregels die u moet toepassen bij het toevoegen of bijwerken van een poortrecept. Het is bedoeld om de rol van Het Debian beleidsmanual, de richtlijnen van Homebrew voor beheerders, en het kookboek van de Homebrew-formulete vervullen.
Algemene doelstellingen voor registerontwerp
Poorten in de huidige basislijn moeten tegelijkertijd kunnen worden geïnstalleerd
We willen gebruikers van benedenstroomse bibliotheken in het gecureerde register kunnen tonen dat de combinatie van bibliotheken in een gegeven basislijn die we publiceren, is getest op samenwerking in ten minste enkele configuraties. Als poorten elkaar kunnen uitsluiten, wordt de mogelijkheid om dergelijke configuraties te testen belemmerd, omdat het aantal builds dat nodig is voor dergelijke tests zou toenemen zoals aangegeven door 2^number_of_such_cases
. Bovendien wordt het installeren van extra afhankelijkheden altijd als 'veilig' beschouwd: er is geen manier voor een poort of eindgebruiker om te bevestigen dat een afhankelijkheid wordt niet geïnstalleerd in hun vereisten.
Als u een dergelijke alternatieve situatie voor gebruikers wilt weergeven, kunt u overwegen te beschrijven hoe iemand een overlaypoort kan maken die het alternatieve formulier implementeert met een notitie in portfile.cmake
, in plaats van extra poorten toe te voegen die nooit zijn ingebouwd in de voortdurende integratie van het samengestelde register. Zie bijvoorbeeld glad@0.1.36.
Vóór de introductie van registers, hebben we verschillende niet-geteste poorten als alternatieven geaccepteerd, zoals boringssl
, waarmee het ontwerpen van overlaypoorten eenvoudiger kan worden. Dit wordt niet meer geaccepteerd omdat registers publicatie van deze niet-geteste poorten toestaan zonder het gecureerde register te wijzigen.
PR-structuur
Afzonderlijke pull-aanvragen per poort maken
Scheid indien mogelijk wijzigingen in meerdere pull requests. Hierdoor zijn ze aanzienlijk gemakkelijker te controleren en te voorkomen dat problemen met een set wijzigingen elke andere wijziging tegenhouden.
Vermijd triviale wijzigingen in ongewijzigde bestanden
Vermijd bijvoorbeeld het opnieuw formatteren of hernoemen van variabelen in poortbestanden die anders geen reden hebben om te worden gewijzigd voor het probleem. Als u het bestand echter moet wijzigen voor het primaire doel van de pull request (het bijwerken van de bibliotheek), dan worden nuttige wijzigingen zoals het corrigeren van typfouten gewaardeerd!
Namen controleren op andere opslagplaatsen
Poortnamen moeten proberen ondubbelzinnig duidelijk te maken welk pakket door de poort wordt geïnstalleerd. In het ideale geval leidt het doorzoeken van de naam van de poort in een zoekmachine u snel naar het bijbehorende project. Een goede service om veel pakketnamen in meerdere opslagplaatsen tegelijk te controleren, is Repology.
Projecten met korte namen of genoemd naar veelvoorkomende woorden kunnen ondubbelzinnigheid vereisen, met name wanneer er geen projecten zijn met een sterke associatie met het opgegeven woord. Een poort met de naam ip
is bijvoorbeeld niet acceptabel, omdat het waarschijnlijk is dat meerdere projecten op dezelfde manier worden genoemd.
Voorbeelden van goede ontambiguers zijn:
- De gebruikersnaam of organisatie van de eigenaar van de opslagplaats:
google-cloud-cpp
. - De naam van een suite bibliotheken waarvan het project deel uitmaakt:
boost-dll
.
Veelvoorkomende voorvoegsels en achtervoegsels die worden gebruikt door C++- en open-sourceprojecten zijn geen geldige onderscheidende kenmerken. Enkele voorbeelden hiervan zijn onder andere:
-
cpp
, -
free
, -
lib
, -
open
, - Cijfers
Wanneer u bijvoorbeeld de volgende poortnamen vergelijkt: ip-cpp
, libip
en ip5
en het verwijderen van de ongeldige ondubbelzinnigheden, worden ze allemaal teruggebracht tot dezelfde stam (ip
) en worden ze dus beschouwd als dezelfde naam.
Een uitzondering op deze richtlijn wordt gemaakt voor namen die sterk zijn gekoppeld aan één project. Bijvoorbeeld: libpng
, openssl
en zlib
.
Gebruik concept-pull requests van GitHub
GitHub concept-PR's zijn een uitstekende manier om CI of menselijke feedback te krijgen over werk dat nog niet gereed is om te integreren. De meeste nieuwe PR's moeten als concept worden aangemaakt en worden omgezet naar normale PR's zodra de CI is geslaagd.
Voor meer informatie over GitHub concept-pull-aanvragen, zie Introductie van concept-pull-aanvragen.
Portfiles
Afgeschafte helperfuncties voorkomen
Op dit moment worden de volgende helpers afgeschaft:
-
vcpkg_extract_source_archive_ex()
moet worden vervangen door de ondersteunde overbelasting vanvcpkg_extract_source_archive()
(doorARCHIVE
) - De afgeschafte overbelasting van
vcpkg_extract_source_archive()
zonderARCHIVE
moet worden vervangen door de ondersteunde overbelasting doorARCHIVE
. -
vcpkg_apply_patches()
moet worden vervangen door dePATCHES
argumenten ten behoeve van de 'extract' helpers (bijvoorbeeldvcpkg_from_github()
) -
vcpkg_build_msbuild()
moet worden vervangen doorvcpkg_install_msbuild()
-
vcpkg_copy_tool_dependencies()
moet worden vervangen doorvcpkg_copy_tools()
-
vcpkg_configure_cmake
moet worden vervangen doorvcpkg_cmake_configure()
na het verwijderen vanPREFER_NINJA
-
vcpkg_build_cmake
moet worden vervangen doorvcpkg_cmake_build()
-
vcpkg_install_cmake
moet worden vervangen doorvcpkg_cmake_install()
-
vcpkg_fixup_cmake_targets
moet worden vervangen doorvcpkg_cmake_config_fixup
Sommige van de vervangende helperfuncties bevinden zich in 'hulpprogrammapoorten' om gebruikers toe te staan hun gedrag vast te maken bij specifieke versies, zodat het gedrag van de helpers op een bepaalde versie kan worden vergrendeld. Poorten voor tools moeten worden toegevoegd aan de "dependencies"
van uw poort, zoals:
{
"name": "vcpkg-cmake",
"host": true
},
{
"name": "vcpkg-cmake-config",
"host": true
}
Vermijd overmatige opmerkingen in portfiles
In het ideale geval moeten portfiles kort, eenvoudig en zo declaratief mogelijk zijn.
Verwijder eventuele opmerkingen van de boilerplaat die door de opdracht create
worden geïntroduceerd voordat u een pull-aanvraag indient.
Poorten mogen niet afhankelijk zijn van het pad
Poorten mogen hun gedrag niet wijzigen op basis van welke poorten al zijn geïnstalleerd in een formulier waarmee wordt gewijzigd welke inhoud die poort installeert. Bijvoorbeeld:
> vcpkg install a
> vcpkg install b
> vcpkg remove a
en
> vcpkg install b
de bestanden die door b
zijn geïnstalleerd, moeten hetzelfde zijn, ongeacht de invloed van de vorige installatie van a
. Dit betekent dat poorten niet mogen proberen te detecteren of er iets is opgegeven in de geïnstalleerde structuur door een andere poort voordat er actie wordt ondernomen. Hieronder wordt een specifieke en algemene oorzaak van dergelijke 'padafhankelijke' werking beschreven in 'Bij het definiëren van functies, expliciet afhankelijkheden beheren'.
Unieke regel voor poorttoeschrijving
In het hele vcpkg-systeem mogen geen twee poorten die een gebruiker gelijktijdig gebruikt hetzelfde bestand leveren. Als een poort probeert een bestand te installeren dat al door een ander bestand is geleverd, mislukt de installatie. Als een poort een zeer algemene naam voor een header wil gebruiken, moet het deze kopteksten in een submap plaatsen in plaats van in include
.
Deze eigenschap wordt regelmatig gecontroleerd door continue integratieruns die proberen alle poorten in het register te installeren, wat mislukt met FILE_CONFLICTS
als twee poorten hetzelfde bestand leveren.
CMake-exports toevoegen in een onofficiële naamruimte
Een kernontwerp ideaal van vcpkg is om geen 'lock-in' te maken voor gebruikers. In het buildsysteem moet er geen verschil zijn tussen het afhankelijk zijn van een bibliotheek van het systeem en het afhankelijk zijn van een bibliotheek van vcpkg. Daarom vermijden we het toevoegen van CMake-exports of -doelen aan bestaande bibliotheken met 'de voor de hand liggende naam', zodat upstreams hun eigen officiële CMake-exports kunnen toevoegen zonder dat dit conflicteert met vcpkg.
Met dat doel moeten alle CMake-configuraties die de poort exporteert en die zich niet in de upstream-bibliotheek bevinden, unofficial-
als voorvoegsel hebben. Eventuele extra doelen moeten zich in de unofficial::<port>::
naamruimte bevinden.
Dit betekent dat de gebruiker het volgende moet zien:
-
find_package(unofficial-<port> CONFIG)
als de manier om het speciaal voor vcpkg ontwikkelde pakket te verkrijgen -
unofficial::<port>::<target>
als geëxporteerd doelwit vanuit die poort.
Voorbeelden:
-
brotli
maakt hetunofficial-brotli
pakket aan en produceert daarbij de doelstellingunofficial::brotli::brotli
.
Copyrightbestand installeren
Elke poort moet een bestand met de naam copyright
opgeven in de map ${CURRENT_PACKAGES_DIR}/share/${PORT}
. Als de licentie-inhoud van een pakket beschikbaar is in de bronbestanden, moet dit bestand worden gemaakt door een aanroep naar vcpkg_install_copyright()
.
vcpkg_install_copyright
bundelt indien nodig ook meerdere copyrightbestanden.
vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE")
Een oudere methode om dit bestand handmatig te maken, is met de ingebouwde opdracht van CMake file
. Dit wordt afgeraden ten gunste van vcpkg_install_copyright
in nieuwe poorten, maar is nog steeds toegestaan.
file(INSTALL "${SOURCE_PATH}/LICENSE" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}" RENAME copyright)
Als de licentie-inhoud in de upstream-bronbestanden niet in tekstvorm is (bijvoorbeeld een PDF-bestand), moet copyright
een uitleg bevatten over hoe een gebruiker de licentievereisten kan vinden. Indien mogelijk moet het ook een koppeling naar de oorspronkelijke bronbestanden bevatten die dit aangeven, zodat gebruikers kunnen controleren of deze up-to-date is.
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
]])
Versiebeperkingen in poorten
Versiebeperkingen binnen poorten moeten over het algemeen worden vermeden, omdat ze de onafhankelijke ontwikkeling van projecten kunnen belemmeren. Het toevoegen van dergelijke beperkingen is alleen toegestaan wanneer er een goed gedocumenteerde reden is, zoals bewezen incompatibiliteit met specifieke eerdere versies. Deze beperkingen mogen niet alleen worden gebruikt om pariteit met onafhankelijke projecten te behouden.
Functies
Geen functies gebruiken om alternatieven te implementeren
Kenmerken moeten worden behandeld als additieve functionaliteit. Als port[featureA]
installeert en port[featureB]
installeert, moet port[featureA,featureB]
worden geïnstalleerd. Bovendien, als een tweede poort afhankelijk is van [featureA]
en een derde poort afhankelijk is van [featureB]
, moeten zowel de tweede als de derde poorten aan hun afhankelijkheden voldoen.
Bibliotheken in deze situatie moeten een van de beschikbare opties kiezen, zoals uitgedrukt in vcpkg, en gebruikers die een andere instelling willen gebruiken, moeten op dit moment overlaypoorten gebruiken.
Bestaande voorbeelden die we vandaag niet zouden accepteren voor achterwaartse compatibiliteit:
-
libgit2
,libzip
,open62541
allemaal functies hebben voor het selecteren van een TLS- of crypto-back-end.curl
heeft verschillende opties voor crypto-back-end, maar staat selectie toe tijdens runtime, wat betekent dat het bovenstaande tenet wordt onderhouden. -
darknet
heeftopencv2
,opencv3
, functies om te bepalen welke versie van opencv kan worden gebruikt voor zijn afhankelijkheden.
Een functie kan preview- of bètafunctionaliteit inschakelen
Ondanks het bovenstaande geldt dat als er een preview-vertakking of vergelijkbaar is wanneer de preview-functionaliteit een hoge kans heeft om de niet-preview-functionaliteit niet te verstoren (bijvoorbeeld geen API-verwijderingen), is een functie acceptabel om deze instelling te modelleren.
Voorbeelden:
- De Azure SDK's (van het formulier
azure-Xxx
) hebben eenpublic-preview
functie. -
imgui
heeft eenexperimental-docking
-functie waarmee hun preview-docking-branch wordt ingeschakeld, die gebruikmaakt van een merge-commit die is gekoppeld aan elk van hun genummerde openbare releases.
Standaardfuncties mogen geen API's toevoegen
Standaardfuncties zijn bedoeld om ervoor te zorgen dat een redelijk functionele build van een bibliotheek wordt geïnstalleerd voor klanten die niet weten dat ze deze gebruiken. Als ze niet weten dat ze een bibliotheek gebruiken, kunnen ze geen functies vermelden.
libarchive
maakt bijvoorbeeld functies beschikbaar die compressiealgoritmen mogelijk maken binnen een bestaande algemene interface; als het zonder deze functies wordt gebouwd, kan de bibliotheek mogelijk geen nut hebben.
U moet zorgvuldig overwegen of een functie standaard moet zijn ingeschakeld, omdat het uitschakelen van standaardfuncties complex is.
Voor het uitschakelen van een standaardfunctie als transitieve consument is het volgende vereist:
- Alle klanten schakelen standaardfuncties expliciet uit via
"default-features": false
of inclusief[core]
in de lijst met functies op de opdrachtregel. - Naamgeving van de transitieve afhankelijkheid op de
vcpkg install
opdrachtregel of als directe afhankelijkheid in het manifest op het hoogste niveau
Als in het gecureerde register van vcpkg extra API's, uitvoerbare bestanden of andere binaire bestanden worden toegevoegd, moet deze standaard uitgeschakeld zijn. Als u twijfelt, markeert u geen functie als standaardfunctie.
Geen functies gebruiken om alternatieven in gepubliceerde interfaces te beheren
Als een consument van een poort alleen afhankelijk is van de kernfunctionaliteit van die poort, mag deze waarschijnlijk niet worden verbroken door de functie in te schakelen. Dit is nog belangrijker wanneer het alternatief niet rechtstreeks wordt beheerd door de consument, maar door compilerinstellingen zoals /std:c++17
/ -std=c++17
.
Bestaande voorbeelden die we vandaag niet zouden accepteren voor achterwaartse compatibiliteit:
-
redis-plus-plus[cxx17]
stuurt een polyfill aan, maar verankert de instelling niet in de installatiestructuur. -
ace[wchar]
wijzigt alle API's omconst wchar_t*
te accepteren in plaats vanconst char*
.
Een eigenschap kan polyfills vervangen door aliassen, mits de vervanging geïntegreerd is in de geïnstalleerde boomstructuur.
Ondanks het bovenstaande kunnen poorten polyfills met een functie verwijderen, zolang:
- Wanneer u de functie inschakelt, worden de polyfills gewijzigd in aliassen van de gepolyfillede entiteit.
- De status van de polyfill is geïntegreerd in de geïnstalleerde headers, waardoor ABI-mismatch 'onmogelijk' runtime-fouten onwaarschijnlijk maakt.
- Het is mogelijk voor een gebruiker van de poort om code te schrijven die in beide modi werkt, bijvoorbeeld door gebruik te maken van een typedef die gepolyfilled is of niet.
Voorbeeld:
-
abseil[cxx17]
wijzigtabsl::string_view
in een vervanging ofstd::string_view
; patch implementeert bakvereiste.
Aanbevolen oplossingen
Als het essentieel is om de onderliggende alternatieven beschikbaar te maken, raden we u aan berichten op het moment van de build op te geven om de gebruiker te instrueren hoe u de poort naar een privé-overlay kopieert:
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")
Bouwtechnieken
Gebruik geen leverancierafhankelijkheden
Gebruik geen ingesloten kopieën van bibliotheken. Alle afhankelijkheden moeten afzonderlijk worden gesplitst en verpakt, zodat ze kunnen worden bijgewerkt en onderhouden.
Gevendorde afhankelijkheden veroorzaken verschillende uitdagingen die conflicteren met de doelen van vcpkg om een betrouwbaar, consistent en onderhoudbaar pakketbeheersysteem te bieden.
Problemen met updates: ingesloten kopieën van bibliotheken maken het moeilijker om updates, inclusief beveiligingspatches, van de upstream-projecten bij te houden en toe te passen. Dit leidt tot potentiële beveiligingsrisico's en verouderde afhankelijkheden in het ecosysteem.
Symboolconflicten: meegeleverde afhankelijkheden kunnen symboolconflicten veroorzaken wanneer meerdere pakketten verschillende versies van dezelfde bibliotheken inclusief hebben.
Bijvoorbeeld: Als pakket A Library X (versie 1) meegeleverd en pakket B Library X (versie 2) meegeleverd, kan een toepassing die beide pakketten verbindt runtimefouten of onbepaald gedrag ondervinden vanwege conflicterende symbolen.
Door afhankelijkheden afzonderlijk te verpakken, zorgt vcpkg ervoor dat één versie van een bibliotheek wordt gebruikt voor alle pakketten, waardoor dergelijke conflicten worden geëlimineerd.
Licentienaleving: door leveranciers geleverde afhankelijkheden kunnen de licentiebepalingen van de ingesloten bibliotheken vertroebelen, waardoor zij mogelijk hun voorwaarden overtreden of compatibiliteitsproblemen kunnen veroorzaken.
Verhoogde onderhoudslast: Het synchroon houden van afhankelijkheden van leveranciers met hun upstream-versies vereist aanzienlijke handmatige inspanning en leidt vaak tot dubbel werk in verschillende pakketten.
Liever CMake gebruiken
Wanneer er meerdere buildsystems beschikbaar zijn, gebruikt u de voorkeur CMake.
Bovendien kan het, indien van toepassing, eenvoudiger en beter te onderhouden zijn om alternatieve buildsystems in CMake te herschrijven met behulp van file(GLOB)
instructies.
Voorbeelden: abseil
Kies statische of gedeelde binaire bestanden
Bij het bouwen van CMake-bibliotheken geeft vcpkg_cmake_configure()
de juiste waarde voor BUILD_SHARED_LIBS
door op basis van de aangevraagde variant van de gebruiker.
U kunt alternatieve configuratieparameters berekenen met behulp van 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}
)
Als een bibliotheek geen configuratieopties biedt om de buildvariant te selecteren, moet de build worden gepatcht. Wanneer u een build patcht, moet u altijd proberen de toekomstige onderhoudbaarheid van de poort te maximaliseren. Dit betekent meestal het minimaliseren van het aantal regels dat moet worden aangepast om het probleem op te lossen.
Voorbeeld: Een CMake-bibliotheek patchen om ongewenste varianten te voorkomen
Wanneer u bijvoorbeeld een CMake-bibliotheek patcht, is het mogelijk voldoende om EXCLUDE_FROM_ALL
toe te voegen aan ongewenste doelen en de install(TARGETS ...)
aanroep in een if(BUILD_SHARED_LIBS)
te verpakken. Dit is korter dan het verpakken of verwijderen van elke regel die de ongewenste variant vermeldt.
Voor een project CMakeLists.txt
met de volgende inhoud:
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)
Alleen de install(TARGETS)
lijn moet worden gepatcht.
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)
Bij het definiëren van functies bepaalt u expliciet afhankelijkheden
Wanneer u een functie definieert waarmee een optionele afhankelijkheid wordt vastgelegd, moet u ervoor zorgen dat de afhankelijkheid niet per ongeluk wordt gebruikt wanneer de functie niet expliciet is ingeschakeld.
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}
)
Het onderstaande fragment met vcpkg_check_features()
is gelijkwaardig.
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
in het fragment is hoofdlettergevoelig. Zie de documentatie voor CMAKE_DISABLE_FIND_PACKAGE_<PackageName>
en CMAKE_REQUIRE_FIND_PACKAGE_<PackageName>
voor meer informatie.
Conflicterende bibliotheken in een manual-link
map plaatsen
Een lib wordt beschouwd als conflicterend als een van de volgende handelingen wordt uitgevoerd:
-
main
definiëren - Malloc definiëren
- Symbolen definiëren die ook in andere bibliotheken worden gedeclareerd
Conflicterende bibliotheken worden doorgaans standaard ontworpen en worden niet beschouwd als een defect. Omdat sommige buildsystemen zijn gekoppeld aan alles in de lib-map, moeten deze worden verplaatst naar een submap met de naam manual-link
.
Versiebeheer
Volg algemene conventies voor het veld "version"
Wanneer u een nieuwe poort maakt, volgt u de versieconventie die wordt gebruikt door de auteur van het pakket. Wanneer u de poort bijwerkt, gebruik dan dezelfde conventie, tenzij upstream anders aangeeft. Zie onze documentatie voor versiebeheer voor een volledige uitleg van onze conventies.
Als upstream al een tijdje geen release heeft gepubliceerd, wijzigt u het versiebeheerschema van de poort niet in version-date
om de meest recente wijzigingen op te halen. Deze commits kunnen wijzigingen bevatten die niet gereed zijn voor gebruik in productie. Vraag in plaats daarvan de upstream-opslagplaats om een nieuwe release te publiceren.
Het veld "port-version"
bijwerken in het manifestbestand van gewijzigde poorten
vcpkg gebruikt dit veld om te bepalen of een bepaalde poort verouderd is en moet worden gewijzigd wanneer het gedrag van de poort wordt gewijzigd.
Onze conventie is om het veld "port-version"
te gebruiken voor wijzigingen in de poort die de upstream-versie niet wijzigen en om de "port-version"
weer in nul te zetten wanneer er een update naar de upstream-versie wordt uitgevoerd.
Bijvoorbeeld:
- De pakketversie van Zlib is momenteel
1.2.1
, zonder expliciete"port-version"
(gelijk aan een"port-version"
van0
). - U hebt ontdekt dat het verkeerde copyrightbestand is geïmplementeerd en dat in het poortbestand is opgelost.
- Werk het veld
"port-version"
in het manifestbestand bij naar1
.
Zie de documentatie voor versiebeheer voor meer informatie.
De versiebestanden bijwerken in versions/
van gewijzigde poorten
vcpkg maakt gebruik van een set metagegevensbestanden om de versiebeheerfunctie uit te schakelen. Deze bestanden bevinden zich op de volgende locaties:
-
${VCPKG_ROOT}/versions/baseline.json
, (dit bestand is gebruikelijk voor alle poorten) en -
${VCPKG_ROOT}/versions/${first-letter-of-portname}-/${portname}.json
(één per poort).
Voor zlib
zijn de relevante bestanden bijvoorbeeld:
${VCPKG_ROOT}/versions/baseline.json
${VCPKG_ROOT}/versions/z-/zlib.json
We verwachten dat telkens wanneer u een poort bijwerkt, u ook de versiebestanden bijwerkt.
De aanbevolen methode om deze bestanden bij te werken, is door de opdracht x-add-version
uit te voeren, bijvoorbeeld:
vcpkg x-add-version zlib
Als u meerdere poorten tegelijk bijwerkt, kunt u in plaats daarvan het volgende uitvoeren:
vcpkg x-add-version --all
om de bestanden voor alle gewijzigde poorten tegelijk bij te werken.
Notitie
Voor deze opdrachten moet u uw wijzigingen aan de poorten hebben doorgevoerd voordat u ze uitvoert. De reden hiervoor is dat de Git SHA van de poortmap vereist is in deze versiebestanden. Maar maak u geen zorgen, de opdracht x-add-version
waarschuwt u als u lokale wijzigingen hebt die niet zijn doorgevoerd.
Zie voor meer informatie de versieverwijzing en registers artikelen.
Bijwerken
vcpkg is een verpakkingsoplossing, niet de ultieme eigenaren van de onderdelen die we implementeren. In sommige gevallen moeten we patches toepassen om de compatibiliteit van onderdelen met platforms of compatibiliteit van onderdelen met elkaar te verbeteren.
- We willen patches voorkomen die:
- upstream zou het hier niet mee eens zijn
- beveiligingsproblemen of crashes veroorzaken
- we zijn niet in staat om upstream-versie-updates te onderhouden
- zijn groot genoeg om licentieverstrengeling met de vcpkg-opslagplaats zelf te veroorzaken
Upstream-eigenaren op de hoogte stellen van relevante upstream patches
Als een patch mogelijk nuttig kan zijn door upstream, moet upstream op de hoogte worden gebracht van de inhoud van de patch. (Patches die vcpkg-specifiek gedrag toepassen dat niet is gerelateerd aan upstream, zoals het verwijderen van een afhankelijkheid, vereisen geen melding.)
Om situaties te voorkomen waarin upstream het niet eens is met de patch, wachten we ten minste 30 dagen om dergelijke patches toe te passen.
We slaan deze wachttijd over als we een hoge betrouwbaarheid hebben dat de wijziging juist is. Voorbeelden van patches met hoge betrouwbaarheid zijn onder andere, maar zijn niet beperkt tot:
- De acceptatie van Upstream als een patch (bijvoorbeeld het backporteren van een specifieke wijziging van een pull-aanvraag upstream is samengevoegd).
- Het toevoegen van ontbrekende
#include
's. - Kleine en duidelijke productcodecorrecties (bijvoorbeeld het initialiseren van een niet-geïnitialiseerde variabele).
- Het uitschakelen van irrelevante in-vcpkg-onderdelen van de build, zoals tests of voorbeelden.
Kies liever voor opties dan voor patching
Het verdient de voorkeur om opties in te stellen in een aanroep naar vcpkg_configure_xyz()
in plaats van het rechtstreeks patchen van de instellingen.
Algemene opties waarmee u patching kunt voorkomen:
- [MSBUILD]
<PropertyGroup>
-instellingen in het projectbestand kunnen worden overschreven via/p:
-parameters - [CMAKE] Aanroepen naar
find_package(XYz)
in CMake-scripts kunnen worden uitgeschakeld via-DCMAKE_DISABLE_FIND_PACKAGE_XYz=ON
- [CMAKE] Cachevariabelen (gedeclareerd als
set(VAR "value" CACHE STRING "Documentation")
ofoption(VAR "Documentation" "Default Value")
) kunnen worden overschreven door ze gewoon door te geven op de opdrachtregel als-DVAR:STRING=Foo
. Een belangrijke uitzondering is als de parameterFORCE
wordt doorgegeven aanset()
. Zie de documentatie CMakeset
voor meer informatie
Geef de voorkeur aan het downloaden van goedgekeurde patches boven het inchecken ervan in de repository.
Als een goedgekeurd of samengevoegd patchbestand kan worden verkregen via upstream, moeten poorten proberen ze te downloaden en toe te passen in plaats van ze toe te passen als onderdeel van de poortbestanden. Dit proces heeft de voorkeur omdat dit het volgende doet:
- Bevestigt dat upstream de patchwijzigingen heeft geaccepteerd
- Vereenvoudigt het beoordelingsproces door de onus upstream te verplaatsen
- Vermindert de grootte van de vcpkg-opslagplaats voor gebruikers die de patch niet gebruiken
- Vermijdt licentieconflicten met de vcpkg-opslagplaats
Patches moeten worden gedownload vanaf een stabiel eindpunt om SHA-conflicten te voorkomen.
Wanneer u patchbestanden downloadt uit een pull-aanvraag of doorvoer vanuit GitHub en GitLab, moet de parameter ?full_index=1
worden toegevoegd aan de download-URL.
Voorbeelden:
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
Geef de voorkeur aan patching boven het overschrijven van VCPKG_<VARIABLE>
waarden.
Sommige variabelen voorafgegaan door VCPKG_<VARIABLE>
hebben een equivalente CMAKE_<VARIABLE>
.
Niet alle worden echter doorgegeven aan de interne build van het pakket (zie implementatie: Windows-hulpprogrammaketen).
Bekijk het volgende voorbeeld:
set(VCPKG_C_FLAGS "-O2 ${VCPKG_C_FLAGS}")
set(VCPKG_CXX_FLAGS "-O2 ${VCPKG_CXX_FLAGS}")
Met behulp van de ingebouwde hulpprogrammaketens van vcpkg
werkt dit, omdat de waarde van VCPKG_<LANG>_FLAGS
wordt doorgestuurd naar de juiste CMAKE_LANG_FLAGS
variabele. Maar een aangepaste hulpprogrammaketen die niet op de hoogte is van de variabelen van vcpkg
, zal deze niet doorsturen.
Daarom is het beter om het buildsysteem rechtstreeks te patchen bij het instellen van CMAKE_<LANG>_FLAGS
.
Patches minimaliseren
Wanneer u wijzigingen aanbrengt in een bibliotheek, streeft u ernaar om de laatste diff te minimaliseren. Dit betekent dat u de upstream-broncode niet opnieuw moet opmaken wanneer u wijzigingen aanbrengt die van invloed zijn op een regio. Wanneer u een voorwaarde uitschakelt, is het beter om een AND FALSE
of && 0
toe te voegen aan de voorwaarde dan om elke regel van de voorwaarde te verwijderen. Als een grote regio moet worden uitgeschakeld, is het korter om een if(0)
of #if 0
rond de regio toe te voegen in plaats van elke regel in de patch te verwijderen.
Voeg geen patches toe als de poort verouderd is en het bijwerken van de poort naar een nieuwere uitgebrachte versie hetzelfde probleem zou oplossen. vcpkg geeft de voorkeur aan het bijwerken van poorten ten opzichte van het patchen van verouderde versies.
Dit helpt om de grootte van de vcpkg-repository te beperken en vergroot de kans dat de patch van toepassing zal zijn op toekomstige versies van de code.
Functies in patches niet implementeren
Het doel van patchen in vcpkg is om compatibiliteit met compilers, bibliotheken en platforms mogelijk te maken. Het is niet om nieuwe functies te implementeren in plaats van het volgen van de juiste Open Source-procedure (het indienen van een probleem/pr/etc).
Bouw geen tests/docs/voorbeelden standaard
Wanneer u een nieuwe poort verzendt, controleert u op opties zoals BUILD_TESTS
of WITH_TESTS
of POCO_ENABLE_SAMPLES
en zorgt u ervoor dat de extra binaire bestanden zijn uitgeschakeld. Dit minimaliseert de buildtijden en afhankelijkheden voor de gemiddelde gebruiker.
U kunt desgewenst een test
functie toevoegen waarmee de tests kunnen worden gebouwd, maar dit mag niet in de Default-Features
lijst staan.
Bestaande gebruikers van de bibliotheek in staat stellen over te schakelen naar vcpkg
Voeg geen CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS
toe
Tenzij de auteur van de bibliotheek deze al gebruikt, mogen we deze CMake-functionaliteit niet gebruiken omdat deze slecht communiceert met C++-sjablonen en bepaalde compilerfuncties onderbreekt. Bibliotheken die geen .def-bestand bieden en geen __declspec() declaraties gebruiken, bieden geen ondersteuning voor gedeelde builds voor Windows en moeten als zodanig worden gemarkeerd met vcpkg_check_linkage(ONLY_STATIC_LIBRARY)
.
Wijzig de naam van binaire bestanden niet buiten de namen die zijn opgegeven door upstream
Dit betekent dat als de upstream-bibliotheek verschillende namen heeft in de release en foutopsporing (libx versus libxd), de naam van de bibliotheek voor foutopsporing niet mag worden gewijzigd in libx
. Omgekeerd, als de upstream-bibliotheek dezelfde naam heeft in de release en foutopsporing, mogen we geen nieuwe naam introduceren.
Belangrijke opmerking:
- Statische en gedeelde varianten moeten vaak worden hernoemd naar een gemeenschappelijk schema. Hierdoor kunnen consumenten een algemene naam gebruiken en de downstreamkoppeling negeren. Dit is veilig omdat we er slechts één voor één beschikbaar maken.
Als een bibliotheek CMake-integratiebestanden (foo-config.cmake
) genereert, moet u de naam wijzigen door de CMake-build zelf te patchen in plaats van gewoon file(RENAME)
aan te roepen in de uitvoerarchieven/LIBs.
Ten slotte mogen DLL-bestanden in Windows nooit na de build van naam worden gewijzigd, omdat dit de gegenereerde LIBs breekt.
Manifesten
We vereisen dat het manifestbestand wordt opgemaakt. Gebruik de volgende opdracht om alle manifestbestanden op te maken:
> vcpkg format-manifest --all
Drieling
We accepteren op dit moment geen verzoeken om niet-gemeenschapsgerelateerde tripletten toe te voegen. Promotie van community tot volledige tripletstatus is voornamelijk gebaseerd op het budget voor de hardware om dergelijke triplets te testen en wordt aangestuurd door metrische gegevens die door vcpkg worden ingediend, om de kans te maximaliseren dat wat mensen daadwerkelijk gebruiken, volledig getest is.
We voegen community-triplets toe als:
- Het is aangetoond dat mensen die community triplet daadwerkelijk zullen gebruiken; en
- We weten niet of zo'n triplet beschadigd is.
We hebben bijvoorbeeld geen triplet toegevoegd in https://github.com/microsoft/vcpkg/pull/29034 omdat de auteur alleen probeerde de set te voltooien in plaats van aan te geven dat ze zoiets daadwerkelijk zouden gebruiken, en we hebben linux-dynamic pas toegevoegd toen de patchelf-oplossing om de resultaten verplaatsbaar te maken was gecreëerd.
Nuttige implementatieopmerkingen
Portfiles worden uitgevoerd in scriptmodus
Hoewel portfile.cmake
's en CMakeLists.txt
een gemeenschappelijke syntaxis en kerntaalconstructs van CMake (ook wel 'Scriptopdrachten' genoemd) delen, worden portfiles uitgevoerd in 'Scriptmodus', terwijl CMakeLists.txt
bestanden worden uitgevoerd in 'Projectmodus'. Het belangrijkste verschil tussen deze twee modi is dat 'Scriptmodus' niet beschikt over de concepten 'Toolchain', 'Taal' en 'Doel'. Gedrag, waaronder scriptopdrachten, die afhankelijk zijn van deze constructies (bijvoorbeeld CMAKE_CXX_COMPILER
, CMAKE_EXECUTABLE_SUFFIX
, CMAKE_SYSTEM_NAME
) is niet juist.
Portfiles hebben directe toegang tot variabelen die zijn ingesteld in het drievoudige bestand, maar CMakeLists.txt
s niet (hoewel er vaak een vertaling is - VCPKG_LIBRARY_LINKAGE
versus BUILD_SHARED_LIBS
).
Portfiles en Project-builds die door portfiles worden aangeroepen, worden uitgevoerd in verschillende processen. Conceptueel:
+----------------------------+ +------------------------------------+
| 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) |
+----------------------------+ +------------------------------------+
Om de host in een poortbestand te bepalen, zijn de standaard CMake-variabelen prima (CMAKE_HOST_WIN32
).
Om het doel in een portfile te bepalen, moeten de vcpkg triplet variabelen worden gebruikt (VCPKG_CMAKE_SYSTEM_NAME
).
Zie ook onze drievoudige documentatie voor een volledige opsomming van mogelijke instellingen.