Gradle - notatki

Notatki o Gradle
Co powinnam wiedzieć o Gradle? Jak stworzyć projekt z podmodułami? A może najpierw: jak stworzyć prosty projekt? Albo jak używać Gradle z Kotlinem?
Ten wpis to zbiór bardzo luźnych notatek, trochę zbyt chaotycznych by traktować je jako pełnowartościowy wpis, uzupełnianych na bieżąco w miarę jak będę poznawać dokumentację Gradle-a.
Mogą być niepełne, a nawet niepoprawne. Jestem w trakcie budowania modelu, jak Gradle działa.
Rodzaje skryptów
Istnieją trzy typy skryptów:
- główny skrypt budujący: jest reprezentowany przez klasę Project
- istnieją też skrypty inicjalizacyjne - służą do przygotowania środowiska przed uruchomieniem właściwego skryptu; nie mają dostępu do
buildSrc
- oraz skrypty z ustawieniami - służące do utworzenia i skonfigurowania hierarchii projektów będących częścią buildu; reprezentowane przez klasę Settings
Gradle DSL jest opisany w Gradle Build Language Reference
Cykl życia
Wywołanie gradle ...
z wiersza poleceń rozpoczyna trzy fazy w “cyklu życia” procesu budowania. Te trzy fazy to:
- inicjalizacja (initialization)- Gradle określa, jakie projekty mają być budowane i tworzy dla każdego z nich instancję
Project
- konfiguracja (configuration)- konfigurowane są obiekty w projekcie/projektach: w tej fazie wykonywane są (uruchamiane) skrypty budujące każdego z projektów (notatka: uruchamiany jest kod wewnątrz closure każdego taska o ile nie jest on zamknięty w blok
doLast
czydoFirst
) - uruchomienie (exeuction) - Gradle ustala, które taski (utworzone i skonfigurowane w fazie konfiguracji) mają być wykonane
Jak czytać kod - notatki
O tym, jak pisać skrypty w Groovy: Źródło
Właściwości, metody, bloki
Właściwości niekwalifikowane mapują się na metody w klasie Project
(a wewnątrz bloku mogą oznaczać metody obiektu delegowanego).
Sygnatura takiej metody określa jej parametry, a jeśli ostatni z nich jest typu closure lub Action, jest to zwykle widoczne w składni jako blok.
Właściwości mogą jednak pochodzić z różnych źródeł:
- objekt Project wspomniany wyżej
- właściwości extra projektu: dowolna mapa klucz-wartość
- rozszerzenia extentions dodawane do projektu przez pluginy jako wartość read only o nazwie takiej, jak rozszerzenie
- właściwości convention zwykle dodawane do projektu przez pluginy (mogą być do zapisu albo do odczytu) - reprezentowane przez obiekt Convention
- zadania (tasks) zadeklarowane w skrypcie; są dostępne przez swoją nazwę - dla każdego taska tworzona jest właściwość o takiej nazwie jak nazwa taska; taka właściwość jest tylko do odczytu
Zależności dla skryptu budującego
Można je zadeklarować w bloku buildscript
(w którym jest konfigurowana instancja ScriptHandler) - zostaną dodane do classpath-a bieżącego skryptu. Np.
|
|
W powyższym fragmencie fragment dependencies {...}
odpowiada wywołaniu getDependencies()
na instancji Scripthandler
(zwracającemu DependencyHandler). Zależności są zgrupowane w konfiguracje - tutaj występuje konfiguracja o nazwie “classpath” .
Konfiguracja to nazwany zbiór zależności.
W ogólności, dodanie zależności wygląda tak:
|
|
Java - pluginy
Podstawowe typy projektów tworzonych w Javie to biblioteka oraz aplikacja. Dla każdego z tych typów powstał odrębny plugin, odpowiednio: java-library oraz application, z których każdy bazuje na pluginie java
.
application
Wcześniej pluginy były włączane w skrypcie budującym przez bezpośrednie wywołanie apply
, jednak teraz zalecane jest użycie bloku plugins; na przykład dla aplikacji:
|
|
Uruchomienie z argumentami wiersza poleceń:
|
|
java library
Java Library Plugin - konfigurujący projekt Gradle do pracy z Javą - posiada trzy konfiguracje standardowe:
- implementation - zależności potrzebne do skompilowania kodu produkcyjnego, ale nie będące częścią API wystawianego przez bibliotekę
- API - zależności potrzebne do skompilowania kodu produkcyjnego, które mają być również “widoczne” dla kodu produkcyjnego
- testImplementation - zależności do skompilowania i uruchomienia źródeł testowych.
Co z tego zrozumiałam: Dzięki wprowadzeniu tych konfiguracji do classpath-a aplikacji/biblioteki korzystającej z pewnej innej biblioteki zostaną dołączone jedynie te zależności, które są w owej pewnej bibliotece zadeklarowane jako ‘API’. “Przechodnie” zależności typu “implementation” nie “zaśmiecają” classpatha.
Zaraz. Przypomina mi to sposób deklarowania zależności w modułach Javy (requires oraz requires transitive). Jak się mają takie deklaracje do konfiguracji Gadle? Sprawdzam…
Użycie modułów
Tutaj dokumentacja dotycząca użycia modułów Javy w Gradle.
To bardzo ciekawe - moduły w javie i konfgiracje zależności w Gradle w zasadzie się pokrywają, jednak ich spójność nie jest (na razie - a więc w przyszłości może będzie?) automatycznie sprawdzana.
Deklarowanie modułu klasy głównej
Uruchamiając klasę w aplikacji wielomodułowej (w rozumieniu Java 9) należy wskazać również nazwę głównego modułu w którym znajduje się główna klasa:
|
|
Ćwiczenia
Oto garść ćwiczeń, które wymyśliłam sobie po to, żeby poznać lepiej system budowania Gradle. Przy okazji ich wykonywania będę rozszerzać sktypt(y) budujący(e) tak, aby pokryły kolejne wymagania.
- Utworzyć skrypt dla zbudowania prostej aplikacji z testami.
- Uruchomić aplikację.
- Uruchomić testy.
- Wydzielić część kodu zewnętrznej biblioteki - zdefiniować ją jako podprojekt
- Użyć biblitekę w aplikacji - jak sprawdzić, czy zależności typu implementation użyte w bibliotece rzeczywiście nie trafiły na classpath aplikacji?
- Przerobić aplikację i bibliotekę na moduły Javy.
- Uruchomić aplikację modularną.
- Uruchomić testy
- Stworzyć dystrybucję aplikacji (jlink?).
- Budując aplikację GUI, wygenerować splashscreen z datą oraz SHA commita, z którego pochodzi build.
- Użyć bazy danych - innej dla testów (z innymi danymi), innej dla aplikacji. Bez Spring Boota.