6

Gradle Cheat Sheet for Android and KMP Projects - Plugins – Touchlab | Kotlin Mu...

 1 year ago
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.
neoserver,ios ssh client

Gradle Cheat Sheet for Android and KMP Projects – Plugins

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:

  1. The Gradle wrapper is downloaded based on the
    gradle-wrapper.properties
    gradle-wrapper.properties
  2. The build detects the
    settings.gradle
    settings.gradle file and evaluates to determine which projects participate.
  3. Project instances are created for every project and their
    build.gradle
    build.gradle scripts are all evaluated.
  4. A task graph for requested tasks is created.
  5. 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

settings.gradle then goes through each submodule defined in the settings, and runs their

build.gradle

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 runs
    build.gradle
    build.gradle of each submodule
    • settings.gradle
      settings.gradle or
      build.gradle
      build.gradle resolves plugins
    • build.gradle
      build.gradle checks for blocks to run (such as
      android
      android and
      kotlin
      kotlin) and runs them
    • Those blocks resolve
      dependencies
      dependencies

The order I like to think of this is:

Settings.gradle

Settings.gradle ->

build.gradle

build.gradle ->

plugins

plugins ->

blocks

blocks ->

dependencies

dependencies

So with that in mind, we’ll first go over plugins, then common

kotlin

kotlin and

android

android blocks, then dependencies, and finally wrap back to some notes about the

settings.gradle

settings.gradle. Gradle Source

Note: Gradle script files can come in two different extensions based on the chosen DSL:

.gradle

.gradle for Groovy DSL and

.gradle.kts

.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 directories
    build.gradle
    build.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
// 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
// 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
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")

kotlin("multiplatform") allows you to add the kotlin block containing sourcesets and targets and adds tasks such as

build iosArm64Binaries

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

build.gradle. First, We add the plugin.

// build.gradle
plugins {
id("com.android.library")
kotlin("multiplatform")
.version(1.8.10) // Optional*
.apply(false) // Optional
// build.gradle
plugins {
    id("com.android.library")
    kotlin("multiplatform")
        .version(1.8.10)  // Optional*
        .apply(false)     // Optional
}

Plugins are added in the

plugins

plugins block, which can either be added to a

build.gradle

build.gradle or to a

pluginManagement

pluginManagement block in the

settings.gradle

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 calling
    id("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")

id("org.jetbrains.kotlin.id") plugin, then it will try to apply that plugin to your

iosMain

iosMain sourceset and cause an error.

Managing plugin

Second, we define where it’s coming from.

// settings.gradle
pluginManagement {
repositories {
google()
mavenCentral()
gradlePluginPortal()
// 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

pluginMagement block. The

pluginManagement

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

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")
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

pluginManagement we use

buildScript

buildScript.

Repositories

Repositories are the same, but note there’s a

Repositories

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 using
    pluginManagement
    pluginManagement, 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

Full Coverage

  • 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, contains
    plugins
    plugins and
    repositories blocks
    repositories blocks. (More Info)
  • BuildScript
    BuildScript: (Legacy for plugin) Defines
    repositories
    repositories 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,
    classpath
    classpath is used in the
    buildscript
    buildscript block
  • apply("id")
    apply("id"): The legacy way to add a plugin

Repositories


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK