Gradle Kotlin DSL - Cannot access 'verbose': it is private in 'CompileOptions' - java

I am trying to set the verbose flag/option to true in the gradle build script (Kotlin DSL).
Gradle throws error that this property is private and not accessible in Kotlin DSL. The same thing works in Groovy DSL though.
Groovy DSL (working)
plugins {
id("java")
}
tasks.named("compileJava") {
options.verbose = true
}
Kotlin DSL (not-working)
plugins {
id("java")
}
tasks.named<JavaCompile>("compileJava") {
options.verbose = true
}
Error
Script compilation error:
Line 32: options.verbose = true;
^ Cannot access 'verbose': it is private in 'CompileOptions'
1 error
I am sure I am missing something. Any help is appreciated. Thanks.

CompileOptions has a setter for verbose, so this will work
tasks.named<JavaCompile>("compileJava") {
options.setVerbose(true)
}
It is also possible to set the flag via property:
tasks.named<JavaCompile>("compileJava") {
options.isVerbose = true
}

Not sure why it is private for Kotlin DSL and not for Groovy DSL, but found an alternative using compilerArgs from this stackoverflow post
tasks.named<JavaCompile>("compileJava") {
val compilerArgs = options.compilerArgs
compilerArgs.add("-verbose")
}
This, to me, feels a bit low-level since we are directly updating the compiler arguments instead of using objects/maps to set them. Will wait for someone to post a better solution (if it exists).

Related

How do we properly create an execution phase tasks?

this is what the ideal build script I have:
I do want to execute tasks "unzip_natives_os" manually. But it seems it only works at config phase. And when I take a test run with this set-up it gives me an error: "java.lang.UnsatisfiedLinkError" but if I change the configuration from "nativesOS" into "runtimeOnly" inside of the dependencies block, it works fine. Do I have to explicitly create this "applicationDefaultJvmArgs" and insert the libraryPath of the natives. Is there any other way? And when I need to unzip the "nativesOS" config it needs an explicit version, it seems it did not see the platform/BOM?
// build.gradle.kts
val nativesOS : Configuration by configurations.creating {
this.isTransitive = false
this.extendsFrom(configurations.runtimeOnly.get())
}
dependencies {
implementation(platform("org.lwjgl:lwjgl-bom:3.2.3"))
listOf(
"", "-assimp", "-openal",
"-opengl", "-glfw"
).map { lib ->
implementation("org.lwjgl:lwjgl$lib")
// I give it an explicit version, because it would not work if I unzip this.
nativeOS("org.lwjgl","lwjgl$lib", "3.2.3", classifier = LWJGL.lwjglNatives)
}
...
}
// unzip_native_os tasks, here is the problem.
tasks.register<Copy>("unzip_native_os") {
this.group = "zip"
doLast {
nativesOS.asFileTree.filter { it.name.contains("natives") }.forEach {
unzipTo(File("$buildDir/libs/natives-os"), it)
}
}
}
Edited: Why this is not working? I config it first then execute it.
tasks.register<Copy>("unzip_native_os") {
this.group = "zip"
val nativesJar = nativesOS.asFileTree.filter { it.name.contains("natives") }.files
doFirst {
nativesJar.forEach {
println(">>>> $it")
unzipTo(File("$buildDir/libs/natives-os/v2"), it)
}
}
}
Edited: I found a possible answer and it looks promising but I did not implement it yet, because I need some learning to do on building this kind of script plugin/inline plugin. Here's the link: gradle custom task execution phase
Edited: found an alternative/another quick solution here: Fix custom tasks in gradle. Want to run it manually via at Execution Phase

Gradle can not compile the code with the generated sources by annotationProcessor

How to make the gradle build/compile a project using generated source by annotationProcessor?
I have a project with 2 modules
app-annotation -> is a module that defines one annotation and a successor of the AbstractProcessor
app-api -> contains Entities with annotation from the previous module
The idea was to generate default CRUD Repositories and Services for each entity, also if it is needed have the possibility to extend some service.
The problem is, it generates all the needed java files (even Intellij Idea see those files) but as soon as I want to extend one of the services it fails while it is being compiled because as I understand at the moment of compiling my class there is not its superclass which is generated after.
If I do then recompile only my class then it is ok
Moreover, eclipse somehow compiles with no error at all, only when I build with Idea or gradlew build.
To fix it the solution below is used, but it looks not very nice
configurations {
preProcessAnnotation
}
def defaultSrcDir = "$projectDir/src/main/java"
def entitySources = "$projectDir/src/main/java/com/abcd/app/entity"
def generatedSources = "$buildDir/generated/sources/annotationProcessor/java/main"
def generatedOutputDir = file("$generatedSources")
// Explicitly run the annotation processor against the entities
task preProcessAnnotation (type: JavaCompile) {
source = entitySources
classpath = sourceSets.main.compileClasspath
destinationDirectory = generatedOutputDir
options.sourcepath = sourceSets.main.java.getSourceDirectories()
options.annotationProcessorPath = configurations.getByName("preProcessAnnotation")
options.compilerArgs << "-proc:only"
options.encoding = "ISO-8859-1"
}
// Explicitly specify the files to compile
compileJava {
dependsOn(clean)
dependsOn(preProcessAnnotation)
def files = []
fileTree(defaultSrcDir).visit { FileVisitDetails details ->
files << details.file.path
}
fileTree(generatedSources).visit { FileVisitDetails details ->
files << details.file.path
}
source = files
options.compilerArgs << "-Xlint:deprecation"
options.compilerArgs << "-Xlint:unchecked"
options.encoding = "ISO-8859-1"
}
....
dependencies {
preProcessAnnotation project(':app-annotation')
// Generate the crud repositories and services
compile project(':app-annotation')
implementation project(':app-annotation')
...
}
I am just curious how similar frameworks of code generation such as Lombok, Dagger2 work without any problem.
PS. I feel it should be much simpler, doesn't it?
Eventually, all it is my mistake, I used wrong method to save a generated java file.
// Wrong!
javax.annotation.processing.Filer#createResource(StandardLocation.SOURCE_OUTPUT, packageName, className + ".java")
// Correct
javax.annotation.processing.Filer#createSourceFile(packageName + "." + className)
As you realised - any code generation must be done before compile.
A cleaner approach is to have your code generation logic / annotation as dependency.
task codeGen {
// creates under build/genSrc
}
//add to default source set
sourceSets.main.java.srcDir "build/genSrc"
//this has access to all code
compile.dependsOn codeGen

Gradle: get a Groovy test script to use an auxiliary Java class

I'm trying to work out how I get a Groovy test script to import a Java class during the testing phase ...
Specifically I want to use JavaFXThreadingRule: .java file from here (or rather here and so included in my Java test source path) and then import it in my Groovy test script to use as an annotation.
The Groovy test script path is src\test\ft\groovy\core\testscript.groovy.
The .java file is src\test\ft\java\core\JavaFXThreadingRule.java.
The package line I've used in both is "package core;"
My "sourceSets" clause in build.gradle looks like this:
sourceSets {
main {
java {
srcDirs = ['src/main/java']
}
}
test {
java {
srcDirs = ['src/test/ft/java' ]
}
groovy {
srcDirs = ['src/test/ft/groovy', 'src/test/ut/groovy']
}
}
}
Interestingly the build.gradle output shows that the compileTestJava task is run before the compileTestGroovy task ... and yet I get
unable to resolve class core.JavaFXThreadingRule # line 18, column 1.
import core.JavaFXThreadingRule ^
NB I also tried "import JavaFXThreadingRule" - same result.
In addition to just wanting to resolve the problem I'm also wondering how Gradle decides what order to do the tasks compileTestJava and compileTestGroovy... and whether I shouldn't perhaps make my compileTestGroovy explicitly dependent on compileTestJava...
Thanks to Tim Yates I found the "workaround" of putting this Java file in with the Groovy ones... but this answer gave me another clue, and I then changed my build.gradle to be like this:
sourceSets {
main {
java {
srcDirs = ['src/main/java']
}
}
test {
groovy {
srcDirs = ['src/test/ft/groovy', 'src/test/ut/groovy', 'src/test/ft/java' ]
}
}
}
... works ... no doubt obvious to old Gradle hands.
That question and answer referenced above were talking about the app code classes (and Gradle tasks). Unless some Gradle expert can say otherwise I'm assuming that the Groovy test compile task and Java test compile task are completely separate and can't "see" one another's classes...

Gradle Project: java.lang.NoClassDefFoundError: kotlin/jvm/internal/Intrinsics

I'm working on a Java project and within this project I did my first try with Kotlin. I started converting some classes to Kotlin with the JavaToKoltin converter provided in the Intellij Idea. Among others my custom exceptions are now converted to Kotlin. But with this the exception handling does not work correct anymore.
If I throw one of my custom exceptions (e.g. MyCustomKotlinException.kt) within the java code, the exception is not catched (see code below).
// Example.java
package foo
import java.util.*;
import java.lang.*;
import java.io.*;
import foo.MyCustomKotlinException;
class Example
{
public static void main (String[] args)
{
try {
// Do some stuff
// if Error
MyCustomKotlinException e = new MyCustomKotlinException("Error Message");
throw e;
} catch (MyCustomKotlinException e) { // <-- THIS PART IS NEVER REACHED
// Handle Exception
} catch (Throwable e) {
e.printStackTrace(); <-- This is catched
} finally {
// Finally ...
}
}
}
So can anyone explain to me why the exception is not catch. MyCustomKotlinException is inheriting from Kotlins RuntimeException, which is just an alias to java.lang.RuntimeException.
// MyCustomKotlinException.kt
package foo
class MyCustomKotlinException(err: String) : RuntimeException(err)
Update:
I split the throw part into 2 lines (instance creation and throwing) and found that the problem is not the throwing. The try block is left after the instance creation. Is anything wrong with my instance creation of this Kotlin class?
Update2:
I added a second catch block with Throwable and the following Throwable is caught.
java.lang.NoClassDefFoundError: kotlin/jvm/internal/Intrinsics
...
Caused by: java.lang.ClassNotFoundException: kotlin.jvm.internal.Intrinsics
Update3:
Changed the title to correct error and fixed problem with adding all project files to jar (see answer below).
Adding the Kotlin runtime lib to gradle does not work for me.
Adding all project files to the jar fixed the problem for me. I added the following line to my build.gradle
jar {
manifest {
attributes ...
}
// This line of code recursively collects and copies all of a project's files
// and adds them to the JAR itself. One can extend this task, to skip certain
// files or particular types at will
from { configurations.compileClasspath.collect { it.isDirectory() ? it : zipTree(it) } }
}
Update: Changed configurations.compile.collect to configurations.compileClasspath.collect according to this answer below.
You need to configure your project with kotlin.
So in Android Studio:
click on Tools => kotlin => Configure kotlin in project
Then in dialog check : All module containing kotlin files
and select version
press ok
Done.
This error is likely due to the fact that the simple jar task doesn’t take all its runtime dependencies.
From gradle documentation, In your build.gradle.kts you can either create a "fatJar" task or add that to your jar task:
tasks.withType<Jar> {
// Otherwise you'll get a "No main manifest attribute" error
manifest {
attributes["Main-Class"] = "com.example.MainKt"
}
// To avoid the duplicate handling strategy error
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
// To add all of the dependencies
from(sourceSets.main.get().output)
dependsOn(configurations.runtimeClasspath)
from({
configurations.runtimeClasspath.get().filter { it.name.endsWith("jar") }.map { zipTree(it) }
})
}
I'm going to say that you're trying to run Kotlin code without the kotlin-runtime library
Check which system you're using and add the neccesary jar file. You can verify that this is your issue by packaging your project into a .jar file and running it with the runtime library
Thanks for the comment. Indeed compile is deprecated. However the accepted answer does not work with implementation. So I looked up the java library plugin configuration and implementation depends on compileClasspath.
So my solution for now is to add
jar {
manifest {
attributes ...
}
// This line of code recursively collects and copies all of a project's files
// and adds them to the JAR itself. One can extend this task, to skip certain
// files or particular types at will
from { configurations.compileClasspath.collect { it.isDirectory() ? it : zipTree(it) } }
}
with
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.50"
//...
}
I feel like this should be done by the org.jetbrains.kotlin.jvm plugin.
Using compile instead of implementation in the dependencies of the build.gradle file solved it for me.
Had the same problem, compiling my project with Ant in console. I've edded kotlin-stdlib.jar into classpath and problem has gone.
Adding the following solved the issue for me:
dependencies {
"kotlinCompilerClasspath"(fileTree("libs/gradle-plugins/kotlin"))
}
Here is the content of libs/gradle-plugins/kotlin:
annotations-13.0.jar
commons-codec-1.9.jar
commons-logging-1.2.jar
gradle-download-task-3.4.3.jar
gson-2.8.5.jar
httpclient-4.5.3.jar
httpcore-4.4.6.jar
kotlin-android-extensions-1.3.40.jar
kotlin-annotation-processing-gradle-1.3.40.jar
kotlin-build-common-1.3.40.jar
kotlin-compiler-1.3.40.jar
kotlin-compiler-embeddable-1.3.40.jar
kotlin-compiler-runner-1.3.40.jar
kotlin-daemon-client-1.3.40.jar
kotlin-gradle-plugin-1.3.40.jar
kotlin-gradle-plugin-api-1.3.40.jar
kotlin-gradle-plugin-model-1.3.40.jar
kotlin-reflect-1.3.40.jar
kotlin-runtime-1.2.71.jar
kotlin-script-runtime-1.3.40.jar
kotlin-scripting-common-1.3.40.jar
kotlin-scripting-compiler-embeddable-1.3.40.jar
kotlin-scripting-compiler-impl-embeddable-1.3.40.ja
kotlin-scripting-jvm-1.3.40.jar
kotlin-stdlib-1.3.40.jar
kotlin-stdlib-common-1.3.40.jar
kotlin-stdlib-jdk7-1.3.40.jar
kotlin-stdlib-jdk8-1.3.40.jar
kotlinx-coroutines-core-1.1.1.jar
org.jetbrains.kotlin.jvm.gradle.plugin-1.3.40.jar
trove4j-1.0.20181211.jar
The complete gradle.build.kts (offline setup):
buildscript {
dependencies {
classpath(fileTree("libs/gradle-plugins/kotlin"))
}
}
plugins {
java
`java-library`
}
apply(plugin = "kotlin")
version = "2019.06.1"
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
kotlinOptions.jvmTarget = "12"
}
repositories {
flatDir {
dirs("libs/compile")
dirs("libs/provided")
}
}
dependencies {
"kotlinCompilerClasspath"(fileTree("libs/gradle-plugins/kotlin"))
compileOnly(":javaee-api-8.0")
api(":kotlin-stdlib-common-1.3.40")
api(":kotlin-stdlib-1.3.40")
api(":kotlin-stdlib-jdk7-1.3.40")
api(":kotlin-stdlib-jdk8-1.3.40")
api(":gson-2.8.5")
}
In my case, a enableFeaturePreview in the settings.gradle caused this issue when migrating to Kotlin 1.3.
In my case adding maven Bom file worked. It does job of downloading and keeping all the kotlin dependencies in sync.
imports {
mavenBom 'org.jetbrains.kotlin:kotlin-bom:<<KOTLIN_VERSION>>'
}
Refer the official documentation here :
https://kotlinlang.org/docs/gradle-configure-project.html#other-ways-to-align-versions

Compiling Scala before / alongside Java with Gradle

The default scala plugin task flow compiles Java before Scala so importing Scala sources within Java causes "error: cannot find symbol".
Java and Scala can be combined in the scala sources to have them compiled jointly, e.g.
sourceSets {
main {
scala {
srcDirs = ['src/main/scala', 'src/main/java']
}
java {
srcDirs = []
}
}
If your java code use some external libraries like Lombok, using scala compiler to build java class will failed, as scala compiler don't know annotations.
My solution is to change the task dependencies, make compiling Scala before Java.
tasks.compileJava.dependsOn compileScala
tasks.compileScala.dependsOn.remove("compileJava")
Now the task compileScala runs before compileJava, that's it.
If your java code depends on scala code, you need to do two more steps,
Separate the output folder of scala and java,
sourceSets {
main {
scala {
outputDir = file("$buildDir/classes/scala/main")
}
java {
outputDir = file("$buildDir/classes/java/main")
}
}
Add the scala output as a dependency for compileJava,
dependencies {
compile files("$sourceSets.main.scala.outputDir")
}
for gradle kotlin dsl you can use this piece
sourceSets {
main {
withConvention(ScalaSourceSet::class) {
scala {
setSrcDirs(listOf("src/main/scala", "src/main/java"))
}
}
java {
setSrcDirs(emptyList<String>())
}
}
test {
withConvention(ScalaSourceSet::class) {
scala {
setSrcDirs(listOf("src/test/scala", "src/test/java"))
}
}
java {
setSrcDirs(emptyList<String>())
}
}
}
Posting this update from the future here, as it would saved me a day.
gradle 6 doesn't support task dependencies modification, but here is what you can do:
// to compile Java after Scala
tasks.compileScala.classpath = sourceSets.main.compileClasspath
tasks.compileJava.classpath += files(sourceSets.main.scala.classesDirectory)
And here is documentation.

Categories

Resources