JavaRush /Курси /Java Server /Gradle Wrapper: спосіб збирання

Gradle Wrapper: спосіб збирання

Java Server
Рівень 2 , Лекція 1
Відкрита

1. Gradle і Wrapper: gradle vs gradlew

На початку дуже легко переплутати дві схожі речі: gradle як програму і gradle Wrapper як спосіб її запуску. Звучать вони майже однаково — як «кава» і «кавоварка», тільки наслідки плутанини зазвичай бадьорять сильніше за ранкове еспресо. Давайте спокійно розберемо, що саме ви запускаєте і чому в навчальному проєкті ми обираємо лише один шлях.

Уявіть, що ви пишете в терміналі:

# Запуск Gradle, встановленого в системі (локально на вашому компʼютері)
gradle build

Це означає: «візьми Gradle, який встановлено на моєму компʼютері, і спробуй зібрати проєкт». А тепер порівняйте з:

# Запуск Gradle через Wrapper (версія Gradle береться з налаштувань проєкту)
./gradlew build

Це вже означає: «візьми Gradle, який прописано в проєкті, і зібрай проєкт». Різниця здається косметичною — лише дві точки і слеш, — але з інженерного погляду це два різні світи.

Системний gradle живе за правилами вашої машини. У вас може бути Gradle 8.x, у вашого друга — 9.x, а у викладача — взагалі нічого (і він не зобовʼязаний здогадуватися, що ви там установили). У підсумку виходить класична ситуація: «у мене збирається», «у тебе не збирається», «а давай ти просто перевстановиш усе про всяк випадок». Це виглядає як план, але це поганий план.

Wrapper робить навпаки: кладе в репозиторій «точку входу», яка гарантує, що проєкт запускається одним і тим самим Gradle незалежно від того, хто його запускає. У нашому курсі це особливо важливо, тому що базову конфігурацію зафіксовано: Gradle Wrapper 9.4.0, Kotlin DSL, Java 25. Нам потрібно, щоб ви могли відкривати будь-який приклад із лекції й отримувати той самий результат, а не проходити квест «вгадай версію».

Для наочності можна запамʼятати коротку формулу:

Команда Хто обирає версію Gradle Чому це важливо
gradle build
ваша ОС / ваш локально встановлений Gradle проєкт стає «привʼязаним до компʼютера»
./gradlew build
сам проєкт (через Wrapper) проєкт стає відтворюваним

І так, іноді системного gradle у вас узагалі не буде — і це нормально. У нашому курсі не потрібно окремо встановлювати Gradle в систему. Якщо вам дуже хочеться щось установити вручну — просто поставте собі нагадування завжди збирати проєкт через Wrapper. Воно корисніше.

2. Wrapper: файли та ролі

Коли ви вперше бачите файли Wrapper у проєкті, рука так і тягнеться подумати: «О, сміття! Це ж не Java-код». Реакція цілком природна, особливо якщо до цього ви писали маленькі програми, які живуть в одному файлі. Але для бекенд-проєкту, навіть навчального, ці файли — як ключі від квартири: ви можете бути чудовим розробником, але без ключів усередину не потрапите.

Мінімальний набір Wrapper виглядає так:

# Структура файлів, які забезпечують запуск Gradle через Wrapper
readlater-starter/
├── gradlew
├── gradlew.bat
└── gradle/
    └── wrapper/
        ├── gradle-wrapper.jar
        └── gradle-wrapper.properties

Давайте перекладемо це з формату «побачив у дереві проєкту» на людський зміст.

gradlew — це скрипт для macOS/Linux. Він запускається як виконуваний файл із кореня проєкту і є вашим головним входом. gradlew.bat — те саме, але для Windows (batch-скрипт). Це не «два різні варіанти на вибір», а два варіанти для різних ОС.

У папці gradle/wrapper/ лежать два критично важливі файли. gradle-wrapper.properties — конфігурація Wrapper, у ній якраз фіксується, яку версію Gradle використовувати. gradle-wrapper.jar — маленька Java-програма (так, jar), яка вміє завантажити потрібний Gradle, а потім запустити його так, як треба проєкту.

Щоб було простіше, ось невеличка «шпаргалка» у вигляді таблиці:

Файл Навіщо потрібен Чи можна видаляти
gradlew
запуск Gradle через Wrapper на macOS/Linux ні
gradlew.bat
запуск Gradle через Wrapper на Windows ні
gradle/wrapper/gradle-wrapper.properties
фіксує версію Gradle і налаштування дистрибутива ні
gradle/wrapper/gradle-wrapper.jar
реалізація Wrapper, яка завантажує і запускає Gradle ні

Тут легко зависнути на запитанні: а звідки ці файли взагалі беруться в самому першому стані проєкту? Їх не пишуть вручну. Зазвичай вони вже приходять разом зі стартовим каркасом проєкту — наприклад, якщо ви створюєте Gradle-проєкт із шаблону або берете готовий навчальний репозиторій. Далі Wrapper живе в репозиторії як частина проєкту, і всі команди йдуть лише через нього.

Слово «ні» в колонці «чи можна видаляти» — не тому, що ми шкідливі. А тому, що якщо ви видалите Wrapper-файли, проєкт перестане мати універсальну точку входу, і ми повернемося в епоху «постав Gradle сам якось».

3. Версія Gradle у gradle-wrapper.properties

Якщо ви шукаєте в проєкті місце, де «насправді» зафіксовано версію Gradle, це не build.gradle.kts і не налаштування IDE. Це файл gradle/wrapper/gradle-wrapper.properties. Він маленький, нудний і саме тому надійний: ніякої магії, лише текст, який читає Wrapper.

Найважливіший рядок там зазвичай виглядає так:

# Звідки Wrapper завантажує Gradle і де фіксується його версія
distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.0-bin.zip

Цей запис буквально означає: «якщо потрібно запустити Gradle, візьми дистрибутив gradle-9.4.0-bin.zip з офіційного сайту Gradle». Тобто версію 9.4.0 зафіксовано в проєкті. Не «остання на сьогодні», не «та, що встановлена», і не «та, що у мене в IDE». А та, з якою цей репозиторій має жити.

Чому це важливо навіть для новачка, який поки що не збирає багатомодульних монстрів? Тому що Gradle — живий інструмент. У різних версіях відрізняються деталі Kotlin DSL, наявні можливості, поведінка деяких задач і навіть повідомлення про помилки. А ви зараз навчаєтеся, і вам потрібно, щоб приклад із лекції збігався з тим, що відбувається на вашому компʼютері.

У Wrapper є й інші властивості: де зберігати завантажений дистрибутив, як розкладати файли та інші параметри. Але в межах нашого курсу достатньо тримати в голові один орієнтир: distributionUrl фіксує версію Gradle і робить запуск відтворюваним.

Ще одна деталь: bin у назві архіву означає «binary distribution», тобто звичайний робочий варіант. Існують і інші варіанти дистрибутива, але ми не перетворюємо цей курс на курс із build-інженерії. Наша мета простіша: однаковий запуск у всіх.

4. Перший запуск: завантаження Gradle

Перший запуск Wrapper часто лякає новачків: ви вводите команду, і замість миттєвого «успіх!» бачите, як щось завантажується, шарудить, розпаковується. Тут важливо не зробити висновок «у мене все зламалося» і не побігти перевстановлювати Java, IDE і, про всяк випадок, клавіатуру.

Механіка приблизно така: коли ви запускаєте ./gradlew ..., Wrapper перевіряє, чи є потрібна версія Gradle в локальному кеші. Якщо ні — завантажує її за distributionUrl, розпаковує і лише потім запускає потрібну задачу (build, run тощо).

В узагальненому вигляді це виглядає так:

# Уся логіка нижче — про те, що робить Wrapper перед тим, як запустити збирання
Ви запускаєте ./gradlew build
→ Wrapper читає gradle-wrapper.properties
→ Бачить gradle-9.4.0-bin.zip
→ Якщо Gradle 9.4.0 ще не завантажено локально — завантажує
→ Запускає Gradle 9.4.0 і виконує build

Де це зберігається? Зазвичай у домашній директорії користувача, у папці .gradle. Тобто завантажений Gradle — це не частина репозиторію, а локальний кеш на вашій машині. Тому перший запуск може бути помітно повільнішим, а другий і третій — уже значно швидшими.

Якщо хочеться побачити, що Wrapper справді живий і працює, можна безпечно виконати команду, яка нічого не компілює, а просто показує інформацію про Gradle:

# Перевіряємо, яку версію Gradle насправді запускає Wrapper
./gradlew --version
# Gradle 9.4.0
# Kotlin: ...
# JVM: ...

Рядок із коментарем під командою — це не точний вивід «байт у байт», він може відрізнятися деталями. Але зміст ви вловлюєте: ви побачите версію Gradle, і це буде саме та версія, що зафіксована у Wrapper.

Якщо перше завантаження триває довго, найчастіше причина прозаїчна: повільний інтернет, перший запуск, іноді корпоративний проксі. Але на рівні курсу ми сприймаємо «перший запуск завантажує Gradle» як нормальну частину життя проєкту. Важливо лише памʼятати: це відбувається один раз на версію Gradle і потім кешується.

5. Задачі через Wrapper

Коли говорять «запускати через Wrapper», йдеться не про філософію, а про цілком конкретний формат команд. Ви запускаєте скрипт із кореня проєкту і передаєте йому імʼя задачі. Якби Gradle був кавомашиною, то Wrapper був би кнопкою «увімкнути», а задача — командою «зроби лате». Так, порівняння дивне, але воно несподівано допомагає запамʼятати структуру.

Загальний шаблон команди такий:

# <taskName> — це імʼя задачі Gradle, наприклад build/run/test тощо
./gradlew <taskName>

Наприклад, найпростіші задачі, які вже скоро активно використовуватимемо, виглядають так:

# Зібрати проєкт (компіляція, тести, пакування — залежить від налаштувань проєкту)
./gradlew build
# Запустити застосунок (коли в проєкті налаштовано задачу run)
./gradlew run

На Windows замість ./gradlew зазвичай використовують gradlew.bat, і це саме імʼя файла, а не «щось із IDE»:

REM На Windows використовуємо batch-скрипт Wrapper із кореня проєкту
gradlew.bat build
gradlew.bat run

Оскільки навіть тут легко заплутатися, ось маленька таблиця-нагадування:

ОС Команда
macOS / Linux
./gradlew build
Windows
gradlew.bat build

Тепер про дивний на перший погляд префікс ./. Він означає «запусти файл із поточної директорії». На Unix-подібних системах (Linux/macOS) поточна папка не входить до PATH за замовчуванням, і це зроблено спеціально з міркувань безпеки. Тому gradlew без ./ часто не запускається. Не тому, що «у вас не той термінал», а тому, що так влаштовано систему.

Ще одна корисна звичка: завжди запускати команди з кореня проєкту — з тієї папки, де лежать gradlew, build.gradle.kts і settings.gradle.kts. Якщо ви стоїте десь углиб src/main/java, Wrapper фізично може не бути за шляхом, і команда не спрацює. Це не «Gradle дивний», а ви просто стоїте не в тій папці.

6. Wrapper у репозиторії

На старті Wrapper-файли часто сприймають як щось тимчасове: «ну я ж уже завантажив Gradle, навіщо зберігати ці скрипти». І тут важливо зловити головну ідею: Wrapper зберігається в репозиторії не тому, що вам ліньки встановити Gradle. Він зберігається тому, що проєкт повинен уміти запускатися сам по собі, без попередніх танців.

У командній розробці проєкт живе так: хтось клонує Git-репозиторій, відкриває README і запускає команди. Якщо в проєкті немає Wrapper, перша команда перетворюється на «спочатку встанови Gradle потрібної версії». А далі починаються уточнення: «а яку версію?», «а де завантажити?», «а що, якщо у мене вже стоїть інша?», «а це точно нічого не зламає?».

Wrapper обриває цю гілку запитань на корені. Він каже: «ось вхід, ось версія, запускай». Саме тому Wrapper-файли мають бути закомічені в Git разом із кодом. І саме тому будь-які правила в .gitignore, які випадково ігнорують gradle-wrapper.jar або gradle-wrapper.properties, — це диверсія проти відтворюваності.

Важливе уточнення: папка build/, яку Gradle створює під час збирання, — це справді згенерований артефакт, його ми зазвичай не комітимо. А от gradle/wrapper/ — це не «результат збирання», а частина опису того, як збирати. Сприймайте це як інструкції до проєкту, які мають лежати поруч із самим проєктом.

7. Схема запуску Wrapper

У новачка дуже часто виникає внутрішній дискомфорт: «я запускаю ./gradlew build, і десь там щось відбувається, але я не розумію що». І це нормальна емоція. Ми зараз не вивчаємо внутрішню будову Gradle, але важливо прибрати відчуття чорної скриньки хоча б на рівні загальної схеми.

Ось спрощена блок-схема того, що відбувається:

flowchart TD
    A["Ви в корені проєкту запускаєте ./gradlew build"] --> B["Скрипт gradlew / gradlew.bat"]
    B --> C["Wrapper (gradle-wrapper.jar)"]
    C --> D["Читає gradle-wrapper.properties і дізнається версію Gradle"]
    D --> E{"Потрібна версія Gradle вже завантажена?"}
    E -->|Ні| F["Завантажує дистрибутив Gradle і кладе його в локальний кеш"]
    E -->|Так| G["Використовує локальний кеш"]
    F --> H["Запускає Gradle потрібної версії"]
    G --> H["Запускає Gradle потрібної версії"]
    H --> I["Gradle виконує задачу build/run за правилами проєкту"]

Ця схема важлива тим, що показує: Wrapper не «замінює Gradle». Він просто гарантує, що Gradle буде правильної версії і що запуск завжди починається однаково.

І тепер можна акуратно привʼязати це до нашого проєкту. ReadLater Starter — це репозиторій, який повинен запускатися однаково для всіх студентів. Тому ми будемо всюди — у README, у прикладах команд і у власних звичках — використовувати лише Wrapper-команди. Це стане «правилом гри» проєкту — таким самим, як «Java-код лежить у src/main/java», а не будь-де.

8. Типові помилки під час роботи з Wrapper

Помилка №1: запускати gradle build замість ./gradlew build.
Це одна з найчастіших плутанин. Команда gradle build звертається до Gradle, встановленого у вашій системі (якщо він узагалі встановлений), і може мати іншу версію. У результаті ви витрачаєте час не на навчання і проєкт, а на вгадування, чому приклад із лекції не збігається з вашим виводом у консолі.

Помилка №2: видаляти або не закомічувати Wrapper-файли, тому що вони «службові».
Здається логічним «прибрати проєкт» і забрати зайве. Але Wrapper — це не сміття і не кеш. Це частина контракту репозиторію: як саме цей проєкт має запускатися. Якщо в репозиторії немає Wrapper, в іншої людини немає гарантованого способу відтворити ваш запуск.

Помилка №3: плутати gradlew і gradlew.bat та намагатися запускати не той файл на своїй ОС.
На macOS/Linux ви зазвичай запускаєте ./gradlew. На Windowsgradlew.bat. Спроба запустити «чужий» скрипт часто закінчується дивними повідомленнями: термінал не розуміє формат файла, не ті права, не те кодування. Простіше прийняти це як факт: є два входи для двох сімейств ОС.

Помилка №4: запускати Wrapper не з кореня проєкту.
Команди ./gradlew ... мають сенс, коли ви стоїте в директорії, де лежить файл gradlew. Якщо ви випадково перейшли в src/main/java і намагаєтеся запускати звідти, то отримаєте «No such file or directory» або аналогічне повідомлення. Це не «Gradle не працює», а ви просто стоїте не в тій папці.

Помилка №5: лякатися довгого першого запуску і сприймати завантаження Gradle за збій.
Під час першого запуску Wrapper справді може завантажити дистрибутив Gradle. Це нормальна механіка, а не помилка. Якщо інтернет є і посилання в distributionUrl коректне, далі все працюватиме швидше завдяки кешу.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ