Gradle Goodness: Inter-Project Artifact Dependencies
When we define dependencies in Gradle we usually define them to compile source files. For example we create a Java project and need the Spring framework, then we define a dependencies
configuration block with a dependency to the Spring libraries for the compile
configuration. We can also use the dependencies
configuration block to define dependencies on artifacts used in other tasks than the compiling source files. For example we might have a multi-module project where we want to aggregate artifacts from several projects into one place with the Copy
task.
In the following example we have a multi-module project where projects projectA
and projectB
have a dist
task to create a Tar file. In the project docker
we want to copy the Tar files from those projects into the build directory. To achieve this we first apply the Gradle base plugin, because then we can use the artifacts
configuration block. Inside the artifacts
configuration we define that our dist
task that creates the Tar file is assigned to the dockerDist
configuration as artifact. This sets up our projects that create the artifact. The docker
project uses these artifacts in the task prepare
. The prepare
task copies the artifacts of projectA
and projectB
to the build directory of the docker
project.
configure(
subprojects
.findAll {
it.name.startsWith('project') }) {
// We need to base plugin for artifacts support.
apply plugin: 'base'
// Archive task where the archive file
// is the artifact for our project we want
// to use in aonther project.
task dist(type: Tar) {
compression 'gzip'
from 'src/data'
}
configurations {
// New configuration to associate
// dist task output with.
dockerDist
}
artifacts {
// Declare output of dist task
// as artifact for the dockerDist
// configuration.
dockerDist dist
}
}
// Project with dependencies on the artifacts
// of projectA and projectB.
project('docker') {
configurations {
// Configuration needed to use
// in the dependencies.
dockerSource
}
dependencies {
// Define that we depend on the artifacts
// of projectA and projectB assigned to the
// dockerDist configuration.
dockerSource project(path: ':projectA', configuration: 'dockerDist')
dockerSource project(path: ':projectB', configuration: 'dockerDist')
}
task prepare(type: Copy) {
into "$buildDir/docker"
// Use the artifacts from the other projects.
// Gradle knows that tasks that created the artifacts
// and will invoke them for us.
from configurations.dockerSource
}
}
Now let's run the :docker:prepare
task from the command line:
$ gradle :docker:prepare
:projectA:dist
:projectB:dist
:docker:prepare
BUILD SUCCESSFUL
Total time: 0.796 secs
$ tree docker/build/
docker/build
└── docker
├── projectA.tgz
└── projectB.tgz
1 directory, 2 files
$
Notice we didn't define a task dependency on the dist
tasks, but Gradle knows by using the dependencies configuration which tasks need to be executed to fulfil all dependencies for the prepare
task.
Written with Gradle 2.11.