-
Notifications
You must be signed in to change notification settings - Fork 0
beetroot-project/docs_compiled
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="X-UA-Compatible" content="IE=Edge" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title><no title> — The Beetroot Project 0.9.0 documentation</title> <link rel="stylesheet" href="_static/alabaster.css" type="text/css" /> <link rel="stylesheet" href="_static/pygments.css" type="text/css" /> <script type="text/javascript" id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script> <script type="text/javascript" src="_static/jquery.js"></script> <script type="text/javascript" src="_static/underscore.js"></script> <script type="text/javascript" src="_static/doctools.js"></script> <link rel="author" title="About these documents" href="about.html" /> <link rel="index" title="Index" href="genindex.html" /> <link rel="search" title="Search" href="search.html" /> <link rel="stylesheet" href="_static/custom.css" type="text/css" /> <meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" /> </head><body> <div class="document"> <div class="documentwrapper"> <div class="bodywrapper"> <div class="body" role="main"> <p>Design rationale ===</p> <p>O tym, że CMake utrudnia definiowanie kompilacji projektu używając funkcji: wymusza globalne zmienne i zupełnie nie ułatwia przekazywanie i weryfikowanie argumentów funkcji.</p> <p>Wykorzystywane są następujące cechy CMake:</p> <ol class="arabic simple"> <li>Targety są definiowane zawsze w jednej globalnej przestrzeni (scope), co oznacza że targety mogą z powodzeniem być definiowane wewnątrz funkcji. Zróbmy z tego regułę.</li> <li>Użytkownik definiuje zależności między używając kodu CMake zamiast</li> </ol> <ol class="arabic simple"> <li>Tworzenie każdego targetu jako funkcja, która przyjmuje zadeklarowane parametry o określonych warunkach walidacji. 1a) Argumenty muszą być przekazywane na 3 sposoby: wartość domyślna podana podczas deklaracji argumentu (lub brak - argument obowiązkowy) -> wartość podana z CACHE lub po prostu ze zmiennych dostępnych w CMake -> wartość podana podczas wywoływania targetu, jako argument funkcji produjującej target. 1b) Niech użytkownik sam zajmuje się dependencies. W szczególności, niech sam przekazuje te parametry, które chce override, np. te, które mają być zafiksowane, lub jakieś własne.</li> <li>Nazywanie targetu na podstawie jego argumentów po to, aby można było kompilować dwa targety różniące się tylko argumentami</li> <li>Kompatybilność z CMakeLists.txt - systemem, który nie pozwala na dynamiczne definiowanie targetów i nie pozwala na deklaracje zmiennych</li> <li>Wygoda dla użytkownika. Zero boilerplate.</li> </ol> <p>## Z tego wynikają następujące cechy:</p> <p>1. System deklaracji parametrów, ich typów, reguł walidacyjnych i wartości domyślnych 1a) System łączący trzy źródła informacji o typach. 1b) Możliwość wywoływania funkcji tworzącej target rekurencyjnie. Dbanie o to, aby przerwać rekurencję - tj. musi być globalna właściwość, która zawiera listę aktualnie definiowanych targetów. 2. Po zebraniu wszystkich argumentów i posortowaniu ich - tworzenie z nich hasha, który tworzy nazwę instancji targetu (być może z prefiksem nazwy targetu). Rozróżnia się dwa pojęcia:</p> <blockquote> <div><ol class="arabic simple"> <li><cite>TARGET_INSTANCE</cite> - nazwa targetu, jaka jest wygenerowana przez <cite>add_executable</cite> lub <cite>add_library</cite> lub <cite>add_custom_target</cite>. Ta nazwa nie jest czytelna dla ludzi i jest hashem argumentów przekazanych do targetu i jego klasy (TARGET_TEMPLATE).</li> <li><cite>TARGET_TEMPLATE</cite> - nazwa przepisu na generowanie targetów. Ta nazwa jest podana przez człowieka i musi być unikalna w całym projekcie. Np. LIB_LOG, GRIDTOOLS, ADVECTION_DRIVER.</li> </ol> </div></blockquote> <ol class="arabic simple" start="3"> <li>Specjalna składnia dla deklarowania targetu jako targetu definiowanego przez CMakeLists.txt. Muszą tam się znaleźć nazwy definiowanych (i używanych przez nas) targetów, katalog źródłowy i nazwa katalogu (już z ew. prefiksami związanymi z wersjami zależności używanych podczas budowy, np. boost, gridtools). Podczas napotkania takiej definicji system sprawdzi, czy w oddzielnym pliku jest zawarta lista parametrów tego CMakeLists.txt. Jeśli jest, to będzie jej używać, a jeśli nie - to w oddzielnym procesie uruchomi CMake po to, aby ją dostać.</li> </ol> <p>4. Plik targets.cmake zawiera: a) <a href="#id1"><span class="problematic" id="id2">``</span></a>` set(TARGET_PARAMETERS #DEFINE_MODIFIERS</p> <blockquote> <div>PATH SCALAR PATH ${CMAKE_costam}</div></blockquote> <p>) set(LINK_PARAMETERS #DEFINE_PARAMETERS</p> <blockquote> <div>PRECISION SCALAR INTEGER 4 ARCH SCALAR CHOICE(GPU;CPU) CPU</div></blockquote> <p>)</p> <dl class="docutils"> <dt>set(TARGET_FEATURES</dt> <dd>USE_GPU OPTION “” 0 COMPONENTS VECTOR STRING “filesystem;log”</dd> </dl> <p>)</p> <dl class="docutils"> <dt>set(TEMPLATE_OPTIONS</dt> <dd>SINGLETON_TARGETS #If set requires TARGET_TEMPLATE and generates error if ENUM_TEMPLATES is specified NO_TARGETS #If set it declares that no targets will be generated. Generates error if <cite>generate_targets()</cite> is defined by the user. LINK_TO_DEPENDEE #calls <cite>target_link_libraries()</cite>, even if the function <cite>apply_dependency_to_target()</cite> is defined GENERATE_TARGETS_INCLUDE_LINKPARS # Make linkpars available in <cite>generate_targets()</cite> LANGUAGES CUDA CXX EXPORTED_VARIABLES USE_GPU #This can be used to utilize LINK_PARAMETERS after the target is built to e.g. write a script.</dd> </dl> <p>)</p> <p>set(ENUM_TEMPLATES <UNIQUE NAME OF TARGET_TEMPLATE>) # Or optional, if for some reasons the target name must be fixed: #set(ENUM_TARGETS <UNIQUE NAME OF TARGET_TEMPLATE>) #the set of actual target names we are capable of providing</p> <p>#optional: set(DEFINE_EXTERNAL_PROJECT</p> <blockquote> <div>SOURCE_PATH gridtools ASSUME_INSTALLED INSTALL_PATH /usr/lib/gridtools WHAT_COMPONENTS_NAME_DEPENDS_ON boost compiler COMPONENTS SerialboxC BUILD_PARAMETERS USE_GPU ARCH</div></blockquote> <p>)</p> <p><a href="#id3"><span class="problematic" id="id4">``</span></a>` Jeśli projekt nie jest external (tj. nie zdefiniowano DEFINE_EXTERNAL_PROJECT), definicję funkcji <cite>generate_targets()</cite> przyjmującej jako argument listę wartości zadeklarowanych w ENUM_TEMPLATES. Ta funkcja jest odpowiedzialna za tworzenie targetu o nazwie ${TEMPLATE_NAME}. Alternatywnie, jeśli dana część projektu nie jest w stanie generować targetu (np. starego typu dependency), to należy pominąć definicję <cite>generate_targets()</cite>, a zamiast napisać funkcję <cite>apply_dependency_to_target(DEPENDEE_TARGET_NAME OUR_TARGET_NAME)</cite> która aplikuje nasz projekt na istniejący target. Oczywiście nie można otrzymać dla takiego template targetu, więc wywołanie <cite>get_targets()</cite> z poziomu <cite>CMakeLists.txt</cite> dla template używającego <cite>apply_dependency_to_target()</cite> zakończy się niepowodzeniem. Za to można używać <cite>get_targets()</cite> z poziomu funkcji <cite>declare_dependencies()</cite>.</p> <p>apply_dependency_to_target() nie jest wywoływana, jeśli target jest external</p> <p>Definicję funkcji <cite>declare_dependencies()</cite> przyjmującej jako argument listę wartości zadeklarowanych w ENUM_TEMPLATES. Ta funkcja jest odpowiedzialna za tworzenie targetu o nazwie ${TEMPLATE_NAME}. Ta funkcja jest wywoływana podczas superbuild pass po to, aby wywołać ExternalProjects_Add dla zewnętrznych zależności. Wewnątrz niej można używać funkcji</p> <p><code class="docutils literal notranslate"><span class="pre">`</span> <span class="pre">get_target(<TEMPLATE_NAME></span> <span class="pre"><INSTANCE_NAME></span> <span class="pre">[PATH</span> <span class="pre"><PATH_TO_TARGETS.CMAKE>]</span> <span class="pre"><ARGS...>)</span> <span class="pre">`</span></code></p> <p>## Co wolno, a czego nie wolno w funkcji generate_targets?</p> <p>Funkcja służy do generowania jednego lub więcej targetów, każdy z nich zadeklarowany w ENUM_TEMPLATES. Funkcja dostaje w argumentach nazwy template, które ma stworzyć (nikt nie zabrania tworzyć ich więcej). Każdy template uważa się za stworzony, jeśli istnieje target o nazwie “${TEMPLATE_NAME}_${ARG_HASH}”. Funkcja używa zmiennej INSTANCE_NAME albo ${TEMPLATE_NAME}_INSTANCE_NAME, jeśli jest więcej niż jeden TEMPLATE zdefiniowany w funkcji.</p> <p>Aby dodać dependency, należy użyć funkcji get_target(<TEMPLATE_NAME> <VAR_INSTANCE_NAME> [PATH <PATH_TO_TARGETS.CMAKE>] <ARGS…>) w ciele funkcji.</p> <p>Wolno dokonywać dowolnych manipulacji na argumentach, które są przekazane jako zmienne (nie argumenty funkcji). Wolno wywoływać inne funkcje CMake, poza generate_targets() i declare_dependencies(). Każde wywołanie <cite>get_target()</cite> przerwie konfigurację z błędem.</p> <p>## Co wolno, a czego nie wolno w declare_dependencies?</p> <p>Wolno wywoływać get_target(<TEMPLATE_NAME> <VAR_INSTANCE_NAME> [PATH <PATH_TO_TARGETS.CMAKE>] <ARGS…>) Wolno wywoływać inne funkcje CMake, poza generate_targets() i declare_dependencies(). Każde wywołanie <cite>add_executable</cite>, <cite>add_library</cite>, <cite>add_custom_target</cite> przerwie konfigurację z błędem.</p> <p>## O czym należy pamiętać pisząc targets.cmake?</p> <p>Plik będzie wykonywany przez CMake wiele raz, co najmniej 2, i to zarówno podczas etapu SuperBuild, jak i podczas etapu naszego projektu</p> <hr class="docutils" /> <p>CMakeLists.txt zawiera wywołania do funkcji <cite>get_target(<TEMPLATE_NAME> <VAR_INSTANCE_NAME> [PATH <PATH_TO_TARGETS.CMAKE>] <OPTS>)</cite>, albo <cite>build_target(<TEMPLATE_NAME> [PATH <PATH_TO_TARGETS.CMAKE>] <OPTS>)</cite> która jest uproszczoną wersją, która po prostu nie pozwala na uzyskanie nazwy targetu.</p> <p>## Algorytm w Superbuild:</p> <p>Sprawdza, czy TEMPLATE_NAME jest zadeklarowany w ENUM_TEMPLATES.</p> <p>Ta funkcja wykonuje: (funkcja: _get_variables)</p> <ol class="arabic simple"> <li>parsuje plik definiujący target (zawierający DEFINE_PARAMETERS z wartościami domyślnymi),</li> <li>nadpisuje wartości domyślne wartościami z pamięci</li> <li>i na końcu wartościami <OPTS>.</li> <li>Następnie robi hash ze wszystkich tych opcji.</li> </ol> <p>Powtarza kroki 1-4 tak długo, aż hash przestanie się zmieniać lub max 10 razy i zwraca błąd, jeśli doszło do 10 razy.</p> <p>Pamiętając, jak się nazywa definiowany TEMPLATE_NAME, wywołuje funkcję użytkownika <cite>declare_dependencies(TEMPLATE_NAME)</cite>, gdzie każde wywołanie get_target jest zapamiętywane i zbierane jako definicja ExternalProject lub ignorowane, jeśli dotyczy głównego projektu. W szczególności: 1. Definicja zależy od ustawionej zmiennej __SUPERBUILD 2. Dodajemy hash dependency do listy lokalnie wyszukiwanych dependency, służącej do wyłapania cyklicznego zapętlenia. 3. Na podstawie nazwy dependency znajdywany jest plik <cite>targets.cmake</cite>, parsowany i uzyskujemy zbiór argumentów. Na ich podstawie generujemy hash i sprawdzamy, czy mamy target o takim hashu. (Jeśli mamy, to sprawdzamy, czy nie został on już dodany w liście lokalnie wyszukiwanych dependency, aby wykluczyć cykliczne zapętlenie) go zwracamy i dodajemy do globalnej listy dependency, którą dodamy, gdy tylko dostaniemy definicję naszego projektu. 4. Jeśli targetu jeszcze nie ma i jest on zewnętrzny, to go tworzymy w poniższy sposób. W przeciwnym razie - ignorujemy go (na razie), jeśli target jest wewnętrzny, lub dodajemy jego <cite>INSTANCE_NAME</cite> do listy dependencies naszego targetu, który próbujemy stworzyć. <jak odróżnić target zewnętrzny od lokalnego - poprzez obecność DEFINE_EXTERNAL_PROJECT> 5. <em>Tworzenie targetu zewnętrznego, etap superbuild:</em></p> <blockquote> <div><ol class="arabic simple"> <li>(Przypomnienie: Jesteśmy tu, bo kod użytkownika w <cite>targets.cmake:declare_dependencies()</cite> wywołał nasz target (i wiemy że on jest zewnętrzny i go jeszcze nie ma). )</li> </ol> <p>2. Instancjonizujemy wszystkie <cite>INSTANCE_NAME</cite> zależności, jakie ten target może mieć. Upewniamy się, że żadna z zależności nie jest wewnętrzna (i zwracamy błąd, jeśli jest) 2. Tworzymy hash wszystkich argumentów, w standardowy sposób. 3. Na podstawie hasha tworzymy nazwę <cite>INSTANCE_NAME</cite> dla naszej dependency (np. Serialbox) 4. Wywołujemy <cite>ExternalProject_Add(${INSTANCE_NAME} …)</cite> tak, aby stworzył się obiekt naszych zależności. Dodajemy do DEPENDENCY wszystkie instancje targetów ew. zależności 5. Dopisujemy nazwę <cite>$INSTANCE_NAME</cite> do globalnej przestrzeni nazw. (funkcja: _store_target_instance)</p> </div></blockquote> <ol class="arabic simple" start="6"> <li>Tworzymy wywołanie ExternalProject_Add odwołujące się do wywołanego, najwyższego <cite>CMakeLists.txt</cite> i ustawiamy tam zmienną <cite>__SUPERBUILD:BOOL=0</cite> i dodając do dependency całą naszą listę dependency. Nie dodaje zmiennych - zmienne znajdzie sobie jeszcze raz.</li> <li>Koniec</li> </ol> <p>## Algorytm w naszym projekcie (nie - superbuild):</p> <ol class="arabic simple"> <li>Tak samo, jak w wywołaniu superbuild, parsuje każde odwołanie do build_target/get_target, które, jak zawsze, zaczyna się od ustalenia zbioru zmiennych (funkcja: _get_variables)</li> <li>Również wywołuje funkcję użytkownika <cite>declare_dependencies(TEMPLATE_NAMES)</cite>, ale tym razem zbiera dependencies inaczej. Zewnętrzne dependencies są zbierane przy pomocy <cite>find_packages</cite>, natomiast wewnętrzne poprzez rekurencyjne budowanie ich, identycznie jak zewnętrzne były zbierane podczas kroku superbuild.</li> <li>Wywołuję <cite>_call_generate_targets()</cite>.</li> <li>Do każdego z <cite>INSTANCE_NAMES</cite> dodaję zależności zebrane w kroku 2.</li> </ol> <p>Zbiór funkcji:</p> <p>Podczas wczytania biblioteki: ustawiana jest zmienna globalna <cite>__GET_TARGET_BEHAVIOUR</cite> na “<cite>GLOBAL_SCOPE</cite>”.</p> <p><cite>get_target(<TEMPLATE_NAME> [PATH <Ścieżka do targets.cmake>] <Args…>)</cite></p> <ol class="arabic simple"> <li>Jeśli wartość zmiennej globalnej <cite>__GET_TARGET_BEHAVIOUR</cite> jest równa <cite>“INSIDE_GENERATE_TARGETS”</cite>. Jeśli tak - to zwracamy błąd, bo nie można naszej funkcji wywoływać wewnątrz <cite>generate_targets()</cite>. (Do tego celu należy użyć funkcję <cite>declare_dependencies()</cite>).</li> <li>Próbujemy znaleźć ścieżkę do <cite>targets.cmake</cite> używając <cite>__find_targets_cmake_by_template_name($TEMPLATE_NAME __OUT_TARGETS_PATH)</cite></li> </ol> <p>3. Jeśli ścieżka nie jest znaleziona - zwraca błąd. 3. Tworzy listę zmiennych używając <cite>_get_variables(<znaleziona ścieżka do targets.cmake> __VARIABLE_DIC __TEMPLATES __EXTERNAL_PROJECT_INFO ${ARGS})</cite> 4. Upewnia się, że <cite>TEMPLATE_NAME</cite> jest zadeklarowany w <cite>ENUM_TEMPLATES</cite>. 5. Wywołuje <cite>_get_dependencies($TEMPLATE_NAME var_dictionary __INSTANCE_NAME_LIST)</cite> 6. Jeśli <cite>IS_EXTERNAL</cite>, to wywołuje <cite>_get_target_external(${TEMPLATE_NAME} __VARIABLE_DIC __INSTANCE_NAME ${__EXTERNAL_PROJECT_INFO})</cite> 7. Jeśli nie jest external, to <cite>_get_target_internal(${TEMPLATE_NAME} <katalog zawierający targets.cmake> __VARIABLE_DIC __INSTANCE_NAME)</cite> 8. Jeśli wywołanie <cite>_get_target_xxx</cite> się powiodło, to zwraca <cite>${__INSTANCE_NAME}</cite>, lub błąd w przeciwnym razie.</p> <p><cite>_find_targets_cmake_by_template_name(<TEMPLATE_NAME> <OUT_SCIEZKA>)</cite></p> <p>Próbuje znaleźć ścieżkę do pliku targets.cmake na podstawie <cite>TEMPLATE_NAME</cite>. Mechanizmu jeszcze nie jestem pewny. Prawdopodobnie, użyjemy zewnętrznego targetu, który użyje CMake to obwąchania wszystkich plików <cite>.cmake</cite> w katalogu definiującym zewnętrzne targety oraz wszystkie pliki <cite>targets.cmake</cite> w naszym źródle, stwoży listę tych plików, i zdefiniuje target zależny od tych plików, który stwoży bazę danych targetów w formie pliku <cite>template_paths.cmake</cite> z zawartością samych linijek <a href="#id5"><span class="problematic" id="id6">``</span></a>` set(__TEMPLATE_PATHS_${TEMPLATE_NAME} “${PATH}”)n …</p> <p><a href="#id7"><span class="problematic" id="id8">``</span></a><a href="#id9"><span class="problematic" id="id10">`</span></a></p> <p>Ten plik będzie includowany przy pierwszym wykonaniu <cite>_find_targets_cmake_by_template_name</cite> zaraz po stworzeniu, zarówno przez SUPERBUILD jak i build wewnętrzny. Ta funkcja będzie też odpowiedzialna za stworzenie tego pliku używając zewnętrzne wywołanie CMake przy każdym pierwszym wywołaniu. Funkcja wpisze słownik do globalnej zmiennej.</p> <p><cite>_get_variables(<ścieżka do pliku targets.cmake>, <out_variables_dic>, <out_template_names>, <out_is_external> <Args…>)</cite></p> <p>Parsuje plikt targets.cmake i na podstawie Args…, zmiennych tam zadeklarowanych i zmiennych już istniejących w przestrzeni nazw, tworzy słownik wszystkich konkretnych wartości argumentów.</p> <ol class="arabic simple" start="0"> <li>Ustawia hash parametrów jako ARGUMENT_HASH=”<nothing>” oraz COUNT=0</li> <li><cite>_read_targets_file(<ścieżka do pliku targets.cmake> __READ_PREFIX)</cite> - parsuje plik definiujący target (zawierający <cite>DEFINE_PARAMETERS</cite> z wartościami domyślnymi),</li> <li><cite>COUNT<-COUNT+1</cite></li> <li>nadpisuje wartości domyślne wartościami z pamięci (<cite>__read_variables_from_cache(“__READ_PREFIX_${DEFINE_PARAMETERS}” “” “” __OUT_CACHED_VALUES )</cite>)</li> <li>i na końcu wartościami <Args…> (<cite>__read_variables_from_arg(“__READ_PREFIX_${DEFINE_PARAMETERS}” “${__OUT_CACHED_VALUES}” __OUT_FINAL_VALUES)</cite>).</li> <li>Następnie robi hash ze wszystkich tych opcji i zapisuje go jako <cite>NEW_ARGUMENT_HASH</cite> (<cite>__calculate_hash(“__READ_PREFIX_${DEFINE_PARAMETERS}” “${__OUT_FINAL_VALUES}” __OUT_VAR_DIC)</cite>)</li> <li>Jeśli <cite>NEW_ARGUMENT_HASH</cite> != <cite>ARGUMENT_HASH</cite> && <cite>COUNT < 10</cite> THEN a) <cite>ARGUMENT_HASH <- NEW_ARGUMENT_HASH</cite> i powtarza kroki 1-5. (czyli tak długo, aż hash przestanie się zmieniać lub max 10 razy i zwraca błąd, jeśli doszło do 10 razy.</li> <li>Jeśli <cite>COUNT == 10</cite> THEN błąd.</li> <li>Zapisuje aktualny słownik zmiennych do <cite>OUT_VARIABLES_DIC</cite>. Poza tym, wpisuje <cite>OUT_TEMPLATE_NAMES</cite> i <cite>OUT_IS_EXTERNAL</cite></li> <li>Koniec.</li> </ol> <p><cite>_get_target_internal(<TEMPLATE_NAME> <path> <var_dictionary> <out_instance_name>)</cite></p> <ol class="arabic simple" start="2"> <li>Jeśli etap SUPERBUILD: robi NIC (zwraca pusty string)</li> <li><cite>_instantiate_variables(0 var_dictionary)</cite></li> <li>Tworzy zmienne o nazwach <cite>${TEMPLATE_NAME}_TARGET_NAME</cite>, które przechowują oczekiwane nazwy targetów danego <cite>TEMPLATE_NAME</cite>.</li> <li>Upewnia się, że flaga <cite>__GATHERING_DEPENDENCIES</cite> jest wyzerowana.</li> </ol> <p>6. Modyfikuje <cite>CMAKE_CURRENT_SOURCE_DIR</cite>, aby wskazywała na katalog, w którym jest wywoływany <cite>targets.cmake</cite> (tj. <cite>path</cite>). 6. Wywołuje funkcję użytkownika <cite>generate_targets(TEMPLATE_NAME)</cite>. Wewnątrz tej funkcji każde wywołanie <cite>get_target()</cite> zwraca błąd z uwagi na wyzerowanie <cite>__GATHERING_DEPENDENCIES</cite>. 7. Sprawdza, czy targety, które chcieliśmy uzyskać, faktycznie są stworzone (<cite>if(TARGET ${TEMPLATE_NAME}_TARGET_NAME)…</cite>). Jeśli nie - zwraca błąd. 8. Zwraca nazwę instance targetu, który chcieliśmy uzyskać.</p> <p><cite>_get_target_external(<TEMPLATE_NAME> <var_dictionary> <out_instance_name> <EXTERNAL_PROJECT_ARGS>)</cite></p> <ol class="arabic simple" start="2"> <li>Jeśli etap SUPERBUILD - Wywołuje <cite>ExternalProject_Add</cite> dla nazwy targetu policzonej na <cite>var_dictionary</cite> i zwraca tą nazwę targetu w <cite>out_instance_name</cite></li> <li>Jeśli etap naszego projektu - wywołuje <cite>find_packages</cite>, tworzy alias dla importowanego targetu i zwraca nazwę <cite>INSTANCE_NAME</cite>.</li> </ol> <p><cite>_read_targets_file(<ścieżka do pliku targets.cmake> <out_prefix>)</cite></p> <p>Wczytuje plik <cite>targets.cmake</cite> i zwraca <cite>DEFINE_PARAMETERS</cite>, <cite>DEFINE_EXTERNAL_PROJECT</cite> i <cite>ENUM_TEMPLATES</cite> poprzedzone prefiksem.</p> <p><cite>_read_variables_from_cache(<PARAMETERS_PREFIX> <ARGUMENTS_PREFIX> <VALUES_PREFIX>|”” <OUT_PREFIX>)</cite></p> <p>Korzysta ze zmiennych wczytanych z <cite>targets.cmake</cite> i podanych poprzez jeden argument <cite>DEFINED_PARAMETERS</cite>. Iteruje się po nich i dla każdej z nich: 1. Pobiera wartość i zapisuje w pamięci pod <cite>__RC_<VARIABLE_NAME></cite> oraz dodaje jej nazwę do <cite>RC__LIST</cite> 2. Jeśli zmienna <cite>${PREFIX}${VARIABLE_NAME}</cite> jest w pamięci, to dla niej wywołuje <cite>_verify_parameter(${VARIABLE_NAME} ${VARIABLE_CONTAINER} ${VARIABLE_TYPE} )</cite> i wpisuje ją do pamięci. W przeciwnym razie: 3. …jeśli <cite>EXISTING_VALUES_PREFIX</cite> jest niezerowe, to sprawdza, czy zmienna czy zmienna jest tam, i jeśli jest, to wpisuje ją do pamięci. 4. Zapisuje wartość do <cite>PARENT_SCOPE</cite> używając prefiksu <cite>__OUT_CACHED_VALUES</cite>. 5. Na końcu, po zakończeniu pętli, wpisuje listę wszystkich zmiennych do <cite>${__OUT_CACHED_VALUES}__LIST</cite>.</p> <p>Efektywnie format zmiennych to:</p> <p><cite>PREFIX__LIST</cite> - lista zmiennych <cite>PREFIX_<var name></cite> - wartość zmiennej</p> <p><cite>__read_variables_from_args(<PARAMETERS_PREFIX> <ARGUMENTS_PREFIX> <OUT_PREFIX> <ARGS…>)</cite></p> <ol class="arabic simple"> <li>Parsuje ARGS korzystając z definicji wczytanej z <cite>DEFINED_PARAMETERS</cite> i zapisuje je prefiksowane <cite>__RV</cite>.</li> <li>Uruchamia <cite>__read_variables_from_cache(“${DEFINED_PARAMETERS}” __RV ${CURRENT_VALUES_PREFIX} __RA )</cite></li> <li><cite>_pass_variables_higher(__RA __RA)</cite></li> </ol> <p><cite>__calculate_hash(<PREFIX> <__OUT_HASH> <EXTRA_STRING>)</cite></p> <ol class="arabic simple"> <li>Sortuje wszystkie zmienne w liście <cite>${PREFIX}__LIST</cite></li> <li>Tworzy pustą zmienną stringową z zawartością <cite>${EXTRA_STRING}</cite></li> <li>Iteruje się po kolejnych elementach tej listy i dodaje wartość do listy</li> <li>Liczy hash tej zmiennej tekstowej</li> <li>Zwraca hash z prefiksem <cite>__OUT_PREFIX</cite>.</li> </ol> <p><cite>_pass_variables_higher(<IN_PREFIX> <OUT_PREFIX>)</cite></p> <p>Makro, które iteruje się po wszystkich zmiennych w <cite>${IN_PREFIX}__LIST</cite> i każdą z wartości zapisuje w <cite>PARENT_SCOPE</cite> z prefiksem <cite>OUT_PREFIX</cite>. Na koniec eksportuje <cite>${IN_PREFIX}__LIST</cite> jako <cite>${OUT_PREFIX}__LIST</cite> w <cite>PARENT_SCOPE</cite></p> <p><cite>_store_target_instance(<template_name> <hash> <instance_name> <path_to_targets>?)</cite> Zapisuje target <instance_name> do globalnej pamięci</p> <p><cite>_exists_target_instance(<template_name> <var_dictionary_prefix> <out_target_exists>)</cite></p> <p>Sprawdza, czy o takiej nazwie i zmiennych już istnieje</p> <p><cite>_name_target_instance(<template_name> <var_dictionary_prefix> <out_instance_name>)</cite></p> <p>Funkcja nazywa instance_name na podstawie zmiennych var_dictionary_prefix i zapisuje nazwę do zmiennej <out_instance_name></p> <p><cite>_instantiate_variables(FLAG_PARENT var_dictionary)</cite></p> <p>Makro przejeżdża się po słowniku <cite>var_dictionary</cite> i każdą napotkaną tam zmienną wpisuje do bierzącego scope, albo - jeśli <cite>FLAG_PARENT</cite> - do <cite>PARENT_SCOPE</cite>.</p> <p><cite>_get_dependencies(<TEMPLATE_NAME> <var_dictionary> <out_dependencies_target_list>)</cite></p> <p>Funkcja zbiera wszystkie zależności danego targetu i zwraca listę <a href="#id11"><span class="problematic" id="id12">`</span></a>INSTANCE_NAME`s.</p> <ol class="arabic simple"> <li>Zapisuje flagę <cite>__GET_TARGET_BEHAVIOUR</cite> na “<cite>GATHERING_DEPENDENCIES</cite>”, która jest odczytywana przez funkcję <cite>get_target()</cite> i modyfikuje zachownie tej funkcji.</li> <li><cite>_instantiate_variables(0 var_dictionary)</cite></li> </ol> <p>3. Dodaje hash z TEMPLATE_NAME i var_dictionary 3. Wywołuje funkcję użytkownika <cite>declare_dependencies(TEMPLATE_NAME)</cite>, która tworzy zależności używając <cite>get_target()</cite> 4. Zbiera ze stosu listę znalezionych dependencies i dodaje je do listy <cite>out_dependencies_target_list</cite></p> <p><cite>_verify_parameter(<VARIABLE_NAME> <VARIABLE_CONTEXT> <VARIABLE_CONTAINER> <VARIABLE_TYPE> <VARIABLE_VALUE>)</cite></p> <p>Weryfikuje parametr o wartości <cite>VARIABLE_VALUE</cite> (przekazaną przez wartość, a nie typ). Sprawdza, czy zgadza się kontener, oraz czy każdy element w kontenerze (jeśli wektor) ma typ kompatybilny z zadeklarowanym. <cite>VARIABLE_NAME</cite> i <cite>VARIABLE_CONTEXT</cite> przekazywane jest tylko dla produkowania ładnych komunikatów błędu.</p> <hr class="docutils" /> <ul class="simple"> <li>Podczas fazy SUPERBUILD zwraca nazwę targetu zewnętrznego projektu wskazywanego przez TEMPLATE_NAME i słownika zmiennych i ignoruje wewnętrzne targety.</li> <li>Podczas fazy wewnętrznej, zwraca INSTANCE_NAME dla targetu zewnętrznego (używając find_packages i pojęcia imported targets) i wewnętrznego.</li> </ul> <p><em>UWAGA!!</em> Funkcja zakłada, że aktualne definicje funkcji <cite>generate_targets()</cite> oraz <cite>declare_dependencies()</cite> są zgodne z plikiem, z którego wczytano <cite>var_dictionary</cite>.</p> <p>Pamiętając, jak się nazywa definiowany TEMPLATE_NAME, wywołuje funkcję użytkownika <cite>declare_dependencies(TEMPLATE_NAME)</cite>, gdzie każde wywołanie get_target jest zapamiętywane i zbierane jako definicja ExternalProject lub ignorowane, jeśli dotyczy głównego projektu. W szczególności: 1. Definicja zależy od ustawionej zmiennej __SUPERBUILD 2. Dodajemy hash dependency do listy lokalnie wyszukiwanych dependency, służącej do wyłapania cyklicznego zapętlenia. 3. Na podstawie nazwy dependency znajdywany jest plik <cite>targets.cmake</cite>, parsowany i uzyskujemy zbiór argumentów. Na ich podstawie generujemy hash i sprawdzamy, czy mamy target o takim hashu. (Jeśli mamy, to sprawdzamy, czy nie został on już dodany w liście lokalnie wyszukiwanych dependency, aby wykluczyć cykliczne zapętlenie) go zwracamy i dodajemy do globalnej listy dependency, którą dodamy, gdy tylko dostaniemy definicję naszego projektu. 4. Jeśli targetu jeszcze nie ma i jest on zewnętrzny, to go tworzymy w poniższy sposób. W przeciwnym razie - ignorujemy go (na razie), jeśli target jest wewnętrzny, lub dodajemy jego <cite>INSTANCE_NAME</cite> do listy dependencies naszego targetu, który próbujemy stworzyć. <jak odróżnić target zewnętrzny od lokalnego - poprzez obecność DEFINE_EXTERNAL_PROJECT> 5. <em>Tworzenie targetu zewnętrznego, etap superbuild:</em></p> <blockquote> <div><ol class="arabic simple"> <li>(Przypomnienie: Jesteśmy tu, bo kod użytkownika w <cite>targets.cmake:declare_dependencies()</cite> wywołał nasz target (i wiemy że on jest zewnętrzny i go jeszcze nie ma). )</li> </ol> <p>2. Instancjonizujemy wszystkie <cite>INSTANCE_NAME</cite> zależności, jakie ten target może mieć. Upewniamy się, że żadna z zależności nie jest wewnętrzna (i zwracamy błąd, jeśli jest) 2. Tworzymy hash wszystkich argumentów, w standardowy sposób. 3. Na podstawie hasha tworzymy nazwę <cite>INSTANCE_NAME</cite> dla naszej dependency (np. Serialbox) 4. Wywołujemy <cite>ExternalProject_Add(${INSTANCE_NAME} …)</cite> tak, aby stworzył się obiekt naszych zależności. Dodajemy do DEPENDENCY wszystkie instancje targetów ew. zależności 5. Dopisujemy nazwę <cite>$INSTANCE_NAME</cite> do globalnej przestrzeni nazw. (funkcja: _store_target_instance)</p> </div></blockquote> <ol class="arabic simple" start="6"> <li>Tworzymy wywołanie ExternalProject_Add odwołujące się do wywołanego, najwyższego <cite>CMakeLists.txt</cite> i ustawiamy tam zmienną <cite>__SUPERBUILD:BOOL=0</cite> i dodając do dependency całą naszą listę dependency. Nie dodaje zmiennych - zmienne znajdzie sobie jeszcze raz.</li> <li>Koniec</li> </ol> <p><cite>_call_generate_targets(<ścieżka do pliku targets.cmake> <TEMPLATE_NAMES> <var_dictionary> <out_instance_name>)</cite></p> <p>Wywołuje funkcję <cite>generate_targets()</cite> dostarczoną przez użytkownika dla zadanego słownika zmiennych i nazw targetów. Po wywołaniu sprawdza, czy rzeczywiście targety zostały zdefiniowane.</p> </div> </div> </div> <div class="sphinxsidebar" role="navigation" aria-label="main navigation"> <div class="sphinxsidebarwrapper"> <h1 class="logo"><a href="index.html">The Beetroot Project</a></h1> <h3>Navigation</h3> <p class="caption"><span class="caption-text">Contents:</span></p> <ul> <li class="toctree-l1"><a class="reference internal" href="about.html">Steps to start using the Beetroot:</a></li> <li class="toctree-l1"><a class="reference internal" href="about.html#how-does-the-beetroot-work">How does the Beetroot work?</a></li> <li class="toctree-l1"><a class="reference internal" href="features.html">List of most important and complex Beetroot functionalities</a></li> <li class="toctree-l1"><a class="reference internal" href="features.html#list-of-the-most-visible-features-of-the-beetroot">List of the most visible features of the Beetroot</a></li> <li class="toctree-l1"><a class="reference internal" href="start.html">Getting started</a></li> </ul> <div class="relations"> <h3>Related Topics</h3> <ul> <li><a href="index.html">Documentation overview</a><ul> </ul></li> </ul> </div> <div id="searchbox" style="display: none" role="search"> <h3>Quick search</h3> <div class="searchformwrapper"> <form class="search" action="search.html" method="get"> <input type="text" name="q" /> <input type="submit" value="Go" /> <input type="hidden" name="check_keywords" value="yes" /> <input type="hidden" name="area" value="default" /> </form> </div> </div> <script type="text/javascript">$('#searchbox').show(0);</script> </div> </div> <div class="clearer"></div> </div> <div class="footer"> ©2019, Adam Ryczkowski. | Powered by <a href="http://sphinx-doc.org/">Sphinx 1.7.6</a> & <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a> | <a href="_sources/readme.rst.txt" rel="nofollow">Page source</a> </div> </body> </html>
About
Compiled version of static html documentation
Resources
Stars
Watchers
Forks
Releases
No releases published
Packages 0
No packages published