Przewodnik po stylu narzędzia CMake
Oczekujemy, że wszystkie skrypty narzędzia CMake, które są albo:
scripts/
W katalogu lubvcpkg-*
W porcie
należy postępować zgodnie z wytycznymi określonymi w tym dokumencie. Istniejące skrypty mogą nie być jeszcze zgodne z tymi wytycznymi; oczekuje się, że będziemy nadal aktualizować stare skrypty zgodnie z tymi wytycznymi.
Te wytyczne mają na celu stworzenie stabilności w naszych skryptach. Mamy nadzieję, że ułatwią one zgodność zarówno do przodu, jak i z poprzednimi wersjami.
Wytyczne
Z wyjątkiem parametrów out-parameters, zawsze używamy
cmake_parse_arguments()
zamiast parametrów funkcji lub odwołując się do${ARG<N>}
.Nie musi to być zgodne z instrukcjami "script-local helper functions"
- W takim przypadku parametry pozycyjne powinny być umieszczane w deklaracji funkcji (zamiast używania
${ARG<N>}
), i powinny być nazwane zgodnie z regułami lokalnymi (tj.snake_case
). - Wyjątek: parametry pozycyjne, które są opcjonalne, powinny mieć nazwę za pośrednictwem
set(argument_name "${ARG<N>}")
metody , po sprawdzeniuARGC
wartości .
- W takim przypadku parametry pozycyjne powinny być umieszczane w deklaracji funkcji (zamiast używania
Parametry wychodzące powinny być pierwszym parametrem funkcji. Przykład:
function(format out_var) cmake_parse_arguments(PARSE_ARGV 1 "arg" ...) # ... set(buffer "output") set("${out_var}" "${buffer}" PARENT_SCOPE) endfunction()
Nie ma żadnych nieparzysty ani nieużywanych argumentów. Zawsze sprawdzaj wartość
ARGN
lubarg_UNPARSED_ARGUMENTS
.FATAL_ERROR
jeśli jest to możliwe,WARNING
w razie potrzeby w celu zapewnienia zgodności z poprzednimi wersjami.Wszystkie
cmake_parse_arguments
muszą używać poleceniaPARSE_ARGV
.Wszystkie
foreach
pętle muszą używaćIN LISTS
pętli ,IN ITEMS
lubRANGE
.Zmienne
${ARGV}
i${ARGN}
nie są wnioskowane, z wyjątkiem przydatnych komunikatów dla użytkownika.- (tj.
message(FATAL_ERROR "blah was passed extra arguments: ${ARGN}")
)
- (tj.
Zawsze używamy funkcji, a nie makr ani kodu najwyższego poziomu.
- Wyjątek: "script-local helper macros". Czasami pomocne jest zdefiniowanie małego makra. Należy to zrobić oszczędnie, a preferowane powinny być funkcje.
- Wyjątek:
vcpkg.cmake
'sfind_package
.
Skrypty w drzewie skryptów nie powinny wymagać obserwowanych zmian w ramach normalnego działania.
- Przykładowe naruszenie:
vcpkg_acquire_msys()
ma zakodowane pakiety i wersje, które wymagają aktualizacji w czasie z powodu upuszczania starych pakietów w projekcie MSYS. - Przykładowy wyjątek:
vcpkg_from_sourceforge()
zawiera listę dublowania, które wymagają konserwacji, ale nie ma zauważalnego wpływu na osoby wywołujące.
- Przykładowe naruszenie:
Reguły cudzysłów: istnieją trzy rodzaje argumentów w CMake — bez cudzysłów (), cudzysłowie (
foo(BAR)
foo("BAR")
) i nawias (foo([[BAR]])
). Postępuj zgodnie z następującymi regułami, aby poprawnie cytować:Jeśli argument zawiera rozszerzenie
${...}
zmiennej , musi być cytowany.Wyjątek: rozszerzenie zmiennej "splat", gdy jedna zmienna zostanie przekazana do funkcji jako wiele argumentów. W takim przypadku argument powinien po prostu mieć wartość
${foo}
:vcpkg_list(SET working_directory) if(DEFINED "arg_WORKING_DIRECTORY") vcpkg_list(SET working_directory WORKING_DIRECTORY "${arg_WORKING_DIRECTORY}") endif() # calls do_the_thing() if NOT DEFINED arg_WORKING_DIRECTORY, # else calls do_the_thing(WORKING_DIRECTORY "${arg_WORKING_DIRECTORY}") do_the_thing(${working_directory})
W przeciwnym razie, jeśli argument zawiera jakiekolwiek sekwencje ucieczki, które nie
\\
są ,\"
lub\$
, argument musi być argumentem cytowanym.- Na przykład:
"foo\nbar"
musi być cytowany.
- Na przykład:
W przeciwnym razie jeśli argument zawiera
\
argument , lub"
$
, argument powinien być nawiasem kwadratowym.Przykład:
set(x [[foo\bar]]) set(y [=[foo([[bar\baz]])]=])
W przeciwnym razie, jeśli argument zawiera znaki, które nie są alfanumeryczne lub
_
, argument powinien być cytowany.W przeciwnym razie argument powinien być bez cudzysłów.
Wyjątek: argumenty typu
if()
<variable|string>
powinny być zawsze cytowane:Oba argumenty operatorów porównania —
EQUAL
,STREQUAL
,VERSION_LESS
itp.Pierwszy argument do
MATCHES
iIN_LIST
Przykład:
if("${FOO}" STREQUAL "BAR") # ... if("${BAZ}" EQUAL "0") # ... if("FOO" IN_LIST list_variable) # ... if("${bar}" MATCHES [[a[bcd]+\.[bcd]+]]) # ...
W przypadku wyrażeń pojedynczych i innych typów predykatów, które nie przyjmują
<variable|string>
, użyj normalnych reguł.
Brak parametrów "wskaźnik" lub "wyjęcie" (gdzie użytkownik przekazuje nazwę zmiennej, a nie zawartość), z wyjątkiem prostych parametrów wyjściowych.
Nie zakłada się, że zmienne są puste. Jeśli zmienna ma być używana lokalnie, musi być jawnie zainicjowana, aby była pusta
set(foo "")
, jeśli jest zmienną ciągu, avcpkg_list(SET foo)
jeśli jest zmienną listy.set(var)
nie należy używać. Użyjunset(var)
polecenia , aby usunąć ustawienie zmiennej,set(var "")
aby ustawić ją na pusty ciąg ivcpkg_list(SET var)
ustawić ją na pustą listę. Uwaga: pusty ciąg i pusta lista są tą samą wartością;jest to różnica notacyjna, a nie różnica w wynikuWszystkie zmienne, które mają być dziedziczone z zakresu nadrzędnego w granicach interfejsu API (tj. nie funkcji pliku lokalnego), powinny być udokumentowane. Wszystkie zmienne wymienione w plikach Triplet są uznawane za udokumentowane.
Parametry wychodzące są ustawiane tylko w
PARENT_SCOPE
parametrach i nigdy nie są odczytywane. Zobacz również pomocnikz_vcpkg_forward_output_variable()
do przekazywania parametrów za pośrednictwem zakresu funkcji.CACHE
Zmienne są używane tylko w przypadku zmiennych globalnych, które są współużytkowane wewnętrznie między silnie powiązanymi funkcjami i stanem wewnętrznym w ramach jednej funkcji, aby uniknąć duplikowania pracy. Powinny one być używane bardzo oszczędnie i powinny używać prefiksuZ_VCPKG_
, aby uniknąć kolizji z dowolnymi zmiennymi lokalnymi, które byłyby zdefiniowane przez dowolny inny kod.- Przykłady:
vcpkg_cmake_configure
's)Z_VCPKG_CMAKE_GENERATOR
z_vcpkg_get_cmake_vars
's)Z_VCPKG_GET_CMAKE_VARS_FILE
- Przykłady:
include()
s są dozwolone tylko w elemecieports.cmake
lubvcpkg-port-config.cmake
.foreach(RANGE)
Argumenty "zawsze muszą być liczbami naturalnymi i<start>
zawsze muszą być mniejsze niż lub równe<stop>
.Należy to sprawdzić w następujący sposób:
if("${start}" LESS_EQUAL "${end}") foreach(RANGE "${start}" "${end}") ... endforeach() endif()
Wszystkie skrypty oparte na portach muszą być używane
include_guard(GLOBAL)
, aby uniknąć wielokrotnego dołączania.
Wersje narzędzia CMake do wymagania
- Wszystkie skrypty narzędzia CMake, z wyjątkiem
vcpkg.cmake
, mogą przyjąć wersję narzędzia CMake, która jest obecna w elemeciecmake_minimum_required
ports.cmake
.- Powinno się to
cmake_minimum_required
pojawić za każdym razem, gdy nowa wersja narzędzia CMake zostanie dodana dovcpkgTools.xml
programu , tak jak wcmake_minimum_required
przypadku wszystkich plików pomocnikaCMakeLists.txt
.
- Powinno się to
vcpkg.cmake
musi przyjąć wersję narzędzia CMake z powrotem do wersji 3.7.2 ogólnie- Określone funkcje i opcje mogą zakładać większą wersję narzędzia CMake; Jeśli to zrobią, pamiętaj, aby dodać komentarz do tej funkcji lub opcji z wymaganą wersją narzędzia CMake.
Zmienianie istniejących funkcji
- Nigdy nie usuwaj argumentów w funkcjach innych niż wewnętrzne; jeśli nie powinny już nic robić, po prostu wziąć je tak normalnie i ostrzegać przed użyciem.
- Nigdy nie należy dodawać nowego obowiązkowego argumentu.
Nazewnictwo zmiennych
cmake_parse_arguments
: ustaw prefiks na"arg"
Zmienne lokalne mają nazwę z
snake_case
Wewnętrzne nazwy zmiennych globalnych są poprzedzone prefiksem
Z_VCPKG_
.Zewnętrzne eksperymentalne nazwy globalnych zmiennych są poprzedzone prefiksem
X_VCPKG_
.Funkcje wewnętrzne są poprzedzone prefiksem
z_vcpkg_
- Funkcje, które są wewnętrzne dla jednej funkcji (tj. funkcji pomocnika) mają nazwę
[z_]<func>_<name>
, gdzie<func>
jest nazwą funkcji, do której służy pomocnik, i<name>
jak działa funkcja pomocnika.z_
należy dodać do przodu, jeśli<func>
nie maz_
elementu , ale nie nazywaj funkcjiz_z_foo_bar
pomocniczej .
- Funkcje, które są wewnętrzne dla jednej funkcji (tj. funkcji pomocnika) mają nazwę
Publiczne zmienne globalne mają nazwę
VCPKG_
.