gradle - Add custom configuration to installDist for a specific task - gradle

I'm trying to make a custom runtime dependency configuration, so that the specified dependencies will only be installed for a specific task. The dependencies are installed using the installDist task. So it seems like I need the configuration to be added to the runtimeClasspath for one task and not the other. I'm thinking I need a custom distribution, but I'm not sure how to set that to have a different runtimeClasspath.
In the example below, I want the run2 task to have the myRuntimeDep dependencies installed, but for the run1 task I do not.
I've be struggling to figure this out all day, does someone know what I'm missing?
Example build.gradle:
configurations {
myRuntimeDep.extendsFrom runtimeOnly
}
dependencies {
...
myRuntimeDep 'the:dependency:1.0'
}
task run1(type: JavaExec, dependsOn: installDist) {
// does not need myRuntimeDep dependencies
}
task run2(type: JavaExec, dependsOn: installDist) {
// needs myRuntimeDep dependencies
}

So after a long weekend, I sort of got something working. Maybe someone can tell me if there's a better way? Also, it doesn't fully work because it doesn't follow transitive dependencies with the configuration (which is kind of a pain because all sub-dependencies need to be manually added).
Solution:
top-level build.gradle
...
subprojects {
configurations {
fooRuntime.extendsFrom runtimeOnly
fooClasspath.extendsFrom runtimeClasspath, fooRuntime
}
distributions {
foo {
contents {
from installDist.destinationDir
from(configurations.fooClasspath) {
into 'lib'
}
}
}
}
installFooDist.dependsOn installDist
}
project A build.gradle
dependencies {
fooRuntime project(':projectB')
fooRuntime project(':projectC') // only need this because transitive dependencies won't work
}
task run(type: JavaExec, dependsOn: installFooDist) {
classpath = fileTree("$installFooDist.destinationDir/lib")
}
project B build.gradle
dependencies {
fooRuntime project(':projectC')
}
task run(type: JavaExec, dependsOn: installFooDist) {
classpath = fileTree("$installFooDist.destinationDir/lib")
}

Related

In gradle, how to copy a subset of compiled test classes

I tried taking a portion of the compiled test classes of a Gradle project, and put them in a jar file (to create a test case). What happened was, only those classes got compiled out of all test classes. Any idea how to do it right?
Here's my build.gradle:
plugins {
id 'java'
}
group 'org.example'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
}
task testSampleJar(type: Zip) {
archiveName "sample.jar"
from compileTestJava {
include "org/example/samples/**"
}
}
test {
dependsOn(testSampleJar)
}
So what seems to be happening is that by just defining the testSampleJar task, the compileTestJava task gets modified to only compile under org.example.samples package. My intent was to use the outputs of compileTestJava and pick something out of them them.
Thanks,
Uri
OK, figured it out, so the two possible solutions are:
//a global filter
task testSampleJar(type: Zip) {
archiveName "sample.jar"
from compileTestJava
include "org/example/samples/**"
}
Or
//Child specification - notice the parentheses around compileTestJava
task testSampleJar(type: Zip) {
archiveName "sample.jar"
from (compileTestJava) {
include "org/example/samples/**"
}
}
I guess the original code was defining compileTestJava instead of using its output, but I don't have a full grasp of Groovy/Gradle DSL to be certain.

Gradle 4.8+ breaks ivy publish with custom configurations

I've got a gradle file which is working in some ancient version of gradle but I want to upgrade to gradle 5.0. Unfortunately its using ivy rather than maven to publish its jars. I've cut it down to a simple test case.
I'm not sure if I'm missing something or its a bug or what. I've attached the gradle below. I'm running it
./gradlew wrapper && ./gradlew publish --info && cat build/publications/ivy/ivy.xml
It works as expected with 4.7. It publishes the main jar and the source jar and adds the dependencies.
If I switch to 4.8 it breaks, it only publishes the source jar, main jar and dependencies are missing.
If I switch to 4.8 and comment out the configurations bit it publishes the main jar and dependencies again.
Perhaps there's a new way of doing things but if so I've failed to find where its documented. Here's the source build.gradle.
plugins {
id 'java'
id 'ivy-publish'
}
sourceSets {
testSupport {
java {
compileClasspath += main.output
runtimeClasspath += main.output
}
}
test {
java {
compileClasspath += testSupport.output
runtimeClasspath += testSupport.output
}
}
}
dependencies {
compile group: 'com.ibm.icu', name: 'icu4j', version: '58.2'
compile group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.3'
compile group: 'io.swagger', name: 'swagger-parser', version: '1.0.32'
}
task sourceJar(type: Jar) {
from sourceSets.main.allJava
}
task testSupportJar(type: Jar) {
from sourceSets.testSupport.output
appendix "test-support"
}
task testSupportSourceJar(type: Jar) {
from sourceSets.testSupport.java.srcDirs
appendix "test-support-sources"
}
artifacts {
archives sourceJar
archives testSupportJar
archives testSupportSourceJar
}
publishing {
repositories {
ivy {
name = 'myRepo'
url = "file://${buildDir}/repo"
layout "pattern", {
artifact "[organisation]/[module]/[revision]/jars/[artifact].[ext]"
ivy "[organisation]/[module]/[revision]/ivys/ivy-[revision].xml"
}
}
}
publications {
ivy(IvyPublication) {
organisation = 'com.example.com'
// If you comment out the configurations below it will generate sensible ivy.xml
configurations {
"compile" {}
"runtime" {}
}
from components.java
artifact(sourceJar) {
type "source"
extension "src.jar"
conf "runtime"
}
}
}
}
wrapper {
// 4.7 works but 4.8+ doesn't.
gradleVersion = '4.7'
}
Oh man I just figured it out. Its the relative ordering of from components.java and the configurations element bits. If configurations is first it seems to take precedence over from components.java and the latter is seemingly ignored. If you put from components.java before configurations it works and you don't have to manually declare the configs it generates by default any more.
FFS gradle.

Gradle: how to add dependencies to the specific task?

I have dependencies block in my configuration:
dependencies {
compile ...
}
Now I'm trying to create a task which will build a specific debug artefact:
task buildDebugRpm (type: Rpm) {
requires('java-1.8.0-openjdk', '1.8.0.0', GREATER | EQUAL)
...
}
Artefact built in this task should include AspectJ libraries in runtime. But I don't want to have them in my common project dependencies.
Is there a way to add "org.aspectj:aspectjrt:1.8.9", "org.aspectj:aspectjweaver:1.8.9" libs only for this specific task?
You can create a custom configuration and add the dependencies to it:
configurations {
debugRpm {
extendsFrom compile
}
}
dependencies {
compile ...
debugRpm 'org.aspectj:aspectjrt:1.8.9'
debugRpm 'org.aspectj:aspectjweaver:1.8.9'
}
Then include these dependencies in the task:
task buildDebugRpm (type: Rpm) {
...
from(configurations.debugRpm) {
into 'lib'
}
}

Gradle copy build script dependency to folder

We are building one of our applications with gradle and part of the distribution I want to include an external jar which is not a run time dependency in a config folder. That jar is needed as part of the application install and it contains some custom ant tasks.
Our build script dependency looks like below:
buildscript {
...
dependencies {
classpath 'org.jfrog.buildinfo:build-info-extractor-gradle:3.1.1'
classpath 'my-group:custom-tasks:1.2.3'
}
}
How would I access and copy the custom-task-1.2.3.jar into a certain folder so I can include it in my distribution? Something like below:
task copyCustomTasks {
doLast {
copy {
// This below is a make up to express what I want
from buildscript.dependencies
include 'custom-tasks*.jar'
into "$buildDir/config"
}
}
}
If this is not the gradle way of doing things please let me know what alternatives I have.
Thank you in advance for your help.
UPDATE
I solved my problem in a different way by creating an extra configuration. However I would still be interested to find out how you can access build script dependencies at run time. Thanks again for your inputs.
configurations {
install {
description = "application install classpath"
transitive = true
}
}
...
dependencies {
...
install('my-group:custom-tasks:1.2.3')
...
}
...
task copyInstallDeps {
doLast {
copy {
from configurations.install
into "$buildDir/config"
}
}
}
You're quite close:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.google.guava:guava:18.0'
}
}
task copyLibs(type: Copy) {
from buildscript.configurations.classpath
into 'lib'
}

Gradle war ignores transitive dependencies when using 'configurations.runtime.asPath' in custom task

I'm facing behavior that I can't explain, using gradle 1.10 I have:
settings.gradle:
include('lib1', 'lib2', 'web')
build.gradle:
subprojects {
apply plugin: 'java'
}
project(':web') {
apply plugin: 'war'
dependencies {
compile project(':lib1')
}
task myTask(type: JavaExec, dependsOn: 'compileJava') {
main = "some.thirdparty.Class"
args "--searchPath", configurations.runtime.asPath
}
}
project(':lib1') {
dependencies {
compile project(':lib2')
}
}
project(':lib2') {
}
When I run gradle clean war I only have lib1.jar in war/build/libs/web.war/WEB-INF/lib.
To make WEB-INF/lib contain both lib1.jar and lib2.jar I have to:
move project('web') block to the end of the file
update configurations.runtime.asPath to configurations.runtime (but I need to provide class path as a path, so it is not a solution)
I read the build lifecycle description, tried to compare --debug outputs but that didn't help.
Why is this happening? And what would be a good solution to provide the module runtime class path as a path in JavaExec task please?
asPath resolves the configuration, but resolution will only work correctly if it happens at execution time rather than configuration time (in particular in the presence of project dependencies). Try to wrap the args line with doFirst { ... }.

Resources