Using Gradle to build a jar with dependencies with Kotlin-DSL - gradle

There is already an answer to the question: how to include all the dependencies in a jar file though it's for Groovy
I'm using gradle with kotlin-dsl and the code is not compatible. I tried to make it work using a few ways including:
tasks.withType<Jar> {
configurations["compileClasspath"].forEach { file: File ->
copy {
from(zipTree(file.absoluteFile))
}
}
}
Though this doesn't work. So how to include the dependencies using kotlin-dsl in gradle?

This will work:
tasks.withType<Jar>() {
configurations["compileClasspath"].forEach { file: File ->
from(zipTree(file.absoluteFile))
}
}
There's no need in copy { ... }, you should call from on the JAR task itself.
Note: Gradle does not allow changing the dependencies after they have been resolved. It means that the block above should be executed only after the dependencies { ... } are configured.

my case
withType<Jar> {
enabled = true
isZip64 = true
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
archiveFileName.set("$project.jar")
from(sourceSets.main.get().output)
dependsOn(configurations.compileClasspath)
from({
configurations.compileClasspath.get().filter {
it.name.endsWith("jar")
}.map { zipTree(it) }
}) {
exclude("META-INF/*.RSA", "META-INF/*.SF", "META-INF/*.DSA")
}
}

Related

Gradle disable javadoc except on deploy

I have enabled the javadoc for a project with
java {
withJavadocJar()
}
The problem with this is that the javadoc is built everytime the library is built. In my case, this takes several minutes. Is there a good way to make the javadoc only run on gradle deloy?
The following did the trick:
// Disables a task unless we're publishing something.
def disableUnlessPublishing(toDisable) {
toDisable.enabled = false
gradle.taskGraph.whenReady {
gradle.taskGraph.allTasks
.findAll { it.group == "publishing" }
.any { toDisable.enabled = true }
}
}
disableUnlessPublishing(tasks.javadocJar)
disableUnlessPublishing(tasks.javadoc)
disableUnlessPublishing(tasks.sourcesJar)

How to exclude all but one specific jar from Gradle distZip task?

On line 192 of https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/java/org/gradle/api/plugins/ApplicationPlugin.java is:
libChildSpec.from(project.getConfigurations().getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME));
Since my project is using Spring Boot and it generates a standalone jar, how do I exclude all the other jars from the distZip task?
distributions {
main {
contents {
into('lib') {
project.configurations.runtimeClasspath.files.findAll { file ->
file.getName() != project.tasks.jar.outputs.files.singleFile.name
}.each { file ->
exclude file.name
}
}
}
}
}

Gradle sourceSet depends on another sourceSet

This Question is similar to Make one source set dependent on another
Besides the main SourceSet I also have a testenv SourceSet.
The code in the testenv SourceSet references the main code, therefor I need to add the main SourceSet to the testenvCompile configuration.
sourceSets {
testenv
}
dependencies {
testenvCompile sourceSets.main
}
This does not work, because you cannot directly add sourceSets as dependencies. The recommended way to do this is:
sourceSets {
testenv
}
dependencies {
testenvCompile sourceSets.main.output
}
But this does not work correctly with eclipse, because when I clean the gradle build folder, eclipse can't compile anymore, since it depends on the gradle build.
Also if I change main code I'd have to rebuild the project in gradle for the changes to take effect in eclipse.
How do I declare the dependencies correctly?
EDIT:
This
sourceSets {
testenv
}
dependencies {
testenvCompile files(sourceSets.testenv.java.srcDirs, sourceSets.testenv.resources.srcDirs)
}
works for the main source, but because I now reference the .java files I am missing generated classes from the Annotation-Processor :(
So after all this is the way to go:
sourceSets {
testenv
}
dependencies {
testenvCompile sourceSets.main.output
}
To make it work correctly with eclipse you have to manually exclude all sourceSet outputs from the eclipse classpath.
This is ugly, but it works for me:
Project proj = project
eclipse {
classpath {
file {
whenMerged { cp ->
project.logger.lifecycle "[eclipse] Excluding sourceSet outputs from eclipse dependencies for project '${project.path}'"
cp.entries.grep { it.kind == 'lib' }.each { entry ->
rootProject.allprojects { Project project ->
String buildDirPath = project.buildDir.path.replace('\\', '/') + '/'
String entryPath = entry.path
if (entryPath.startsWith(buildDirPath)) {
cp.entries.remove entry
if (project != proj) {
boolean projectContainsProjectDep = false
for (Configuration cfg : proj.configurations) {
boolean cfgContainsProjectDependency = cfg.allDependencies.withType(ProjectDependency).collect { it.dependencyProject }.contains(project)
if(cfgContainsProjectDependency) {
projectContainsProjectDep = true
break;
}
}
if (!projectContainsProjectDep) {
throw new GradleException("The project '${proj.path}' has a dependency to the outputs of project '${project.path}', but not to the project itself. This is not allowed because it will cause compilation in eclipse to behave differently than in gradle.")
}
}
}
}
}
}
}
}
}

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'
}

How to keep Java code and Junit tests together building with Gradle

I have a project in which the main source and the test cases for that source are kept in the same package/directory. Each test class is the name of the class which it is testing with "Test" appended on the end. So if I have a Foo.java there will be a FooTest.java right next to it.
My question is, how do I build this project with Gradle? I'd still like to keep the class files separate, i.e. a folder for main classes and a folder for test classes.
This should do the trick:
sourceSets {
main {
java {
srcDirs = ["some/path"]
exclude "**/*Test.java"
}
}
test {
java {
srcDirs = ["some/path"]
include "**/*Test.java"
}
}
}
For reference, here is the code I used to try to get around the Eclipse plugin's classpath issue. Using this in combination with Peter's answer above seems to work.
// The following ensures that Eclipse uses only one src directory
eclipse {
classpath {
file {
//closure executed after .classpath content is loaded from existing file
//and after gradle build information is merged
whenMerged { classpath ->
classpath.entries.removeAll { entry -> entry.kind == 'src'}
def srcEntry = new org.gradle.plugins.ide.eclipse.model.SourceFolder('src', null)
srcEntry.dir = file("$projectDir/src")
classpath.entries.add( srcEntry )
}
}
}
}
this work for me:
eclipse {
classpath {
file {
withXml {
process(it.asNode())
}
}
}
}
def process(node) {
if (node.attribute('path') == 'src/test/java' || node.attribute('path') == 'src/test/resources')
node.attributes().put('output', "build/test-classes")
else
node.children().each {
process(it)
}}

Resources