Gradle Extra Properties: Difference between revisions
(36 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. | |||
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 [[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. | |||
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 are declared using an "ext" namespace closure applied to the model object we intend to declare the extra properties for: | |||
<syntaxhighlight lang='groovy'> | <syntaxhighlight lang='groovy'> | ||
ext { | ext { | ||
color = 'blue' | |||
} | } | ||
</syntaxhighlight> | |||
An equivalent assignment is: | |||
<syntaxhighlight lang='groovy'> | |||
gradle.ext.color = 'blue' | |||
</syntaxhighlight> | |||
or | |||
<syntaxhighlight lang='groovy'> | |||
project.ext.color = 'blue' | |||
</syntaxhighlight> | |||
A benefit of using the closure over the other syntax is that multiple assignments can be declared compactly: | |||
<syntaxhighlight lang='groovy'> | |||
ext { | |||
color = 'blue' | |||
shape = 'square' | |||
size = 10 | |||
} | |||
</syntaxhighlight> | |||
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'> | |||
project.ext.color = 'green' | project.ext.color = 'green' | ||
project.color = 'red' // project.ext.color and project.color are equivalent after property initialization | project.color = 'red' // project.ext.color and project.color are equivalent after property initialization | ||
task displayColor { | task displayColor { | ||
doLast { | |||
println project.ext.color | |||
} | println project.color | ||
println color | |||
println gradle.color | |||
} | |||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
For the above example, './gradlew displayColor | 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
- Gradle Properties - Runtime and Project Configuration
- Gradle Project Coordinates, State and Configured Properties
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")