I'm trying to craft a Gradle multiproject build for a situation in which my project layout is already dictated to me. I have something like this:
-->Shared\
---->SharedComponent1\
------>build.gradle
------>src\
...
---->SharedComponent2\
------>build.gradle
...
-->Product1\
---->ProductComponent1\
------>build.gradle
---->ProductComponent2\
------>build.gradle
...
---->build\
------>settings.gradle
My settings.gradle looks like this:
rootProject.name = 'Product1'
rootProject.projectDir = new File( "${ProjectsRoot}" )
include 'Shared:SharedComponent1'
include 'Shared:SharedComponent2'
include 'Product1:ProductComponent1'
include 'Product1:ProductComponent2'
When I run Gradle in the build folder like this:
gradle -PProjectsRoot=c:\my\project\root\dir projects
I get:
:projects
------------------------------------------------------------
Root project
------------------------------------------------------------
Root project 'build'
No sub-projects
To see a list of the tasks of a project, run gradle <project-path>:tasks
For example, try running gradle :tasks
BUILD SUCCESSFUL
i.e. it doesn't find the projects I'm trying to build.
Is what I'm trying to do possible with Gradle's multiproject support? Or am I barking up the wrong tree?
A couple of pointers:
- Gradle strictly separates the logical project hierarchy (the way Gradle organizes your build into a logical hierarchy of projects) from the physical directory layout. Just about any mapping is possible. (One exception that comes to mind is that you can't have two projects sharing the same project directory.)
- To implement a custom directory layout, you'll have to set
projectDir
for all projects, not just the root project. You should use relative paths, e.g. rootProject.projectDir = new File(settingsDir, "../foo")
and project(":sub1").projectDir = new File(rootDir, "bar")
. Here, settingsDir
refers to the directory containing settings.gradle
, and rootDir
is a shorthand for rootProject.projectDir
.
- To configure projects generically, you can recursively walk
(root)Project.children
. Note that settings.gradle
and build.gradle
use different types to represent a project - ProjectDescriptor and Project, respectively.
- Gradle has to be invoked from the directory containing
settings.gradle
, or a subdirectory thereof. From a usability perspective, it is therefore best to put settings.gradle
into the root of the directory hierarchy.
For more information, see Settings in the Gradle Build Language Reference, and the Multi-Project Builds chapter in the Gradle User Guide.
For completeness, the settings.gradle
that solved my specific example above is as follows:
rootProject.name = 'Product1'
def projectTreeRootDir = new File( "${ProjectsRoot}" )
// Shared components
def sharedRootDir = new File( projectTreeRootDir, 'Shared' )
include ':SharedComponent1'
project( ':SharedComponent1' ).projectDir = new File( sharedRootDir, 'SharedComponent1' )
include ':SharedComponent2'
project( ':SharedComponent2' ).projectDir = new File( sharedRootDir, 'SharedComponent2' )
// Product components
includeFlat 'ProductComponent1', 'ProductComponent2'
Clearly this doesn't scale to large numbers of subprojects and it could be done significantly better using the hints provided by Peter above.