Gradle Cheat Sheet for Android and KMP Projects - Plugins – Touchlab | Kotlin Mu...
source link: https://touchlab.co/gradle-cheat-sheet/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Gradle Cheat Sheet for Android and KMP Projects – Plugins
Gradle can be confusing and difficult to follow. When you create a new Android project they generate some Gradle files and send you off. Often, developers end up copying and pasting code from GitHub or Stack Overflow, not really understanding what’s going on.
This series will provide some definition of commonly seen code in Gradle builds, and act as a cheat sheet you can reference in the future. In addition to this post, I’ve also created a GitHub Gist that should cover a typical Gradle project setup, and contain a markdown cheatsheet. If you want to follow along with an existing project, I’d recommend either this multiplatform compose template or KaMP Kit, which is a great starting point for a KMM project.
In this article we’ll explore how gradle works, dive deeper into Gradle Plugins, and leave you with some handy Flashcards for reference.
What actually happens in a Gradle build
Before we start going over plugins let’s go over what happens in a build:
- The Gradle wrapper is downloaded based on the gradle-wrapper.properties
gradle-wrapper.properties
- The build detects the settings.gradle
settings.gradle
file and evaluates to determine which projects participate. - Project instances are created for every project and their build.gradle
build.gradle
scripts are all evaluated. - A task graph for requested tasks is created.
- Each of the selected tasks are scheduled and executed, in the order of their dependencies.
The main thing to note here is the order the build runs in. It first checks the
settings.gradle
then goes through each submodule defined in the settings, and runs their
build.gradle
files. Then as mentioned it executes tasks in order of dependencies. The actual order may be complex, but as a simplification in a KMP example we can say this:
- Settings.gradle
Settings.gradle
runsbuild.gradlebuild.gradle
of each submodule- settings.gradle
settings.gradle
orbuild.gradlebuild.gradle
resolves plugins - build.gradle
build.gradle
checks for blocks to run (such asandroidandroid
andkotlinkotlin
) and runs them - Those blocks resolve dependencies
dependencies
The order I like to think of this is:
Settings.gradle
->
build.gradle
->
plugins
->
blocks
->
dependencies
So with that in mind, we’ll first go over plugins, then common
kotlin
and
android
blocks, then dependencies, and finally wrap back to some notes about the
settings.gradle
. Gradle Source
Note: Gradle script files can come in two different extensions based on the chosen DSL:
.gradle
for Groovy DSL and
.gradle.kts
for Kotlin DSL. This blog post refers to these two extensions interchangeable, as it discusses the concepts of Gradle rather than just the syntax.
Note: In Gradle there are many ways to do the same thing. This post won’t necessarily go over best practices for location, but will give some suggestions on how to structure definitions in a multi-module project.
Note: This is not only a cheatsheet for you, but also for me. I am still learning, so if I have not covered something, or covered something incorrectly let me know.
Definitions
Before we start here are some terms I use during the post that might not be clear:
- Level
Level
: In this post when I say “level” I mean the module level. For example the root or top level would imply the root directoriesbuild.gradlebuild.gradle
and module. DSL
: Domain Specific Language. Examples: Kotlin DSL, Plugins DSL, Gradle DSL
Plugins Overview
Plugins DSL
// yourModule/build.gradle.kts plugins { kotlin("multiplatform") // This is where you add your plugin }
// settings.gradle.kts (root) pluginManagement { // Where you configure the plugins used in this project. repositories { // Listing where you want to pull the plugins from google() mavenCentral() // The Central Maven Repository (more about maven later on) gradlePluginPortal() // Default Gradle plugin portal (https://plugins.gradle.org/) } plugins { // Listing the plugins you will use kotlin("multiplatform") .version(1.8.10) // Plugins must contain a version in their definition at some level .apply(false) // You can choose to not apply plugins, in case you don't want to use the plugin at a certain level } }
Legacy Plugin Application
buildscript { repositories { // Listing where you want to pull the plugins from maven { url = uri("https://plugins.gradle.org/m2/") } } dependencies { classpath("do.re.mi.exam:ple:1.8.20") // This a dependency for the plugins you want to add } } apply(plugin = "org.jetbrains.kotlin.multiplatform") // Here is where you define a plugin
Gradle Docs
What are plugins
Plugins add functionality to your Gradle build. They add new tasks, domain objects, and features to the project. More info here
Example: Adding the
kotlin("multiplatform")
allows you to add the kotlin block containing sourcesets and targets and adds tasks such as
build iosArm64Binaries
How are plugins added?
Adding plugin to module
Let’s view this from a top down approach, starting at a modules
build.gradle
. First, We add the plugin.
// build.gradle plugins { id("com.android.library") kotlin("multiplatform") .version(1.8.10) // Optional* .apply(false) // Optional }
Plugins are added in the
plugins
block, which can either be added to a
build.gradle
or to a
pluginManagement
block in the
settings.gradle
(we’ll get to that). Submodules inherit plugins, so if you want to share plugins among submodules they can be defined to the root module.
There are two ways to include a plugin:
- id("id")
id("id")
: With id you are importing a plugin, by passing in the group ID and name of the plugin - kotlin("id")
kotlin("id")
: Kotlin is a nice shorthand, that simply means we’re using the “org.jetbrains.kotlin” group ID. This is the same as callingid("org.jetbrains.kotlin.id")id("org.jetbrains.kotlin.id")
Version: You must add a version to the plugin in your project. If you share the plugin with submodules you can define the version in the root module, otherwise you set the version in the module it’s used. Versions are inherited by submodules, but you can also override versions in submodules if needed.
Apply: You can choose to apply or not apply plugins using apply. This is good in cases where you want to define the plugin globally in the root project, but don’t want to actually use it in the root module. Submodules that declare this plugin will automatically have it applied.
KMP Note: Plugins defined in a module apply to all sourcesets. For example if you include the
id("org.jetbrains.kotlin.id")
plugin, then it will try to apply that plugin to your
iosMain
sourceset and cause an error.
Managing plugin
Second, we define where it’s coming from.
// settings.gradle pluginManagement { repositories { google() mavenCentral() gradlePluginPortal() } }
You need to define where the plugins come from, otherwise Gradle has no idea what you’re talking about. By default Gradle checks for plugins at the gradlePluginPortal. If the plugin you’re using is in another repo you can define it in the
pluginMagement
block. The
pluginManagement
block is where you set the repositories your plugins come from. Additionally you can set plugins here as well, using the same syntax as mentioned above. We’ll go over maven in a future post but for now know that
mavenCentral
is a popular repository used for plugins and dependencies.
Legacy
buildscript { repositories { mavenCentral() } dependencies { classpath( "org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.20" ) } } apply(plugin = "org.jetbrains.kotlin.multiplatform")
Legacy is a little different. Instead of
pluginManagement
we use
buildScript
.
Repositories
are the same, but note there’s a
Repositories
block in this version. This is where you define classpaths, which are dependencies for plugins.
Personal recommendation
There’s a lot of different ways of defining plugins, but as of May, 2023, here is what I would recommend:
- Follow the android guidelines
- Define all plugin information settings.gradle
settings.gradle
usingpluginManagementpluginManagement
, with versions, but set apply to false. - Then include plugins in submodules, but without the version
Flashcards
Here are some quick references to code surrounding Gradle plugins
Blocks
- plugins
plugins
: Where you define the plugins you want to use (More Info) - repositories
repositories
: A block that tells Gradle where to look for items (More Info) - pluginManagement
pluginManagement
– Where you define the project’s plugins, containspluginsplugins
andrepositories blocksrepositories blocks
. (More Info) - BuildScript
BuildScript
: (Legacy for plugin) Definesrepositoriesrepositories
and dependencies for adding plugins. Can also be used to add variables such as versions that are used across the project (More Info)
Plugins
- id("id")
id("id")
: Add a plugin with a group ID and a name (ex: “com.android.library”) (More Info) - kotlin("id")
kotlin("id")
: Kotlin simply means we’re using the “org.jetbrains.kotlin” group ID - version("version")
version("version")
: Setting the version of the plugin, required at some module level (More Info) - apply(boolean)
apply(boolean)
: Whether to apply the plugin or not. Useful if you want to define the plugin in the root module, but only use it in other certain submodules (More Info)
Legacy
- classpath
classpath
: A dependency for the plugins you want to add,classpathclasspath
is used in thebuildscriptbuildscript
block - apply("id")
apply("id")
: The legacy way to add a plugin
Repositories
- gradlePluginPortal()
gradlePluginPortal()
: The default Gradle plugin portal (https://plugins.gradle.org/). If no repository is defined for plugins then Gradle will use this as a default (More Info) - mavenCentral()
mavenCentral()
: The Central Maven Repository (https://repo1.maven.org/maven2/) (More Info)
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK