How do you disable distZip in a multi project builds on Kotlin DSL in Gradle - gradle

I have set up a Gradle multi project build using Kotlin DSL. This is build.gradle.kts in the root:
plugins {
kotlin("jvm") version "1.2.70" apply false
}
allprojects {
repositories {
mavenCentral()
}
}
subprojects {
version = "1.0"
}
This is sub/build.gradle.kts in my sub project:
plugins {
application
kotlin("jvm")
}
application {
mainClassName = "me.package.MainKt"
}
dependencies {
compile(kotlin("stdlib"))
compile("io.github.microutils:kotlin-logging:1.6.10")
compile("ch.qos.logback:logback-classic:1.2.3")
}
When I run $ gradle build the application plugin creates me a distribution in sub/build/distribution.
I don't need the zip distribution and I want no version number in the tar distribution. Both should be trivial in the regular build.gradle like:
distZip.enabled = false
distTar.archiveName = "${project.name}.tar"
Whatever I try using Kotlin DSL, I get Unresolved reference: distZip. How do I address the distZip and distTar tasks?

What you need is:
val distZip by tasks
distZip.enabled = false
val distTar by tasks
distTar.archiveName = "${project.name}.tar"
or:
tasks.getByName<Zip>("distZip").enabled = false
tasks.getByName<Tar>("distTar").archiveName = "${project.name}.tar"

Related

How to setup a multi-module gradle project with Quarkus?

A multi-module gradle project with the Quarkus plugin applied in the root build.gradle.kts fails at the :quarkusBuild step with a NoSuchElementException:
> Task :quarkusBuild FAILED
building quarkus jar
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':quarkusBuild'.
> java.util.NoSuchElementException
The root build.gradle.kts is like so:
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
kotlin("jvm") version "1.3.72"
id("io.quarkus") version "1.9.1.Final"
}
group = "org.example"
version = "1.0-SNAPSHOT"
allprojects {
repositories {
mavenCentral()
}
}
subprojects {
apply {
plugin("kotlin")
}
dependencies {
implementation(kotlin("stdlib"))
}
}
However move the line id("io.quarkus") version "1.9.1.Final" to the sub projects' build.gradle.kts and the build succeeds. It seems that the quarkus build step is run where the plugin is declared, rather than where it is actually applied.
Ideally I want to declare the plugin once in the root, then apply it to subprojects only, not have it execute against the root project, where there's obviously nothing to build.
Any ideas?
You need to add apply false
plugins {
kotlin("jvm") version "1.3.72" apply false
id("io.quarkus") version "1.9.1.Final" apply false
}
https://docs.gradle.org/current/userguide/plugins.html#sec:subprojects_plugins_dsl
Your build also assumes that every sub-module will be a Kotlin module which may or may not be true. You can do something a little more like this to apply specific configurations to specific tasks:
subprojects { subproject ->
subproject.tasks.withType(JavaCompile).configureEach {
sourceCompatibility = JavaVersion.VERSION_11
}
subproject.tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
kotlinOptions {
jvmTarget = JavaVersion.VERSION_11
}
}
}

Running PMD with gradle without compiling

I need to integrate PMD into the build process, so I created a file, 'check.gradle' under a separate directory and added it to the build.gradle which is a main file for the build process.
build.gradle
buildscript {
ext {
sbDir = "${projectDir.parent}"
}
repositories {
mavenCentral()
jcenter()
}
}
allprojects {
repositories {
mavenCentral() // maven { url: 'http://jcenter.bintray.com' }
}
}
apply from: file('../build/pmd/check.gradle')
check.gradle
subprojects {
apply plugin: 'pmd'
pmd {
consoleOutput = true
toolVersion = "6.21.0"
reportsDir = file("pmd/reports")
ruleSets = ["../build/pmd/MyRuleSet.xml"]
ignoreFailures = true
}
}
The code base is written in Java. The problem is that I want to run it before compile happens or i don't want to run it separately as a simple task. Our compile task is pretty complicated, cuz it depends on many libraries.
I am running as like this.
gradlew.bat --build-file bundles/build.gradle check
Is there a way to scan all the java source code (we have 200 bundles - each bundle is packaged with many java files) without compiling java source code?

How to define dependency version only once for whole Gradle multi-module project?

I made a decision to migrate from Dependency Management Plugin to Gradle built-in BOM import support. Since Gradle built-in BOM import support has better performance But
I run into the issue:
I cannot find alternatives for dependency and dependencySet in native Gradle:
dependencyManagement {
dependencies {
dependency("org.springframework:spring-core:4.0.3.RELEASE")
}
}
//or
dependencyManagement {
dependencies {
dependencySet(group:'org.slf4j', version: '1.7.7') {
entry 'slf4j-api'
entry 'slf4j-simple'
}
}
}
and then I could use dependency without version
dependencies {
compile 'org.springframework:spring-core'
}
How can I get the same behavior in naive Gradle? I mean: I'd like to define a version once as I did it when using Dependency Management Plugin
Solution below helps to avoid versions copy-paste. However it isn't the same with Dependency Management plugin.
For Gradle Kotlin Dsl:
You can create buildSrc with you own code, when you can place any constants.
Algorithm:
Create folder buildSrc/src/main/kotlin
Create file buildSrc/src/main/kotlin/Versions.kt with content:
object Versions {
const val junitVersion = "5.5.5" // just example
}
Create file buildSrc/build.gradle.kts with content:
plugins {
`kotlin-dsl`
}
Use the following syntax in your gradle.kts files:
dependencies {
testImplementation("org.junit.jupiter:junit-jupiter:${Versions.junitVersion}")
}
For Gradle Groovy:
Create file gradle.properties
Put versions there with syntax like okhttp_version=4.2.0
Use the following syntax in your gradle files:
dependencies {
compile group: 'com.squareup.okhttp3', name: 'okhttp', version: okhttp_version
}
You can do so on the gradle.properties file. I.e.:
# APPLICATION PROPERTIES
name=projectName
group=com.domain
version=1.0.0
description=A brief description
gradleScripts=https://raw.githubusercontent.com/hexagonkt/hexagon/1.2.0/gradle
# DEPENDENCIES VERSIONS
kotlinVersion=1.3.61
kotlinCoroutinesVersion=1.3.2
Or in settings.gradle if you don't want to create another file:
rootProject.name = "hexagon-contact-application"
gradle.rootProject {
allprojects {
version = "1.0.0"
group = "org.hexagonkt"
description = "Contact application backend api"
}
extensions.gradleScripts = "https://raw.githubusercontent.com/hexagonkt/hexagon/1.0.18/gradle"
extensions.kotlinVersion = "1.3.50"
extensions.kotlinCoroutinesVersion = "1.3.2"
extensions.hexagonVersion = "1.0.21"
extensions.logbackVersion = "1.2.3"
extensions.bcryptVersion="0.8.0"
extensions.javaJwtVersion="3.8.2"
}
And if you want to avoid adding the version variable to all related dependencies, you can create a method in the build file:
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.3.50'
}
apply from: "$gradleScripts/kotlin.gradle"
apply from: "$gradleScripts/service.gradle"
apply from: "$gradleScripts/junit.gradle"
defaultTasks("test")
mainClassName = 'com.hexagonkt.contact.ApplicationKt'
applicationDefaultJvmArgs = ["-Xms64M", "-Xmx2G", "-XX:+UseNUMA", "-XX:+UseParallelGC"]
dependencies {
httpkt(it, "http_server_jetty")
httpkt(it, "store_mongodb")
httpkt(it, "hexagon_web")
implementation("at.favre.lib:bcrypt:$bcryptVersion")
implementation("com.auth0:java-jwt:$javaJwtVersion")
testImplementation("com.hexagonkt:port_http_client:$hexagonVersion")
}
private void httpkt(final def dependencies, final String artifact) {
dependencies.implementation("com.hexagonkt:$artifact:$hexagonVersion")
}

How to ignore gradle build of root project for a multi-project Kotlin Spring Boot application?

Background:
I currently have a multi-module (multi-project) application repo. The "root" is not a runnable application. It's merely the source directory where I have a root build.gradle.kts file which holds the dependencies and plugins that are common between all my sub-projects. Each of my sub-projects have their own build.gradle.kts.
So my overall project structure looks sort of like this:
my_root_project
- gradle
- wrapper
- gradle-wrapper.jar
- gradle-wrapper.properties
- gradle.build.kts
- settings.gradle.kts
- my_nested_project_a
- src
- main
- kotlin
- my_nested_project_b
...
Issue:
Every time I run gradle build, I get an error saying:
> Task :bootJar FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':bootJar'.
> Main class name has not been configured and it could not be resolved
However when I run any one of my sub-projects (e.g. build :my_nested_project_a:build), it builds just fine.
Current Gradle Build Files
Here's what I currently have in the "root" gradle.build.kts:
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
group = "com.example"
version = "1.0.0"
java.sourceCompatibility = JavaVersion.VERSION_1_8
java.targetCompatibility = JavaVersion.VERSION_1_8
plugins {
id("org.springframework.boot") version "2.1.8.RELEASE" apply false
id("io.spring.dependency-management") version "1.0.8.RELEASE" apply false
kotlin("jvm") version "1.3.50"
kotlin("plugin.spring") version "1.3.50"
kotlin("plugin.jpa") version "1.3.50"
kotlin("plugin.allopen") version "1.3.50"
}
allprojects {
repositories {
maven(url = "https://my.company.com/repo/with/all/the/stuff/I/need")
}
apply(plugin = "org.jetbrains.kotlin.jvm")
apply(plugin = "java")
apply(plugin = "org.springframework.boot")
apply(plugin = "io.spring.dependency-management")
apply(plugin = "org.jetbrains.kotlin.plugin.spring")
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
}
tasks.withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = "1.8"
}
}
}
NOTE: I'm using apply false on my plugins because I thought it would keep gradle from trying to find a main class when building using gradle build.
What I'm trying to do:
I have a CI pipeline that I'd like to simply run gradle build which should run the build task for all of the sub-projects. However, in that process, I'd like to ignore running the build for the "root" project or bypass it since it's not a runnable application, and just build the sub-projects.
Any help would be greatly appreciated! :)
If you want to ignore task bootJar,s o add the following configuration.
bootJar {
enabled = false
}
In your root build.gradle.kts, ignore bootJar task, with Kotlin DSL :
import org.springframework.boot.gradle.tasks.bundling.BootJar
tasks.getByName<BootJar>("bootJar") {
enabled = false
}
If you have the plugin applied in allprojects session, you're applying it to the root as well, and since it's the first one resolved in gradle build, you should have the main class configured there.
Alternatively, you can remove the apply(plugin = "org.springframework.boot") line from the root and apply the plugin only to the module that has the main method annotated with #SpringBootApplication, and point the plugin to the main class there.
Say your main class is in my_nested_project_a/src/main/com/example/MainClass.kt.
Your my_nested_project_a/build.gradle.kts should look like:
plugins {
id("org.springframework.boot")
}
springBoot {
mainClassName = "com.example.MainClass"
}
dependencies {
...
}
And you should remove this line from the root build.gradle.kts:
apply(plugin = "org.springframework.boot")
I have a similar setup and question. I replaced allprojects with subprojects and added jar.enabled(false) to the root build.gradle file and it worked.
plugins {
id("java-library")
id('org.jetbrains.kotlin.jvm') version "${kotlinVersion}"
id("com.diffplug.spotless") version "${spotlessVersion}"
id("maven-publish")
}
jar.enabled(false)
subprojects {
apply plugin: "java-library"
apply plugin: "org.jetbrains.kotlin.jvm"
apply plugin: "com.diffplug.spotless"
apply plugin: "maven-publish"
group = GROUP
version = VERSION_NAME
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
dependencies {
testImplementation 'org.jetbrains.kotlin:kotlin-test'
testImplementation("org.junit.jupiter:junit-jupiter:${junitVersion}")
}
publishing {
publications {
library(MavenPublication) {
from components.java
}
}
repositories {
maven {
url "https://gitlab.mhighpoint.com/api/v4/projects/${System.getenv('CI_PROJECT_ID')}/packages/maven"
credentials(HttpHeaderCredentials) {
name = "Job-Token"
value = System.getenv('CI_JOB_TOKEN')
}
authentication {
header(HttpHeaderAuthentication)
}
}
}
}
spotless {
java {
googleJavaFormat() // googleJavaFormat('1.1') to specify a specific version
}
kotlin {
target '**/src/**/*.kt'
ktlint("0.41.0").userData('disabled_rules': 'no-wildcard-imports,import-ordering')
trimTrailingWhitespace()
indentWithSpaces()
endWithNewline()
}
format 'misc', {
target '**/*.gradle'
trimTrailingWhitespace()
indentWithSpaces() // or spaces. Takes an integer argument if you don't like 4
endWithNewline()
}
}
test {
useJUnitPlatform()
}
jar {
archiveBaseName = "${rootProject.name}-${project.name}"
}
tasks {
assemble.dependsOn(spotlessApply)
}
}

Kotlin Quasar example not working

I am testing the Kotlin Quasar actor example.
Quasar and Kotlin – a Powerful Match
So the question is, is this example out of date and is there any documentation in which I can find out how to use Kotlin and Quasar?
This is my gradle.build file.
group 'no.inmeta.kotlin.akka'
version '1.0-SNAPSHOT'
buildscript {
ext.kotlin_version = '1.0.1'
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: 'kotlin'
repositories {
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
compile "co.paralleluniverse:quasar-kotlin:0.7.4"
testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
}
I'm part of the Quasar team.
The post cites Quasar tests which you can run by cloning the Quasar repo and running e.g. gradle :quasar-kotlin:build (requires Gradle installed) but for new projects/experiments I suggest to start instead from the Gradle template, kotlin branch which now uses the latest Kotlin 1.0.1-2 (and for simplicity the latest Quasar 0.7.5-SNAPSHOT that depends on it).
Starting from that template I built this project (more info about how to configure it and run it in the main README) that runs the same Quasar actor tests as normal programs rather than tests. Here's its build.gradle:
group 'no.inmeta.kotlin.akka'
version '1.0-SNAPSHOT'
buildscript {
ext.kotlinVer = '1.0.1-2'
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVer"
}
}
apply plugin: 'kotlin'
apply plugin: 'application'
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
sourceCompatibility = 1.8 // 1.7
targetCompatibility = 1.8 // 1.7
configurations {
quasar
}
configurations.all {
resolutionStrategy {
failOnVersionConflict()
}
}
repositories {
// mavenLocal()
mavenCentral()
maven { url "https://oss.sonatype.org/content/repositories/releases" }
maven { url 'https://oss.sonatype.org/content/repositories/snapshots' }
// maven { url 'https://maven.java.net/content/repositories/snapshots' }
}
ext.classifier = ':jdk8' // ':'
ext.quasarVer = '0.7.5-SNAPSHOT'
dependencies {
compile "co.paralleluniverse:quasar-core:${quasarVer}${classifier}"
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVer"
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlinVer"
compile "co.paralleluniverse:quasar-kotlin:${quasarVer}"
quasar "co.paralleluniverse:quasar-core:${quasarVer}${classifier}#jar"
}
applicationDefaultJvmArgs = [
"-Dco.paralleluniverse.fibers.verifyInstrumentation=true",
"-Dco.paralleluniverse.fibers.detectRunawayFibers=false",
"-javaagent:${configurations.quasar.singleFile}" // =v, =d
]
// mainClassName = 'co.paralleluniverse.kotlin.actors1.PingPongKt'
mainClassName = 'co.paralleluniverse.kotlin.actors2.PingPongWithDeferKt'
task wrapper(type: Wrapper) {
gradleVersion = '2.12'
}
defaultTasks 'run'
Some notes about the differences with your build file:
Since I converted the tests to programs, I'm including the application plugin and its configuration (here, applicationDefaultJvmArgs and mainClassName) as well as setting the default Gradle task to run.
In addition to the above, a gradle wrapper has been generated and pushed so that ./gradlew is all you need on the command line, with no need to have a local Gradle installation (how to run it in an IDE depends on the IDE).
You need to run the Quasar agent (or AoT instrumentation but using the agent here) so there's a quasar configuration pointing to the artifact that is then used to pass the -javaagent:${configurations.quasar.singleFile} JVM argument.
Using Java 8 as Quasar has a specific optimized build for it.
Also note that there is now a 1.0 branch of the quasar-kotlin-jetbrains-webinar project (which is now the HEAD one in fact), which contains the companion source code of this guest webinar with IntelliJ, ported to the latest Kotlin and Quasar as well.
Let me know if this helps.

Resources