Using Gradle Setup Info Outside of Gradle

There is a Dev/Ops at my company that is always trying to be clever. His ultimate goal is reduce build times, so I can’t get upset. Recently, he was trying to figure out what project were building and where they were located. He generated this list by making some assumptions about how our Gradle build was determining subprojects and created a script to generate a list of those locations. The problem with that is, if the scheme for subproject generation changed he would have to manually maintain his script.

In comes a little cheat.

Most project that you work on will have more than one subproject. It is good to separate concerns even if all the parts of the project are required to work together. This eliminates pesky problems like circular dependencies, full recompilation, etc. (See, Chapter 57.5) You can use the settings.gradle file to setup a multiproject build. A typical settings.gradle file looks like so: (Actually, this one comes from the Gradle github page.)

include 'distributions'
.
.
.
include 'modelGroovy'
include 'cunit'
include 'platformPlay'
 
rootProject.name = 'gradle'
rootProject.children.each {project ->
    String fileBaseName = project.name
    String projectDirName = "subprojects/$fileBaseName"
    project.projectDir = new File(settingsDir, projectDirName)
    project.buildFileName = "${fileBaseName}.gradle"
}

This is typical of a multiproject build–create a bunch of subprojects and set their properties. In fact, instead of listing each subproject individually, you can set a standard location for projects and resolve them dynamically.

new File("$settingsDir/subprojects/").eachDir {
    include it.name
}

Where include is the method to specify new subprojects.

The goal of the Dev/Ops is to get the list of projects and their locations. There are two ways of accomplishing this task: 1) Create a task in Gradle (that is essentially only a task with a doLast block). 2) Or, use a Groovy script to read the settings file. The problem with the first option is that once your company wide Gradle system starts to grow, so does the configuration time. This configuration time is inconsequential with the respect to the rest of the build. But you might become impatient if all you want is a quick list of projects and project locations. The problem with the second one is that it hacky. But sometimes that fun.

I’ll assume you know how to use Gradle to get this task done and just show the groovy script.

The secret is Groovy Bindings. The script goes in the root directory next to settings.gradle file. It uses bindings to mock out the key pieces that are usually found in the settings file (settindsDir, rootProject, include, project). After creating the mock data you call evaluate on the settings.gradle file. In the end the fake Project object will hold each project.


Binding binding = new Binding()
def workingDir =  new File().getCanonicalPath()

binding.setVariable("settingsDir", workingDir)

binding.setVariable('rootProject', ['name':''])
def include = { component ->
}
def projects = []
def project = {projectName->
    def currentProject = new Project(projectName)
    projects << currentProject 
    
    return  currentProject 
}
binding.setVariable("include", include)
binding.setVariable("project", project)
GroovyShell shell = new GroovyShell(binding)

shell.evaluate(new File(workingDir, 'settings.gradle'))

class Project{
    def name
    def projectDir
    def buildFileName
    def Project(def name){
        this.name = name
    }
}
def getProjects() {
    return projects
}

Groovy Syntax Highlight Update for Vim

The Groovy syntax highlighting that come with the Vim installation has a few thing that I don’t care for. As I transition more away from Eclipse as my main development environment, I’ll spend more time trying to get Vim setup to support more efficient development. Below I’ve enumerated what changes I made to the syntax file and why.

The TODO:

Bold, yellow highlighting of TODO and FIXME tags. I’m not a big fan of blaring reminders. It’s also not good to rely on just stumbling on a TODO as a way of indicating work to be done. If you really going “todo” it, go ahead and make sure you do more than make a tag for the next sap to come along. He might not have TODO and FIXME highlighted in his editor and might not notice your rushed programming.

Why Should def Be Any Different:

“def” is a type in Groovy; Similar to Integer, int, String, Array, etc. The word didn’t come up as highlighted and was getting lost when I would skim code.

Important Variable Obscured by Greedy RexEx

The match regex used for matching import statements was too greedy. It would highlight parts of the variables that had the word, import, in the name (e.g. importFileFromURL or someimportantmethod).

“””GStrings Deserve the Same Respect as String”””

The most common use in my code for GStrings is when I am lazily slapping xml into a test and want to be able to still read it and add variable replacement. The original Syntax file was only recognizing the first line of a GString.

The regex for matching import statements was taken from a Java syntax file. The GString update was from Tobias Rapp version 0.1.11 of the Groovy syntax file. I’ll maintain my version of the file on github with the caveat that some of the changes are skewed to my preferences and that I might add more. Hopefully, the README file will be kept up-to-date.