How to control module dependencies, effectively postponing the build of a specific module?


(Jesper Thuun-Petersen) #1

I have a module building a distribution build when all other modules have been build.

I’ve tried to control the order in which modules are build by programmatically letting it depend on all other modules:

// from the build.gradle in the distribution module
afterEvaluate {
 def children = rootProject.allprojects.collect {if (it.name != 'distribution') it}
 children.each { dep ->
  if (dep != null)
   project.dependencies.add("compile",dep)
 }
}

Unfortunately this does not seem to work. The distribution module is still build somewhere in the middle…

What it the best way to handle this?

Regards /Jesper Thuun-Petersen


(Luke Daley) #2

In a nutshell, you’re doing it wrong :slight_smile:

Take a look at: http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:project_jar_dependencies

There’s a specific mechanism for this.


(Jesper Thuun-Petersen) #3

@Luke, you’re right, I’m obviously doing it the wrong way, but I’m afraid you’re reference didn’t help me, as it doesn’t seem to address the issue of programmatically adding dependencies to a module.

Let me try to elaborate on my problem:

I have a multi-module build with ~150 modules, all with different module-dependencies.

One of the modules is a non-java module, but responsible for putting together a large distribution zip file for installation on a server. This module, called ‘distribution’, must be build as the very last module, as it depends on artifacts produced by all the other modules. I do not want to explicitly set these dependencies, as that would have me manually add any new module I introduce. Hence the logic sketched above. Essentially, I want to add all the modules in the settings.gradle, except for the distribution itself.

Could you advice me how I do this in a smart way that actually works?

Regards /Jesper


(Luke Daley) #4

The understanding you are missing is the understanding of project dependencies. They are how you consume the output of another project in a project.

Something like…

afterEvaluate {

rootProject.subprojects { Project subproject ->

if (subproject.name == “distribution”) {

return

}

rootProject.dependencies {

compile project(subproject.path)

}

}

}


(Jesper Thuun-Petersen) #5

Thanks luke, but the problem actually seems to lie somewhere else.

Here’s the resulting list of tasks gradle must execute (after I applied your suggested code):

https://gist.github.com/anonymous/5440962

It does actually make sure that all modules has been compiled.

What I actually need, is for all modules to have been assembled, as the distribution module needs the ‘bndtask’ to have been run on all modules. This is not the case now, as the task list shows (search for distribution).

I’m not sure if this is actually possible to control in Gradle?


(Luke Daley) #6

Do you need the outputs of the subprojects (i.e. to do something with them) or are you just trying to build them all with one command?


(Jesper Thuun-Petersen) #7

The process looks something like this - each module is compiled and jarred like a normal project - the output of each module is OSGi-bundled using the bnd library - the bundle is put in a special output directory - when all bundles has been build, the distribution module assembles the bundles with some other stuff

Right now, the distribution assembly is linked to the classes task of that module. Perhaps this is wrong?

classes << { …call legacy ant target to build distribution }

When this target is called, none of the bundling has been performed, as you can see from the list of targets in the link above.

we have a bnd-task for the bundling, depending on the jar-task. The assemble-task has been redirected to depend on the bnd-task. Right now, I’m experimenting with the distribution module, letting it’s zip task depend on all other modules’ bnd-tasks.