Can't get multi project build of non-java projects to trigger build of dependencies


(aaa) #1

I’m trying to create a gradle multi project build for a hierarchy of projects. They aren’t java projects, and I don’t know of any other plugin type that would fit either. I want to take advantage of gradle’s support for dependencies and build order.

My problem is that when I build a project, I can’t get gradle to trigger a build of the projects I am depending on.

Let’s say I have projects proj-a and proj-b that all need to build something. proj-b is dependent on proj-a building first: proj-b -> proj-a

If I build proj-b, I want proj-a to automatically build first. I’ve tried creating this as a multi project build, but I can’t get it working. This is what i’ve got so far:

// settings.gradle
include ( 'proj-a', 'proj-b')
  // build.gradle
subprojects {
    task buildStuff(type: Jar) << {
         println "buildStuff for $project.name"
    }
    configurations {
        compile
    }
    artifacts {
        compile buildStuff
    }
}
  project(':proj-b') {
    dependencies {
        compile project(path: ':proj-a', configuration: 'compile')
    }
}
  project(':proj-a') {
}

I thought that this would mean that proj-b is dependent on proj-a’s “compile” configuration, which in turn is supposed to run task “buildStuff”. I thought that this would mean that when I run “buildStuff” on proj-b, it would trigger running “buildStuff” on proj-a, but I’m obviously not getting it.

The actual results are:

If I run ’ gradle dependencies’ for proj-b, I get: ‘’’ compile — gradle-deps:proj-a:unspecified ‘’’

And if I run ‘gradle buildStuff’ in proj-b, I get: ‘’’ :proj-b:buildStuff buildStuff for proj-b ‘’’

My expectation here was that “:proj-a:buildStuff” would be built before “:proj-b:buildStuff”, but it isn’t.

What am I getting wrong here? Am I missing some detail, or have I completely misunderstood project dependencies and configuratons?

Any tips on how I change my scripts to get this working?


(Perryn Fowler) #2

Hi Magnus

I think you have got the basic gist, but you are (quite understandably) missing one basic concept:

When you say

configurations {
        compile
    }

You are simply declaring a configuration named ‘compile’. The fact that it is called ‘compile’ is of no particular significance to vanilla Gradle; you might as well have called it ‘foo’.

A configuration named compile is of significance to the compileJava task of the Java plugin. It uses that configuration to build up the classpath it uses when compiling.

You are not compiling Java though, so you need to make your ‘buildStuff’ task use your compile configuration somehow. Since I don’t know what language you are using I don’t know how, but here is a simplistic example that assumes all ‘buildStuff’ does is zip up the source. See how I told the ‘buildStuff’ task that the compile configuration is an input?

apply plugin: 'base'
  subprojects {
    apply plugin: 'base'
      configurations {
        compile
    }
      task buildStuff(type: Zip) {
         from "src"
        from configurations.compile
        baseName project.name
        doLast {println "buildStuff for $project.name"}
              }
    artifacts {
        compile buildStuff
    }
}
  project(':proj-b') {
   dependencies {
       compile project(path: ':proj-a', configuration: 'compile')
   }
}
  project(':proj-a') {
}

Some extra things to note about this: - I used the ‘base’ plugin. It provides some nice defaults for a number of things, but should not be strictly necessary. - I used a Zip task, rather than Jar (Not sure why you would use Jar if your project isn’t Java)

BTW what language are you using out of interest?


(aaa) #3

Hi, thanks for a great answer, it resolved my issue!

The language used is actually java, but it’s tightly coupled to a proprietary ant based build system (100+ projects) with no automatic dependency resolution.

Rather than immediately switching to gradle, I thought I might do it in increments. The first step I’m working on now is to bolt-on a thin gradle script that would invoke ant on the projects in the (correct) order of dependencies…

Does this sound reasonable? Or is there a better way to go about this, do you think?