Gradle Kotlin DSL multi project build with Java Modules - gradle

I'm creating a new project (using IntelliJ IDEA) that will be using:
Gradle as the build system
Kotlin DSL for build scripts
Java 9 modules for "organisation"
Kotlin as the primary language
I'm having problems setting up Gradle to properly build my project. Most examples I've found are for Groovy and not Kotlin DSL, and most only cover some of the features I want, but not all.
Right now I have two modules, core and lib, where the core module requires the lib module. My gradle build scripts are:
build.gradle.kts
plugins {
base
kotlin("jvm") version "1.3.41" apply false
}
subprojects {
afterEvaluate {
tasks.withType<JavaCompile> {
inputs.property("moduleName", extra["moduleName"])
options.compilerArgs.addAll(arrayOf("--module-path", classpath.asPath))
classpath = files()
}
}
repositories {
mavenCentral()
jcenter()
}
}
core/build.gradle.kts
extra.set("moduleName", "myproject.core")
plugins {
kotlin("jvm")
}
dependencies {
compile(kotlin("stdlib"))
compile(project(":networking"))
}
lib/build.gradle.kts
extra.set("moduleName", "myproject.lib")
plugins {
kotlin("jvm")
}
dependencies {
compile(kotlin("stdlib"))
}
Doing this, configuration fails with:
A problem occurred configuring project ':core'.
Cannot get property 'moduleName' on extra properties extension as it does not exist
If I remove the inputs.property() line the configuration succeeds, but the core compilation fails (lib compiles successfully) with :
Task :core:compileKotlin
e: Module myproject.lib cannot be found in the module graph
I assume the issue is is my root build.gradle.kts, but I cannot figure out how to make it work. Googling around, Kotlin DSL for Gradle is somewhat new and not as widely used, and documentation is pretty scarce.
Any advice would be appreciated!

Naturally after posting the question I found the solution. There exists a Gradle plugin that does exactly what's needed in this situation, with a KotlinDSL example: https://github.com/java9-modularity/gradle-modules-plugin/tree/master/test-project-kotlin
Using the plugin, all I needed to do is change the root build.gradle.kts file:
plugins {
base
kotlin("jvm") version "1.3.41" apply false
id("org.javamodularity.moduleplugin") version "1.5.0" apply false
}
subprojects {
apply(plugin = "org.javamodularity.moduleplugin")
repositories {
mavenCentral()
jcenter()
}
}
Note: Make sure that your module-info.java file is in the java src folder, and not in the kotlin src folder, otherwise the plugin will not detect the module.

Related

Gradle precompiled script plugin: External Quarkus plugin dependency not found

Background
I am currently developing a gradle multi-project with multiple quarkus microservices. In order to bundle my quarkus dependencies I use a precompile script plugin with kotlin-dsl. Given the configuration below, executing quarkusBuild works fine.
Problem
Executing the quarkusDev task for a microservice subproject fails with
Unable to find quarkus-gradle-plugin dependency in project ':microservice'
Do you have any idea why this happens? I have put hours into this and I still do not see why it fails. https://github.com/quarkusio/quarkus/issues/12509 seems to be related, but the suggested solution did not work for me. Any help is greatly appreciated!
Edit
I realize there might be a difference between gradle.plugin.io.quarkus:quarkus-gradle-plugin:2.2.3.Final and io.quarkus:gradle-application-plugin:2.2.3.Final, but swapping the dependencies doesnt help much.
Configuration
This is a minimal version of my project which allows to reproduce the error.
This minimal example can also be checked out here: https://github.com/lorenzjosten/gradle-plugin-quarkus
rootProject
- buildSrc
- src/main/kotlin
quarkus-conventions.gradle.kts
build.gradle.kts
settings.gradle.kts
gradle.properties
- microservice
- src/...
build.gradle.kts
build.gradle.kts
settings.gradle.kts
gradle.properties
rootProject/buildSrc/src/main/kotlin/quarkus-conventions.gradle.kts
plugins {
java
id("io.quarkus")
}
val quarkusUniverseBomVersion: String by project
dependencies {
implementation(enforcedPlatform("io.quarkus:quarkus-universe-bom:$quarkusUniverseBomVersion"))
implementation("io.quarkus:quarkus-kotlin")
implementation("io.quarkus:quarkus-resteasy-reactive")
implementation("io.quarkus:quarkus-resteasy-reactive-jackson")
implementation("io.quarkus:quarkus-hibernate-reactive-panache")
implementation("io.quarkus:quarkus-reactive-pg-client")
implementation("io.quarkus:quarkus-smallrye-reactive-messaging-amqp")
implementation("io.quarkus:quarkus-arc")
testImplementation("io.quarkus:quarkus-junit5")
}
rootProject/buildSrc/build.gradle.kts
val quarkusPluginVersion: String by project
plugins {
`kotlin-dsl`
}
repositories {
mavenCentral()
maven("https://plugins.gradle.org/m2/")
gradlePluginPortal()
}
dependencies {
implementation("io.quarkus:gradle-application-plugin:${quarkusPluginVersion}")
}
rootProject/buildSrc/gradle.properties
quarkusPluginVersion=2.3.0.Final
rootProject/microservice/build.gradle.kts
plugins {
id("quarkus-conventions")
}
rootProject/settings.gradle.kts
include("microservice")
rootProject/build.gradle.kts
plugins {
idea
}
repositories {
mavenCentral()
maven("https://plugins.gradle.org/m2/")
gradlePluginPortal()
}
allprojects {
apply(plugin = "idea")
idea {
module {
isDownloadSources = true
isDownloadJavadoc = true
}
}
}
rootProject/gradle.properties
quarkusUniverseBomVersion=2.2.3.Final
The Gradle plugin likely cannot find the Java dependency:
// https://mvnrepository.com/artifact/io.quarkus/quarkus-universe-bom
implementation("io.quarkus:quarkus-universe-bom:2.2.3.Final")
It was a bug that should be fixed with quarkus release version 2.4.CR1
See Github issues
https://github.com/quarkusio/quarkus/issues/20595
https://github.com/quarkusio/quarkus/issues/20531

How to change name of java library when build with gradle?

I'm trying to build a java library for my other java projects. I'm also trying to learn gradle. There is a tutorial : https://docs.gradle.org/current/samples/sample_building_java_libraries.html shows how to build libraries with gradle.
But somehow when I use gradlew build it always gives me lib-< version >.jar and creates a folder called lib and I can't change it.
This is my settings.gradle
rootProject.name = 'myOwnLibrary'
include('lib')
this is my build.gradle (inside lib folder)
plugins {
// Apply the java-library plugin for API and implementation separation.
id 'java-library'
}
version = "0.1.1"
tasks.named('jar') {
manifest {
attributes('Implementation-Title': project.name,
'Implementation-Version': project.version)
}
}
repositories {
// Use JCenter for resolving dependencies.
jcenter()
}
dependencies {
// Use JUnit test framework.
testImplementation 'junit:junit:4.13'
// This dependency is exported to consumers, that is to say, found on their compile classpath.
api 'org.apache.commons:commons-math3:3.6.1'
// This dependency is used internally, and not exposed to consumers on their own compile classpath.
implementation 'com.google.guava:guava:29.0-jre'
}
With Kotlin DSL example, you can add in your tasks jar the following snippet:
tasks.jar {
manifest {
attributes(mapOf("Implementation-Title" to rootProject.name,
"Implementation-Version" to project.version))
}
archiveBaseName.set(rootProject.name)
}
where rootProject.name, is the value localized into settings.gradle.kts file.

Gradle share properties in multi-project

I'm quite new to Gradle, trying to make multi-project. In root project declares all common libs (also their versions as properties) and apply plugins.
For example, root and child common projects.
In root's settings.gradle type:
rootProject.name = 'root'
include 'common'
In root's build.gradle type:
buildscript {
ext.kotlin_version = '1.3.11'
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
subprojects {
buildscript {
repositories {
mavenCentral()
}
}
apply plugin: 'kotlin'
repositories {
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}
}
And now I'd like to use another library only in specific child project. Do this in common's build.gradle:
buildscript {
dependencies {
classpath "org.jetbrains.kotlin:kotlin-allopen:$kotlin_version"
}
}
It's work fine when running gradle commands from root's folder, but failed with message Could not get unknown property 'kotlin_version' for object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler when running from common's folder.
What I'm doing wrong? Or is there any way around? And what are best practices for sharing libs and properties in multi-project?
For me, it looks like common know nothing about it's "parent" project, all relations defined in root's settings.
The reason why Gradle cannot resolve the property is because the project in folder common is named commons. This is caused by a spelling mistake in common's settings.gradle. This is fortunately easy to fix (common/settings.gradle) :
rootProject.name = 'common'
Alternatively, just delete the common/settings.gradle, it's fully optional in this case.
Consider reading the official Gradle documentation for authoring multi-project builds and the guide create multi-project builds for more information and best practices around multi-project builds.

Kotlin Gradle DSL - Precompiled script in buildSrc not working

I am using Gradle version 4.10.3 (need Android support) and am trying to put a test precompiled script into my buildSrc folder for use with various modules within the project. Here is my basic code setup:
//maven-deploy.gradle.kts, a custom precompiled plugin under
// buildSrc\src\main\kotlin\maven-deploy.gradle.kts
plugins {
maven
signing
}
//a test task
tasks {
register("hello") {
doLast {
println("hello")
}
}
}
//buildSrc build.gradle.kts
plugins {
`kotlin-dsl`
`kotlin-dsl-precompiled-script-plugins`
}
repositories {
jcenter()
}
//main project root's build.gradle.kts
plugins {
base
kotlin("jvm") version Vof.kotlin apply false
kotlin("android") version Vof.kotlin apply false
kotlin("android.extensions") version Vof.kotlin apply false
id("kotlinx-serialization") version Vof.kotlin apply false
id("maven-deploy")
}
and I'm getting this error:
error:Plugin [id: 'maven-deploy'] was not found in any of the following sources:
- Gradle Core Plugins (not a core plugin, please see https://docs.gradle.org/4.10.3/userguide/standard_plugins.html for available core plugins)
- Plugin Repositories (plugin dependency must include a version number for this source)
Am I doing this incorrectly? I am following this guide on the Gradle website. Is this outdated? Any help is appreciated!
EDIT: I got this working by adding java-gradle-plugin (with tildes) to the buildSrc's build.gradle.kts file under plugins. Not sure if that is the correct way to go about this, however.

How to configure a plugin to depend on a specific version of gradle?

I am writing a set of Gradle plugins, but I want to control the specific versions of groovy and gradle that are used.
I don't want the plugins to depend on whatever versions of Gradle/Groovy are installed, like the following would do:
dependencies {
compile localGroovy()
compile gradleApi()
}
Another reason I don't want to use the local method - when you use a proper dependency specification, Gradle then knows about the source code for those libs and the IDE plugins can hookup the source automatically.
Below are the relevant sections of my build script:
allprojects { Project iProject ->
apply plugin: 'idea'
apply plugin: 'maven'
repositories {
jcenter()
}
}
subprojects { Project iProject ->
apply plugin: 'groovy'
dependencies {
compile 'org.codehaus.groovy:groovy-all:2.3.2'
}
}
project(':eclipsei2g') {
group = 'eclipsei2g'
version = '0.0.1-SNAPSHOT'
dependencies {
compile 'org.gradle:gradle-core:2.0'
}
}
project(':g2idea13') {
group = 'g2idea13'
version = '0.0.1-SNAPSHOT'
dependencies {
compile 'org.gradle:gradle-core:2.0'
compile 'org.gradle-plugins:gradle-ide:2.0'
}
}
When I run this I get an error resolving the gradle-ide dependency:
Could not resolve all dependencies for configuration ':g2idea13:compile'.
> Could not find org.gradle:gradle-ide:2.0.
Searched in the following locations:
http://jcenter.bintray.com/org/gradle/gradle-ide/2.0/gradle-ide-2.0.pom
http://jcenter.bintray.com/org/gradle/gradle-ide/2.0/gradle-ide-2.0.jar
Required by:
g2idea13:g2idea13:0.0.1-SNAPSHOT
There doesn't seem to be anything on the jcenter repository since 0.9 for the plugins stuff.
I also tried 'org.gradle:gradle-ide:2.0'.
Is this even how I should be doing this? Is there another way to specify a specific gradle version? Am I just using the wrong repository? I couldn't even get gradle-core to resolve on mavenCentral(). Is there an official Gradle repository somewhere that I should be using?
gradleApi() is the way to go. There isn't currently a public list of dependencies for Gradle plugins.

Resources