19.10. Additional Information for Rule Authors

The following sections describe Groovy interfaces of objects that are available to rule programmers.

19.10.1. Interface to the abuild Object

The abuild variable, provided in the Groovy binding to all scripts run in abuild, is the primary object that you will interact with. Here we describe its intended public interface. [40]

19.10.1.1. Accessing Parameters

These methods are used to access the values of definitions, parameters, and interface variables. They can be used either in Abuild.groovy files or in custom rule code.

resolve('name',defaultValue)

If name represents a definition (specified with VAR=val on the command line), return the definition value. Otherwise, if a parameter named name is a parameter, return the parameter value. Otherwise, if name is an interface variable, return the value of the interface value. Otherwise, return defaultValue.

The implementation of this method is what is responsible for implementing the effect of command-line definitions overriding parameter settings and interface variables, which gives the Groovy backend the same behavior as make and ant.

resolve('name')

calls resolve('name', null)

resolveAsString('name', defaultValue)

If resolve('name', defaultValue) returns other than null or a string, fail. Otherwise, return value as type String.

resolveAsString('name')

calls resolveAsString('name', null)

resolveAsList('name', defaultValue)

If resolve('name', defaultValue) returns a list, return that value. Otherwise, return a list containing that value. This makes it convenient to deal with parameters whose values may contain a single value or a list of values without having to handle the special case in the target.

19.10.1.2. Modifying Parameters

Most of the time, you will set and modify parameters inside a parameter block (Section 19.2.1, “Parameter Blocks”). Setting and modifying parameters inside a parameter block is essentially just “syntactic sugar” for the underlying interface, which is described here. This interface is available if you need to modify parameters from somewhere other than a parameter block.

setParameter('name', value)

Sets parameter name to value, replacing any previous value that may have been set.

appendParameter('name', value)

If parameter name has been previously set with setParameter (and not subsequently deleted), this is an error. Otherwise, makes the value of the parameter a list and appends value to it.

deleteParameter('name')

Removes any previous value for parameter name. Note that if an interface variable by the same name exists, deleting the parameter will re-expose the value of the interface variable to calls to resolve.

19.10.1.3. Build Environment

The following methods supply information about the build environment. These are most often used from within rule code, but they can also be useful in Abuild.groovy for setting parameter values.

buildDirectory

A File object containing the build directory (the abuild output directory)

sourceDirectory

A File object containing the source directory (the build item directory)

itemPaths[item]

Contains The full path to the given build item. This is intended primarily for rule code to get the location of the build item providing the rule code (i.e., for build items to get their own paths) or, in some cases, paths of items they directly control or contain. Paths are only available for items in the dependency chain of the current build item.

Warning

You should not use itemPaths to find the location of arbitrary build items. If you need information about where something is in a build item, the build item in question should provide that information through an interface variable.

19.10.1.4. Target Configuration

These methods are used to create or modify targets. You would call these methods from custom rule code. They would not be called from Abuild.groovy.

configureTarget('name', named parameters) { closure }

Registers target name; i.e., causes it to exist if it does not already exist.

If a closure is provided, adds it to the list of closures for target name.

If the deps named parameter is specified, its value must be a string or a list of strings representing dependencies. Each dependency is added as a dependency of target name.

If the replaceClosures named parameter is specified, its value must be a boolean. If true, any previous closures associated with name are removed before adding any newly specified closure.

configureTarget('name')

Calls the three-argument configureTarget with no named parameters or closure body; i.e., just causes the target to exist.

addTarget('name')

Synonym for configureTarget('name')

configureTarget('name', named parameters)

Calls the three-argument configureTarget with no closure body

addTargetDependencies('name', ['dep1', 'dep2'])

Calls configureTarget('name', 'deps': ['dep1', 'dep2']); i.e., creates the target and adds to its dependency list

configureTarget('name') { closure }

Calls three-argument configureTarget with no named parameters

addTargetClosure('name') { closure }

Synonym for configureTarget('name') { closure }

19.10.1.5. Build Support

The following methods are provided for use in custom rules.

runActions(String targetParameter, Closure defaultAction, Map defaultAttributes)

targetParameter is the name of a parameter that, if defined, resolves to a list whose elements are either maps or closures. If not defined, it is treated as if its value were a list containing an empty map.

For each element in the resulting list, if it is a closure, call it. If it is a map, then expand the map by copying entries from defaultAttributes for keys that are not present in the map. Then call defaultAttributes on the resulting map.

For an example of runActions, see Section 22.3, “Code Generator Example for Groovy”.

fail(String message)

Causes the build to fail immediately by throwing an instance of AbuildBuildFailure.

error(String message)

Issues an error message and continues to the end of the closure. After the closure finishes, the build is considered to have failed, so unless -k has been specified, no additional closures will be called.

runTarget(target)

If target has not yet been run, runs target preceded by its full dependency chain. No target is ever run more than once.

It is seldom necessary to call runTarget. It is generally better to let targets get run automatically through the dependency chain, though there are some instances in which it might make sense to use this method. For example, abuild uses it internally to have the check and test targets depend on all and call test-only, making it possible for test-only to provide test functionality without have any of its own dependencies. Without this facility, it would be necessary to implement the test functionality multiple times as is the case with the make backend. The runTarget method gives this Groovy-based build framework capability beyond what can be done with make's target framework.

runTargets([target, ...])

Runs each target specified in the order given subject to the constraints that no target is run more than once and that no target is run before all of its dependencies have been run.

19.10.2. Using org.abuild.groovy.Util

The org.abuild.groovy.Util class provides a small number of static methods and fields that may be useful to rule authors. You can gain access to this class by importing it in your Groovy code.

  • absToRel(path, basedir): convert path into a path relative to basedir. Most of the time, you need absolute paths, which you can easily get from the File object, but sometimes you explicitly need a relative path, such as when generating relative links. This method can help you with that task.

  • inWindows: a field whose value is true if you are in a Windows environment. You should use this very sparingly as it is possible to create platform-dependent output files in what is supposed to be a platform-independent directory. (See Chapter 30, Best Practices for a discussion.) However, sometimes when you are executing external programs, it becomes necessary to do it different on a Windows system from a UNIX system. This field can help you in those cases.



[40] Groovy 1.x does not enforce access control on method or field invocations.