0% found this document useful (0 votes)
2 views

Build Systems

The document provides an overview of Kotlin build systems, focusing on Maven and Gradle. It explains key concepts such as project configuration, dependency management, and task execution within these systems. Additionally, it highlights the structure of Gradle projects and the use of plugins for enhanced functionality.

Uploaded by

Triveni Patle
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views

Build Systems

The document provides an overview of Kotlin build systems, focusing on Maven and Gradle. It explains key concepts such as project configuration, dependency management, and task execution within these systems. Additionally, it highlights the structure of Gradle projects and the use of plugins for enhanced functionality.

Uploaded by

Triveni Patle
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 29

Kotlin

Build
Systems

@kotlin | Developed by JetBrains


What? Why?

Build system – Software that automates the process of getting some kind of an artifact (executable,
library) from the source code. Build systems can be used for:

● Configuring your build once and using it forever (copy-paste into new projects)
● Unifying builds and reusing logic in various projects
● Dependencies management*
● Testing and verification
● Incremental builds*
How?
Maven

pom.xml

xml Project Object Model

Declarative: You define the configuration without specifying how to achieve it.
Convention: You describe what you need with specific rules.
Lifecycle: It can support everything from compilation to tests and so on.
Plugins allow you to do the unconventional heavy-lifting.
Coordinates are located in pom.xml: groupId, artifactId, version.
Repositories: You can load (and cache) the dependencies on demand.
Learn more: search.maven.org (Maven Central)
pom.xml
<project xmlns="http:</maven.apache.org/POM/4.0.0" xmlns:xsi="http:</www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http:</maven.apache.org/POM/4.0.0 http:</maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>

<properties>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>

<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Gradle

build.gradle

gradle settings.gradle

DSL: It uses Kotlin or Groovy instead of XML.


Tasks: You can define actions which might depend on each other and be quite complex.
Plugins provide unconventional predefined tasks to do the heavy-lifting.
Modules have independent compilation units. Each unit is built into a separate JAR (or some other kind of artifact).
Repositories: You can reuse Maven repositories.
Dependency Management: You can easily declare and resolve dependencies.
Language Agnostic: Gradle can be used for Kotlin, Java, Scala, C++, JS, and COBOL.
Learn more: docs.gradle.org
Gradle project structure
├── gradle
│ └── wrapper Don’t push
│ ├── gradle-wrapper.jar to GitHub
│ └── gradle-wrapper.properties
├── src
├── build.gradle.kts / build.gradle
├── gradle.properties
├── gradlew
├── gradlew.bat
└── settings.gradle.kts / settings.gradle

● Gradle root project == IntelliJ IDEA project

● Gradle project != IntelliJ IDEA project

● Gradle module != IntelliJ IDEA module

● Gradle project ~ IntelliJ IDEA module

● Gradle root project might have subprojects that have subprojects and so on

● Tasks may be defined in any project


Gradle DSL

Fill out the build.gradle or plugins {


kotlin("jvm") version "1.7.10"
build.gradle.kts file to set up the
}
project.
repositories {
mavenCentral()
}

dependencies {
implementation(kotlin("stdlib"))
}

tasks {
withType<JavaCompile> {
targetCompatibility = "11"
}
}
Gradle repositories

Specify where to find the libraries needed by the project. The search is carried out from top to bottom

repositories {
mavenCentral()
google()
maven {
url = uri("https://your.company.com/maven")
credentials {
username = "admin"
Don’t push the credentials to GitHub, please!
password = "12345"
}
Use secrets, environmental variables, etc.
}
flatDir {
dirs("libraries")
}
}
Gradle dependencies

● compilationOnly – Used only during compilation


● runtimeOnly – Used only during runtime
● implementation – Used in both
● api – Dependency “leaks”, meaning you can access its dependencies

● testCompilationOnly
● testRuntimeOnly
● testImplementation
● testApi
Gradle dependencies
val ktorVersion: String = "6.6.6"

dependencies {
// string notation, e.g. group:name:version
implementation("commons-lang:commons-lang:2.6")
implementation("io.ktor:ktor-serialization-jackson:$ktorVersion")
// map notation:
implementation("org.jetbrains.kotlinx", "kotlinx-datetime", "7.7.7")
// dependency on another project
implementation(project(":neighborProject"))
// putting all jars from 'libs' onto the compile classpath
implementation(fileTree("libs"))
// api dependency – internals are accessible
api("io.ktor:ktor-server-content-negotiation:$ktorVersion")
// test dependencies
testImplementation("org.jetbrains.kotlin:kotlin-test-junit")
testImplementation(kotlin("test"))
}
Gradle dependencies
dependencies {
implementation("org.hibernate:hibernate") {
version {
// If there is a version conflict, strictly select version "3.1" of hibernate
strictly("3.1")
}
exclude(module = "cglib") // by artifact name
exclude(group = "org.jmock") // by group
exclude(group = "org.unwanted", module = "buggyModule") // by both
// disabling all transitive dependencies of this dependency
isTransitive = false
}
}
BOM

There are direct and transitive dependencies, which may lead to version conflicts.
myProject /> thing:1.0 /> anotherThing:1.1
myProject /> thirdThing:1.0 /> anotherThing:1.2

Maven’s Bill Of Materials (BOM) offers a solution.


val ktorVersion: String = "2.0.0"

dependencies {
implementation(enforcedPlatform("io.ktor:ktor-bom:$ktorVersion"))
implementation(enforcedPlatform("io.ktor:ktor-server-core"))
implementation(enforcedPlatform("io.ktor:ktor-server-netty"))
}
Gradle tasks
Partial task graph for a standard
Java build
A task is a set of instructions for Gradle to perform:
● Compile the source code compileJava processResources

● Run tests
● Build a JAR
classes
● Publish to Maven (or somewhere else)
● Etc.
test jar

There are default tasks, tasks from plugins, and your custom
tasks. check assemble

The most popular tasks are init, wrapper, build, clean,


test build

For all available tasks, see ./gradlew tasks


Gradle tasks

// build.gradle.kts – buildfile
tasks.create<Copy>("copy") {
description = "Copies sources to the destination directory"
group = "Custom"

from("src")
into("dst")
}

Older versions of Gradle only support the create(…) API, which eagerly creates and configures tasks
when it is called and should be avoided. You can use register(//.) instead.
Gradle tasks

Kotlin (and Groovy) are actually too powerful to be build configuration languages.

tasks.register("Fib") { > Task :Fib


var first = 0 What is going on?
var second = 1 Result = 89
doFirst {
println("What is going on?")
for (i in 1/.11) {
second += first
first = second - first
}
}
doLast {
println("Result = $first")
}
}
Gradle tasks
abstract class FibonacciTask : DefaultTask() {
@get:Input
abstract val n: Property<Int>

@TaskAction
fun execute() {
if (n.get() < 0) {
throw StopExecutionException("n must be non-negative")
}
var first = 0
var second = 1
for (i in 1/.n.get()) {
second += first
first = second - first
} tasks.register<FibonacciTask>("Fib_11") {
println("Result = $first") n.set(11)
} }
}
Gradle tasks

Tasks can have dependencies on each other.

tasks.withType<Test> {
dependsOn(tasks.withType<PublishToMavenLocal>{}, "jar_name")
}

All PublishToMavenLocal tasks will be executed before all Test tasks


Gradle plugins

Plugin – A set of tasks that help deal with something specific: Kotlin, Java, Protobuf, etc.
Plugins block is compiled separately before everything else. Artifacts are placed in the classpath,
which allows the IDE to provide auto-completion and other useful features.
`apply false` is useful when you need the plugin for some subprojects.

plugins {
kotlin("jvm") version "1.7.10"
application // A plugin that runs a project as a Java application
id("org.jlleitschuh.gradle.ktlint") version "10.3.0" apply false
}
Gradle plugins

// projectRoot/build.gradle.kts
class SamplePlugin : Plugin<Project> {
override fun apply(target: Project) {
target.tasks.register("pluginTask") {
doLast { println("A plugin task was called") }
}
}
}

apply<SamplePlugin>()
Gradle plugins
// projectRoot/buildSrc/build.gradle.kts // projectRoot/buildSrc/src/main/kotlin/SamplePlugin.kt
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import org.gradle.api.XXX

plugins { abstract class SampleTask : DefaultTask() {


kotlin("jvm") version "1.7.10" init {
`java-gradle-plugin` description = "Just a sample template task"
} group = "custom"
}
gradlePlugin {
plugins { @get:Input
create("samplePlugin") { @get:Option(description = "Whom to greet?")
id = "sample" abstract val username: Property<String>
implementationClass = "SamplePlugin" // property `name` is reserved ;^)
}
} @TaskAction
} fun greet() {
logger.lifecycle("Name is: ${username.orNull}")
repositories { println("Hello, ${username.orNull}!")
mavenCentral() }
} }
Gradle plugins

// projectRoot/buildSrc/src/main/kotlin/SamplePlugin.kt [CONTINUED]

class SamplePlugin : Plugin<Project> {


override fun apply(target: Project) {
target.tasks.register("PluginTask", SampleTask/:class.java) { task />
task.username.set("world")
}
}
}
Gradle properties

Properties are used to configure the behavior of Gradle itself and specific projects.
From highest to lowest precedence:
● Command-line flags, such as /-build-cache

● Properties stored in a local gradle.properties file.

● Properties stored in the ~/.gradle/gradle.properties file.

● Gradle properties, such as org.gradle.caching=true, which are typically stored in a


gradle.properties file in a project root directory or GRADLE_USER_HOME environment
variable.

● Environment variables

For all available properties, see ./gradlew properties


Gradle properties
// gradle.properties
kotlin.code.style=official
username=student

// build.gradle.kts
val username: String by project
val kotlinCodeStyle = project.property("kotlin.code.style") as String
tasks.register("printProps") {
doLast {
println(username)
println(kotlinCodeStyle)
println(System.getProperty("idea.version"))
}
}
Gradle settings

Before Gradle assembles the projects for a build, it creates a Settings instance and loads the
settings file into it. Only one settings file is stored in the Gradle project, and it is used to:

● add subprojects to the build

● modify the parameters from the command line, e.g., add a new project property

● access the global Gradle object to register lifecycle handlers


Gradle settings
// settings.gradle.kts
rootProject.name = "Project’s name"
include(
"Module1",
"Module2"
)

// Include a repository from GitHub


sourceControl {
gitRepository(URI.create("Repository URL")) {
producesModule("Module")
}
}
Gradle wrapper

A Gradle wrapper (gradlew) is a shell script that downloads and caches the required version of Gradle.
● gradlew – used in *nix
● gradlew.bat – used in Windows

The version is specified in projectRoot/gradle/wrapper/gradle-wrapper.properties:


distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
Gradle can do so much more!

Gradle support many additional features which we won’t be covering today:

● Caching
● Multi-module projects
● More blocks:
○ allprojects { } and subprojects { }
○ publishing { }
○ artifacts { }
● Compatibility
● Resolution strategies
● Source sets
Thanks!

@kotlin | Developed by JetBrains

You might also like