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 | проєкт стає «привʼязаним до компʼютера» |
|
сам проєкт (через 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, а потім запустити його так, як треба проєкту.
Щоб було простіше, ось невеличка «шпаргалка» у вигляді таблиці:
| Файл | Навіщо потрібен | Чи можна видаляти |
|---|---|---|
|
запуск Gradle через Wrapper на macOS/Linux | ні |
|
запуск Gradle через Wrapper на Windows | ні |
|
фіксує версію Gradle і налаштування дистрибутива | ні |
|
реалізація 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 | |
| Windows | |
Тепер про дивний на перший погляд префікс ./. Він означає «запусти файл із поточної директорії». На 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. На Windows — gradlew.bat. Спроба запустити «чужий» скрипт часто закінчується дивними повідомленнями: термінал не розуміє формат файла, не ті права, не те кодування. Простіше прийняти це як факт: є два входи для двох сімейств ОС.
Помилка №4: запускати Wrapper не з кореня проєкту.
Команди ./gradlew ... мають сенс, коли ви стоїте в директорії, де лежить файл gradlew. Якщо ви випадково перейшли в src/main/java і намагаєтеся запускати звідти, то отримаєте «No such file or directory» або аналогічне повідомлення. Це не «Gradle не працює», а ви просто стоїте не в тій папці.
Помилка №5: лякатися довгого першого запуску і сприймати завантаження Gradle за збій.
Під час першого запуску Wrapper справді може завантажити дистрибутив Gradle. Це нормальна механіка, а не помилка. Якщо інтернет є і посилання в distributionUrl коректне, далі все працюватиме швидше завдяки кешу.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ