Gradle multi repository/separately deployable projects

Posted on stackoverflow: http://stackoverflow.com/q/28108370/1043419

I have a setup of (at least) two development projects (A and B) and a shared API

A is core and implements the API

B is integration and uses the API

The projects are separate in that I can deploy each separately. They are also in two separate repositories.

Use case 1: I’m working in core and only wants to see the released version of the API

Use case 2: I’m working on integration and only want to use the released version of API

Use case 3: I’m developing the API and want the source of both core (A) and integration (B)

You would need three completely separate builds. In use case 1 and 2 I would like to use a maven dependency, where I in use case 3 would like to use a gradle project dependency.

How would you setup your gradle builds to this (very common?) usage?

NOTE:

A way to think of it is when opening an IDE. In use case 1 and 2, the IDE would open the source of core and integration respectfully and using a jar-file dependency for API. For use case 3 the IDE would have sources for core, integration, and API (all three repos open)

My comment from stackoverflow: When you are working with the API (and not only one or the other side), you want to refactor among other things. (It’s not an external API). If API is a misleading word, then think of abstract module whose intent is inversion of control

Put a conditional around the dependency definition so you can select either the project or maven dep.

Well yes we have done that. But project A, B, and the ‘API’ needs to be separate gradle projects, so that you can checkout and build then separatly. So at this point we are using tasks of type GradleBuild to initiate builds from A to ‘API’

This however seems like a very lowlevel solution, where you loose lots of gradle capabilities, for a problem that seems very basic for anything but the smallest projects.

We’re working on core support for this use case. In the meantime you have some options:
- Prezi Pride: https://github.com/prezi/pride
- Elastic-deps: https://github.com/pniederw/elastic-deps

Well it sounds great that you are adding support for this use case.

Do you have any documentation, wiki, or discussion group around this feature?

We looked at your two links, and have some comments to both of them:

Prezi Pride: In my view, the biggest problem with this plugin is, that it steps out of the domain of gradle. You need an extra program install, which again removes the benefits of the wrapper.

Elastic-deps: The biggest problem here (in my view), is that you need a pseudo root project. The subprojects should be complete standalone gradle projects. With a root project you remove the possibility to work on a subproject ‘standalone’.

Both: Both projects tries to solve the problem by adding an artificial root project. By adding this, you get all the gradle goodness, and that’s probably why they did it that way.

Our humble hackish plugin (we will probably publish it if we get time to clean it up): The basic premises is that we want it to be just another dependency, so instead of e.g.

“compile ‘group:name:verison’” or “compile project(’:someProject’)”

we want

“compile gradleProject('entireGradleProject”, ‘subproject’)"

and then some configuration that defines whether the gradleProject dependency resolves to either a maven dependency, or the actual jars (and dependencies) produced by the gradle project referred.

Example of our configuration closure for this:

multiProject {

api {

//directory where local files are placed

directory = file("${rootProject.projectDir}/…/api")

//maven version, used if useLocal = false

version = ‘0.1’

//maven group, name is taken from the subproject defined in our gradleProject call.

groupId = ‘org.group’

//whether we use the local checked out files defined by ‘directory’

useLocal = false

}

} ’

This then enables us to use gradleProject(‘api’, ‘module’), which resolves to either* ‘org.group:module:0.1’* if we have useLocal=false, or the actual project if we have useLocal=true. You write: ’

dependencies {

compile gradleProject(‘api’, ‘subproject’)

} ’ Currently our hackish solution does this utilizing the gradleBuild task type to call across to the other project, but we are having both concurrency issues with that (linked here: http://gsfn.us/t/4og1c ) and things like generating idea files, cleaning and general performance does not work as smoothly as a native solution, also we utilize temporary generated files to get dependencies across our various projects.

This is of cause due to the fact that we went another road then the root project, and thereby lost lots of gradle utils. Clearly not an optimal solution for us as a third party, but our feeling after making this plugin, is that a native version of this could work, and should fit into the gradle model quite nicely.

This “hack” sounds very interesting. We have similar requirements (I work at Jyske Bank).

Please do make it available (with or without cleanup). I might be able to take some time to help improve it - we use Eclipse, so I’d have to add support for that at least.