Aarjav
Aarjav

Reputation: 1374

How to let subprojects choose their own repository configurations in a multi-project build?

I'm new to using build tools and working on multi-project environments in general but I'll try explain the best I can.

Structure

This is the directory structure. (there's more modules actually but I tried to keep it simple for the purpose of this question)

Project vcs repo root
+---Project A/
|       build.gradle
|       settings.gradle
|
+---Project B/
|       build.gradle
|
+---Project C/
|   |   build.gradle
|   \---libs/
|   
+---Project D/
|       build.gradle
|       settings.gradle
|
+---Shared libs/
|
\---build.gradle

Project depedencies:

Each project can get its dependency from one of three places:

  1. mavenCentral
  2. a libs directory from its own root directory. (the libs dir under Project C is only for Project C to use)
  3. Shared libs directory in the project's parent directory.

however the libs folders contents are not guaranteed to be in certain format, (it is not a dir with all jars, there might be sub dirs and such)

Goal

I want each project to be buildable from the project's root directory, and I do not want to keep a redundant copy of repositories/dependencies of a child project in a parent project build. I should only have to provide the locations and possibly version numbers of child projects in the parent's build file.

My Attempt

in C/build.gradle:

apply plugin: 'java'
repositories {
    mavenCentral()
    def myLibsDir = 'libs'
    flatDir name: 'Foo', dirs: "$myLibsDir/foo/4.20"
    //and then do a similar thing for shared libs if needed.
}

dependencies {
    // atrifacts we can get from mavenCentral or 'C/libs/foo/4.20'
}

This works just fine for Project C, All tasks work as expected.

then when setting up A: settings.gradle:

includeFlat 'Project B', 'Project C'

build.gradle:

repositories {
    mavenCentral()
    def sharedLibsDir = '../Shared libs'
    flatDir name: 'Blazer', dirs: "$sharedLibsDir/blz/pls/13.37"
}
dependencies {
    //non-subproject dependencies
    compile project('Project B')
    compile project('Project C')
}

this almost works. only problem is that, unlike dependencies, each sub project's repositories {} is ignored and the parent's is used instead. So if C depends on something in C/libs I'd have to include that in A/build.gradle 's repositories{}

my guess is I could also use something like this and then depend on the subproject's artifact(s) directly. Idk why exactly but this method seems harder to maintain.

Upvotes: 3

Views: 2095

Answers (1)

Kevin Claas
Kevin Claas

Reputation: 61

This answer is obviously late, but I thought I'd post it for anybody else who runs into this problem (as I did). In the subproject's build.gradle, instead of writing:

repositories { ... }

you can write:

[rootProject, this].each {
    it.repositories { ... }
}

This effectively copies the repository block to both the current subproject, and to whatever project is acting as root. The root project no longer needs to know about the repositories its dependents need, which should make this more maintainable.

Upvotes: 6

Related Questions