Monday, February 25, 2013

Gradle "extra" properties

Extra properties in Gradle are very versatile--so versatile in fact, that sometimes they can induce a little confusion.  Here's a quick entry to sort them out.

Let's start with the ways to get and set them with a script.  We'll use project properties as an example.

Here are the myriad of ways to set a project property:

 project.ext.myprop1 = 'a'  
 project.ext.set('myprop1', 'a')  
 project.ext['myprop1'] = 'a'  
 project.ext {  
    myprop1 = 'a'  
 }  

And here's how we get one back:

 assert myprop1 == 'a'  
 assert project.myprop1 == 'a'  
 assert project.ext.myprop1 == 'a'  
 assert project.ext.get('myprop1') == 'a'  
 assert project.ext['myprop1'] == 'a'  

These are essentially straight out of the Gradle DSL, but ordered, I think, a little more clearly.  Notice that specifying the 'ext' property is necessary in all cases when setting a property, but it's optional when getting it.

Project properties can be specified both in a single properties.gradle file, or also command-line using the -P operator.  They end up in in the same 'ext' bucket with all other extra properties.

Properties are most commonly set on the project, but can be set on other objects as well.  Any object that implements ExtensionAware has this 'ext' property and can follow these rules.  The only other object type that implements this by default are tasks.

 task myTask {  
      ext.newprop = 'a'  
 }  
 assert myTask.newprop == 'a'  

The existence of properties can be generally be tested using the hasProperty() method as described in the Gradle docs, but be a little careful with it's use.  Due to a bug, it will not work inside allprojects{} or subprojects{} blocks without being qualified.

 project.ext.testProp = 'a'  
 if ( hasProperty('testProp') ) {  
      println "Can see testProp!"  
 }  
 allprojects {  
      if ( project.hasProperty('testProp')) {  
           println "Can see testProp!"  
      }  
      if ( hasProperty('testProp')) {  
           println "Can see testProp!"  
      } else {  
           println "CANNOT see testProp!"  
      }  
 }  

Outputs:

 Can see testProp!  
 Can see testProp!  
 CANNOT see testProp!  

Also, hasProperty() will not work within a settings.gradle file.  You must use a try-catch block to test for the existence of properties.

 try {  
      println myProp // if this doesn't exist, an exception will be thrown  
 } catch (MissingPropertyException e) {  
      ...  
 }  

Using extra properties in Gradle is pretty straightforward, but there are a few hitches to be aware of.  Hopefully this helps the new Gradle user sort them out.