How to specify output.classesDir for custom sourceSet in Gradle? - gradle

My build uses source code from two projects: ProjectA and ProjectB, and produces JAR with classes and resources from ProjectB. I defined custom sourceSet mainProjectB which is supposed to have output in a separate directory:
sourceSets {
mainProjectB {
output.classesDir = "$buildDir/build/classes/projectB"
output.resourcesDir = "$buildDir/build/resources/projectB"
java { srcDirs = ['src/main/java']}
resources { srcDirs = ['src/main/resources']}
}
mainProjectA {
java { srcDirs = [
'../projectA/src/main/java'
]}
resources { srcDirs = [
'../projectA/src/main/resources'
]}
}
test {
java {
srcDirs = [
'../projectA/src/test/java',
'src/test/java'
]}
resources {
srcDirs = [
'../projectA/src/test/resources',
'src/test/resources'
]}
}
}
compileJava {
source sourceSets.mainProjectB.allJava
source sourceSets.mainProjectA.allJava
}
processResources {
from sourceSets.mainProjectB.resources
from sourceSets.mainProjectA.resources
}
jar {
from sourceSets.mainProjectB.output.classesDir
from sourceSets.mainProjectB.output.resourcesDir
}
Problem: custom sourceSet mainProjectB ingores specified output directories.
The directories "$buildDir/build/classes/projectB" and "$buildDir/build/resources/projectB" are not created, and as a consequence, JAR includes files from both projects (instead of ProjectB).
UPDATE:
Projects A and B have circular dependencies. That is why they have to share source code.

I would consider to use subprojects and project to achieve your goal - gradel docs . With the following approach you can get any kind of jar file depending on your build :
group 'CoreProject'
version '1.0-SNAPSHOT'
subprojects {
apply plugin: 'java'
repositories {
mavenCentral()
}
}
project (':projectA') {
}
project (':projectB') {
def generatedResources = "$buildDir"
//in case you want resources and classes to be written to custom location where
//redefined paths are relative to projectB root folder
sourceSets {
main {
output.classesDir = 'build/classes/projectB'
output.resourcesDir = 'build/resources/projectB'
}
}
dependencies {
compile project(':projectA')
}
jar {
manifest.mainAttributes(
'Main-Class': "ProjectBClass"
)
}
//To create fat Jar that will contain classes and resources from all dependencies
task fatJar(type: Jar) {
manifest.from jar.manifest
classifier = 'all'
from {
configurations.runtime.collect { it.isDirectory() ? it : zipTree(it) }
} {
exclude "ProjectAResource" //if want to exclude resources from projectA
exclude "META-INF/*.SF"
exclude "META-INF/*.DSA"
exclude "META-INF/*.RSA"
}
with jar
}
}
If you run jar task of projectB following jars will be created, each including only its own classes and resources : projectA/build/libs/projectA.jar , projectB/build/libs/projectB.jar('JAR with classes and resources from ProjectB' as you asked in your comment)
If you run farJar task of projectB the following jar file will be created that includes classes and resources from both projects and you can exclude any files patterns from projectA and projectB projects to create any final jar you like : projectB/build/libs/projectB-all.jar
Here is a screenshot of projects folders structure I created to mimic your scenario(as I understood it):
P.S. Also make sure none of the folders projectB/build and projectA/build are locked by any process and remove those handles if any, as otherwise Gradle will fail to run.

Related

Gradle ShadowJar jar of jars without unzipping classes

I am trying to create a jar of jars without unzipping class files from each jar. Unfortunately shadowJar unzip's all jars and resulting jars contain directories instead of jars.
My build.gradle file is:
apply plugin: 'com.github.johnrengelman.shadow'
dependencies {
compile("ldapjdk:ldapjdk:1.0"){
transitive = false
}
compile("support:activemq-core:5.3.1"){
transitive = false
}
compile("support:concurrent:0.0"){
transitive = false
}
compile("dom4j:dom4j:${dom4j_version}"){
transitive = false
}
compile("commons-lang:commons-lang:${commons_lang_version}") {
transitive = false
}
}
task copyRuntimeLibs(type: Copy) {
from(project(':server').configurations.runtime)
include 'commons-lang2*'
include 'ldapjdk*'
include 'dom4j*'
include 'concurrent*'
}
task copyFiles(dependsOn: [copyRuntimeLibs])
task copyToLib( type: Copy ) {
into "$buildDir/lib"
from configurations.runtime
}
jar { dependsOn copyToLib }
shadowJar {
zip64 true
baseName = "service"
from("$buildDir/lib") {
include '**'
}
}
I've tried from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }. This also extracts classes, MANIFEST, etc.
Is there a way to not extract classes from each jar & instead make a jar of jars?
Thanks a lot.
You may want to see this GitHub issue.
https://github.com/johnrengelman/shadow/issues/111
It is actually not solved yet in the Shadow plugin, there some workarounds are shown there.

How to collect javadoc jars into a zip file

For a multi-project Gradle project, foo, bar and baz. I'm trying to create a task which creates a zip file with both libraries and javadoc, i.e. foo.jar, AND foo-javadoc.jar..
./build.gradle
./settings.gradle
./foo/build.gradle
./bar/build.gradle
./baz/build.gradle
settings.gradle
include ":foo"
include ":bar"
include ":baz"
Top level build
allprojects {
apply plugin: 'java'
task generateJavadoc (type : Javadoc) {
source = sourceSets.main.allJava
classpath = sourceSets.main.compileClasspath
failOnError = false
}
task javadocJar(type: Jar, dependsOn: generateJavadoc) {
classifier = 'javadoc'
from generateJavadoc.destinationDir
}
artifacts {
archives javadocJar
}
}
task buildZip(type: Zip, dependsOn: build) {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
from (project(':foo').configurations.runtime) {
into 'jars'
}
from (project (':foo').configurations.archives.all) {
into 'jars'
}
}
When I invoke this with gradle clean buildZip a zip file is created, but without the any -javadoc JARs I was expecting... The JavaDoc jars are generated into the project build directories, e.g. foo/build/lib/foo-javadoc.jar I've tried multiple combinations of from project (':foo').artifacts etc.
This is possible using the following. Note javadocJar is the name of the task defined in the allprojects block
from (rootProject.allprojects.javadocJar.outputs) {
into 'javadoc'
}

Configuration for projects in subdirectory

I have a Gradle multi-project build that looks like this:
rootProject
build.gradle
settings.gradle
shared/
SharedLib
SharedLib2
plugins/
FirstPlugin
SecondPlugin
I'd like to add all projects in the directory shared as dependencies to all projects in plugins.
More generally speaking: How do I configure subprojects by directory?
Contents of settings.gradle:
include 'plugins:FirstPlugin', 'plugins:SecondPlugin', 'shared:SharedLib', 'shared:SharedLib2'
Contents of build.gradle:
task wrapper(type: Wrapper) { gradleVersion = "2.1" }
allprojects{ apply plugin:"java" }
subprojects {
group = "eu.test.myGroup"
repositories { mavenCentral() }
dependencies { testCompile "junit:junit:4.11" }
}
Adding this to build.gradle does what I wanted to achieve:
// Define what's a plugin and what's a shared library by directory paths.
// Ignore empty projects
def plugins = subprojects.findAll{ it.path.contains("plugins") && hasSrc(it) }
def sharedLibs = subprojects.findAll{ it.path.contains("shared") && hasSrc(it)}
/** Checks whether a project has a source directory */
def hasSrc(proj){
return new File(proj.projectDir, "src").exists()
}
// Configure the plugins to depend on the shared libraries at compile time
configure(plugins) { dependencies { sharedLibs.each{compile it} } }

Is it possible to customise the source sets used by the Gradle license plugin?

buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'nl.javadude.gradle.plugins:license-gradle-plugin:0.6.0'
}
}
apply plugin: 'license'
license {
sourceSets {
main {
java {
exclude '**'
}
test {
exclude '**'
}
}
}
mapping {
javascript='JAVADOC_STYLE'
xml='XML_STYLE'
xsl='XML_STYLE'
html='XML_STYLE'
Rptdesign='XML_STYLE'
}
}
I have read that by default license is added to all sourceSets created by Java Plugin.to customise sourceSets - when i add sourceSets license is not adding to .java files,when i remove sourceSets block license is updating all .java,.groovy files in src/main/ test & java directiries but i have to add license for specfic files like .xml,.xsl at root directory and some specific java files like which starts with s*.java, can any one helpme.
I had the same problem and I found a solution here : https://github.com/hierynomus/license-gradle-plugin/issues/9
You can add the following to your build.gradle and then the license plugin skips the excluded files.
import nl.javadude.gradle.plugins.license.License
tasks.withType(License).each { licenseTask ->
licenseTask.exclude '/*.json'
licenseTask.exclude '/*.properties'
}
( and remove license { sourceSets { ... } })

Build jar for each main class using gradle

1.My project has two main class i want to build jar for each main class using gradle. my source has 2 files ValidationRule.java
SupportValidator.java both the file have one main class each i want to
build the jar for each main class
i can achieve the same from eclipse working fine
2.I want to load the source file for my project from 2 different folder,some part is there in one folder and remaining is
there in
another folder i.e like
project/src snd another folder outside the project(../../../SharedClass)
my script as follows
apply plugin: 'eclipse'
apply plugin: 'java'
sourceCompatibility = 1.6
archivesBaseName = 'Process_XY'
configurations {
configurations.compile.transitive = false
}
dependencies {
compile fileTree(dir:'/trunk/Solutions/project/Source/Binaries/CommonFunctions/build/libs', include: '*.jar')
compile fileTree(dir:'/trunk/Solutions/project/lib/GeoTools/geotools-2.7.4-bin/geotools-2.7.4', include: '*.jar')
compile "org.apache.hadoop:hadoop-core:1.0.3"
compile "commons-collections:commons-collections:3.2.1"
compile "commons-configuration:commons-configuration:1.6"
compile "commons-discovery:commons-discovery:0.2"
compile "commons-lang:commons-lang:2.4"
compile "commons-logging:commons-logging:1.1.1"
compile "commons-logging:commons-logging:1.0.4"
compile "log4j:log4j:1.2.16"
compile "com.vividsolutions:jts:1.8"
compile "commons-net:commons-net:1.4.1"
compile "org.apache.hadoop:hadoop-core:1.0.3"
compile "commons-httpclient:commons-httpclient:3.0.1"
compile "org.mortbay.jetty:servlet-api:2.5-20081211"
compile "org.apache.hbase:hbase:0.94.0"
compile "org.apache.zookeeper:zookeeper:3.4.3"
}
repositories {
mavenCentral()
maven { url "https://repository.cloudera.com/artifactory/cloudera-repos/" }
maven { url "http://repo.springsource.org/libs-release" }
maven { url "http://repo.springsource.org/libs-milestone" }
maven { url "http://repo.springsource.org/libs-snapshot" }
maven { url "http://www.datanucleus.org/downloads/maven2/" }
maven { url "http://oss.sonatype.org/content/repositories/snapshots" }
maven { url "http://people.apache.org/~rawson/repo" }
}
jar {
from configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
manifest.attributes("Main-Class":"org.project.seismic.Process_XY")
}
sourceSets {
main {
java {
source = ['src/org', '../../../SharedClass/org']
}
}
}
above in sourceSets method i tried to load source from 2 folder but it
didnt worked
Thanks in advance..!!
How to achieve using gradle.
Ok, first of all, the source on a SourceDirectorySet takes another SourceDirectorySet. The srcDirs method however takes paths. Change that block to the following:
sourceSets {
main {
java {
srcDirs ['src/org', '../../../SharedClass/org']
}
}
}
And you can easily add a second jar task as follows:
task secondJar(type: Jar) {
name = other-main-jar
from ...
manifest.attributes(...)
}
assemble.dependsOn(secondJar)
This will register a new Jar task called secondJar and makes sure that when the project is assembled, this jar is also created.

Resources