Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
W tym dokumencie wymieniono zestaw zasad, które należy zastosować podczas dodawania lub aktualizowania definicji portu. Ma ona pełnić rolę Podręcznika Polityki Debiana, Wytycznych Opiekuna Homebrew i Podręcznika Formuł Homebrew.
Ogólne cele projektowania rejestru
Porty w bieżącym punkcie odniesienia muszą być instalowane jednocześnie
Chcemy pokazać podrzędnym użytkownikom bibliotek w wyselekcjonowanym rejestrze, że kombinacja bibliotek w danym punkcie odniesienia, które publikujemy, została przetestowana pod kątem współpracy w co najmniej niektórych konfiguracjach. Zezwolenie na to, aby porty wykluczały się nawzajem, uniemożliwia testowanie takich konfiguracji, ponieważ liczba kompilacji niezbędnych do takich testów wzrośnie jako 2^number_of_such_cases
. Ponadto instalowanie dodatkowych zależności jest zawsze uznawane za "bezpieczne": nie ma możliwości, aby port lub użytkownik końcowy stwierdził, że zależność nie jest zainstalowana w ich wymaganiach.
Jeśli chcesz przedstawić taką alternatywną sytuację dla użytkowników, rozważ opisanie sposobu, w jaki ktoś może utworzyć port nakładkowy implementujący alternatywną formę za pomocą komentarza , zamiast dodawać dodatkowe porty nigdy niewbudowane w ciągłą integrację nadzorowanego rejestru. Zobacz na przykład glad@0.1.36.
Przed wprowadzeniem rejestrów zaakceptowaliśmy kilka nietestowanych portów jako alternatyw, takich jak boringssl
, które mogłyby ułatwić tworzenie portów nakładki. Nie jest to już akceptowane, ponieważ rejestry zezwalają na publikowanie tych nietestowanych portów bez modyfikowania nadzorowanego rejestru.
Użyj małych liter dla ciągów cyfr szesnastkowych
Wiele funkcji w narzędziu vcpkg polega na porównywaniu ciągów cyfr szesnastkowych. Niektóre przykłady obejmują, ale nie są ograniczone do, skrótów SHA512, identyfikatorów zatwierdzeń usługi Git i skrótów obiektów drzewa.
Wewnętrznie vcpkg używa normalizacji małych liter do porównań takich wartości, w których wielkość liter nie ma znaczenia. Jednak narzędzia oparte na infrastrukturze vcpkg mogą nie uwzględniać tych samych zagadnień. Z tego powodu wymagamy ciągów szesnastkowych
aby były zapisane małymi literami dla spójności w następujących scenariuszach:
-
SHA512
Parametr w funkcjach pomocnika vcpkg. -
REF
Parametr w funkcjach pomocnika vcpkg, gdy wartość jest ciągiem szesnastkowym. - Obiekt
git-tree
w plikach baz danych wersji. - Obiekt
sha512
wscripts/vcpkg-tools.json
pliku. - Inne miejsca, w których wielkość liter ciągu szesnastkowego jest nieważna.
Struktura PR
Składaj oddzielne żądania ściągnięcia dla każdego portu
Jeśli to możliwe, należy oddzielić zmiany w wielu żądaniach ściągnięcia. To znacznie ułatwia ich przeglądanie i zapobiega problemom, które jeden zestaw zmian może powodować, opóźniając inne zmiany.
Unikaj trywialnych zmian w nietkniętych plikach
Na przykład należy unikać ponownego formatowania lub zmieniania nazw zmiennych w portfiles, które w przeciwnym razie nie wymagają modyfikacji dla rozwiązywania aktualnego problemu. Jeśli jednak musisz zmodyfikować plik w podstawowym celu żądania ściągnięcia (aktualizowanie biblioteki), oczywiście korzystne zmiany, takie jak naprawianie literówek, są doceniane!
Sprawdzanie nazw w innych repozytoriach
Nazwy portów powinny dążyć do jednoznacznego określenia, który pakiet jest instalowany przez port. W idealnym przypadku wyszukiwanie nazwy portu w wyszukiwarce powinno szybko prowadzić do odpowiedniego projektu. Dobrą usługą do sprawdzania wielu nazw pakietów w wielu repozytoriach jednocześnie jest Repology.
Projekty z krótkimi nazwami lub nazwane po typowych słowach mogą wymagać uściślania, szczególnie jeśli nie ma projektów z silnym skojarzeniem danego słowa. Na przykład port o nazwie ip
nie jest akceptowalny, ponieważ prawdopodobnie wiele projektów będzie nazwanych podobnie.
Przykłady dobrych uściślaczów to:
- Nazwa użytkownika lub organizacja właściciela repozytorium:
google-cloud-cpp
. - Nazwa zestawu bibliotek, którego częścią jest projekt:
boost-dll
.
Typowe prefiksy i sufiksy używane przez projekty języka C++ i open source nie są prawidłowymi uściślaczami. Niektóre przykłady obejmują między innymi:
-
cpp
, -
free
, -
lib
, -
open
, - Liczby
Na przykład, podczas porównywania następujących nazw portów: ip-cpp
, libip
i ip5
oraz usuwania nieprawidłowych uściślaczy, wszystkie one są zredukowane do tego samego rdzenia (ip
), a tym samym są uznawane za te same nazwy.
Wyjątkiem od tych wytycznych jest nazwa, które są silnie skojarzone z pojedynczym projektem. Na przykład: libpng
, openssl
i zlib
.
Wersje robocze pull requestów w usłudze GitHub
Żądania ściągnięcia wersji roboczej w usłudze GitHub to doskonały sposób na uzyskanie informacji zwrotnych dotyczących ciągłej integracji lub ludzkiej opinii na temat pracy, która nie jest jeszcze gotowa do scalenia. Większość nowych żądań ściągnięcia powinna być otwierana jako wersje robocze i konwertowana na normalne żądania ściągnięcia po pomyślnym zakończeniu testów ciągłej integracji.
Aby uzyskać więcej informacji na temat wersji roboczych pull requestów GitHub, zobacz Wprowadzenie do roboczych pull requestów.
Portfile (Pliki portów)
Unikaj przestarzałych funkcji pomocnika
Obecnie następujące pomocniki są przestarzałe:
-
vcpkg_extract_source_archive_ex()
należy zastąpić obsługiwanym przeciążeniemvcpkg_extract_source_archive()
(zARCHIVE
) - Przestarzałe przeciążenie
vcpkg_extract_source_archive()
bezARCHIVE
powinno zostać zastąpione przez obsługiwane przeciążenie zARCHIVE
. -
vcpkg_apply_patches()
argumenty powinny zostać zastąpionePATCHES
argumentami pomocników "wyodrębniania" (np.vcpkg_from_github()
) -
vcpkg_build_msbuild()
element powinien zostać zastąpiony przezvcpkg_install_msbuild()
-
vcpkg_copy_tool_dependencies()
element powinien zostać zastąpiony przezvcpkg_copy_tools()
-
vcpkg_configure_cmake
element powinien zostać zastąpiony przezvcpkg_cmake_configure()
po usunięciuPREFER_NINJA
-
vcpkg_build_cmake
element powinien zostać zastąpiony przezvcpkg_cmake_build()
-
vcpkg_install_cmake
element powinien zostać zastąpiony przezvcpkg_cmake_install()
-
vcpkg_fixup_cmake_targets
element powinien zostać zastąpiony przezvcpkg_cmake_config_fixup
Niektóre funkcje pomocnika zastępczego znajdują się w "portach narzędzi", aby umożliwić konsumentom przypięcie ich zachowania w określonych wersjach, aby umożliwić blokowanie zachowania pomocników w określonej wersji. Porty narzędzi należy dodać do portu "dependencies"
w następujący sposób:
{
"name": "vcpkg-cmake",
"host": true
},
{
"name": "vcpkg-cmake-config",
"host": true
}
Unikaj nadmiernego komentarza w plikach portów
W idealnym przypadku pliki portów powinny być krótkie, proste i jak najbardziej deklaratywne.
Usuń wszelkie komentarze szablonowe na skutek polecenia create
przed przesłaniem PR.
Porty nie mogą być zależne od ścieżki
Porty nie mogą zmieniać ich zachowania na podstawie tego, które porty są już zainstalowane w postaci, która spowoduje zmianę zawartości instalowanej przez port. Na przykład na podstawie:
> vcpkg install a
> vcpkg install b
> vcpkg remove a
oraz
> vcpkg install b
pliki zainstalowane przez b
program muszą być takie same, niezależnie od wpływu poprzedniej a
instalacji programu . Oznacza to, że porty nie mogą próbować wykrywać, czy coś znajduje się w drzewie zainstalowanym przez inny port, zanim podejmą jakieś działania. Określoną i typową przyczyną takiego zachowania "zależnego od ścieżki" opisano poniżej w sekcji "Podczas definiowania funkcji jawnie kontrolować zależności".
Unikatowa reguła przypisywania portów
W całym systemie vcpkg nie powinno być dwóch portów, które użytkownik oczekuje używać jednocześnie, mogących dostarczać ten sam plik. Jeśli port spróbuje zainstalować plik już dostarczony przez inny plik, instalacja zakończy się niepowodzeniem. Jeśli port chce użyć niezwykle pospolitej nazwy nagłówka, na przykład należy umieścić te nagłówki w podkatalogu, a nie w include
.
Ta właściwość jest regularnie sprawdzana przez uruchomienia ciągłej integracji, które próbują zainstalować wszystkie porty w rejestrze, co zakończy się niepowodzeniem FILE_CONFLICTS
, jeśli dwa porty dostarczają ten sam plik.
Dodawanie eksportów narzędzia CMake w nieoficjalnej przestrzeni nazw
Podstawowym rozwiązaniem projektowym vcpkg jest nie tworzenie "blokady" dla użytkowników. W systemie kompilacji nie powinno istnieć różnic między poleganiem na bibliotece z systemu a poleganiem na bibliotece z programu vcpkg. W tym celu unikamy dodawania eksportów lub obiektów docelowych CMake do istniejących bibliotek o "oczywistej nazwie", aby umożliwić nadrzędnym dodawanie własnych oficjalnych eksportów CMake bez konfliktu z vcpkg.
W tym celu wszystkie konfiguracje CMake eksportowane przez porty, które nie znajdują się w bibliotece nadrzędnej, powinny mieć prefiks unofficial-
. Wszystkie dodatkowe elementy docelowe powinny znajdować się w unofficial::<port>::
przestrzeni nazw.
Oznacza to, że użytkownik powinien zobaczyć:
-
find_package(unofficial-<port> CONFIG)
jako sposób uzyskania pakietu unikalnego dla vcpkg -
unofficial::<port>::<target>
jako wyeksportowany cel z tego portu.
Przykłady:
-
brotli
tworzy pakietunofficial-brotli
, produkując docelowyunofficial::brotli::brotli
.
Instalowanie pliku praw autorskich
Każdy port musi podać plik o nazwie copyright
w folderze ${CURRENT_PACKAGES_DIR}/share/${PORT}
. Jeśli zawartość licencji pakietu jest dostępna w jego plikach źródłowych, ten plik powinien zostać utworzony przez wywołanie metody vcpkg_install_copyright()
.
vcpkg_install_copyright
w razie potrzeby zawiera także wiele plików praw autorskich.
vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE")
Starszą metodą ręcznego tworzenia tego pliku jest wbudowane file
polecenie CMake. Jest to odradzane na rzecz vcpkg_install_copyright
nowych portów, ale nadal jest dozwolone.
file(INSTALL "${SOURCE_PATH}/LICENSE" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}" RENAME copyright)
Jeśli zawartość licencji w nadrzędnych plikach źródłowych nie jest w postaci tekstowej (np. pliku PDF), copyright
powinna zawierać wyjaśnienie, w jaki sposób użytkownik może znaleźć wymagania licencyjne. Jeśli to możliwe, powinien również zawierać link do oryginalnych plików źródłowych wskazujących to, aby użytkownicy mogli sprawdzić, czy jest aktualna.
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
]])
Ograniczenia wersji w portach
Należy unikać ograniczeń wersji na portach, ponieważ mogą one utrudniać niezależną ewolucję projektów. Dodanie takich ograniczeń jest dopuszczalne tylko wtedy, gdy istnieje dobrze udokumentowane uzasadnienie, takie jak sprawdzona niezgodność z określonymi wcześniejszymi wersjami. Te ograniczenia nie powinny być wykorzystywane jedynie do utrzymania równoważności z niezależnymi projektami.
Zmienne w MAYBE_UNUSED_VARIABLES
muszą mieć zastosowanie do co najmniej jednej konfiguracji
Podczas dodawania nowej zmiennej w MAYBE_UNUSED_VARIABLES
celu wyciszenia ostrzeżenia podczas kroku konfiguracji narzędzia CMake należy dodać komentarz wyjaśniający przypadek zastosowania nowej zmiennej. Jeśli zmienna nie ma zastosowania w żadnej konfiguracji, jest bardzo prawdopodobne, że istnieje podstawowa usterka (na przykład nazwa błędu zmiennej) i dodanie jej nie ma rzeczywistego wpływu na kompilację.
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
)
Funkcje
Nie używaj funkcji do implementowania alternatyw
Funkcje muszą być traktowane jako funkcje addytywne. Jeśli port[featureA]
zainstaluje się i port[featureB]
zainstaluje się, to port[featureA,featureB]
musi zostać zainstalowane. Ponadto, jeśli drugi port zależy od i trzeci port zależy od [featureA]
[featureB]
, instalacja zarówno drugiego, jak i trzeciego portu powinna mieć spełnione zależności.
Biblioteki w tej sytuacji muszą wybrać jedną z dostępnych opcji, zgodnie z wyrażeniami w vcpkg, a użytkownicy, którzy preferują inne ustawienia, muszą obecnie korzystać z portów typu overlay.
Istniejące przykłady nie zostaną dziś zaakceptowane w celu zachowania zgodności z poprzednimi wersjami:
-
libgit2
,libzip
open62541
wszystkie mają funkcje do wybierania zaplecza TLS lub kryptografii.curl
ma różne opcje silników kryptograficznych, ale umożliwia wybór między nimi w czasie działania, co oznacza, że powyższa zasada jest utrzymana. -
darknet
maopencv2
,opencv3
funkcje do kontrolowania, której wersji opencv użyć dla swoich zależności.
Funkcja może włączać tryb wersji zapoznawczej lub beta
Niezależnie od powyższego, jeśli istnieje gałąź w wersji zapoznawczej lub podobna, w której funkcja w wersji zapoznawczej ma duże prawdopodobieństwo, że nie zakłóca działania funkcji innych niż wersja zapoznawcza (na przykład brak usuwania interfejsu API), funkcja jest akceptowalna do modelowania tego ustawienia.
Przykłady:
- Zestawy SDK platformy Azure (w formacie
azure-Xxx
) mają funkcjępublic-preview
. -
imgui
experimental-docking
ma funkcję, która angażuje swoją gałąź dokowania w wersji zapoznawczej, która używa zatwierdzenia scalania dołączonego do każdej z ich publicznych numerowanych wersji.
Funkcje domyślne nie mogą dodawać interfejsów API
Funkcje domyślne są przeznaczone do zapewnienia, że instalowana jest wystarczająco funkcjonalna wersja biblioteki dla klientów, którzy nie wiedzą, że z niej korzystają. Jeśli nie wiedzą, że korzystają z biblioteki, nie mogą wiedzieć, jak wymienić funkcje. Na przykład libarchive
uwidacznia funkcje, które umożliwiają korzystanie z algorytmów kompresji do istniejącego interfejsu ogólnego. Jeśli nie utworzono żadnej z takich funkcji, biblioteka może nie mieć żadnego narzędzia.
Należy dokładnie rozważyć, czy funkcja powinna być włączona domyślnie, ponieważ wyłączenie funkcji domyślnych jest złożone.
Wyłączenie funkcji domyślnej jako użytkownika przejściowego wymaga:
- Wszyscy klienci, którzy jawnie wyłączają funkcje domyślne poprzez
"default-features": false
lub uwzględniają[core]
w liście funkcji w wierszu polecenia. - Określanie zależności przechodnich na
vcpkg install
wierszu polecenia lub jako bezpośrednia zależność w manifeście najwyższego poziomu
W rejestrze kuratorowanym przez vcpkg, jeśli funkcja dodaje dodatkowe interfejsy API, pliki wykonywalne lub inne pliki binarne, musi ona być domyślnie wyłączona. W razie wątpliwości nie oznaczaj funkcji jako domyślnej.
Nie używaj funkcji do kontrolowania alternatyw w opublikowanych interfejsach
Jeśli użytkownik portu zależy tylko od podstawowych funkcji tego portu, z dużym prawdopodobieństwem nie może zostać przerwany przez włączenie funkcji. Jest to jeszcze ważniejsze, gdy alternatywa nie jest bezpośrednio kontrolowana przez użytkownika, ale przez ustawienia kompilatora, takie jak /std:c++17
/ -std=c++17
.
Istniejące przykłady nie zostaną dziś zaakceptowane w celu zachowania zgodności z poprzednimi wersjami:
-
redis-plus-plus[cxx17]
kontroluje działanie polyfill, ale nie wbudowuje ustawienia w zainstalowane drzewo. -
ace[wchar]
zmienia wszystkie interfejsy API tak, aby akceptowałyconst wchar_t*
zamiastconst char*
.
Funkcja może zastąpić polyfills aliasami, pod warunkiem że zamiana jest wbudowana w strukturę instalacyjną.
Niezależnie od powyższego, porty mogą usuwać polyfille za pomocą funkcji, o ile:
- Włączenie funkcji powoduje zmianę wielowypełnień na aliasy jednostki poliwypełnionej
- Stan poliwypełniania jest zintegrowany z zainstalowanymi nagłówkami, dzięki czemu błędy ABI, które teoretycznie są "niemożliwe" podczas działania programu, są mało prawdopodobne.
- Użytkownik portu może napisać kod, który działa w obu trybach, na przykład przy użyciu definicji typu, która jest poliwypełniana lub nie
Przykład:
-
abseil[cxx17]
zmieniaabsl::string_view
na zamiennik lubstd::string_view
; poprawka wprowadza wymaganie pieczenia.
Zalecane rozwiązania
Jeśli kluczowe jest uwidocznienie bazowych alternatyw, zalecamy udostępnienie komunikatów w czasie kompilacji, aby poinstruować użytkownika o tym, jak skopiować port do prywatnej nakładki:
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")
Techniki budowania
Nie używaj zależności od dostawcy
Nie używaj osadzonych kopii bibliotek. Wszystkie zależności powinny być podzielone i spakowane oddzielnie, aby można je było aktualizować i konserwować.
Zależności załączone wprowadzają kilka wyzwań, które są w sprzeczności z celami programu vcpkg, dążącymi do zapewnienia niezawodnego, spójnego i łatwego do zarządzania systemu zarządzania pakietami.
Trudności w aktualizacjach: osadzone kopie bibliotek utrudniają śledzenie i stosowanie aktualizacji, w tym poprawek zabezpieczeń, z projektów nadrzędnych. Prowadzi to do potencjalnych zagrożeń bezpieczeństwa i nieaktualnych zależności w ekosystemie.
Konflikty symboli: Wbudowane zależności mogą powodować konflikty symboli, gdy wiele pakietów zawiera różne wersje tej samej biblioteki.
Na przykład: Jeśli pakiet A zawiera bibliotekę X (wersja 1), a pakiet B zawiera bibliotekę X (wersja 2), aplikacja łącząca oba pakiety może napotkać błędy w czasie wykonywania lub niezdefiniowane zachowanie z powodu konfliktujących symboli.
Dzięki oddzielnemu pakowaniu zależności vcpkg zapewnia, że pojedyncza wersja biblioteki jest używana we wszystkich pakietach, eliminując takie konflikty.
Zgodność z licencjami: zależności pochodzące od zewnętrznych dostawców mogą zaciemniać kwestię licencjonowania osadzonych bibliotek, co może prowadzić do naruszania ich warunków lub problemów z kompatybilnością.
Zwiększone obciążenie konserwacją: utrzymywanie zależności dostawców w synchronizacji z ich nadrzędnymi wersjami wymaga znacznego nakładu pracy ręcznej i często prowadzi do zduplikowanej pracy między pakietami.
Preferuj korzystanie z narzędzia CMake
Jeśli dostępnych jest wiele systemów kompilacji, preferuj korzystanie z narzędzia CMake.
Ponadto, jeśli jest to konieczne, można łatwiej i bardziej konserwować ponowne zapisywanie alternatywnych systemów kompilacji w narzędziu CMake przy użyciu file(GLOB)
dyrektyw.
Przykłady: abseil
Wybieranie plików binarnych statycznych lub udostępnionych
Podczas kompilowania bibliotek vcpkg_cmake_configure()
CMake zostanie przekazana poprawna wartość na BUILD_SHARED_LIBS
podstawie żądanego wariantu użytkownika.
Możesz obliczyć alternatywne parametry konfiguracji przy użyciu polecenia 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}
)
Jeśli biblioteka nie oferuje opcji konfigurowania w celu wybrania wariantu kompilacji, kompilacja musi zostać poprawiona. Podczas stosowania poprawek do kompilacji zawsze należy dążyć do maksymalizacji przyszłej łatwości utrzymania portu. Zazwyczaj oznacza to zminimalizowanie liczby wierszy, które należy zmienić, aby rozwiązać problem.
Przykład: stosowanie poprawek biblioteki CMake w celu uniknięcia tworzenia niechcianych wariantów
Na przykład podczas stosowania poprawek biblioteki opartej na narzędziu CMake może wystarczyć dodanie EXCLUDE_FROM_ALL
do niechcianych obiektów docelowych i opakowanie wywołania install(TARGETS ...)
w elemencie if(BUILD_SHARED_LIBS)
. Będzie to krótsze niż zawijanie lub usuwanie każdego wiersza, który wspomina o niechcianym wariantie.
W przypadku projektu CMakeLists.txt
z następującą zawartością:
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)
Tylko linia install(TARGETS)
musi zostać poprawiona.
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)
Podczas definiowania funkcji jawne kontrolowanie zależności
Podczas definiowania funkcji, która przechwytuje opcjonalną zależność, upewnij się, że zależność nie będzie używana przypadkowo, gdy funkcja nie jest jawnie włączona.
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}
)
Poniższy fragment z użyciem vcpkg_check_features()
jest równoważny.
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
w fragmencie kodu ma znaczenie wielkość liter. Aby uzyskać więcej informacji, zobacz dokumentację CMAKE_DISABLE_FIND_PACKAGE_<PackageName>
i CMAKE_REQUIRE_FIND_PACKAGE_<PackageName>
.
Umieszczanie bibliotek powodujących konflikt w manual-link
katalogu
Biblioteka jest uważana za powodującą konflikt, jeśli wykonuje dowolną z następujących czynności:
- Zdefiniuj
main
- Zdefiniuj malloc
- Definiowanie symboli zadeklarowanych również w innych bibliotekach
Biblioteki powodujące konflikt są zwykle zgodne z projektem i nie są uznawane za wadę. Ponieważ niektóre systemy kompilacji łączą się ze wszystkimi elementami w katalogu lib, powinny one zostać przeniesione do podkatalogu o nazwie manual-link
.
Wersjonowanie
Postępuj zgodnie z typowymi konwencjami dla "version"
pola
Podczas tworzenia nowego portu postępuj zgodnie z konwencją przechowywania wersji używaną przez autora pakietu. Podczas aktualizowania portu kontynuuj korzystanie z tej samej konwencji, chyba że nadrzędne polecenie mówi inaczej. Pełne wyjaśnienie naszych konwencji można znaleźć w naszej dokumentacji dotyczącej przechowywania wersji.
Jeśli nadrzędne źródło nie opublikowało wydania od pewnego czasu, nie zmieniaj schematu wersjonowania portów, aby uzyskać najnowsze zmiany. Te zatwierdzenia mogą obejmować zmiany, które nie są gotowe do produkcji. Zamiast tego poproś repozytorium nadrzędne o opublikowanie nowej wersji.
"port-version"
Zaktualizuj pole w pliku manifestu wszystkich zmodyfikowanych portów
Narzędzie vcpkg używa tego pola do określenia, czy dany port jest nieaktualny i powinien zostać zmieniony za każdym razem, gdy zachowanie portu ulegnie zmianie.
Nasza konwencja polega na użyciu "port-version"
pola dla zmian w porcie, które nie zmieniają wersji nadrzędnej, i zresetowania "port-version"
z powrotem do zera po wprowadzeniu aktualizacji do nadrzędnej wersji.
Na przykład:
- Wersja pakietu Zlib jest obecnie
1.2.1
, bez jawnego"port-version"
(odpowiadającego"port-version"
0
). - Odkryliśmy, że wdrożono niewłaściwy plik praw autorskich i naprawiono to w pliku portfile.
- Należy zaktualizować
"port-version"
pole w pliku manifestu na1
.
Aby uzyskać więcej informacji, zobacz dokumentację dotyczącą przechowywania wersji.
Zaktualizuj pliki wersji w versions/
dowolnych zmodyfikowanych portów
Narzędzie vcpkg używa zestawu plików metadanych do zasilania funkcji przechowywania wersji. Te pliki znajdują się w następujących lokalizacjach:
-
${VCPKG_ROOT}/versions/baseline.json
, (ten plik jest wspólny dla wszystkich portów) i -
${VCPKG_ROOT}/versions/${first-letter-of-portname}-/${portname}.json
(jeden na port).
Na przykład, w przypadku zlib
, pliki, które są istotne, to:
${VCPKG_ROOT}/versions/baseline.json
${VCPKG_ROOT}/versions/z-/zlib.json
Oczekujemy, że za każdym razem, gdy zaktualizujesz port, zaktualizujesz również jego pliki wersji.
Zalecaną metodą aktualizacji tych plików jest uruchomienie x-add-version
polecenia, np.:
vcpkg x-add-version zlib
Jeśli aktualizujesz jednocześnie wiele portów, możesz zamiast tego uruchomić następujące polecenie:
vcpkg x-add-version --all
aby zaktualizować pliki dla wszystkich zmodyfikowanych portów jednocześnie.
Aby uzyskać więcej informacji, zobacz artykuły Versioning reference i Registries.
Stosowanie poprawek
vcpkg to rozwiązanie do tworzenia pakietów, a nie ostateczni właściciele wdrażanych składników. W niektórych przypadkach musimy zastosować poprawki, aby poprawić zgodność składników z platformami lub zgodność składników ze sobą.
- Chcemy uniknąć poprawek, które:
- nadrzędne nie zgadzałoby się z
- powodować luki w zabezpieczeniach lub awarie
- Nie jesteśmy w stanie utrzymywać aktualizacji wersji nadrzędnych
- są wystarczająco duże, aby spowodować konflikt licencji w samym repozytorium vcpkg
Powiadamianie właścicieli nadrzędnych o odpowiednich poprawkach nadrzędnych
Jeśli poprawka może być przydatna dla głównego repozytorium, należy powiadomić o jej treści. (Poprawki stosujące zachowanie specyficzne dla vcpkg, niezwiązane z kodem źródłowym nadrzędnym, takie jak usuwanie zależności, nie wymagają powiadomienia.)
Aby uniknąć sytuacji, w których zespół nadrzędny nie zgadza się z poprawką, odczekamy co najmniej 30 dni przed zastosowaniem takich poprawek.
Pominiemy ten okres oczekiwania, jeśli mamy wysoką pewność, że zmiana jest poprawna. Przykłady poprawek o wysokiej pewności obejmują, ale nie są ograniczone do:
- Akceptacja zmian przez projekt źródłowy jako poprawki (na przykład przeniesienie wstecz określonej zmiany z zintegrowanego żądania w projekt źródłowy).
- Dodawanie brakujących elementów
#include
. - Małe i oczywiste poprawki kodu produktu (na przykład inicjowanie niezainicjowanej zmiennej).
- Wyłączanie zbędnych składników kompilacji vcpkg, takich jak testy lub przykłady.
Preferuj opcje stosowania poprawek
Preferowane jest ustawianie opcji w wywołaniu vcpkg_configure_xyz()
niż bezpośrednie wprowadzanie zmian w ustawieniach.
Typowe opcje, które pozwalają uniknąć stosowania poprawek:
- [MSBUILD]
<PropertyGroup>
ustawienia wewnątrz pliku projektu można zastąpić za pomocą/p:
parametrów - [CMAKE] Wywołania
find_package(XYz)
w skryptach CMake można wyłączyć za pomocą-DCMAKE_DISABLE_FIND_PACKAGE_XYz=ON
- [CMAKE] Zmienne pamięci podręcznej (zadeklarowane jako
set(VAR "value" CACHE STRING "Documentation")
luboption(VAR "Documentation" "Default Value")
) można przesłonić, przekazując je tylko w wierszu polecenia jako-DVAR:STRING=Foo
. Jednym z możliwych wyjątków jest przekazanie parametruFORCE
doset()
. Aby uzyskać więcej informacji, zobacz dokumentację CMakeset
Preferuj pobieranie zatwierdzonych poprawek zamiast umieszczania ich w porcie.
Jeśli można uzyskać zatwierdzony lub połączony plik poprawki z upstream, porty powinny próbować je pobrać i zastosować, zamiast dołączać je do plików portów. Ten proces jest preferowany, ponieważ:
- Potwierdza, że źródło nadrzędne zaakceptowało zmiany w poprawkach.
- Upraszcza proces przeglądania, przenosząc odpowiedzialność na wcześniejszy etap.
- Zmniejsza rozmiar repozytorium vcpkg dla użytkowników, którzy nie korzystają z poprawki
- Unika konfliktów licencji z repozytorium vcpkg
Poprawki należy pobrać ze stabilnego punktu końcowego, aby uniknąć konfliktów SHA.
Podczas pobierania plików poprawek z żądania ściągnięcia lub zatwierdzenia na GitHub i GitLab, należy dołączyć parametr ?full_index=1
do adresu URL pobierania.
Przykłady:
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
Preferuj stosowanie łat zamiast nadpisywania VCPKG_<VARIABLE>
wartości
Niektóre zmienne poprzedzone prefiksem VCPKG_<VARIABLE>
mają odpowiednik CMAKE_<VARIABLE>
.
Jednak nie wszystkie z nich są przekazywane do wewnętrznej kompilacji pakietu (zobacz implementacja: łańcuch narzędzi systemu Windows).
Rozważmy następujący przykład:
set(VCPKG_C_FLAGS "-O2 ${VCPKG_C_FLAGS}")
set(VCPKG_CXX_FLAGS "-O2 ${VCPKG_CXX_FLAGS}")
Użycie wbudowanych vcpkg
łańcuchów narzędziowych działa, ponieważ wartość VCPKG_<LANG>_FLAGS
jest przekazywana do odpowiedniej zmiennej CMAKE_LANG_FLAGS
. Jednak niestandardowy łańcuch narzędzi, który nie jest świadomy zmiennych vcpkg
, nie będzie ich przekazywać dalej.
W związku z tym zaleca się stosowanie poprawek systemu kompilacji bezpośrednio podczas ustawiania polecenia CMAKE_<LANG>_FLAGS
.
Minimalizuj poprawki
Podczas wprowadzania zmian w bibliotece staraj się zminimalizować ostateczną różnicę. Oznacza to, że podczas wprowadzania zmian wpływających na region nie należy ponownie sformatować nadrzędnego kodu źródłowego. Podczas wyłączania instrukcji warunkowej lepiej jest dodać AND FALSE
lub && 0
do warunku niż usunąć każdy wiersz instrukcji warunkowej. Jeśli duży region musi być wyłączony, łatwiej jest dodać if(0)
lub #if 0
wokół regionu zamiast usuwać każdy wiersz w poprawce.
Nie dodawaj poprawek, jeśli port jest nieaktualny i aktualizowanie portu do nowszej wersji rozwiąże ten sam problem. Narzędzie vcpkg preferuje aktualizowanie portów zamiast poprawiania nieaktualnych wersji.
Pomaga to zmniejszyć rozmiar repozytorium vcpkg oraz zwiększa prawdopodobieństwo, że poprawka będzie pasować do przyszłych wersji kodu.
Nie implementuj funkcji w poprawkach
Celem stosowania poprawek w narzędziu vcpkg jest zapewnienie zgodności z kompilatorami, bibliotekami i platformami. Nie należy implementować nowych funkcji zamiast przestrzegać odpowiedniej procedury open source (zgłaszanie problemu/wniosku o połączenie itp.).
Domyślnie nie kompiluj testów/dokumentacji/przykładów
Podczas przesyłania nowego portu sprawdź wszelkie opcje, takie jak BUILD_TESTS
lub WITH_TESTS
lub POCO_ENABLE_SAMPLES
i upewnij się, że dodatkowe pliki binarne są wyłączone. Minimalizuje to czas kompilacji i zależności dla przeciętnego użytkownika.
Opcjonalnie możesz dodać test
funkcję, która umożliwia kompilowanie testów, jednak nie powinna ona znajdować się na Default-Features
liście.
Umożliwianie istniejącym użytkownikom biblioteki przełączania się do programu vcpkg
Nie dodawaj CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS
O ile autor biblioteki nie korzysta już z niej, nie powinniśmy używać tej funkcji narzędzia CMake, ponieważ współdziała ona źle z szablonami języka C++ i przerywa działanie niektórych funkcji kompilatora. Biblioteki, które nie udostępniają pliku .def i nie używają deklaracji __declspec() po prostu nie obsługują udostępnionych kompilacji dla systemu Windows i powinny być oznaczone jako takie:
if(VCPKG_TARGET_IS_WINDOWS)
vcpkg_check_linkage(ONLY_STATIC_LIBRARY)
endif()
Nie zmieniaj nazw plików binarnych na inne niż nazwy nadane przez źródło
Oznacza to, że jeśli biblioteka nadrzędna ma różne nazwy w wersji i debugu (libx a libxd), biblioteka debugowania nie powinna być zmieniana na libx
. Na odwrót, jeśli biblioteka nadrzędna ma taką samą nazwę w wersji i debugu, nie powinniśmy wprowadzać nowej nazwy.
Ważne zastrzeżenie:
- Często należy zmienić nazwy wariantów statycznych i udostępnionych na wspólny schemat. Dzięki temu konsumenci mogą używać nazwy pospolitej i ignorować powiązania podrzędnego. Jest to bezpieczne, ponieważ udostępniamy tylko jeden naraz.
Jeśli biblioteka generuje pliki integracji narzędzia CMake (foo-config.cmake
), zmiana nazwy należy wykonać za pomocą poprawek kompilacji narzędzia CMake zamiast po prostu wywoływać file(RENAME)
archiwa wyjściowe/jednostki LIB.
Na koniec pliki DLL w systemie Windows nigdy nie powinny być przemianowane po kompilacji, ponieważ przerywa to wygenerowane pliki LIB.
Manifesty
Wymagamy sformatowania pliku manifestu. Użyj następującego polecenia, aby sformatować wszystkie pliki manifestu:
> vcpkg format-manifest --all
Trojaczki
Obecnie nie akceptujemy próśb o dodanie trójek niezwiązanych ze społecznością. Promocja ze społeczności do pełnego statusu trójki opiera się głównie na budżecie przeznaczonym na testowanie sprzętu i będzie napędzana przez metryki dostarczone przez vcpkg, aby zmaksymalizować prawdopodobieństwo, że to, czego ludzie faktycznie używają, jest w pełni przetestowane.
Dodamy trójki społeczności, jeśli:
- Wykazano, że ludzie będą rzeczywiście korzystać z tej trójki społeczności; i
- nie wiemy, że taka trójka jest złamana.
Na przykład nie dodaliśmy trójki w https://github.com/microsoft/vcpkg/pull/29034, ponieważ autor po prostu próbował "ukończyć zestaw", zamiast wskazać, że rzeczywiście użyje takiego elementu, a my nie dodaliśmy linux-dynamic, dopóki rozwiązanie patchelf umożliwiające przenoszenie wyników nie zostało stworzone.
Przydatne uwagi dotyczące implementacji
Pliki portów są uruchamiane w trybie skryptu
Chociaż pliki portfile.cmake
i CMakeLists.txt
mają wspólną składnię i podstawowe konstrukcje języka CMake (znane również jako "Scripting Commands"), portfiles działają w trybie skryptowym, podczas gdy pliki CMakeLists.txt
działają w trybie projektowym. Najważniejszą różnicą między tymi dwoma trybami jest to, że "Tryb skryptu" nie przewiduje koncepcji "łańcucha narzędziowego", "języka" i "celu". Wszelkie zachowania, w tym polecenia skryptów, które zależą od tych konstrukcji (np. CMAKE_CXX_COMPILER
, CMAKE_EXECUTABLE_SUFFIX
, ), CMAKE_SYSTEM_NAME
nie będą poprawne.
Pliki Portfile mają bezpośredni dostęp do zmiennych ustawionych w pliku triplet, ale CMakeLists.txt
s już nie (chociaż często odbywa się jakieś tłumaczenie — VCPKG_LIBRARY_LINKAGE
versus BUILD_SHARED_LIBS
).
Kompilacje Portfile i Project wywoływane przez pliki portów są uruchamiane w różnych procesach. Koncepcyjnie:
+----------------------------+ +------------------------------------+
| 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) |
+----------------------------+ +------------------------------------+
Aby określić hosta w pliku portfile, standardowe zmienne CMake są poprawne (CMAKE_HOST_WIN32
).
Aby określić obiekt docelowy w pliku portfile, należy użyć zmiennych potrójnych vcpkg (VCPKG_CMAKE_SYSTEM_NAME
).
Zapoznaj się również z naszą dokumentacją trypletów, aby uzyskać pełne wyliczenie możliwych ustawień.