· 5 min read Posted by Tadeas Kriz
Gradle Properties
In our last post about Gradle,
we talked about how configuring org.gradle.jvmargs
can lead to unexpected out of memory errors.
Now let’s talk about all the places Gradle gets its configuration from,
so we can make sure you’re in full control of your build.
Most of your projects will have a gradle.properties
file in the root.
But not all the properties in that file have the same behavior.
The Configuring the Build Environment page in Gradle documentation tries to explain the different property types and their behavior. From our testing it behaves slightly differently than the page might lead you to believe. The table Priority for configurations looks like this:
Priority | Method | Location | Example | Details |
---|---|---|---|---|
1 | Command-line flags | Command line | --build-cache | These have precedence over properties and environment variables. |
2 | System properties | Project Root Dir | systemProp.http.proxyPort=443 | Stored in a gradle.properties file |
3 | Gradle properties | GRADLE_USER_HOME Project Root Dir GRADLE_HOME | org.gradle.logging.level=quiet | Stored in a gradle.properties file |
4 | Environment variables | Environment | GRADLE_OPTS | Sourced by the environment that executed Gradle |
Once you start playing around with properties,
you’ll find that this table misses some important information.
For example,
System properties are actually loaded from GRADLE_HOME
and GRADLE_USER_HOME
too,
not just the Project Root Dir.
And if you’re using a Gradle wrapper (invoking Gradle with ./gradlew
which you probably do),
then the gradle.properties
file in $GRADLE_HOME
is ignored.
With that in mind, let’s make our own tables. Yes, tables plural as we’ll capture behaviors of different property types. You see, the documentation speaks about Project, System and Gradle properties, as if they were completely separate. Instead we need to separate how are properties passed in, and how properties can be used in our build script. So let’s make a table for each property type.
System properties
System properties are used in JVM to pass in configuration using the -D
argument.
Though Gradle allows setting system properties in similar ways to project properties in gradle.properties
files.
Priority | Method | Example | Details | |
---|---|---|---|---|
1 | Command-line flags | -Da-system-property=cmdline | These have precedence over property files and environment variables. | |
2 | gradle.properties file in $GRADLE_USER_HOME | systemProp.a-system-property=gradle-user-home | Defaults to ~/.gradle/gradle.properties if GRADLE_USER_HOME not set | |
3 | gradle.properties file in project root directory | systemProp.a-system-property=project-dir | Stored in a gradle.properties file | |
4 | gradle.properties file in $GRADLE_HOME | systemProp.a-system-property=gradle-home | Ignored if started using a Gradle Wrapper | |
5 | Environment variables | GRADLE_OPTS="-Da-system-property=env" | Sourced by the environment that executed Gradle |
Project properties
There are many ways to access project properties in your build script.
One such way is findProperty("a-project-property")
which returns a value or null if not set.
Priority | Method | Example | Details |
---|---|---|---|
1 | Command-line flags | -Pa-project-property=cmdline | These have precedence over property files and environment variables. |
2 | System properties | -Dorg.gradle.project.a-project-property=cmdline (any system property with org.gradle.project. prefix) | See the table above for priorities |
3 | gradle.properties file in $GRADLE_USER_HOME | a-project-property=gradle-user-home | Defaults to ~/.gradle/gradle.properties if GRADLE_USER_HOME not set |
4 | gradle.properties file in project root directory | a-project-property=project-dir | Stored in a gradle.properties file |
5 | gradle.properties file in $GRADLE_HOME | a-project-property=gradle-home | Ignored if started using a Gradle Wrapper |
6 | Environment variables | ORG_GRADLE_PROJECT_a_project_property=env (hyphens - not supported this way) | Sourced by the environment that executed Gradle |
Notice that project properties can be set using a system property.
If the system property name starts with org.gradle.project.
,
Gradle will automatically create a project property using the remaining suffix as its name.
Consider the following two lines from a gradle.properties
file:
systemProp.org.gradle.project.a-project-property=hello
a-project-property=world
You might expect that the a-project-property
will have value world
,
but it’s hello
instead.
That’s because the project property set through a system property has a higher priority.
When declared in a single gradle.properties
file,
it might not be that big of a deal.
But it can easily be something you spend a lot of time debugging,
if you have it set in multiple gradle.properties
files,
or even in GRADLE_OPTS
.
Another interesting behavior is that anything you declare in one of the gradle.properties
files,
will be available as a project property.
So findProperty("systemProp.org.gradle.project.a-project-property")
will give you the same value as findProperty("a-project-property")
in the above example.
But if you pass in -Pa-project-property=cmdline
to the Gradle invocation,
findProperty("a-project-property")
is overridden,
while findProperty("systemProp.org.gradle.project.a-project-property")
stays the same.
Gradle properties
Lastly we have the Gradle properties, which are special.
Priority | Method | Example | Details |
---|---|---|---|
1 | Command-line flags | --console=plain | These have precedence over property files and environment variables. |
2 | System properties* | -Dorg.gradle.console=plain | * only on command-line or GRADLE_OPTS |
3 | gradle.properties file in $GRADLE_USER_HOME | org.gradle.console=plain | Defaults to ~/.gradle/gradle.properties if GRADLE_USER_HOME not set |
4 | gradle.properties file in project root directory | org.gradle.console=plain | Stored in a gradle.properties file |
5 | gradle.properties file in $GRADLE_HOME | org.gradle.console=plain | Ignored if started using a Gradle Wrapper |
Note that if configured using gradle.properties
,
it becomes a project property as well.
That means that findProperty("org.gradle.console")
would return a value.
Similarly,
if configured using a system property,
we can use System.getProperty("org.gradle.console")
.
However,
if that value is overridden by a command line flag,
value we’d get from either wouldn’t be correct.
Common issues with $GRADLE_USER_HOME
Now that we looked at the priorities,
we can look at one common issue caused by them.
Notice that the gradle.properties
in $GRADLE_USER_HOME
has a higher priority than the one in your project’s root.
It’s common that we consider whatever is closest to the project to have the highest priority,
but that isn’t the case with gradle.properties
.
Anything that you put into $GRADLE_USER_HOME/gradle.properties
will override your project’s gradle.properties
and if you’re not careful, can lead to unexpected behavior.
For example,
let’s say you’ve set org.gradle.jvmargs
in $GRADLE_USER_HOME/gradle.properties
so that all your Gradle daemons have the same JVM args.
Some time passes and you’re working on a project that needs more heap size.
So you update the project’s gradle.properties
and nothing happens.
Unless you remember that you’ve set it in $GRADLE_USER_HOME/gradle.properties
,
you might spend too much time trying to figure it out (don’t ask me how I know).
It’d be really helpful if there was a way to ask Gradle to print all properties and where are they coming from.
That’d make debugging this way easier.
- Tags:
- gradle