I have a subfolder api which holds multiple api related subprojects. I have included an api subproject in my settings.gradle as
include "api:invenio"
project(":api:invenio").name = 'metadata-api-invenio'
folder structure looks like this
root/api/invenio/build.gradle
For some reason gradle is treating api as a subproject as well even though this is just a folder to hold subprojects. Its creating a build directory in api folder. How can I tell gradle to exclude api folder from subprojects.
Thanks
Take a look at Gradle's settings.gradle for an example. Basically you can do somethings like
include 'invenio'
project(':invenio').projectDir = new File(settingsDir, 'api/invenio')
Related
Typically, a multi project Gradle build would be setup something like this:
root
subproject1
subproject2
And in root's settings.gradle file, I'd have something like:
rootProject.name = 'root'
include 'subproject1'
include 'subproject2'
This kind of multi-project setup is straightforward. However, what if subproject1 or subproject2 aren't contained within root? For example, I might have an existing subproject on my machine that is stored somewhere far away from root. How do I configure the setting.gradle file to account for this "non-standard" structure? Is it just a matter of providing an absolute path to the subproject folder in the settings.gradle file?
This post covers it: https://discuss.gradle.org/t/how-to-include-sub-projects-in-settings-gradle-file/5096
Basically, you have to overwrite the project.projectDir attribute of your subproject so that it points to the location of the subproject on your machine.
In the Gradle samples (included with version 2.2.1) there is a java/multiproject project.
The settings.gradle file defines the following projects:
include "shared", "api", "services:webservice", "services:shared"
Note that services is not itself a project, merely a directory which contains the webservice and shared projects.
When I run the command gradle build from the root directory, I notice that after gradle successfully builds it creates inside the /services directory a /build directory containing /lib and a /tmp directories.
Inside of /services/build/lib is a jar: services-1.0.jar which contains very little; specifically just a META-INF/MANIFEST.MF file containing:
Manifest-Version: 1.0
provider: gradle
So what is causing Gradle to build a jar for this non-project? And how can I prevent this behavior in my similarly structured multiproject project?
/services isn't a project, I don't want to create anything inside /build folder at all. Yes I could just delete it, but I would like to avoid the unnecessary work of building this jar/running any tasks on this non-project in the first place.
To be honest I've no reasonable idea why gradle builds this folder. I guess that because it's a kind of a transient folder. However it can be excluded by adding the following piece of code to main build.gradle script:
project(':services').jar { onlyIf { false } }
Desired effect (services.jar elimination) can be also obtained with the following settings.gradle content:
include "shared", "api", "services/webservice", "services/shared"
File instead of project paths are included.
My guess would be that this is a combination of the next 2 gradle rules:
When you're including subprojects in the build.settings file using the include keyword according to Gradle Documentation here:
the inclusion of the path 'services:hotels:api' will result in
creating 3 projects: 'services', 'services:hotels' and
'services:hotels:api'.
In simple words, this means that the inclusion of services::webservice will also build the services project
The bulid.gradle file in your root that applies the 'java' plugin. According to Gradle Documentation here every configuration defined in the root.gradle takes effect for all sub projects. This means that it will also hold as the default configuration for the services project. As the 'java' plugin was applied a jar will be created, but as there is no src/main folder under the services directory nothing will be compiled and the jar will include only a META-INF/MANIFEST.MF file.
In a multi-project build I have a module that in itself is composed of two sub-projects. If I just want the option of building the top-level module but also ensure both the sub-projects within it are also built, how I do achieve this?
include 'moduleA', 'moduleB', 'moduleC' (root project settings.gradle)
project(':moduleC').projectDir = new File('path to custom module that includes sub-projects)
project(':moduleC').settingsDir = ?? (gradle fails because there is no settingsDir path)
but moduleC has a settings.gradle in itself that has
include 'api'
include 'server'
Now I want both these to be triggered when I specify gradlew :moduleC:build, but instead it just builds moduleC root project. Is there a way? This use case does seem valid to me (i.e. for modularity, you want to keep the inclusion of sub-projects at moduleC's level and not at root level).
Thanks,
Paddy
As of Gradle 2.2, only a single settings.gradle per build is supported. If that file contains include "moduleC:api" and include "moduleC:server", then running gradle build from moduleC's project directory will also build api and server.
I see a lot of examples of Gradle-built Java/Groovy projects that have the following structure:
some-app/
src/
main/
test/
docs/
README.md
build.gradle
gradlew
gradlew.bat
settings.gradle
gradle.properties
gradle/
*.gradle
I understand that build.gradle is the main buildscript and that gradle.properties is its properties file. But settings.gradle really throws me. Inside it I see:
rootProject.name = "someApp"
But this seems like it belongs in gradle.properties. I'm also wondering where the gradlew and gradlew.bat files come from, they seem to be generated.
Finally, I'm wondering why there are so many *.gradle files under the gradle/ dir: are these plugins, or extension scripts of some sort. They are all pulled in from the main build.gradle like so:
apply "gradle/fizz.gradle"
apply "gradle/buzz.gradle"
etc.
So:
What properties are supposed to go in settings.gradle that are not supposed to go in gradle.properties?
How are the gradlew/gradlew.bat files generated?
Why would someone have so many disparate *.gradle files? Why not just 1 big build.gradle buildscript?
1) gradle.properties is normal properties file, while settings.gradle is also a build script. You can add there some code that will be executed during build. Typically this file is needed when You have a multi-module project.
2) When You type gradle tasks in project build directory (empty build.gradle is enough to see it) You'll see wrapper task. This task is used to generate scripts You're asking about. More info.
3) The reason is that all these files have different responsibilities that are cleanly separated.
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.