Getting Gradle to publish a source Jar instead of a standard compiled Jar - gradle

I am slowly moving two projects over to Gradle. Project A produces a jar file that is used by Project B.
Project A is a GWT component and Project B is a GWT application.
How do I get Gradle to generate a Jar that contains the Java source code of Project A rather than the compiled classes?
I have tried adding the following to the build.gradle file, but this generates a second Jar file containing the source - I want the main artefact to contain the source, so that it is published to my local Maven repository when I run the install task.
task sourceJar(type: Jar) {
classifier = 'sources'
from sourceSets.main.allSource
}
artifacts {
archives sourceJar
}
Is there a way to override the standard Jar creation task?

You can define your own 'myArtifacts' configuration and publish that instead. Note that since the install task is of type Upload, you should be able to change the default artifacts configuration from archives to sourceArchives:
configurations{
sourceArchives
}
artifacts{
sourceArchives sourceJar
}
install.configuration = configurations.sourceArchives
Hopefully, install should now just publish members of sourceArchives configuration.

Related

Defining multi-module dependency using custom configuration in Gradle does not trigger required tasks

I have two modules in my Gradle project:
ts containing single page app sources
edge containing Java sources which will serve said SPA
I have managed to integrate Yarn build with Gradle so that executing gradle :ts:assemble will produce single zip file with compiled js files and also including that archive in the final JAR via gradle :edge:processResources using custom configuration that expects zip files. Everything works fine if I just manually invoke gradle :ts:assemble :edge:processResources however if I try gradle :edge:processResources the build will fail immediately with File not found error. Somehow Gradle doesn't know that it should assemble ts project before processing resources of edge
ts/build.gradle
configurations {
create("default")
}
artifacts {
add("default", assemble) {
name = project.name
version = project.version
classifier = extension
}
}
//Yarn tasks omitted for brevity
edge/build.gradle
configurations {
bundle
}
dependencies {
bundle project(":ts")
//other dependencies
}
processResources {
configurations.bundle.files.each { bundle ->
from zipTree(bundle)
into "public"
}
}

Gradle include jar produced by another project in war

Currently I have two projects with gradle build.gradle. The first is going to create a fat jar file, which I would like to include in a war file. I thought compiling it would be enough, but it doesn't seem to be ending up in the /lib directory of my war file. Anyone have thoughts I am quite new to gradle.
dependencies {
compile project(':JarProject')
providedCompile 'javax.servlet:javax.servlet-api:3.1.0'
providedCompile 'org.apache.tomcat:tomcat-jsp-api:7.0.55'
}
war {
archiveName 'WarProject.war'
from 'JarProject/build/libs'
webXml = file('src/web.xml')
}
Does the second project war need to be in providedRuntime? Or should I publish the jar from the other project in the local maven repo and include it that way?
The War task essentially behaves like a CopyTask with regards to stuff it packs in the war, so the documentation on working with files is useful. In essence, I think you need something like (untested):
from fileTree('JarProject/build/libs') {
into("lib")
}
That being said, using mavenLocal() and publishing there also works, but it can lead to unexpected results when the war includes some old version from local, picking up the jar explicitly from the file system like above is better.
I think the elegant solution would be to use multi project builds and project level dependencies. You would have the two builds as separate projects of the same Gradle build and add the "jar project" as a regular compile dependency.
How have you declared the dependency? I assume you have a multi-project build with subprojects A and B, both using the War plugin. I made an experiment using Gradle 2.4 and if I declare B/build.gradle like this:
apply plugin: 'war'
dependencies {
compile project(':A')
}
then B.war contains WEB-INF/lib/A.jar. If you correctly follow conventions of Gradle War plugin (place web resources in A/src/main/webapp/ and code-related resources in A/src/main/resources/), then A.jar should contain what you want.
see this

How can I get gradle to populate jars with dependency metadata?

So if I build a jar in Maven, say for example jackson-core-2.5.1.jar, I find the following in the artifact:
META-INF/maven/
META-INF/maven/com.fasterxml.jackson.core/
META-INF/maven/com.fasterxml.jackson.core/jackson-core/
META-INF/maven/com.fasterxml.jackson.core/jackson-core/pom.properties
META-INF/maven/com.fasterxml.jackson.core/jackson-core/pom.xml
Gradle, however, does not seem to create this data. Problem is that we have several components of our build, including a parent project, that aren't hosted in the same SCM location. For our large and complex build, how would Gradle know that a locally built artifact in one SCM location depends on a locally built artifact in another, if there's no metadata? What is the Gradle way to manage this situation?
Repositories contain a separate copy of pom.xml. It usually lives next to the JAR file in the physical structure on the disk. This applies to binary repositories like Nexus or Artifatory and also to your local Maven repository (under $HOME/.m2/repo).
If for some reason you want to copy the behavior of Maven you can tell Gradle to do create those files. We use this customization in subprojects closure that configures our multi-project Gradle build.
jar {
// until we have better solution
// https://discuss.gradle.org/t/jar-task-does-not-see-dependency-when-using-maven-publish/11091
if (project.tasks.findByName('generatePomFileForMavenJavaPublication')) {
dependsOn 'generatePomFileForMavenJavaPublication'
} else {
project.tasks.whenTaskAdded { addedTask ->
if (addedTask.name == 'generatePomFileForMavenJavaPublication') {
project.tasks.jar.dependsOn 'generatePomFileForMavenJavaPublication'
}
}
}
into("META-INF/maven/$project.group/$project.archivesBaseName") {
/*
from generatePomFileForMavenJavaPublication
*/
from new File(project.buildDir, 'publications/mavenJava')
rename ".*", "pom.xml"
}
}
It would be simpler if there wasn't a problem with generatePomFileForMavenJavaPublication task being created lazily sometimes. And you need to check how to create your properties file. I guess you can dump properties from a running Gradle process there.

Zipping up a directory and uploading it to local maven

I'm attempting to zip up a directory of minified javascript and css, and then publish it to my local maven repo.
I can't simply publish the artifact, because publishing requires the install task, which is only available if I include BOTH the maven AND java plugin.
Including the java plugin produces a jar file, which I do not want.
I've attempted to use the maven-publish plugin, but it also seems to only want to publish .jar and .war files.
Is there any way to simply zip up my build directory (which only contains minified js and css produced from gulp) and upload it to my local maven repo without involving unneeded plugins?
In this case you can simply declare your own Upload task to accomplish this.
apply plugin: 'maven'
task install(type: Upload) {
configuration = configurations.archives
repositories {
maven {
url "file://${System.getProperty('user.home')}/.m2/repository"
}
}
}
artifacts {
archives archiveTask // replace with name of task that builds you .zip
}

How to add a war build to a distribution

We have a gradle project that does a distTar to create a tar distribution file.
Each dependency project builds good placing all the dependencies and project jar files into the distribution libs folder.
We need to add a project that builds a war file. By adding the project as a dependency it adds all the war dependencies ... we need just the war file from the project war task.
Also the war project war task is not being executed.
Instead the jar task is being executed from distTar of the distribution project.
How do we execute the project war task and add just the war file to a "gui" folder in the tar distribution?
To get the built war file into the distribution add a task which the distTar depends. Have the depends on task depend on the other project war task. Take the output files and put them in the distribution. The key is to do the into/from in a doLast so the depends on other project war completes before the into/from for the distribution.
// create a task depends on other project war
// put into the distribution gui folder the war.output.files
// the doLast gives visibility to the war.outputs.files
// after the depends on is complete
task otherProjectWar(dependsOn: ':OtherProject:war') {
doLast {
applicationDistribution.into("gui") {
from( project(':OtherProject').war.outputs.files )
}
}
}
// add depends on for distTar
distTar {
dependsOn otherProjectWar
...
}
I believe the proper approach is to include desired task outputs to the distribution. Here is sample script that adds jar built by the project to the main distribution (for war use war outputs instead of jar outputs).
apply plugin: 'java'
apply plugin: 'distribution'
distributions {
main {
contents {
from jar.outputs
}
}
}
Running the distribution task then correctly resolves dependencies for both zip and tar.
> gradlew distTar
:clean
:compileJava
:processResources NO-SOURCE
:classes
:jar
:distTar
You'll need to add a dependency to the output of the war task. By default, ProjectDependency simply adds a dependency to the default configuration of that project.
dependencies {
compile project(':myproject').war.outputs.files
}
Edit: To clarify, compile probably isn't the best configuration to add this dependency to, this is just an example. If indeed all this project is doing is aggregating dependencies into a single distribution archive then the configuration is likely irrelevant.

Resources