Why won't gradle jar build a jar that gradle build does? - gradle

In my Gradle project, I define an additional sourceSet.
sourceSets {
sample {
java {
srcDir 'sample/java'
}
compileClasspath += sourceSets.main.output + sourceSets.main.compileClasspath
}
}
I then add a task:
task sampleJar(type: Jar) {
classifier 'sample'
from sourceSets.sample.output
}
artifacts {
archives sampleJar
}
If I do > gradle build the additional jar file builds from the additional source set. However, if I do > gradle jar, it doesn't. any reason why?
When I go through the output messages, I see:
gradle build has sampleJar in the Tasks to be executed:
but
gradle jar doesn't.
But unsure as to why?

Because jar is just the task that assembles the main jar file.
build, on the other hand, is the top-level life-cycle task, which depends on assemble. And assemble is documented as
Depends on: jar, and all other tasks that create artifacts attached to the archives configuration.
Since your sampleJar pecisely creates an artifact attached to the archives configuration, assemble, and thus build depends on it.

Related

How to set output file from another gradle build script's task from GradleBuild task?

I have project A with gradle build. I have another project B with gradle build also. I want to include project B's jar into project A's war. I can call project B's build script from project A's build script (see below).
But I can not set project B's jar as output file of task buildB.
Is there any way to set project B's jar (which is output file of task jar) as output file of task buildB?
task buildB(type: GradleBuild) {
buildFile = "../BProject/build.gradle"
tasks = ["clean", "jar"] // jar task produce xxx.jar as it's outputs.files
// HERE, any script to set xxx.jar as outputs.files of task buildB???
}
war {
from (buildB) { // can not get xxx.jar from buildB
into "WEB-INF/classes"
}
}
You probably need to configure a multi module project and define a project-scope dependency.
Since the answer full answer will be lengthy, here you can find a demo that shows how it can be done.
The demo consists of two projects. One project is built to war and has a dependency to another project which is built to war. If you build a project, b will be built automatically and included as a jar.
This is what I did.
/settings.gradle
include 'AProject', 'BProject'
/AProject/build.gradle
task buildB(type: GradleBuild) {
buildFile = "../BProject/build.gradle"
tasks = ["clean", "jar"] // jar task produce xxx.jar as it's outputs.files
}
war {
dependsOn buildB
doFirst {
from (project(':BProject').tasks['jar']) {
into "WEB-INF/classes"
}
}
}

maven project as dependency in gradle project

I have a project which is using Gradle as build tool and a second subproject which is using Maven's POM. I don't have the freedom of changing build tool on the subproject.
What I want to achieve is to add my project with Maven POM as dependency on my Gradle project.
Where root (current dir) is my project with Gradle and contains the build.gradle, the Maven project is under vendor/other-proj/ with POM file just under that directory.
I have tried these variations on my build.gradle file:
1st try:
include("vendor/other-proj/")
project(':other-proj') {
projectDir = new File("vendor/other-proj/pom.xml")
}
dependencies {
compile project(':other-proj')
}
2nd try:
dependencies {
compile project('vendor/other-proj/')
}
3rd try:
dependencies {
compile project('vendor/other-proj/pom.xml')
}
4th try:
dependencies {
compile files 'vendor/other-proj/pom.xml'
}
I can't find anything related on the web, it seems most Gradle/Maven use cases are affected by publishing to Maven or generating POM, but I dont want to do any of those.
Can anybody point me to right direction?
you can "fake" including a Maven project like this:
dependencies {
compile files("vendor/other-proj/target/classes") {
builtBy "compileMavenProject"
}
}
task compileMavenProject(type: Exec) {
workingDir "vendor/other-proj/"
commandLine "/usr/bin/mvn", "clean", "compile"
}
This way Gradle will execute a Maven build (compileMavenProject) before compiling. But be aware that it is not a Gradle "project" in the traditional sense and will not show up, e.g. if you run gradle dependencies. It is just a hack to include the compiled class files in your Gradle project.
Edit:
You can use a similar technique to also include the maven dependencies:
dependencies {
compile files("vendor/other-proj/target/classes") {
builtBy "compileMavenProject"
}
compile files("vendor/other-proj/target/libs") {
builtBy "downloadMavenDependencies"
}
}
task compileMavenProject(type: Exec) {
workingDir "vendor/other-proj/"
commandLine "/usr/bin/mvn", "clean", "compile"
}
task downloadMavenDependencies(type: Exec) {
workingDir "vendor/other-proj/"
commandLine "/usr/bin/mvn", "dependency:copy-dependencies", "-DoutputDirectory=target/libs"
}
You cannot "include" a maven project in gradle settings.gradle. The simplest way would be to build the maven project and install it to your local repo using mvn install(can be default .m2, or any other custom location) and then consume it from your gradle project using groupname:modulename:version
repositories{
mavenLocal()
}
dependencies{
implementation 'vendor:otherproj:version'
}
It is possible to depend directly on the jar of the maven project using compile files but this isn't ideal because it wont fetch transitive dependencies and you'll have to add those manually yourself.

Why does my jar file not not contain any class files?

I'm trying to add a task (gen or gen2) to my build.gradle that does exactly the same as the Jar-task:
version = "0.0.1"
apply plugin: 'java'
task('gen', type: Jar) {
}
task gen2(type: Jar)
Running
gradle jar
generates a JAR-file that contains .class-files, while running
gradle gen
or
gradle gen2
generate a JAR-file that does NOT contain any .class-files.
Whats wrong with my class definition?
To build a jar with all the classes from main, as a default jar task would, do this:
task gen2(type: Jar){
baseName = 'gen2Jar'
from sourceSets.main.output
}
You can also do from(sourceSets.main.output){ include "package" } to customize what packages are included.
Alternatively, to copy settings from the default jar task:
task gen(type: Jar){
baseName = 'genJar'
with jar
}
Infact you can have both of these in the same build.gradle. Running gradle jar builds default jar. gradle gen builds genJar.jar and gradle gen2 builds gen2Jar.jar, all of which contain all the classes from java.main

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.

Gradle : Generating sources from WSDL & XSD and adding it to main classpath for compilation

I am failry new to gradle and have a multiproject gradle build to which want to add a WSDL2Java related tasks to one of the project.
I have coded the necessary tasks to generate,compile,package the generated stubs into a jar and add it to the classpath.
Now , i want to perform these tasks before the java compilation is started.
Below is how i coded the new tasks
task genClasses(type: JavaExec) {
//Run WSDL2Java and generate java source files.
}
task compileClasses(dependsOn:'genClasses'){
//Use ant.javac or add type:JavaCompile in task defination as shown below
// task compileClasses(dependsOn:'genClasses',type:JavaCompile)
}
task packageClasses(dependsOn:'compileClasses',type:Jar){
//package my jar
}
task createStubs(dependsOn: 'packageClasses'){
//add created jar to the classpath
}
compileJava.dependsOn createStubs
The build fails with exception and shows below message
Circular dependency between tasks. Cycle includes [task ':projectx:genWsdlClasses', task ':projectx:classes'].
I figured out that the compileClasses tasks somehow is causing this circular dependency, but not sure how to get rid of it?
Are there any other better or idiomatic ways to perform this source generation, compilation of generated source,packaging and adding it to the main sourceset classpath before the main source gets build?
I use the Jaxb-Plugin available here. My Gradle build file looks like this:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'no.entitas.gradle.jaxb:gradle-jaxb-plugin:2.0'
}
}
dependencies {
jaxb 'com.sun.xml.bind:jaxb-xjc:2.2.5-1'
jaxb 'com.sun.xml.bind:jaxb-impl:2.2.5-1'
}
generateSchemaSource.destinationPackage = "my.custom.package"
I believe that this will create the jaxb classes that you want. Does that help?
Use the plugin "no.nils.wsdl2java"
https://plugins.gradle.org/plugin/no.nils.wsdl2java
The plugin takes care of hooking it in to the build and clean tasks.

Resources