Gradle User Manual
Gradle Build Tool is a fast, dependable, and adaptable open-source build automation tool with an elegant and extensible declarative build language.
In this User Manual, Gradle Build Tool is abbreviated Gradle.
Why Gradle?
Gradle is a widely used and mature tool with an active community and a strong developer ecosystem.
- Gradle is the most popular build system for the JVM and is the default system for Android and Kotlin Multi-Platform projects. It has a rich community plugin ecosystem.
- Gradle can automate a wide range of software build scenarios using either its built-in functionality, third-party plugins, or custom build logic.
- Gradle provides a high-level, declarative, and expressive build language that makes it easy to read and write build logic.
- Gradle is fast, scalable, and can build projects of any size and complexity.
- Gradle produces dependable results while benefiting from optimizations such as incremental builds, build caching, and parallel execution.
Gradle, Inc. provides a free service called Build Scan® that provides extensive information and insights about your builds. You can view scans to identify problems or share them for debugging help.
Supported Languages and Frameworks
Gradle supports Android, Java, Kotlin Multiplatform, Groovy, Scala, Javascript, and C/C++.
Compatible IDEs
All major IDEs support Gradle, including Android Studio, IntelliJ IDEA, Visual Studio Code, Eclipse, and NetBeans.
You can also invoke Gradle via its command-line interface (CLI) in your terminal or through your continuous integration (CI) server.
Education
The Gradle User Manual is the official documentation for the Gradle Build Tool.
- Getting Started Tutorial — Learn Gradle basics and the benefits of building your App with Gradle.
- Training Courses — Head over to the courses page to sign up for free Gradle training.
Support
- Forum — The fastest way to get help is through the Gradle Forum.
- Slack — Community members and core contributors answer questions directly on our Slack Channel.
Licenses
Gradle Build Tool source code is open and licensed under the Apache License 2.0. Gradle user manual and DSL reference manual are licensed under Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
Gradle: 5 полезностей для разработчика
Привет, Хабр! Настало время, когда можно сказать, что «new build system» Gradle является стандартом отрасли Android-разработки. Инструмент сделан настолько просто и удобно, что большинство разработчиков не испытает трудностей, даже не зная, как он устроен, и какие дополнительные возможности в нём есть — возникающие проблемы легко решаются с помощью 5 минут на StackOverflow, путем копирования «магического кода» в конфигурационные файлы. Возможно, в том числе из-за этого не все разработчики изучают Gradle детально и не знают о многих его полезных возможностях, которые существенно облегчают жизнь.
Речь пойдет о:
- Увеличении быстродействия
- Расширении BuildConfig
- Использовании переменных
- Выключении Crashlytics
- Уменьшении количества конфигураций ресурсов
1. Увеличиваем быстродействие
Время сборки напрямую влияет на скорость разработки. Тесты показывают, что каждая из версий, начиная с Gradle 2.0, становилась медленнее предыдущей. Однако затем разработчики исправились и хорошенько поработали над быстродействием в Gradle 2.4.
1. Поэтому первым делом следует убедиться, что вы используете актуальную версию Gradle 2.4+
sm:~ sm$ gradle -v Gradle 2.4
2. Затем, удостоверившись, что вы пытаетесь ускорить свою рабочую машину, а не сервер CI, включить Gradle демон — это даст значительный прирост в скорости сборки.
Строки конфигурации стоит добавлять в файл ./%project%/gradle.properties, если вы хотите распространить конфигурацию на все проекты, то необходимо конфигурировать файл, лежащий в домашней папке вашего пользователя
~/.gradle/gradle.properties
org.gradle.daemon=true # включаем демон
Почему на CI-сервере не стоит включать Gradle Daemon
Gradle демон позволяет делать сборки более быстро, но при Gradle переиспользует runtime предыдущей сборки, по этой причине крайне важные требования для CI не выполняются. А именно стабильность и предсказуемость, чистота runtime и полная изолируемость от предыдущих сборок.
3. После чего, проверив что модули вашего проекта не используют друг-друга как зависимости, тем самым создавая перекрёстные ссылки, можно смело включать режим параллельного выполнения, что также ускорит скорость сборки до ~30%.
org.gradle.parallel=true # включаем режим параллельного выполнения
Если в проекте используется много модулей, то стоит также включить режим конфигурации при необходимости:
org.gradle.configureondemand=true
Чем больше модулей в вашем проекте, тем большее вы заметите ускорение, на малом количестве модулей его может и не быть.
2. Расширяем BuildConfig
Как известно, файл конфигурации сборки (build.gradle) предоставляет возможность определить Product Flavors и Build Types, что даёт нам массу вариантов для разделения сборок по назначению. Например, “Сборка с тестовым сервером”, “Сборка с боевым сервером”, ”Сборка с логированием” и другие. Использование их для расширения BuildConfig (который генерируется каждый раз при сборке) даёт нам потрясающую гибкость. Например, удобное переключение между back-end-сервером, с которым работает наше приложение; включение/выключение определённого функционала – например, логи.
android < . buildTypes < debug < buildConfigField "String", "SERVER_PREFIX", "\"test.\"" >release < buildConfigField "String", "SERVER_PREFIX", "\"\"" >> >
// … public final class NetworkConstants < // … public static final String SERVER_ADDRESS = "http://" + BuildConfig.SERVER_PREFIX + "server.com/"; // … >
Разница между Product Flavors и Build Types
Product Flavor — это механизм, который позволяет нам определять различные варианты сборки приложения. У одного проекта могут быть различные варианты сборки(flavors), при выборе варианта(flavor) будет изменяться генерируемое приложение.
Build Type — конфигурация того, как приложение будет упаковано. У каждого приложения по умолчанию есть два Build Type – debug и release. Можно сделать и другие. Идеологически Build Type не предназначен для изменения приложения, только упаковки. Собственно это и является основным различием, которое выливается в различные наборы параметров, которые предоставляются для настройки Product Flavors и Build Types.
3. Используем переменные
Время не стоит на месте, а значит инструменты, библиотеки и Android имеют свойство обновляться. И если приложение развивается, то приходится открывать build.gradle и менять как минимум compileSdkVersion, buildToolsVersion, версии Android Support Library и Google Play Services. А если у нас в проекте используется много модулей или различные части библиотеки Google Play Services, это ведет к большому количеству мест изменений, и можно легко потерять время из-за опечатки в каком-то из файлов. Кроме того, возможно использование различных библиотек и инструментов в разных проектах, что плохо и может стать причиной проблем. Избежать подобной ситуации помогут gradle-переменные.
В самый верхний build.gradle добавляем
// … ext.compileSdkProjectVersion= 23 ext.buildToolsProjectVersion= '23.0.1' ext.supportLibraryVersion = '23.1.0' ext.googlePlayVersion = '8.3.01’
В остальных ./%module%/build.gradle их можно будет использовать, выглядеть это будет примерно так:
android < compileSdkVersion compileSdkProjectVersion buildToolsVersion buildToolsProjectVersion //… >dependencies
4. Выключаем Crashlytics
В большинстве случаев собирать аварийные завершения необходимо только в Release-сборках, которые мы выпускаем для пользователей/тестирования. Debug сборки разработчик использует для себя, и аварийные завершения будут видны ему в лог-файле, значит, дабы не засорять список реальных аварийных завершений у пользователей, необходимо выключить Crashlytics для Debug-сборок.
Задачу можно выполнить банальной проверкой типа сборки:
// App.java // … public final class App extends Application < // . @Override public void onCreate() < // … if ( !BuildConfig.DEBUG ) < Fabric.with(this, new Crashlytics()); >// … > // … >
Но это не самое лучшее решение, т.к. плагин Fabric Gradle всё равно будет тратить время на генерацию и встраивание в ресурсы приложения уникального id сборки, чтобы Crashlytics back-end затем понял, какая сборка прислала данные. Поэтому применим более удобное решение, которое позволит ускорить время сборки debug-версии приложения.
android < //… buildTypes < debug < ext.enableCrashlytics = false // … >> // … >
После этого debug-сборки не будут получать id, и процесс сборки ускорится, но следует учитывать, что если разработчик попытается инициализировать в такой сборке Crashlytics, то приложение упадёт с выводом:
com.crashlytics.android.core.CrashlyticsMissingDependencyException: This app relies on Crashlytics. Please sign up for access at https://fabric.io/sign_up`
Т.е. обязательно оставьте проверку на тип сборки и используйте Crashlytics только для Release сборок или воспользуйтесь решением, приведённым в документации к Crashlytics на сайте Fabric:
// App.java // … public final class App extends Application < // . @Override public void onCreate() < // … //Создаём Crashlytics,выключенный для debug сборок Crashlytics crashlyticsKit = new Crashlytics.Builder() .core(new CrashlyticsCore.Builder().disabled(BuildConfig.DEBUG).build()) .build() // Инициализируем Fabric с выключенным crashlytics. Fabric.with(this, crashlyticsKit); // … >// … >
5. Уменьшаем количество конфигураций ресурсов
В разрабатываемых нами приложениях мы часто используем сторонние библиотеки, например, Android Support Library, Google Play Services и другие. Многие из библиотек поставляются с различными внутренними ресурсами, которые в наших приложениях абсолютно не нужны. Например, Google Play Services поставляется с переводом на языки, которые ваше приложение не поддерживает. Вероятно, вы также не захотите поддерживать mdpi или tvdpi-разрешение в своём приложении.
Благодаря Android Gradle Plugin мы можем установить языки и разрешения, которые используются в приложении, остальные будут исключены, что позволит уменьшить вес приложения.
// build.gradle android < defaultConfig < resConfigs "en", "ru" resConfigs "nodpi", "hdpi", "xhdpi", "xxhdpi", "xxxhdpi" >>
При необходимости можно подойти более радикально и начать использовать multi-APK, тем более когда появился новый удобный механизм Splits.
Вместо заключения
Этим рубрику полезных советов по Gradle закончим, их ещё много, но, на мой взгляд, вышеперечисленные являются наиболее интересными. Наверняка у вас есть и свои, интересно будет увидеть их в комментариях 🙂 На этом всё, спасибо за внимание!
5 Basics of Gradle for Android Developers
Does Gradle script look like a magic spell to you? You’ve been writing apps for some time and your interactions with Gradle were limited to adding dependencies, updating compile and target SDK, Gradle plugin version, working with build flavors and build types, and going to Stack Overflow every time your build fails. Maybe you even went as far as splitting the monolith app into modules and touched gradle.settings but still haven’t read a page of Gradle docs? Then this article is for you!
What is Gradle?
Gradle is a build automation tool that uses build script and through configuration describes information about the application. Gradle then uses that information to build your app. Gradle build scripts are written using Groovy or Kotlin DSL.
In this article, I am focusing on Groovy DSL due to it being widely used. In addition to that, in order to migrate an existing project into Kotlin DSL, a developer should have at least some understanding of what’s going on in Groovy script.
What makes Gradle so confusing for many of us?
- Not paying attention to it as it is just a build tool and not the product it is building.
- Many ways of doing the same thing + Legacy support.
- Stack Overflow with even more legacy code snippets.
- Groovy magic.
Let’s try to understand Gradle a little bit.
1) Why do we use gradlew taskName instead of gradle taskName to execute a task?
It is because in our projects we use Gradle wrapper to have 1 version of Gradle among all the developers on a project. In fact, you probably don’t have Gradle installed on your machine so you can’t even execute gradle commands outside of projects with the Gradle wrapper.
2) Android Studio’s Modules and Gradle’s Projects
An Android project is also a Gradle project. Gradle has a 1-to-1 relationship between its projects and build.gralde files. At the same time what Android Studio calls a «module», in Gradle is referred to as a project.
3) Should I use ‘ or « for string literals?
Groovy recognizes both double and single quotation marks as a string.
Not all Strings are made equal. String types in Groovy:
- ‘Hello World 1’ — String
- “Hello World 2” — String
- “Hello World $count” — GString
4) Function calls, properties, and when to use round brackets?
In Groovy:
- If a function has at least one parameter curly brackets can be ignored.
- Fields are properties, so each class field generates a setter and getter for a declared field.
Look at the code below and try to guess, how many times the Foo.name() function will be triggered when executing ./gradlew showMagic (Mac) or gradlew.bat showMagic (Windows).
Entities:
- Project — a top-level entity that allows you to interact with all other entities from the build file. It is a so-called “God object”. Gradle documentation refers to it as a “collection of Gradle tasks”.
- Task — has a number of default properties, which you’ve probably seen such as group , description , dependsOn and methods doFirst , doLast and a mix of those two that you can find in docs. An important thing to know about the tasks is that they have outcomes/states, which determine how fast the task execution will be.
- Action — the actual code that gets executed during the task run.
- Plugin — a set of tasks and configurations that extend the functionality of Gradle plugin. Added with apply plugin: , apply from:
Build script blocks:
- buildScript <> — this is where it all starts. You can define additional dependencies to later apply plugins and extend functionality. It usually contains repositories <> and dependencies <> .
- repositories <> — declare sources where dependencies and plugins are going to be fetched from.
- configurations <> — you probably haven’t seen this one, but this is a block to declare scopes for the dependencies to be used inside the dependeincies<> block. You can think of it as a block where you configure scopes for example with logic for dependency conflict resolution strategy. Examples of configurations are classPath , implementation , api and ones that the Android plugin adds androidTestImplementation , debugImplementation , etc.
- dependencies <> — declare dependencies/libraries that are used in a project.
- plugins <> — it must be the first block of the script. It contains applied plugin ids id ‘plugin.name’ . This block is of type PluginDependenciesSpec and can be replaced with apply plugin: instead of plugin id and apply from: ‘dependencies.gradle’ to apply dependency script.
- allProjects <> / subProjects <> — what are the repositories and dependencies that need to be applied to every project/sub-project.
I hope now, after reading this article, Gradle scripts are looking less like a magic spell and making more sense to you!
JUnit 5 Gradle Example
In this JUnit 5 Gradle example, we will learn how to get the required dependencies for writing JUnit 5 tests with Gradle. Also, we will learn how to configure the JUnit Gradle plugin to run the tests.
This article is part of the JUnit 5 Tutorial.
Required dependencies
First, to be able to write JUnit 5 tests we need the junit-jupiter artifact as a dependency in build.gradle :
Now all we need is to tell to use the JUnit platform in the tests:
Now we have the most basic setup for writing and running JUnit 5 tests with Gradle.
Configuration for Older Versions
Beginning from JUnit Jupiter 5.4.0 there is now an aggregator artifact junit-jupiter that transitively pulls in dependencies on junit-jupiter-api , junit-jupiter-params , and junit-jupiter-engine for simplified dependency management. This means that we don’t need additional dependencies to be able to write parameterized tests.
To be able to write JUnit 5 tests using an older version we need the junit-jupiter-api artifact as a dependency. We also need the JUnit Jupiter test engine in the test runtime classpath:
Beginning from Gradle 4.6 there is now native support for JUnit Jupiter. When using Gradle 4.5 or older, to be able to run JUnit 5 tests we have to configure the JUnit Gradle plugin:
Now we have the setup for writing and running JUnit 5 tests with older versions of Gradle.
Running tests
The JUnit Gradle plugin discovers tests under src/test/java directory by default.
Let’s check if our configuration works by adding a very simple test that does nothing:
Now we can run our tests on the command line with:
We should see output similar to this:
There we go! JUnit Gradle plugin is now running our tests.
Summary
In this JUnit 5 Gradle example we have learned how to add the required dependency for writing JUnit 5 tests and how to configure JUnit Gradle plugin to be able to run the tests.
The example code for this guide can be found on GitHub.
Clean Code Corner
Short, simple, and actionable tips on developing quality software.
Join for free. No spam. Unsubscribe at any time.
Arho Huttunen
Software Crafter
A software professional seeking for simple solutions to complex problems.
© 2015-2023 Arho Huttunen. All rights reserved.