Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Include scripts with Gradle Kotlin DSL

I'm trying to start using Kotlin DSL with gradle in the project with the following restrictions:

  • Project has different modules (moreover: sometimes these modules use different plugins, however if two projects uses the same plugin then version of the plugins are the same).
  • Project has internal corporate repositories only (e.g. we don't use jcenter directly, we use proxy for it).

What we have with Groovy:

  • Some common configurations items are excluded to the separate scripts. Please check the example below.
  • Gradle modules include these files.

As a result (just based on my example):

  • We don't need to add the same code lines into the each module.
  • The most of projects have difference just with dependency list.

I tried to reproduce the same with Gralde KTS and received the following difficulties:

  • I'm unable to apply plugin in the include file and use it in the module. In this case I receive compilation error (because plugin types are not added into the module script).
  • I'm unable to extract constants to the something common to use them in the each scripts (root build.gradle.kts inclusive). With Groovy I can just use variable like springBootVersion, however with Kotlin Script I have to create the same property in the each module file.
  • Precompiled script plugins does not work without public repositories access (e.g. I'm unable to configure common script file with idea "just use default embedded Kotlin Script version, download all dependencies from these urls: ...".

Include file sample:

apply plugin: 'kotlin'

compileKotlin {
    kotlinOptions {
        jvmTarget = "1.8"
    }
}

compileTestKotlin {
    kotlinOptions {
        jvmTarget = "1.8"
    }
}

Gradle module sample:

apply from: "${rootDir}/gradle/include/kotlin-common-include.gradle"

dependencies {
    compile project(':my.project.libraries.common') 

    compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: springBootVersion
}

Questions:

  • How can I put all common constants (such as dependency versions) to the separate file to include them just by using something like springBootVersion or Constants.springBootVersion with compile-time checks?
  • How can I extract plugin applying to the include scripts (to avoid Gradle module scripts overload)?
  • How can I use precompiled script plugins without public global repositories access?

Additional links:

  • Issue for Gradle KTS for plugin applying.
  • Issue for Gradle KTS for shared constants extracting.
like image 754
Manushin Igor Avatar asked Mar 25 '19 10:03

Manushin Igor


1 Answers

There are limitations in Kotlin DSL currently (5.3) that prevents to have compile-time checks everywhere. In order for Kotlin DSL to work it has to add extensions on top of the Gradle API and it can't do it magically. First of all you need to go through Kotlin DSL Primer page to understand it.

How can I extract plugin applying to the include scripts (to avoid Gradle module scripts overload)?

The one way to do it is to use precompiled build scripts with Kotlin DSL Plugin. In order to do it you need to move your script into $rootDir/buildSrc project. Here how it might look like:

// $rootDir/buildSrc/build.gradle.kts
plugins {
  `kotlin-dsl`
}
repositories {
   maven {
     url = uri("http://host:8082/artifactory/...")
  }
}

Then put your common script like that:

// $rootDir/buildSrc/src/main/kotlin/common.gradle.kts
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
  kotlin("jvm") version "1.3.21"
}
tasks.compileKotlin {
  kotlinOptions.jvmTarget = "1.8"
}
tasks.compileTestKotlin {
  kotlinOptions.jvmTarget = "1.8"
}

Then you can apply this script as to a plugin like that:

// $rootDir/build.gradle.kts
subprojects {
  apply(id = "common")
}

How can I use precompiled script plugins without public global repositories access?

Configuring custom repositories for pre-compiled scripts plugin is no different that your usual build script. Do it like that:

// $rootDir/buildSrc/settings.gradle.kts
pluginManagement {
  repositories.maven {
    url = uri("http://host:8082/artifactory/...")
  }
}

The other way around that if you don't want to use precompiled plugins is to configure extensions explicitly. You can do it like that:

// $rootDir/gradle/common.gradle.kts
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
tasks.withType<KotlinCompile> {
  kotlinOptions.jvmTarget = "1.8"
}

And in main script:

// $rootDir/build.gradle.kts
subprojects {
  apply {
    plugin(KotlinPlatformJvmPlugin::class)
    from("common.gradle.kts")
  }
}

How can I put all common constants (such as dependency versions) to the separate file to include them just by using something like springBootVersion or Constants.springBootVersion with compile-time checks?

There is no good way to do it currently. You can use extra properties, but it won't guarantee compile time checks. Something like that:

// $rootDir/dependencies.gradle.kts

// this will try to take configuration from existing ones
val compile by configurations
val api by configurations
dependencies {
  compile("commons-io:commons-io:1.2.3")
  api("some.dep")
}

// This will put your version into extra extension
extra["springBootVersion"] = "1.2.3"

And you can use it like this:

// $rootDir/build.gradle.kts
subprojects {
  apply {
    plugin<JavaLibraryPlugin>()
    from("$rootDir/dependencies.gradle.kts")
  }

And in your module:

// $rootDir/module/build.gradle.kts
// This will take existing dependency from extra
val springBootVersion: String by extra
dependencies {
  compile("org.spring:boot:$springBootVersion")
}
like image 198
Izbassar Tolegen Avatar answered Oct 20 '22 12:10

Izbassar Tolegen