Wstęp
Tematem tej recenzji będzie system automatycznego budowania Gradle. W języku angielskim systemy kompilacji nazywane są
narzędziami kompilacji .
Dlaczego jest to w ogóle konieczne? Ręczne budowanie projektów w Javie jest procesem dość pracochłonnym. Konieczne jest prawidłowe wskazanie bibliotek i frameworków, których potrzebuje projekt i od których zależy projekt. Tutaj możesz przeczytać doskonały artykuł na temat Habré: „
Praca z Javą w wierszu poleceń ”. Prędzej czy później zaczniesz tworzyć skrypty automatyzujące ten proces. A teraz wyobraź sobie, że wszyscy programiści na całym świecie tak robią i wszyscy od nowa piszą to, co ktoś już napisał dla ich projektu. A potem pojawiły się systemy montażu projektowego, które automatyzują ten proces. Ponadto z jednej strony pozwalają skompletować projekt tak, jak sobie tego życzysz, z drugiej strony udostępniają mniej lub bardziej wystandaryzowane narzędzia. Alternatywą dla Gradle jest zautomatyzowany system kompilacji Maven. Te dwa systemy montażu z jednej strony różnią się od siebie, ale z drugiej strony łączy je szereg podobieństw. Na stronie Gradle znajduje się materiał na ten temat: „
Migracja z Mavena do Gradle ”. Jak stwierdzono w tym samouczku, Gradle i Maven mają różne spojrzenie na sposób budowania projektu. Gradle opiera się na grafie zadań, które mogą być od siebie zależne. Zadania wykonują jakąś pracę. Maven posługuje się modelem pewnych faz, z którymi powiązane są określone „cele”. Przy tych celach wymagana jest pewna praca. Jednak przy tych różnych podejściach oba systemy kompilacji są zgodne z tą samą konwencją, a zarządzanie zależnościami jest podobne. Aby rozpocząć korzystanie z Gradle, musisz go pobrać. W Google lub Yandex wpisujemy „Gradle Build Tool” i w pierwszych wynikach widzimy oficjalną stronę:
https://gradle.org . Na głównej stronie Gradle znajduje się link z tekstem „Dokumenty”, który prowadzi do
dokumentacji Gradle . Najpierw musimy zainstalować (zainstalować) Gradle, dlatego interesuje nas sekcja „
Instalowanie Gradle ” w dokumentacji. Sposobów instalacji jest wiele, łącznie z metodą „staromodną”, tj. ręcznie („
Instalacja ręczna ”). Zgodnie z instrukcją pobierz plik typu „
binary-only ”, który będzie miał nazwę np. gradle-5.1.1-bin.zip. Następnie rozpakuj archiwum i skonfiguruj zmienną środowiskową PATH zgodnie z instrukcją. Najważniejsze jest to, że po wykonaniu instrukcji polecenie
gradle -v
pokazuje wersję zainstalowanego Gradle. Może wystąpić problem, że podczas określania lokalizacji system znajdzie Gradle nie tam, gdzie chcesz. Dlatego w systemie Windows możesz to zrobić (w * nix są analogi):
for %i in (gradle.bat) do @echo. %~$PATH:i
Być może teraz możemy zacząć się poznawać.
Inicjowanie projektu Gradle
Od razu zaznaczę, że Gradle polega na wykonywaniu zadań zwanych
zadaniami (nazwę je zadaniami). Zadania udostępniane są przez różne
wtyczki . Radzę przeczytać więcej o wtyczkach w oficjalnej dokumentacji: „
Korzystanie z wtyczek Gradle ”. Istnieje zestaw „Core Plugins”, które są zawsze dostępne po zainstalowaniu Gradle. Istnieją różne kategorie tych wtyczek, ale nas interesuje kategoria „
Utility ”. Zestaw ten zawiera wtyczkę „
Build Init Plugin ”, która udostępnia zadania inicjowania projektu Gradle. Jesteśmy zainteresowani utworzeniem projektu typu: „
aplikacja java ”. Uruchommy zadanie Gradle:
gradle init --type java-application
Odpowiedzmy po drodze na kilka pytań, na przykład, że chcemy używać Groovy DSL (standardowy język opisu zadań dla Gradle) i frameworka testowego JUnit (porozmawiamy o tym w innej recenzji). Po utworzeniu otrzymamy następujący zestaw plików:
Po pierwsze, po inicjalizacji otrzymujemy specjalny wrapper, wstępnie skonfigurowany dla naszej wersji Gradle - jest to specjalny skrypt. Radzę przeczytać więcej na ten temat w oficjalnej dokumentacji - „
The Gradle Wrapper ”. Po drugie, widzimy skrypt budowania Gradle - plik build.gradle. Jest to plik główny, który opisuje z jakich bibliotek i frameworków korzysta nasz projekt, jakie wtyczki należy podłączyć do projektu oraz opisuje różne zadania. Radzę przeczytać więcej na temat tego pliku w oficjalnej dokumentacji: „
Podstawy budowania skryptu ”.
Wtyczki i zadania
Jeśli teraz spojrzymy na zawartość skryptu kompilacji, zobaczymy sekcję wtyczek:
plugins {
id 'java'
id 'application'
}
Są to te same wtyczki, o których mówiliśmy wcześniej. A jeśli są wtyczki, to są teraz dla nas dostępne zadania. Możemy uruchomić polecenie gradle tasks i zobaczyć, co możemy teraz zrobić z projektem:
Przykładowo wykonując
gradle run
uruchomimy główną klasę naszej aplikacji Java:
Jak widzimy, to samo jest napisane poniżej.Co
2 actionable tasks: 1 executed, 1 up-to-date
to oznacza? Oznacza to, że w sumie zostały wykonane 2 zadania: Co więcej, 1 zostało faktycznie wykonane, a jedno nie zostało wykonane, ponieważ... jest aktualny, czyli stan jest aktualny i nic nie zostało zrobione. Możemy wykonać tzw. „Dry Run”:
gradle run -m
Wykonajmy to polecenie, zobaczymy, jakie zadania zostaną wykonane, aby wykonać zadanie run:
Jak widzimy, w sumie ukończono 4 zadania: przed wykonaniem run wykonał klasy zadań zależności. Same klasy mają 2 zależności i dlatego wykonały również kompilację Java i ProcessResources. Kiedy wykonujemy jakieś zadanie, możemy je wykonać przeglądając określony poziom logów (poziom logowania określa jak ważne wiadomości chcemy widzieć). Możemy to zrobić na przykład
gradle run -i
. Spowoduje to również wyświetlenie nam komunikatów informacyjnych, takich jak:
Task :classes UP-TO-DATE
Skipping task ':classes' as it has no actions.
Aby uzyskać więcej informacji na temat logowania do Gradle, radzę zapoznać się z oficjalną dokumentacją: „
Gradle Logging ”. Jak widać zadanie zajęć zostało pominięte bo jest
U-TO-DATE czyli stan jest aktualny, nic nie trzeba robić, więc nie było żadnych działań. Dzieje się tak, ponieważ domyślnie Gradle ma „
Kontrolę aktualności ” lub tak zwaną kompilację przyrostową. Więcej o tym mechanizmie możesz przeczytać w dokumentacji Gradle: „
Aktualne kontrole (AKA Inkrementalna kompilacja) ”. Ale ten mechanizm można wyłączyć, wykonując zadanie z flagą --rerun-tasks. Na przykład,
gradle run --rerun-tasks
. Wtedy zobaczymy:
2 zadania wykonalne: 2 wykonane Jak widać, liczba wykonanych zadań uwzględnia tylko pierwszy poziom wykresu, czyli samo uruchomione zadanie oraz te zadania, od których bezpośrednio zależy, czyli , zajęcia. Zadania, od których zależą klasy, nie są tu liczone (chociaż są wykonywane w momencie wykonania zadania klas). Warto przeczytać także o zadaniach:
Zależności
Jednym z głównych zadań każdego systemu kompilacji jest zarządzanie zależnościami, czyli bibliotekami/frameworkami, których potrzebuje nasz projekt. System kompilacji musi zadbać o to, aby były one dostępne we właściwym czasie i we właściwy sposób zmontować końcowy artefakt naszej aplikacji. Domyślnie po inicjowaniu stopni dla aplikacji Java w skrypcie budującym zobaczymy następującą treść:
dependencies {
implementation 'com.google.guava:guava:26.0-jre'
testImplementation 'junit:junit:4.12'
}
Tutaj od razu widać, co łączymy. Ale bez pewnego zrozumienia nie jest jasne, czym jest implementacja i testImplementacja? W tym miejscu musimy ponownie zwrócić się do dokumentacji Gradle, ponieważ dokumentacja Gradle jest dobrze napisana. Nazywa się to „
Zarządzanie konfiguracjami zależności ”. Jak podano w dokumentacji, każda zależność deklarowana jest z pewnym zakresem – obszarem, w którym dana zależność będzie dostępna. Ten zakres jest wyznaczony przez pewną konfigurację, z których każda ma unikalną nazwę. Ciekawe jest również to, że wiele wtyczek Gradle dodaje predefiniowane konfiguracje. Aby dowiedzieć się jakie mamy konfiguracje możemy uruchomić:
gradle --console plain dependencies
W ten sposób zobaczymy listę wszystkich dostępnych konfiguracji i ich zależności. Możemy przefiltrować tę listę, tak aby zobaczyć tylko same dostępne konfiguracje:
gradle --console plain dependencies | find " - "
Skąd mamy wiedzieć, czego użyć? Będziesz musiał tu trochę poczytać. Ponieważ Korzystamy z wtyczki „Java”, więc zacznijmy od jej dokumentacji i sekcji „
Zarządzanie zależnościami ”. Widzimy tutaj, że istniała kiedyś konfiguracja (czyli zakres) zwana „kompilacją” i oznaczała „zależność wymaganą podczas kompilacji”. Ale potem został zastąpiony (w języku angielskim zastąpiony) wdrożeniem. Więcej o wymianie przeczytasz w dziale „
Separacja API i implementacji ”. Okazuje się, że ta zależność będzie dotyczyć „ścieżki klas kompilacji”. Czasami jednak chcemy, aby nasza zależność została uwzględniona w ostatecznym artefakcie. Po co? Na przykład będziemy mieli wykonywalny słoik, który sam powinien zawierać wszystko, co niezbędne. Co w takim razie powinniśmy zrobić? Po pierwsze, nie ma takiego wsparcia „od razu po wyjęciu z pudełka” (czyli domyślnie bez żadnych dodatkowych działań). Wyjaśnia to fakt, że każdy chce gromadzić archiwum na swój sposób, a Gradle stara się być minimalistyczny. Nie możemy także używać archiwów jar w ścieżce klas (bez dodatkowych manipulacji w kodzie), ponieważ to nie działa w ten sposób ( więcej szczegółów można znaleźć w artykule „
Oracle: Dodawanie klas do ścieżki klas pliku JAR ”). Dlatego najpiękniej jest następujący kod w skrypcie kompilacji:
jar {
manifest {
attributes 'Main-Class': 'jrgradle.App'
}
from configurations.compileClasspath.collect { it.isDirectory() ? it : zipTree(it) }
}
W ustawieniach zadania jar określamy, co zostanie dodane do manifestu pliku jar (patrz „
Oracle: Ustawianie punktu wejścia aplikacji ”). A potem mówimy, że wszystkie zależności potrzebne do kompilacji zostaną zawarte w słoiku. Alternatywą jest użycie
wtyczki Gradle Shadow . Może się to wydawać skomplikowane, ale inne wtyczki mogą ułatwić życie. Przykładowo tworząc aplikację webową (w odróżnieniu od normalnie działającej aplikacji w Javie) użyjemy specjalnej wtyczki – „
Gradle War Plugin ”, która zachowuje się inaczej i dzięki niej będzie nam łatwiej żyć (wszystkie niezbędne zależności zostaną być umieszczone przez samą wtyczkę w osobnym, specjalnym katalogu. Taka praca jest regulowana sposobem projektowania aplikacji internetowych. Ale to już zupełnie inna historia).
Wyniki
Gradle to doskonały wybór do systemów tworzenia projektów. Potwierdza to fakt, że korzystają z niego twórcy tak znanych projektów jak Spring i Hibernate. Powyżej omówiono tylko najbardziej podstawowe kwestie. Za nimi kryje się milion funkcji i możliwości, jakie mają programiści. Gradle obsługuje także tworzenie projektów wielomodułowych, co nie jest omówione w tej recenzji, ale sam Gradle ma doskonały samouczek: „
Tworzenie kompilacji wieloprojektowych ”. Mam nadzieję, że ta recenzja pokazała również, że dokumentacja Gradle'a jest napisana na poziomie 5+ i możesz łatwo znaleźć to, czego potrzebujesz, jeśli wiesz, gdzie szukać. A to przyjdzie, kiedy zrozumiesz podstawy. Ponadto Gradle ma świetne tutoriale. Chciałbym zakończyć małą listą tego, co jeszcze możesz zobaczyć za pomocą Gradle:
#Wiaczesław
GO TO FULL VERSION