I have a gradle project with the following structure:
rootDir
|--agent-v1.0.0
|--agent.jar
|--proj1
|-- // other project files
|--build.gradle
|--proj2
|-- // other project files
|--build.gradle
|--build.gradle
I would like to run test.jvmArgs = ['javaagent:agent-v1.0.0/agent.jar'] for all subprojects, so I wrote the following task in the root build.gradle:
subprojects {
task cs {
outputs.upToDateWhen { false }
dependsOn test.jvmArgs = ['javaagent:../agent-v1.0.0/agent.jar']
}
}
But this fails with:
Could not determine the dependencies of task ':proj1'.
Task with path 'javaagent:../agent-v1.0.0/agent.jar' not found in project ':proj1'.
I've tried this by putting the agent-v1.0.0 in both the root, and in each project, and it still fails. What am I missing?
Why are you wrapping that logic in a new task? And then passing the return from jvmArgs to dependsOn?
Just configure the test tasks correctly:
subprojects {
tasks.withType(Test) {
jvmArgs "-javaagent:${project.rootDir}/agent-v1.0.0/agent.jar"
}
}
A task can depend on another task. So dependsOn expects a task as argument. test.jvmArgs = ['javaagent:../agent-v1.0.0/agent.jar'] is not a task.
If you want to configure all the test tasks of all subprojects to have additional jvm args, then the syntax would be
subprojects {
// this block of code runs for every subproject
afterEvaluate {
// this block of code runs after the subproject has been evaluated, and thus after
// the test task has been added by the subproject build script
test {
// this block of code is used to configure the test task of the subproject
// this configures the jvmArgs property of the test task
jvmArgs = ['javaagent:../agent-v1.0.0/agent.jar']
}
}
}
But just don't copy and paste this code. Read the grade user guide, and learn its fundamental concepts.
Related
in our project we are working with
springBoot 2.2.11
groovy 2.5.6
Our build.gradle looks like the following:
...
plugins {
id 'groovy'
id 'java'
id 'idea'
}
configurations {
testCompile.extendsFrom compile
testRuntime.extendsFrom runtime
...
}
...
sourceSets {
test {
java { srcDirs = ['src/test/java'] }
groovy {srcDirs = ['src/test/groovy'] }
}
...
}
...
springBoot {
buildInfo()
}
...
When we run gradlew test --info we get the following output:
...
> Task :bootBuildInfo
Caching disabled for task ':bootBuildInfo' because:
Build cache is disabled
Task ':bootBuildInfo' is not up-to-date because:
Value of input property 'properties.time' has changed for task ':bootBuildInfo'
...
> Task :compileJava UP-TO-DATE
...
Skipping task ':compileJava' as it is up-to-date.
...
> Task :compileTestGroovy
Caching disabled for task ':compileTestGroovy' because:
Build cache is disabled
Task ':compileTestGroovy' is not up-to-date because:
Input property 'astTransformationClasspath' file C:\projects\test-project\build\resources\main\META-INF\build-info.properties has changed.
The input changes require a full rebuild for incremental task ':compileTestGroovy'.
...
The build-info.properties file which is generated by spring-boots buildInfo step contains a build.time property which is updated on every execution.
The Java Compiler excludes this file apperently as the up-to-date check for :compileJava is returning true. However, the compileGroovy tasks includes this file into his sourceSet which is why it returns false on the up-to-date check.
I already tried the exclude option as follows with no success.
sourceSets {
test {
java { srcDirs = ['src/test/java'] }
groovy {
srcDirs = ['src/test/groovy']
excludes = [file("${buildDir}/resources/main/META-INF/build-info.properties")]
}
}
}
Any ideas on how to fix this? Idealy I would like to exclude the file build\resources\main\META-INF\build-info.properties from the up-to-date-check (or even the input sourceSet of compileGroovy).
You need to make spring-boot.properties generated with no time part(what makes springBoot task out of dated what in turn leads compileJava outdated)
springBoot {
buildInfo {
properties {
// to make compileJava up to date
// https://docs.spring.io/spring-boot/docs/current/gradle-plugin/reference/htmlsingle/#integrating-with-actuator.build-info
time = null
}
}
}
I am unable to delombok my Java source code, apparently due to jar dependencies that the project has, and I don't understand why. There are two jar files that have to be committed to the repo to tag along, and they are added to the project in the dependencies node of the build.gradle file by adding the line compile files('myproj1.jar'). So, the relevant part of the build.gradle file looks like this:
dependencies {
compile files('myproj1.jar')
compile files('myproj2.jar')
.....
}
When I run the delombok task I get the following error:
Execution failed for task ':delombok'.
> taskdef class lombok.delombok.ant.Tasks$Delombok cannot be found
using the classloader AntClassLoader[/path/to/repo/myproj1.jar:/path/to/repo/myproj2.jar]
Why would delombok task be using the AntClassLoader from the jar files?
I have tried the delombok'ing code from this post
Here is the task from my build.gradle file
def srcJava = 'src/main/java'
def srcDelomboked = 'build/src-delomboked'
task delombok {
// delombok task may depend on other projects already being compiled
dependsOn configurations.compile.getTaskDependencyFromProjectDependency(true, "compileJava")
// Set up incremental build, must be made in the configuration phase (not doLast)
inputs.files file(srcJava)
outputs.dir file(srcDelomboked)
doLast {
FileCollection collection = files(configurations.compile)
FileCollection sumTree = collection + fileTree(dir: 'bin')
ant.taskdef(name: 'delombok', classname: 'lombok.delombok.ant.Tasks$Delombok', classpath: configurations.compile.asPath)
ant.delombok(from:srcJava, to:srcDelomboked, classpath: sumTree.asPath)
}
}
I expect to be able to delombok my Java source code as part of the build process so that when the project is compiled there are no dependencies on Lombok.
So after continued trial an error, I have a working implementation. To answer my own question, the problem has nothing to do with the additional Jar files. Rather, when gradle runs the delombok task, the classes in the lombok jar are not in the classpath of the org.gradle.api.AntBuilder (ie, the ant task), and so it does not have a reference to lombok.delombok.ant.Tasks$Delombok anywhere (which seems obvious at this point, but not at the time).
The solution thus far has been to add those references in from configurations.compile
Combining code snippits from this post and this post you can do it with something like this:
def srcDelomboked = 'build/src-delomboked'
task delombok {
description 'Delomboks the entire source code tree'
def srcJava = 'src/main/java'
inputs.files files( srcJava )
outputs.dir file( srcDelomboked )
doFirst {
ClassLoader antClassLoader = org.apache.tools.ant.Project.class.classLoader
def collection = files( configurations.compile + configurations.testCompile )
def sumTree = collection + fileTree( dir: 'bin' )
sumTree.forEach { File file ->
antClassLoader.addURL(file.toURI().toURL())
}
ant.taskdef( name: 'delombok', classname: 'lombok.delombok.ant.Tasks$Delombok',
classpath: configurations.compile.asPath + configurations.testCompile.asPath )
ant.delombok( from: srcJava, to: srcDelomboked, classpath: sumTree.asPath )
}
}
sourceSets {
main {
java { srcDirs = [ srcDelomboked ] } //blow away the old source sets so that we only use the delomboked source sets
}
test {
java { srcDirs += [ srcDelomboked ] } //but add those new source sets to the tests so that their references are available at test time
}
}
compileJava.dependsOn(delombok)
bootJar {
mainClassName = 'com.myproj.MyMainClass' // you will need this if its a Spring Boot project
}
Hope this helps whomever else needs to delombok their code.
We have a gradle project with mutliple modules - so each module - eg admin, ends up having something like this:
task admintest(type: Test) {
description = "Tests of admin"
testClassesDir = sourceSets.admintest.output.classesDir
classpath += sourceSets.admintest.runtimeClasspath
}
check.dependsOn admintest
now - we are generating a jacoco report - the report actually includes all the classes from all the different modules, but only has coverage from the tests that ran as part of the main module, ie the "test" task - while the admintests and others run, the coverage is always zero. How do I get jacoco to also pick up the coverage from the admintests, and other module tests?
Found it - for those who are trying to do this - the secret sauce is to specify the other modules test tasks in the executionData
eg:
jacocoTestReport {
executionData test, admintest, commontest
}
This is old thread , but this might help someone :
We only need this in build.gradle of root project.
Define a common location
Provide same to sonarqube as well.
plugins {
..
id "org.sonarqube"
}
apply plugin: 'org.sonarqube'
allprojects {
apply plugin: 'jacoco'
}
task jacocoRootReport(type: JacocoReport) {
dependsOn = subprojects.test
description = 'Generates aggregate report from all subprojects.'
.....
reports {
xml.enabled true
xml.destination(file("${jacoco.reportsDir}/all-tests/jacocoRootReport.xml"))
csv.enabled false
}
}
sonarqube {
properties {
property "sonar.coverage.jacoco.xmlReportPaths", jacocoRootReport.reports.xml.destination
}
}
I try to build jar and after that copy it to another folder.
task createJar(type: Jar) {
archiveName = "GradleJarProject.jar"
manifest {
attributes 'Implementation-Title': 'Gradle Jar File Example',
'Implementation-Version': version,
'Main-Class': 'me.test.Test'
}
baseName = project.name
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
}
task copyJarToBin {
copy {
from 'build/libs/GradleJarProject.jar'
into "d:/tmp"
}
}
task buildApp (dependsOn: [clean, createJar, copyJarToBin])
But I can't figure out one problem.
copyJarToBin task try to copy old jar. If I delete /build folder in the project and run buildApp() task, task createJar() will generate .jar file, but copyJarToBin() won't find that .jar file.
Could you help me?
Thanks.
The culprit is your copyJarToBin task. when doing
task copyJarToBin {
copy {
from 'build/libs/GradleJarProject.jar'
into "d:/tmp"
}
}
you copy the jar during the configuration time by using the copy method. (see the gradle user guide at https://docs.gradle.org/current/userguide/userguide_single.html#sec:build_phases to understand the build lifecycle)
You want to run the actual copy operation during the execution phase (the execution of the task).
One way to solve that is to move the call of the copy method into a doLast block:
task copyJarToBin {
doLast {
copy {
from 'build/libs/GradleJarProject.jar'
into "d:/tmp"
}
}
}
The problem with this approach is that you won't benefit of gradles incremental build feature and copy that file every single time you execute the task even though the file hasn't changed.
A better and more idiomatic way of writing your copyJarToBin task is to change your task implementation to use the Copy task type:
task copyJarToBin(type: Copy) {
from 'build/libs/GradleJarProject.jar'
into "d:/tmp"
}
We can even improve this snippet by taking advantage of gradle's autowiring feature. You can declare the output of one task as input to another. So instead of writing `build/libs/GradleJarProject.jar' you can simply do:
task copyJarToBin(type: Copy) {
from createJar // shortcut for createJar.outputs.files
into "d:/tmp"
}
Now you don't need to bother about task ordering as gradle know that the createJar task must be executed before the copyJarToBin task can be executed.
I think the above answer is somehow old. Here is an answer using gradle 3.3
jar {
baseName = 'my-app-name'
version = '0.0.1'
}
task copyJar(type: Copy) {
from jar // here it automatically reads jar file produced from jar task
into 'destination-folder'
}
build.dependsOn copyJar
Just made few corrections to above Answers:
jar {
baseName = "$artifactId"
version = '0.0.1'
}
task copyJar(type: Copy) {
from jar // copies output of file produced from jar task
into 'destination-folder'
}
build.finalizedBy copyJar
You probably need to ensure they are run in the right order,
task copyJarToBin(type:Copy,dependsOn:[createJar]) {
copy {
from "${buildDir}/GradleJarProject.jar" // needs to be gstring
into "d:/tmp"
}
}
In my use case I needed projectA to consume (unzip) contents from projectB's jar output. In this case the embedded doLast { copy { .. }} was required.
configurations {
consumeJarContents
}
dependencies {
consumeJarContents project(':projectB')
}
task copyFromJar() {
dependsOn configurations.consumeJarContents
doLast {
copy {
configurations.consumeJarContents.asFileTree.each {
from( zipTree(it) )
}
into "$buildDir/files"
}
}
}
The problem with task copyFromJar(type: Copy) in this scenario is that the Copy configuration phase checks for the jar file, which it does not find because it has not yet been created, and so declares NO-INPUT for the task at execution time.
I need to execute a java class which has a main method in it before compiling the code. This is what I have tried so far:
task runSimple(type: JavaExec) {
main = 'jjrom.ObjectGen'
classpath = sourceSets.main.runtimeClasspath
File prop1 = file(propFilePath)
args '-sqlserver', '-force', prop1.path
println "I'm done executing."
}
compileJava {
dependsOn runSimple
}
When I execute this script with the command "gradle compileJava" , I get this error message:
I'm done executing.
FAILURE: Build failed with an exception.
What went wrong: Circular dependency between the following task: :classes --- :compileJava --- :runSimple --- :classes (*)
If you need to execute this class before compiling the code, you can't give it classpath = sourceSets.main.runtimeClasspath. The latter includes the compiled code, and so Gradle automatically infers runSimple.dependsOn compileJava, which together with your compileJava.dependsOn runSimple gives a cyclic task dependency. (To be precise, Gradle infers runSimple.dependsOn classes, which in turn depends on compileJava.)
If you need to run JavaExec only with dependecies classpath, just change classpath variable to something like:
classpath = configurations.compile
Or if you are interested in very specific classpath, you could add custom configuration like this:
configurations {
customClasspath
}
dependencies {
customClasspath files('path/to/your.jar')
}
task runSimple(type: JavaExec) {
main = 'jjrom.ObjectGen'
classpath = configurations.customClasspath
File prop1 = file(propFilePath)
args '-sqlserver', '-force', prop1.path
println "I'm done executing."
}
compileJava {
dependsOn runSimple
}