Reputation: 785
I'm trying to make a dist of a multi project build. The root project looks something like this:
apply plugin: 'distribution'
version 1.0
distributions {
main {
baseName = 'someName'
contents {
from 'nodes'
into 'nodes'
}
}
}
It just copies a folder with some files to the dist.
I now want each subproject to inject its stuff into the dist. I want to add each subprojects jar, any dependecies, and possibly some other files etc...
I have no idea how to inject from the subproject to the root. Should I even do something like that? What i mean is something like this:
subprojects {
apply java...
...
// pseudocode
jack into the root project dist plugin
put my produced jars and dependencies in a folder with my name
...
}
Does anyone have any examples, or just point me in the right direction?
thanks!
Upvotes: 21
Views: 10171
Reputation: 51
Simple as that.
distributions {
main {
contents {
into('lib') {
from subprojects*.jar
from subprojects*.configurations.runtimeClasspath
}
into('doc') {
from subprojects*.javadocJar
}
}
}
}
Upvotes: 0
Reputation: 3139
This is the setup I'm using in a project with multiple libraries to create a "release" archive:
apply plugin: 'distribution'
distributions {
main {
baseName = libVersion
contents {
project.subprojects.each { sub ->
into('lib') {
from sub.jar
}
into('src') {
from sub.sourcesJar
}
into('doc') {
from sub.javadocJar
}
}
}
}
}
Using distZip
task creates an archive with all libraries with their files separated into three folders (lib
contains the actual jars, src
contains jars with sources and doc
contains - you guessed it - Javadoc jars).
Upvotes: 1
Reputation: 10833
I found a solution that has been working well for me. The key is that you add a separate subproject for creating the dist. This subproject is sibling to the other subprojects. That is, do not try to script the distribution in your top-level build.gradle
file.
Let's call the new subproject dist
. The first thing to do is to add it to your top-level settings.gradle
file in your multi-project root:
include "subproject1", "subproject2", "subproject3", ....... , "dist"
Your dist
project must at minimum include:
build.gradle
- to be detailed below src/main/dist/at_least_one_dummy_file.txt
- the distribution plugin always requires a src/main/$distribution.name
directory. Having a non-empty one with a distribution.name
of main
tricks the plugin into following all the transitive dependencies of all the main
sourcesets of all the sibling projects.Next, the build.gradle
file for the dist
project:
/* Hook in all sibling project jars and their transitive dependencies */
apply plugin: 'java'
dependencies {
compile project(':subproject1')
compile project(':subproject2')
compile project(':subproject3')
. . .
}
/* Distribution */
apply plugin: 'java-library-distribution'
distributions {
main {
baseName = "your-top-level-project-name"
contents {
exclude "dist-${version}.jar"
. . .
}
}
}
Then run gradle distZip
. The ZIP
file in dist/build/distributions
will have a lib
subdirectory with every single JAR
you want: the sibling project JAR
s and their transitive dependencies.
Because of the trickery we used, the distribution plugin will make an empty JAR
called dist-${version}.jar
. For cosmetic reasons, I remove it with the exclude
call above, but it is harmless. You could also use a second exclude
call to remove the at_least_one_dummy_file.txt
if there really is no content under src/main/dist
that you want to include. If you do not want add any artifacts and/or remove the ones mentioned here, then you don't even need a contents
section at all.
I also have found ways of selectively including different artifacts based on whether this is a "dev" or "prod" distribution, a la Maven profiles. If you want me to add that, please post in comments and I will.
Upvotes: 7
Reputation: 14637
I actually made it work by combining the approaches from both, pvdissel and sparc_spread.
In my root project I created a directory src/main/dist
where I put exactly one file called .gitkeep
.
The build.gradle
file of my root project looks as follows:
apply plugin: 'java-library-distribution'
allprojects {
....
}
dependencies {
// let root project depend on all subprojects that have the
// application plugin enabled
project.subprojects.each { p ->
p.plugins.withType(ApplicationPlugin) {
compile p
}
}
}
distributions {
main {
contents {
// exclude unnecessary files from archive
exclude ".gitkeep"
exclude "cs3d-toolbox-${version}.jar"
// add start scripts of all plugins that have the
// application plugin enabled to the archive
project.subprojects.each { p ->
p.plugins.withType(ApplicationPlugin) {
into('bin') {
from { p.startScripts.outputs.files }
fileMode = 0755
}
}
}
}
}
}
Works quite well for me. Tested with Gradle 2.0.
Upvotes: 3
Reputation: 163
I was looking for the same thing. With some peeking at the API docs and Gradle' own build files, I came to the following:
apply plugin: 'distribution'
distributions {
main {
contents {
into('bin') {
from { project(':subproject1').startScripts.outputs.files }
from { project(':subproject2').startScripts.outputs.files }
fileMode = 0755
}
into('lib') {
def libs = []
libs << project(':subproject1').configurations.runtime - project(':runner').configurations.runtime
libs << project(':subproject2').configurations.runtime
from libs
from project(':subproject1').jar
from project(':subproject2').jar
}
}
}
}
The contents {} closure is a CopySpec, knowing that makes using the distribution plugin way simpler :)
Check out Gradle' own subprojects/distributions/distributions.gradle file for some great examples of using the CopySpec.
This works.
Sadly, currently I've no clue on how to scale this to more than two projects in a clean way. Atleast we're one step closer :)
Upvotes: 14