Gradle Extra Properties: Difference between revisions

From NovaOrdis Knowledge Base
Jump to navigation Jump to search
 
(24 intermediate revisions by the same user not shown)
Line 1: Line 1:
=External=
* https://docs.gradle.org/current/userguide/writing_build_scripts.html#sec:extra_properties
=Internal=
=Internal=
* [[Gradle Runtime and Project Configuration#Gradle_Extra_Properties|Gradle Runtime and Project Configuration]]
* [[Gradle Properties - Runtime and Project Configuration#Gradle_Extra_Properties|Gradle Properties - Runtime and Project Configuration]]
* [[Gradle_Project_Coordinates,_State_and_Configured_Properties#Extra_Properties|Gradle Project Coordinates, State and Configured Properties]]
 
=Overview=
=Overview=
An '''extra property''' is a property that can be declared on most model object instances available to the closure being executed. Extra properties allow defining variables that are used multiple times within the same script, such as a file that is referred from multiple locations of the build script. An extra property is equivalent to a user-defined variable.  
An '''extra property''' is a property that can be declared on most model object instances available to the closure being executed. Extra properties allow defining variables that are used multiple times within the same script, such as a file that is referred from multiple locations of the build script. An extra property is equivalent to a user-defined variable.  


Internally, extra properties are stored as key-value pairs in a map, associated with the model object instance. For [[settings.gradle]], the available model objects are [[Gradle_Settings|Settings]] and [[Org.gradle.api.invocation.Gradle|Gradle]] (ProjectDescriptor does not allow defining extra properties). [[Gradle_Settings|Settings]] allows defining extra properties, but those properties cannot be easily accessed at [[Gradle_Concepts#Configuration|configuration]] and [[Gradle_Concepts#Execution|execution]] phase, so the best candidate for defining extra properties during the configuration phase is [[Org.gradle.api.invocation.Gradle|Gradle]].
The extra property name cannot contain dots, dashes, etc.
 
For [[build.gradle]], extra properties can be defined on any available object model instances, and the most common object to define properties on is the project instance. <font color=darkgray>The the extra properties defined on the project instance are known as [[Gradle Project Properties|project properties]]</font>.  
 
 
 


Internally, extra properties are stored as key-value pairs in a map, associated with the model object instance. For [[settings.gradle]], the available model objects are [[Gradle_Settings|Settings]] and [[Org.gradle.api.invocation.Gradle|Gradle]] (ProjectDescriptor does not allow defining extra properties). They allow defining extra properties at the [[Gradle_Concepts#Initialization|build initialization phase]]. [[Gradle_Settings|Settings]] allows defining extra properties, but those properties cannot be easily accessed at [[Gradle_Concepts#Configuration|configuration]] and [[Gradle_Concepts#Execution|execution]] phase, so the best candidate for defining extra properties during the configuration phase is [[Org.gradle.api.invocation.Gradle|Gradle]], that allows accessing extra properties with the gradle.<property-name> syntax.


They can be declared with a special syntax described below. Once the properties have been declared, they can be read and set like predefined properties. Extra properties can be accessed from anywhere their owning object can be accessed, giving them a wider scope than [[#Local_Variable|local variables]].  
For [[build.gradle]], extra properties can be defined on any available object model instances. The most common object to define properties on is the project instance. <span id='Project_Extra_Properties'></span>The extra properties defined on the project instance are considered [[Gradle_Project_Coordinates,_State_and_Configured_Properties#Extra_Properties|project properties]], alongside other project properties provided with [[Gradle_Project_Coordinates,_State_and_Configured_Properties#-P_Command-Line_Options|-P on command line]] or in [[gradle.properties#Overview|gradle.properties]].


Extra properties on a project are visible from its sub-projects, [[#Extra_Properties_and_Multi-Project_Builds|but not vice-versa]].
Extra properties on a project are visible from its sub-projects, [[#Extra_Properties_and_Multi-Project_Builds|but not vice-versa]].


By requiring special syntax for adding a property, Gradle can fail fast when an attempt is made to set a [[#Predefined_Properties|predefined]] or [[#Extra_Properties|extra property]] but the property is misspelled or does not exist.
Extra properties are declared using an "ext" namespace closure applied to the model object we intend to declare the extra properties for:
 
 
To add properties, use an "ext" namespace closure:
<syntaxhighlight lang='groovy'>
<syntaxhighlight lang='groovy'>
ext {
ext {
Line 26: Line 24:
</syntaxhighlight>
</syntaxhighlight>
An equivalent assignment is:
An equivalent assignment is:
<syntaxhighlight lang='groovy'>
gradle.ext.color = 'blue'
</syntaxhighlight>
or
<syntaxhighlight lang='groovy'>
<syntaxhighlight lang='groovy'>
project.ext.color = 'blue'
project.ext.color = 'blue'
</syntaxhighlight>
</syntaxhighlight>
A benefit of using the closure over the other syntax is that multiple assignments can be declared compactly:
A benefit of using the closure over the other syntax is that multiple assignments can be declared compactly:
<syntaxhighlight lang='groovy'>
<syntaxhighlight lang='groovy'>
Line 39: Line 40:
</syntaxhighlight>
</syntaxhighlight>


Note that the "ext" script block or <code>project.ext</code> syntax must be used only for the declaration of the property, for subsequent access the extra property can be looked up directly on the project instance.
By requiring special syntax for adding a property, Gradle can fail fast when an attempt is made to set an extra property but the property name is misspelled or the property does not exist. Note that the "ext" script block or <code>project.ext</code> syntax must be used only for the declaration of the property, for subsequent access the extra property can be looked up directly on the project instance: once the properties have been declared, they can be read and set like predefined properties.


<syntaxhighlight lang='groovy'>
<syntaxhighlight lang='groovy'>
Line 50: Line 51:
     println project.color
     println project.color
     println color
     println color
    println gradle.color
   }
   }
}
}
</syntaxhighlight>
</syntaxhighlight>
For the above example, <code>./gradlew displayColor</code> will display "red".
For the above example, <syntaxhighlight lang='text'>./gradlew displayColor</syntaxhighlight> will display "red" (for project) and "blue" (for gradle).
 
Extra properties can be accessed from anywhere their owning object can be accessed. This gives them a wider scope than [[Gradle Local Variables|local variables]].
 
=Extra Properties and Multi-Project Builds=
 
The extra properties are not available and throw an execution error if they are accessed before are defined. That is why a multi-project build that declares extra properties in sub-projects' [[build.gradle]] and attempts to use them in the root project [[build.gradle]] will fail at the configuration phase:
<syntaxhighlight lang='text'>
BUILD FAILED in 3s
...
* Where:
Build file '.../root-project/build.gradle' line: 17
* What went wrong:
A problem occurred evaluating root project 'root-project'.
> Could not get unknown property 'myProperty' for project ':sub-project-A' of type org.gradle.api.Project.
</syntaxhighlight>
 
The error occurs even "myProperty" was declared in sub-project-A's build.gradle, because the build file was not evaluated at the time the root project file is executed. If we log build.gradle evaluation, we get something like:
<syntaxhighlight lang='text'>
exiting root project build.gradle ....
entering sub-project-A build.gradle ....
exiting sub-project-A build.gradle ....
</syntaxhighlight>
which shows that the sub-project build script is executed after the root project build script is executed.
 
=Programmatic Access to Extra Properties=
Programmatic access to extra properties is useful if developing [[Extending_Gradle_with_a_Custom_Enhanced_Task#Programmatic_Access_to_Properties|custom enhanced tasks]] or plugins.
<syntaxhighlight lang='groovy'>
getProject().getProperties().get("myProperty")
</syntaxhighlight>

Latest revision as of 22:39, 10 November 2020

External

Internal

Overview

An extra property is a property that can be declared on most model object instances available to the closure being executed. Extra properties allow defining variables that are used multiple times within the same script, such as a file that is referred from multiple locations of the build script. An extra property is equivalent to a user-defined variable.

The extra property name cannot contain dots, dashes, etc.

Internally, extra properties are stored as key-value pairs in a map, associated with the model object instance. For settings.gradle, the available model objects are Settings and Gradle (ProjectDescriptor does not allow defining extra properties). They allow defining extra properties at the build initialization phase. Settings allows defining extra properties, but those properties cannot be easily accessed at configuration and execution phase, so the best candidate for defining extra properties during the configuration phase is Gradle, that allows accessing extra properties with the gradle.<property-name> syntax.

For build.gradle, extra properties can be defined on any available object model instances. The most common object to define properties on is the project instance. The extra properties defined on the project instance are considered project properties, alongside other project properties provided with -P on command line or in gradle.properties.

Extra properties on a project are visible from its sub-projects, but not vice-versa.

Extra properties are declared using an "ext" namespace closure applied to the model object we intend to declare the extra properties for:

ext {
  color = 'blue'
}

An equivalent assignment is:

gradle.ext.color = 'blue'

or

project.ext.color = 'blue'

A benefit of using the closure over the other syntax is that multiple assignments can be declared compactly:

ext {
  color = 'blue'
  shape = 'square'
  size = 10
}

By requiring special syntax for adding a property, Gradle can fail fast when an attempt is made to set an extra property but the property name is misspelled or the property does not exist. Note that the "ext" script block or project.ext syntax must be used only for the declaration of the property, for subsequent access the extra property can be looked up directly on the project instance: once the properties have been declared, they can be read and set like predefined properties.

project.ext.color = 'green'
project.color = 'red' // project.ext.color and project.color are equivalent after property initialization

task displayColor {
  doLast {
    println project.ext.color
    println project.color
    println color
    println gradle.color
  }
}

For the above example,

./gradlew displayColor

will display "red" (for project) and "blue" (for gradle).

Extra properties can be accessed from anywhere their owning object can be accessed. This gives them a wider scope than local variables.

Extra Properties and Multi-Project Builds

The extra properties are not available and throw an execution error if they are accessed before are defined. That is why a multi-project build that declares extra properties in sub-projects' build.gradle and attempts to use them in the root project build.gradle will fail at the configuration phase:

BUILD FAILED in 3s
...
* Where:
Build file '.../root-project/build.gradle' line: 17
 
* What went wrong:
A problem occurred evaluating root project 'root-project'.
> Could not get unknown property 'myProperty' for project ':sub-project-A' of type org.gradle.api.Project.

The error occurs even "myProperty" was declared in sub-project-A's build.gradle, because the build file was not evaluated at the time the root project file is executed. If we log build.gradle evaluation, we get something like:

exiting root project build.gradle ....
entering sub-project-A build.gradle ....
exiting sub-project-A build.gradle ....

which shows that the sub-project build script is executed after the root project build script is executed.

Programmatic Access to Extra Properties

Programmatic access to extra properties is useful if developing custom enhanced tasks or plugins.

getProject().getProperties().get("myProperty")