xpybuild.propertysupport

Contains functions and classes for use in build files when you need to define and use properties and options.

Build properties

Properties are named, immutable values that are defined in build files (or read from a .properties file), and can be used throughout the build using ${PROP_NAME} syntax. To avoid typos and mistakes, every property must be explicitly defined in exactly one .py build file or .properties file. There are several permitted types for property values, and the type is indicated where they are defined:

defineStringProperty(name, default)

Define a string property which can be used in ${…} substitution.

definePathProperty(name, default[, mustExist])

Define a string property that will be converted to an absolute path.

defineOutputDirProperty(name, default)

Define a string property that will also be registered as an output directory (indicating that it will always be deleted during a clean).

defineEnumerationProperty(name, default, …)

Defines a property that must take one of the specified values.

defineBooleanProperty(name[, default])

Defines a boolean property that will have a True or False value.

definePropertiesFromFile(propertiesFile[, …])

Defines a set of string properties by reading a .properties file.

Properties can be overridden on the command line using PROPNAME=value or if using an environment variable if the enableEnvironmentPropertyOverrides function is called.

Usually property values should not be resolved until the build phase beings, using methods such as xpybuild.buildcontext.BaseContext.getPropertyValue. However in some cases it is necessary to evaluate a property during the initialization phase while reading the build files which can be achieved using getPropertyValue or expandListProperty.

To see a list of the property names and values for the current build and machine, run:

xpybuild.py --properties

Target options

Options provide a way to customize the behaviour of targets either globally throughout the build or for specific targets. For example, location of the JDK used for compiling Java programs, or the default class used for handling output from a custom command (e.g. CustomCommand.outputHandlerFactory).

Often an option will be set to the value of a ${...} property, so that the property setting, reuse and overriding mechanisms can be used.

Information about the defined option names and their value type and default is available in the documentation for the associated targets. To specify the default value for an option globally for all targetsin your build, call setGlobalOption() from one of the build files. To override an option for an individual target ion your build file, call the xpybuild.basetarget.BaseTarget.option() function. Target authors should use xpybuild.basetarget.BaseTarget.getOption() or BaseTarget.options to get the fully-resolved values for that target (whether from the global default or a per-target overrride).

To see a list of the option names and global values for all (currently imported) targets in the current build, run:

xpybuild.py --options

Late-binding property functions (functors)

The concept of functors is useful when you need to pass a value to a target that should be determined dynamically during the build phase of the build (once all properties have been defined) rather than statically when the build files are read. For example, taking a path property value and extracting the directory name from it. The following functors are provided in-the-box:

dirname(path)

A late-binding function which performs property expansion on its argument and then removes the file parts of the argument.

basename(path)

A late-binding function which performs property expansion on its argument and then removes the directory parts of the argument.

sub(pat, rep, arg)

A late-binding function which performs regex substitution.

joinPaths(pathset[, pathsep])

A late-binding function which resolves the specified PathSet and then joins its contents together to form a string using os.pathsep or a specified separator character.

ExtensionBasedFileEncodingDecider

class xpybuild.propertysupport.ExtensionBasedFileEncodingDecider(extToEncoding={}, default=None)[source]

Bases: object

Can be used for the common.fileEncodingDecider option which decides what file encoding to use for reading/writing a text file given its path.

For example:

setGlobalOption("common.fileEncodingDecider", ExtensionBasedFileEncodingDecider({
        '.foo': 'utf-8', 
        '.bar': ExtensionBasedFileEncodingDecider.BINARY,
        }, default=ExtensionBasedFileEncodingDecider.getDefaultFileEncodingDecider()))

This decider is called with arguments (context, path), and returns the name of the encoding to be used for this path. Additional keyword arguments may be passed to the decider function in future, so accept additional **kwargs in the method signature if overriding.

This extension-based decider uses the specified dictionary of extensions to determine which extension to use, including the special value ExtensionBasedFileEncodingDecider.BINARY which indicates non-text files.

Parameters
  • extToEncoding

    A dictionary whose keys are extensions such as ‘.xml’, ‘.foo.bar.baz’ and values specify the encoding to use for each one, or the constant ExtensionBasedFileEncodingDecider.BINARY which indicates a non-text file (not all targets support binary). The extensions can contain ${…} properties.

    Extensions are matched case insensitively.

  • default

    Specifies what to do if none of the specified extensions match.

    Can be: the name of the default encoding to be used as a string (e.g. "utf-8"), a decider function to delegate to (such as ExtensionBasedFileEncodingDecider.getDefaultFileEncodingDecider()), or None to defer to the configured global option (or throw an exception if this is itself the global option).

    Recommended values are: ‘utf-8’, ‘ascii’ or xpybuild.buildcommon.PREFERRED_ENCODING.

BINARY = '<binary>'

This constant should be used with ExtensionBasedFileEncodingDecider to indicate binary files that should not be opened in text mode.

decide(context, path, **forfutureuse) → str[source]

Decides what encoding to use for a given path.

Can be overridden by subclasses.

Parameters
  • context – The BuildContext

  • path – The full expanded path of the file to be decided.

Returns

The encoding name to return.

static getDefaultFileEncodingDecider()[source]

Creates the file encoding decider that is used by default if per-target or global option is not specified.

Currently this supports utf-8 encoding of json/xml/yaml/yml files, and binary for common non-application/text mime types such as image files (based on the mime settings of the current machine).

Additional types may be added to this in future releases, so you should use setGlobalOption('common.fileEncodingDecider', ...) if you wish to control the encodings precisely and ensure identical behaviour across machines.

Option

class xpybuild.propertysupport.Option(name, default)[source]

Bases: object

Represents an option definition. Options customize the behaviour of one or more targets, for example by providing default compiler arguments, timeouts, or paths to locally installed tools.

An instance of this class is returned by defineOption. To set the value of options in your build, call xpybuild.basetarget.BaseTarget.option or setGlobalOption.

dirname

class xpybuild.propertysupport.dirname(path)[source]

Bases: xpybuild.utils.functors.Composable

A late-binding function which performs property expansion on its argument and then removes the file parts of the argument.

Parameters

path – The input path, possibly containing unreplaced properties.

resolveToString(context)[source]

Perform the expansion and dirname on the argument path.

Parameters

context – a BuildContext

>>> str(dirname("path/"))
'dirname()'
>>> str(dirname("path/${foo}/bar"))
'dirname(path/${foo})'
>>> str(dirname("path/${foo}/bar/"))
'dirname(path/${foo})'
>>> dirname("${PATH}").resolveToString(xpybuild.buildcontext.BaseContext({'PATH':'/path/base'})).replace(os.sep,'/')
'/path'
>>> dirname("${PATH}").resolveToString(xpybuild.buildcontext.BaseContext({'PATH':'/path/base/'})).replace(os.sep,'/')
'/path'
>>> str("${OUTPUT_DIR}/"+dirname("${INPUT}"))
'${OUTPUT_DIR}/+dirname(${INPUT})'
>>> ("${OUTPUT_DIR}"+dirname("${INPUT}")).resolveToString(xpybuild.buildcontext.BaseContext({'OUTPUT_DIR':'/target', 'INPUT':'/libs/foo'})).replace(os.sep,'/')
'${OUTPUT_DIR}/libs'
>>> str(dirname("${A}"+dirname("${B}")))
'dirname(${A}+dirname(${B}))'
>>> dirname("${A}"+dirname("${B}")).resolveToString(xpybuild.buildcontext.BaseContext({'A':'/foo/bar-', 'B':'/baz/quux'})).replace(os.sep,'/')
'/foo/bar-'

basename

class xpybuild.propertysupport.basename(path)[source]

Bases: xpybuild.utils.functors.Composable

A late-binding function which performs property expansion on its argument and then removes the directory parts of the argument.

Parameters

path – The input path, possibly containing unreplaced properties.

resolveToString(context)[source]

Perform the expansion and basename on the argument path.

Parameters

context – a BuildContext

>>> str(basename("path/"))
'basename(path)'
>>> str(basename("path/${foo}/bar"))
'basename(bar)'
>>> str(basename("path/${foo}/bar/"))
'basename(bar)'
>>> basename("${PATH}").resolveToString(xpybuild.buildcontext.BaseContext({'PATH':'/path/base'}))
'base'
>>> basename("${PATH}").resolveToString(xpybuild.buildcontext.BaseContext({'PATH':'/path/base/'}))
'base'
>>> str("${OUTPUT_DIR}/"+basename("${INPUT}"))
'${OUTPUT_DIR}/+basename(${INPUT})'
>>> ("${OUTPUT_DIR}/"+basename("${INPUT}")).resolveToString(xpybuild.buildcontext.BaseContext({'OUTPUT_DIR':'/target', 'INPUT':'/libs/foo'}))
'${OUTPUT_DIR}/foo'
>>> str(basename("${A}"+basename("${B}")))
'basename(${A}+basename(${B}))'
>>> basename("${A}"+basename("${B}")).resolveToString(xpybuild.buildcontext.BaseContext({'A':'/foo/bar-', 'B':'/baz/quux'}))
'bar-quux'

sub

class xpybuild.propertysupport.sub(pat, rep, arg)[source]

Bases: xpybuild.utils.functors.Composable

A late-binding function which performs regex substitution. The pattern is passed through verbatim, the replacement and the input have property expansion performed on them before invoking the regular expression.

The pattern/replacement syntax is the same as re.sub

Parameters
  • pat – the regex pattern to match

  • rep – the replacement string

  • arg – the input

resolveToString(context)[source]

Do property expansion on the inputs and then perform the regex

Parameters

context – a BuildContext

>>> str(sub('a','b','aa'))
'sub(a,b,aa)'
>>> sub('a','b','aa').resolveToString(xpybuild.buildcontext.BaseContext({}))
'bb'
>>> str("output/"+sub('a', '${REP}', '${INPUT}'))
'output/+sub(a,${REP},${INPUT})'
>>> ("output/"+sub('a', '${REP}', '${INPUT}')).resolveToString(xpybuild.buildcontext.BaseContext({'REP':'c', 'INPUT':'aa'}))
'output/cc'
>>> str("output/"+sub('b', sub('c','d','${REP}'), sub('a','b','${INPUT}')))
'output/+sub(b,sub(c,d,${REP}),sub(a,b,${INPUT}))'
>>> ("output/"+sub('b', sub('c','d','${REP}'), sub('a','b','${INPUT}'))).resolveToString(xpybuild.buildcontext.BaseContext({'REP':'c', 'INPUT':'aa'}))
'output/dd'

joinPaths

class xpybuild.propertysupport.joinPaths(pathset, pathsep=':')[source]

Bases: xpybuild.utils.functors.Composable

A late-binding function which resolves the specified PathSet and then joins its contents together to form a string using os.pathsep or a specified separator character.

resolveToString(context)[source]

Do property expansion on the inputs and then perform the regex

Parameters

context – a BuildContext

defineStringProperty

xpybuild.propertysupport.defineStringProperty(name, default)[source]

Define a string property which can be used in ${…} substitution.

Do not use this generic function for any properties representing a file system path, or a boolean/enumeration.

Parameters
  • name – The property name

  • default – The default value of the propert (can contain other ${…} variables) If set to None, the property must be set on the command line each time

Returns

The resolved property value.

definePathProperty

xpybuild.propertysupport.definePathProperty(name, default, mustExist=False)[source]

Define a string property that will be converted to an absolute path.

Path is normalized and any trailing slashes are removed. An error is raised if the path does not exist when the property is defined if mustExist=True.

Paths are always absolutized.

For paths which represent output directories of this build, call registerOutputDirProperties afterwards.

Parameters
  • name – The name of the property

  • default – The default path value of the property (can contain other ${…} variables). If a relative path, will be resolved relative to the build file in which it is defined. If set to None, the property must be set on the command line each time

  • mustExist – True if it’s an error to specify a directory that doesn’t exist (will raise a BuildException)

Returns

The resolved property value.

defineOutputDirProperty

xpybuild.propertysupport.defineOutputDirProperty(name, default)[source]

Define a string property that will also be registered as an output directory (indicating that it will always be deleted during a clean).

Equivalent to calling definePathProperty then registerOutputDirProperties.

registerOutputDirProperties

xpybuild.propertysupport.registerOutputDirProperties(*propertyNames)[source]

Registers the specified path property name(s) as being an output directory of this build, meaning that they will be created automatically at the beginning of the build process, and removed during a global clean.

Typical usage is to call this just after definePathProperty.

defineEnumerationProperty

xpybuild.propertysupport.defineEnumerationProperty(name, default, enumValues)[source]

Defines a property that must take one of the specified values.

Parameters
  • name – The name of the property

  • default – The default value of the property (can contain other ${…} variables) If set to None, the property must be set on the command line each time

  • enumValues – A list of valid values for this property (can contain other ${…} variables)

Returns

The resolved property value.

defineBooleanProperty

xpybuild.propertysupport.defineBooleanProperty(name, default=False)[source]

Defines a boolean property that will have a True or False value.

Parameters
  • name – The property name

  • default – The default value (default = False) If set to None, the property must be set on the command line each time

Returns

The resolved property value.

definePropertiesFromFile

xpybuild.propertysupport.definePropertiesFromFile(propertiesFile, prefix=None, excludeLines=None, conditions=None)[source]

Defines a set of string properties by reading a .properties file.

Parameters
  • propertiesFile (str) – The file to include properties from (can include ${…} variables)

  • prefix (str) – if specified, this prefix will be added to the start of all property names from this file

  • excludeLines (list(str)) – a string of list of strings to search for, any KEY containing these strings will be ignored

  • conditions (set(str)) –

    An optional set or list of lower_case string conditions that can appear in property keys to dyamically filter based on the platform and what kind of build is being performed.

    For example MY_PROPERTY<windows>=bar. Each line is only included if the condition matches one of the condition strings passed to this function.

    For more advanced cases, a Python eval string can be specified, evaluated in a scope that includes the conditions set, a reference to the context (for property lookups), the IS_WINDOWS constant, and the Python import_module function for accessing anything else. You cannot use the = character anywhere in the eval string (since this is a properties file, after all!), but in most cases using the in operator is more useful anyway. For example:

    MY_PROPERTY<      IS_WINDOWS and 'debug' not in conditions  > = windows-release.dll
    MY_PROPERTY< not (IS_WINDOWS and 'debug' not in conditions) > = everything-else.dll
    

getPropertyValue

xpybuild.propertysupport.getPropertyValue(propertyName) → object[source]

Return the current value of the given property (can only be used during build file parsing).

Where possible, instead of using this method defer property resolution until the build phase (after all files have been parsed) and use xpybuild.buildcontext.BuildContext.getPropertyValue instead.

For Boolean properties this will be a python Boolean, for everything else it will be a string.

expandListProperty

xpybuild.propertysupport.expandListProperty(propertyName) → List[str][source]

Utility method for use during build file parsing property and target definition that returns a list containing the values of the specified list property.

This is useful for quickly defining multiple targets (e.g. file copies) based on a list defined as a property.

Parameters

propertyName – must end with [] e.g. ‘MY_JARS[]’

enableEnvironmentPropertyOverrides

xpybuild.propertysupport.enableEnvironmentPropertyOverrides(prefix)[source]

Turns on support for value overrides for defined properties from the environment as well as from the command line.

Allows any property value to be overridden from an environment variable, provided the env var begins with the specified prefix.

This setting only affects properties defined after the point in the build files where it is called.

Property values specified on the command line take precedence over env vars, which in turn take precedence over the defaults specified when properties are defined.

Parameters

prefix – The prefix added to the start of a build property name to form the name of the environment variable; the prefix is stripped from the env var name before it is compared with properties defined by the build. This is mandatory (cannot be empty) and should be set to a build-specific string (e.g. XYZ_) in order to ensure that there is no chance of build properties being accidentally overridden. (e.g. many users have JAVA_HOME in their env but also in their build, however it may be important for them to have different values, and subtle bugs could result if the build property was able to be set implicitly from the environment).

defineOption

xpybuild.propertysupport.defineOption(name, default)[source]

Define an option controlling some behaviour of the build.

A default value is provided, which can be overridden on individual targets, or globally throughout the build using setGlobalOption.

This method is typically used only when implementing a new kind of target, and often nested in an Options class under the target, e.g.:

class MyTarget(BaseTarget):
        class Options:
                """ Options for customizing the behaviour of this target. To set an option on a specific target call 
                `xpybuild.basetarget.BaseTarget.option` or to se a global default use `xpybuild.propertysupport.setGlobalOption`. 
                """

                myOption = defineOption("MyTarget.myOption", 123)
                """
                Configures the XXX. 
                """

Unlike properties, option values are not accessed by ${...} expansion, but rather using self.options from any xpybuild.basetarget.BaseTarget subclass implementation.

Parameters
  • name – The option name, which should usually be in lowerCamelCase, with a TitleCase prefix specific to this target or group of targets, often matching the target name, e.g. Javac.compilerArgs.

  • default – The default value of the option. If you need a callable, try to use named functions rather than lambdas so that the string representation is human-friendly.

Returns

A new instance of Option.

setGlobalOption

xpybuild.propertysupport.setGlobalOption(key, value)[source]

Globally override the default for an option