Confused regarding the types of "Properties"

I am trying to understand how Gradle works, reading through the documentations on Build Environment.

After reading the whole page I am confused regarding the nature of properties, types of properties and the relationship between them. I have searched through stackoverflow and I have ran tests before posting here, I would really appreciate any help or answers because I am just completely stuck… The more I re-read the page, the more confused I got :melting_face:.

Can someone please explain in detail, how the concepts and terms 1.Gradle Properties, 2.System Properties and 3.Project Properties relate to each other, and how are they structured/organized?

 

Some questions I have, for example, are System Properties and Project properties part of Gradle properties?

  • On the page’s context menu, Gradle Properties, Project Properties and System Properties are clearly arranged as siblings
  • From gradle --help, the only options available that specifies properties are -D and -P, which are for System and Project properties respectively. Gradle Properties is not seen here as an option.

Here I would presume that System Properties and Project properties ARE “children/supersets” of Gradle properties,
i.e. system/project “extends” or “implements” gradle properties.

However, on Gradle properties, quote:
The final configuration taken into account by Gradle is a combination of all Gradle properties set on the command line and your gradle.properties files. If an option is configured in multiple locations, the *first one* found in any of these locations wins:
* command line, as set using -D.
Here I thought, why isn’t -P mentioned? -D only configures System Properties, so Project Properties is handled differently?

Next, when trying to retrieve a property in a build script, we could use exist methods under ProviderFactory.java like:
project.providers.gradleProperty(key)
project.providers.systemProperty(key)
A method named “projectPropety” does NOT exist, but the method gradleProperty can retrieve Project Properties passed down through command line’s -P option.

What is going on? I am just stuck and confused, are Project Properties even Gradle Properties?

 
Again I would really appreciate any help, thank you in advance!

Can someone please explain in detail, how the concepts and terms 1.Gradle Properties, 2.System Properties and 3.Project Properties relate to each other, and how are they structured/organized?

Gradle properties and Project properties are often used as interchangeable term, especially as you can get both in same ways and can set both in mostly same ways.
There are just slight difference between them.
For example some properties cannot be set using -P (as project property) but need to be set using -D with the actual name to be effective, for example -P org.gradle.debug=true does not work as it is evaluated too late, but has to be used like -Dorg.gradle.debug=true to be in effect in time.
But there are places where you can set both the same way, like in the various gradle.properties files.
So basically said, what you can set via -D from the command line (without a naming prefix) is a Gradle property, what you can set via -P from the command line is a Project property.

System properties are a standard Java feature, the things you can set on any Java program using -D. But you can set them on the Gradle executable directly to set system properties or you can set them in any other way like using environment variable JAVA_TOOL_OPTIONS=-Dorg.gradle.caching=false that is picked up automatically by all JREs I know, independently of Gradle.
So things that are system properties like javax.net.debug=all or Gradle properties like org.gradle.caching or whatever can be set using -D and so on.

Gradle properties and project properties can be set in the various gradle.properties files, or also via -D for the former or -P for the latter.

Project properties can also be set from environment variables or system properties with using ORG_GRADLE_PROJECT_ for the former or org.gradle.project. for the latter as prefix before the actual property name, which is often useful for CI environments or integrations.

Or in the other direction, you can put systemProp.javax.net.debug=all to the various gradle.properties files to make Gradle set the javax.net.debug system property for you.

So yes, this is a bit intertwined and complex if you want to understand everything in detail. :slight_smile:

2 Likes

Thanks for the reply it cleared up concepts for me! :slightly_smiling_face:

On this highly voted answer on stackoverflow, quote:

The -P flag is for gradle properties, and the -D flag is for JVM properties.

With your explanation on the second paragraph about system properties, now it makes sense for me why someone would refer to system properties as JVM properties
I can also see how like you said gradle properties and project properties are often used as interchangeable terms, because as shown on --help the option -P is for project properties, and this answer on stackoverflow would say “-P flag is for gradle properties”

May I ask what exactly are “naming prefixes”?
So -D is for BOTH system properties and gradle properties, depending on whether the name of the property specifies Java system properties?

Creating a new task “testingProperties”:

task("testingProperties") {
    group = "temp tests"
    fun findProperty(key: String) {
        println("----> Finding property with key: $key")
        println(project.providers.gradleProperty(key).orNull)
        println(project.providers.systemProperty(key).orNull)
        println(if (project.hasProperty(key)) project.property(key) else null)
        println(project.findProperty(key))
        println(project.properties.getOrDefault(key, null))
    }
    doFirst {
        findProperty("propertyAtCmdP")
        findProperty("propertyAtCmdD")
    }
}

And executing command:

gradle :testingProperties -PpropertyAtCmdP="P" -DpropertyAtCmdD="D"

The output is:

> Task :testingProperties
----> Finding property with key: propertyAtCmdP
P
null
P
P
P
----> Finding property with key: propertyAtCmdD
null
D
null
null
null

It seems like the ways to get Gradle properties and Project properties are different, no?

On this highly voted answer on stackoverflow, quote:

The -P flag is for gradle properties, and the -D flag is for JVM properties.

Yeah, as I said, the terms are often mixed up and that statement is not really 100 % correct as I explained above. :slight_smile: “JVM property” is just a different name for “system property” that person used, but “system property” is the official term.

May I ask what exactly are “naming prefixes”?

What I explained further down, the prefixes for environment variables or system properties with which you can set project properties.

So -D is for BOTH system properties and gradle properties , depending on whether the name of the property specifies Java system properties?

Actually my statement was not fully correct either.
What you set with -D is a system property.
And Gradle properties are also taken from system properties with the exact name. (Opposed to project properties that need the prefix mentioned later for that).
So setting a system property with the exact name of a Gradle property is a way to set a Gradle property, so effectively you set Gradle properties and system properties with -D, techincally and directly you just set a system property. :smiley:

Creating a new task “testingProperties”:

two sidenotes:

  • do not use task("...") { ... } that is against Task Configuration Avoidance
  • always use the Gradle wrapper and not a gradle from some installed Gradle version, I ususally do not even have and Gradle version installed but bootstrap new projects simply using the wrapper of an exisiting project

It seems like the ways to get Gradle properties and Project properties are different, no?

Your example is not really much meaningful and additionally the naming of the provider method greatly adds to the confusion.

As mentioned above, with -D you set a system property.
Gradle properties can be set as system property or in a gradle.properties file.
Project properties can be set as system property with naming prefix, as environment variable with naming prefix, or in a gradle.properties file.

If a Gradle property is set as system property, you cannot get its value using providers.gradleProperty, because acutally providers.gradleProperty does not get you Gradle properties, but Project properties.

If a Gradle property is set in a gradle.properties file though, it is at the same time also set as Project property. And as providers.gradleProperty actually returns Project properties you can then get its value through it.

You can easily test this by changing your code to findProperty("org.gradle.caching") and then calling it with gradle :testingProperties -Dorg.gradle.caching=false -i and gradle :testingProperties -Dorg.gradle.caching=true -i. In the output you will see that the Gradle property is effective (search for “Using local directory build cache”) but only providers.systemProperty will show its value.

I’m not sure whether this is actually intended or a bug though.

1 Like