Multiproject configurations


(Conall Prendergast) #1

Hi,
I have a Multi-project structured like:

-A
—B
—C

I want to edit A’s build.gradle with something along the lines of:

allprojects {
    configurations {
            mycompile
    }
}

So in B and C I can use:

dependencies {
    mycompile .......
}

This is so that when I am building an RPM in project A, I can filter the dependencies of each sub-project and include the “mycompile” dependencies with the RPM.
“mycompile” dependencies should also be resolved during build/compile as normal.

However, I keep getting an error:
Could not find method mycompile() for arguments []

I would really appreciate some support on this.
Thanks


(Stefan Oehme) #2

Could you please provide a minimal example project, e.g. on GitHub?


(Conall Prendergast) #3

After a little bit of debugging, I have discovered that the issue only appears when I apply the nebula.rpm plugin.

I have created two build gradle files, one of which works as expected and one which fails.

thanks


(Stefan Oehme) #4

This line evaluates all child projects before you have set up the configuration further down in your build file. A better, lazy alternative would be

dependsOn { subprojects*.build }

Generally you should stay away from reaching into other projects. What you probably want is something more along the lines of:

configurations {
 libs
}

dependencies {
  libs subprojects
}

ospackage {
  from(configurations.libs) {
    into 'bin'
  }
}

(Conall Prendergast) #5

Thanks for the tip. That certainly simplifies things.
Thanks very much, your help is greatly appreciated


(Conall Prendergast) #6

Ok, so I found out what the issue was. It turns out that the build.gradle was laid out in the wrong order. The

allprojects{
    configurations{
        ..............
    }
}

block should have been before the RPM block.

My build.gradle looks like this.

plugins {
  id "nebula.ospackage" version "4.0.0"
}



allprojects {
    repositories{
            jcenter()
    }


    configurations{
            compileRpm
            compile.extendsFrom(compileRpm)
    }
}

ospackage {
    packageName = 'foo'
    version = '1.2.3'
    release = '1'
    arch = I386
    os = LINUX


    into '/opt/foo'


    from(subprojects.configurations.compileRpm.collect()) {
        into 'bin'
    }
}

buildRpm {
    dependsOn getTasksByName('build', true)
}

(Stefan Oehme) #7

That’s what I said :slight_smile: And I also pointed out a better way to do dependsOn which doesn’t have this ordering problem. See the first part of my post above.

But again, this build can be greatly simplified and be made more robust with the change I suggested in the second part. Reaching into subprojects exposes you to all kinds of ordering problems. Using proper dependency declarations fixes that.


(Conall Prendergast) #8

Oh I see what you meant now. Sorry for the confusion. Your method is alot simpler and much cleaner, i think I will use that.
Thanks


(Conall Prendergast) #9

Hi Again,
When I type:

dependencies {
    lib project("foo")
}

How does gradle know that in order to satisfy that dependency it has to make a jar from project foo? Why cant it assume that the dependency is a zip file from the distZip task?


(Stefan Oehme) #10

When you call project('foo'), that’s a shorthand for project(name: 'foo', configuration: 'default'). The default configuration for a Java project includes the jar and the runtime dependencies for instance. But you can depend on any other configuration too.

So for instance if you do this in the subproject:

configurations {
  dist
}

archives {
  dist distZip
}

Then you can get the distZip by having a dependency on project(name: 'foo', configuration: 'dist')


(Conall Prendergast) #11

My God, gradle is powerful.
Many thanks again and apologies for the inconvenience