Example #1
0
def include(file):
    """ Parse and register the targets and properties in in the specified 
	xpybuild.py file. 
	
	Targets should only be defined in files included using this method, 
	not using python import statements. 
	
	@param file: a path relative to the directory containing this file. 
	"""

    from buildcontext import getBuildInitializationContext
    from utils.buildfilelocation import BuildFileLocation

    file = getBuildInitializationContext().expandPropertyValues(file)

    assert file.endswith(
        '.xpybuild.py')  # enforce recommended naming convention

    filepath = getBuildInitializationContext().getFullPath(
        file, os.path.dirname(BuildFileLocation._currentBuildFile[-1]))

    BuildFileLocation._currentBuildFile.append(
        filepath)  # add to stack of files being parsed

    namespace = {}
    execfile(filepath, namespace, namespace)

    del BuildFileLocation._currentBuildFile[-1]

    return namespace
Example #2
0
def defineAtomicTargetGroup(*targets):
    """ The given targets must all be built before anything which depends on any of those targets.
	
	Returns the flattened list of targets. 
	"""

    from buildcontext import getBuildInitializationContext
    targets = flatten(targets)
    getBuildInitializationContext().defineAtomicTargetGroup(targets)
    return targets
Example #3
0
def defineStringProperty(name, default):
	""" 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. 
	
	@param name: The property name

	@param 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
	"""
	init = getBuildInitializationContext()
	if init: init.defineProperty(name, default, lambda v: getBuildInitializationContext().expandPropertyValues(v))
Example #4
0
def defineBooleanProperty(name, default=False):
    """ Defines a boolean property that will have a True or False value. 
	
	@param name: The property name

	@param default: The default value (default = False)
	If set to None, the property must be set on the command line each time
	"""

    # Expands property values, then converts to a boolean
    def _coerceToValidValue(value):
        value = getBuildInitializationContext().expandPropertyValues(
            str(value))
        if value.lower() == 'true':
            return True
        if value.lower() == 'false' or value == '':
            return False
        raise BuildException(
            'Invalid property value for "%s" - must be true or false' % (name))

    init = getBuildInitializationContext()
    if init:
        init.defineProperty(name,
                            default,
                            coerceToValidValue=_coerceToValidValue)
Example #5
0
    def tags(self, *tags):
        """
		Append one or more 'tag' strings that will be associated with this target.

		These tags can be supplied on the command line to build associated groups of targets, 
		or just provide a shorter, well-known, name.

		@param tags: the tag, tags or list of tags to add to the target.
		
		>>> BaseTarget('a',[]).tags('abc').getTags()
		<using test initialization context> <using test initialization context>
		['abc', 'all']
		>>> BaseTarget('a',[]).tags(['abc', 'def']).getTags()
		<using test initialization context> <using test initialization context>
		['abc', 'def', 'all']
		>>> BaseTarget('a',[]).tags('abc', 'def').tags('ghi').getTags()
		<using test initialization context> <using test initialization context> <using test initialization context>
		['ghi', 'abc', 'def', 'all']
		"""
        taglist = getStringList(list(tags))
        self.__tags = taglist + self.__tags
        assert sorted(list(set(self.__tags))) == sorted(list(
            self.__tags))  # check for duplicates
        init = getBuildInitializationContext()
        if init:
            init.registerTags(self,
                              taglist)  # init will be None during doctests
        return self
Example #6
0
def enableEnvironmentPropertyOverrides(prefix):
	"""
	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. 
	
	@param 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).
	"""
	init = getBuildInitializationContext()
	if init:
		init.enableEnvironmentPropertyOverrides(prefix)
Example #7
0
def setGlobalOption(key, value):
	"""
		Globally override the default for an option
	"""
	init = getBuildInitializationContext()
	if init:
		init.setGlobalOption(key, value)
Example #8
0
	def _coerceToValidValue(value):
		value = getBuildInitializationContext().expandPropertyValues(str(value))
		if value.lower() == 'true':
			return True
		if value.lower() == 'false' or value=='':
			return False
		raise BuildException('Invalid property value for "%s" - must be true or false' % (name))
Example #9
0
def setGlobalOption(key, value):
    """
		Globally override the default for an option
	"""
    init = getBuildInitializationContext()
    if init:
        init.setGlobalOption(key, value)
Example #10
0
def defineStringProperty(name, default):
    """ 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. 
	
	@param name: The property name

	@param 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
	"""
    init = getBuildInitializationContext()
    if init:
        init.defineProperty(
            name, default,
            lambda v: getBuildInitializationContext().expandPropertyValues(v))
Example #11
0
def defineEnumerationProperty(name, default, enumValues):
    """ Defines a property that must take one of the specified values.

	@param name: The name of the property

	@param 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

	@param enumValues: A list of valid values for this property (can contain other ${...} variables)
	"""

    # Expands properties, then checks that it's one of the acceptible values
    def _coerceToValidValue(value):
        value = getBuildInitializationContext().expandPropertyValues(value)
        if value in enumValues: return value

        # case-insensitive match
        for e in enumValues:
            if e.lower() == value.lower():
                return e

        raise BuildException(
            'Invalid property value for "%s" - value "%s" is not one of the allowed enumeration values: %s'
            % (name, value, enumValues))

    init = getBuildInitializationContext()
    if init:
        init.defineProperty(name,
                            default,
                            coerceToValidValue=_coerceToValidValue)
Example #12
0
def defineEnumerationProperty(name, default, enumValues):
	""" Defines a property that must take one of the specified values.

	@param name: The name of the property

	@param 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

	@param enumValues: A list of valid values for this property (can contain other ${...} variables)
	"""

	# Expands properties, then checks that it's one of the acceptible values
	def _coerceToValidValue(value):
		value = getBuildInitializationContext().expandPropertyValues(value)
		if value in enumValues: return value
		
		# case-insensitive match
		for e in enumValues:
			if e.lower()==value.lower():
				return e
			
		raise BuildException('Invalid property value for "%s" - value "%s" is not one of the allowed enumeration values: %s' % (name, value, enumValues))
		
	init = getBuildInitializationContext()
	if init:
		init.defineProperty(name, default, coerceToValidValue=_coerceToValidValue)
Example #13
0
 def clearTags(self):
     """ Removes any tags other than "all" from this target """
     init = getBuildInitializationContext()
     init.removeFromTags(self, self.__tags)
     self.__tags = ['all'] if 'all' in self.__tags else []
     init.registerTags(self, self.__tags)
     return self
Example #14
0
def enableEnvironmentPropertyOverrides(prefix):
    """
	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. 
	
	@param 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).
	"""
    init = getBuildInitializationContext()
    if init:
        init.enableEnvironmentPropertyOverrides(prefix)
Example #15
0
def definePropertiesFromFile(propertiesFile,
                             prefix=None,
                             excludeLines=None,
                             conditions=None):
    """
	Defines a set of properties from a .properties file
	
	@param propertiesFile: The file to include properties from (can include ${...} variables)

	@param prefix: if specified, this prefix will be added to the start of all property names from this file

	@param excludeLines: a string of list of strings to search for, any KEY containing these strings will be ignored
	
	@param conditions: an optional list of string conditions that can appear in property 
	keys e.g. "FOO<condition>=bar" where lines with no condition in this list 
	are ignored. Conditions are typically lowercase. 
	"""
    if conditions:
        assert not isinstance(
            conditions, basestring), 'conditions parameter must be a list'
    __log.info('Defining properties from file: %s', propertiesFile)
    context = getBuildInitializationContext()

    propertiesFile = context.getFullPath(
        propertiesFile,
        BuildFileLocation(raiseOnError=True).buildDir)
    try:
        f = open(propertiesFile, 'r')
    except Exception, e:
        raise BuildException('Failed to open properties file "%s"' %
                             (propertiesFile),
                             causedBy=True)
Example #16
0
def getPropertyValue(propertyName):
    """ Return the current value of the given property (can only be used during build file parsing).
	
	For Boolean properties this will be a python Boolean, for everything else it will be a string. 
	"""
    context = getBuildInitializationContext()
    assert context, 'getProperty can only be used during build file initialization phase'
    return context.getPropertyValue(propertyName)
Example #17
0
def getPropertyValue(propertyName):
	""" Return the current value of the given property (can only be used during build file parsing).
	
	For Boolean properties this will be a python Boolean, for everything else it will be a string. 
	"""
	context = getBuildInitializationContext()
	assert context, 'getProperty can only be used during build file initialization phase'
	return context.getPropertyValue(propertyName)
Example #18
0
    def disableInFullBuild(self):
        """ Stops this target from building in 'all' mode, therefore it must be called 
		explicitly or via a tag.
		"""
        self.__tags = list(set(self.__tags) - set(['all']))
        init = getBuildInitializationContext()
        init.removeFromTags(self, ['all'])
        return self
Example #19
0
 def _coerceToValidValue(value):
     value = getBuildInitializationContext().expandPropertyValues(
         str(value))
     if value.lower() == 'true':
         return True
     if value.lower() == 'false' or value == '':
         return False
     raise BuildException(
         'Invalid property value for "%s" - must be true or false' % (name))
Example #20
0
	def _coerceToValidValue(value):
		value = getBuildInitializationContext().expandPropertyValues(value)
		if value in enumValues: return value
		
		# case-insensitive match
		for e in enumValues:
			if e.lower()==value.lower():
				return e
			
		raise BuildException('Invalid property value for "%s" - value "%s" is not one of the allowed enumeration values: %s' % (name, value, enumValues))
Example #21
0
    def _coerceToValidValue(value):
        value = getBuildInitializationContext().expandPropertyValues(value)
        if value in enumValues: return value

        # case-insensitive match
        for e in enumValues:
            if e.lower() == value.lower():
                return e

        raise BuildException(
            'Invalid property value for "%s" - value "%s" is not one of the allowed enumeration values: %s'
            % (name, value, enumValues))
Example #22
0
	def _coerceToValidValue(value):
		value = getBuildInitializationContext().expandPropertyValues(value)
		
		if not os.path.isabs(value):
			# must absolutize this, as otherwise it might be used from a build 
			# file in a different location, resulting in the same property 
			# resolving to different effective values in different places
			value = BuildFileLocation(raiseOnError=True).buildDir+'/'+value
		
		value = normpath(value).rstrip('/\\')
		if mustExist and not os.path.exists(value):
			raise BuildException('Invalid path property value for "%s" - path "%s" does not exist' % (name, value))
		return value
Example #23
0
def registerOutputDirProperties(*propertyNames):
	""" 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. 
	"""
	init = getBuildInitializationContext()
	if init:
		for p in propertyNames:
			p = init.getPropertyValue(p)
			if not os.path.isabs(p): raise BuildException('Only absolute path properties can be used as output dirs: "%s"'%p)
			init.registerOutputDir(normpath(p)) 
Example #24
0
def defineOption(name, default):
	""" Define an option with a default (can be overridden globally or on targets).
	
	Options are not available for ${...} expansion (like properties), but 
	rather as used for (optionally inheritably) settings that affect the 
	behaviour of one or more targets. 
	
	@param name: The option name

	@param default: The default value of the option
	"""
	init = getBuildInitializationContext()
	if init:
		init._defineOption(name, default)
Example #25
0
    def _coerceToValidValue(value):
        value = getBuildInitializationContext().expandPropertyValues(value)

        if not os.path.isabs(value):
            # must absolutize this, as otherwise it might be used from a build
            # file in a different location, resulting in the same property
            # resolving to different effective values in different places
            value = BuildFileLocation(raiseOnError=True).buildDir + '/' + value

        value = normpath(value).rstrip('/\\')
        if mustExist and not os.path.exists(value):
            raise BuildException(
                'Invalid path property value for "%s" - path "%s" does not exist'
                % (name, value))
        return value
Example #26
0
def registerOutputDirProperties(*propertyNames):
    """ 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. 
	"""
    init = getBuildInitializationContext()
    if init:
        for p in propertyNames:
            p = init.getPropertyValue(p)
            if not os.path.isabs(p):
                raise BuildException(
                    'Only absolute path properties can be used as output dirs: "%s"'
                    % p)
            init.registerOutputDir(normpath(p))
Example #27
0
def definePathProperty(name, default, mustExist=False):
    """ Define a property that corresponds to a 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. 

	@param name: The name of the property

	@param 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

	@param mustExist: True if it's an error to specify a directory that doesn't
	exist (will raise a BuildException)
	
	"""

    # Expands properties, makes the path absolute, checks that it looks sensible and (if needed) whether the path exists
    def _coerceToValidValue(value):
        value = getBuildInitializationContext().expandPropertyValues(value)

        if not os.path.isabs(value):
            # must absolutize this, as otherwise it might be used from a build
            # file in a different location, resulting in the same property
            # resolving to different effective values in different places
            value = BuildFileLocation(raiseOnError=True).buildDir + '/' + value

        value = normpath(value).rstrip('/\\')
        if mustExist and not os.path.exists(value):
            raise BuildException(
                'Invalid path property value for "%s" - path "%s" does not exist'
                % (name, value))
        return value

    init = getBuildInitializationContext()
    if init:
        init.defineProperty(name,
                            default,
                            coerceToValidValue=_coerceToValidValue)
Example #28
0
def defineOption(name, default):
    """ Define an option with a default (can be overridden globally using setGlobalOption() or on individual targets).
	
	This method is typically used only when implementing a new kind of target. 
	
	Options are not available for ${...} expansion (like properties), but 
	rather as used for (optionally inheritably) settings that affect the 
	behaviour of one or more targets. They are accessed using self.options 
	in any target instance. 
	
	@param name: The option name, which should be in lowercase, and contain a prefix specific
	to this target or group of targets, e.g. "java.home"

	@param default: The default value of the option
	"""
    init = getBuildInitializationContext()
    if init:
        init._defineOption(name, default)
Example #29
0
    def __init__(self, name, dependencies):
        """ Normal constructor, should only be called from sub-classes since this is a stub.

		@param name: a unique name for this target (may contain unexpanded ${...}
		variables). Should correspond to the file or directory which is created
		as a result of running this target.
		@param dependencies: a list of dependencies, which may need to be 
		flattened/expanded by the build system; may be any combination of 
		strings, PathSets and lists and may also contain unexpanded variables.
		"""

        self._optionsTargetOverridesUnresolved = {
        }  # for target-specific option overrides. for internal use (by buildcontext), do not use
        self.__optionsResolved = None  # gets assigned during end of initialization phase

        if isinstance(name, basestring):
            if '//' in name:
                raise BuildException(
                    'Invalid target name: double slashes are not permitted: %s'
                    % name)
            if '\\' in name:
                raise BuildException(
                    'Invalid target name: backslashes are not permitted: %s' %
                    name)
        self.__name = str(name)
        self.__path_src = name
        self.__tags = ['all']
        self.__priority = 0.0  # default so we can go bigger or smaller
        self.log = logging.getLogger(self.__class__.__name__)

        init = getBuildInitializationContext()
        if not init:  # doc-test mode
            self.location = BuildFileLocation(raiseOnError=False)
        else:
            self.location = BuildFileLocation(raiseOnError=True)
            init.registerTarget(self)

        # should ensure changes to the build file cause a rebuild? probs no need
        # PathSet will perform all necessary flattening etc
        self.__dependencies = PathSet(dependencies)

        self.__path = None  # set by _resolveTargetPath
        self.__workDir = None
Example #30
0
def defineBooleanProperty(name, default=False):
	""" Defines a boolean property that will have a True or False value. 
	
	@param name: The property name

	@param default: The default value (default = False)
	If set to None, the property must be set on the command line each time
	"""

	# Expands property values, then converts to a boolean
	def _coerceToValidValue(value):
		value = getBuildInitializationContext().expandPropertyValues(str(value))
		if value.lower() == 'true':
			return True
		if value.lower() == 'false' or value=='':
			return False
		raise BuildException('Invalid property value for "%s" - must be true or false' % (name))
	
	init = getBuildInitializationContext()
	if init:
		init.defineProperty(name, default, coerceToValidValue=_coerceToValidValue)
Example #31
0
def expandListProperty(propertyName):
	""" Utility method for use during 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. 
	
	@param propertyName: must end with [] e.g. 'MY_JARS[]'
	
	"""
	assert not propertyName.startswith('$')
	assert propertyName.endswith('[]')
	context = getBuildInitializationContext()

	# although this isn't a valid return value, it's best to avoid triggering the assertion 
	# below to support doc-testing custom xpybuild files that happen to use this method
	if (not context) and 'doctest' in sys.argv[0]: return ['${%s}'%propertyName]

	assert context, 'expandListProperty utility can only be used during build file initialization phase'
	return context.expandListPropertyValue(propertyName)
Example #32
0
def definePathProperty(name, default, mustExist=False):
	""" Define a property that corresponds to a 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. 

	@param name: The name of the property

	@param 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

	@param mustExist: True if it's an error to specify a directory that doesn't
	exist (will raise a BuildException)
	
	"""

	# Expands properties, makes the path absolute, checks that it looks sensible and (if needed) whether the path exists
	def _coerceToValidValue(value):
		value = getBuildInitializationContext().expandPropertyValues(value)
		
		if not os.path.isabs(value):
			# must absolutize this, as otherwise it might be used from a build 
			# file in a different location, resulting in the same property 
			# resolving to different effective values in different places
			value = BuildFileLocation(raiseOnError=True).buildDir+'/'+value
		
		value = normpath(value).rstrip('/\\')
		if mustExist and not os.path.exists(value):
			raise BuildException('Invalid path property value for "%s" - path "%s" does not exist' % (name, value))
		return value
		
	init = getBuildInitializationContext()
	if init: init.defineProperty(name, default, coerceToValidValue=_coerceToValidValue)
Example #33
0
def expandListProperty(propertyName):
    """ Utility method for use during 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. 
	
	@param propertyName: must end with [] e.g. 'MY_JARS[]'
	
	"""
    assert not propertyName.startswith('$')
    assert propertyName.endswith('[]')
    context = getBuildInitializationContext()

    # although this isn't a valid return value, it's best to avoid triggering the assertion
    # below to support doc-testing custom xpybuild files that happen to use this method
    if (not context) and 'doctest' in sys.argv[0]:
        return ['${%s}' % propertyName]

    assert context, 'expandListProperty utility can only be used during build file initialization phase'
    return context.expandListPropertyValue(propertyName)
Example #34
0
def defineOption(name, default):
    """ Define an option with a default (can be overridden globally using setGlobalOption() or on individual targets).
	
	This method is typically used only when implementing a new kind of target. 
	
	Options are not available for ${...} expansion (like properties), but 
	rather as used for (optionally inheritably) settings that affect the 
	behaviour of one or more targets. They are accessed using self.options 
	in any target instance. 
	
	@param 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". 

	@param default: The default value of the option
	"""
    init = getBuildInitializationContext()
    if init:
        init._defineOption(name, default)
    elif 'doctest' not in sys.argv[0] and 'epydoc' not in sys.modules:
        # this check is so we notice if unfortunate module order causes us to try to
        # define options before we have a real context to put them in
        assert False, 'Cannot define options at this point in the build as there is no initialization build context active'
Example #35
0
def definePropertiesFromFile(propertiesFile, prefix=None, excludeLines=None, conditions=None):
	"""
	Defines a set of properties from a .properties file
	
	@param propertiesFile: The file to include properties from (can include ${...} variables)

	@param prefix: if specified, this prefix will be added to the start of all property names from this file

	@param excludeLines: a string of list of strings to search for, any KEY containing these strings will be ignored
	
	@param conditions: an optional list of string conditions that can appear in property 
	keys e.g. "FOO<condition>=bar" where lines with no condition in this list 
	are ignored. Conditions are typically lowercase. 
	"""
	if conditions: assert not isinstance(conditions,basestring), 'conditions parameter must be a list'
	__log.info('Defining properties from file: %s', propertiesFile)
	context = getBuildInitializationContext()
	
	propertiesFile = context.getFullPath(propertiesFile, BuildFileLocation(raiseOnError=True).buildDir)
	try:
		f = open(propertiesFile, 'r') 
	except Exception, e:
		raise BuildException('Failed to open properties file "%s"'%(propertiesFile), causedBy=True)
Example #36
0
def registerPreBuildCheck(fn):
    """ Defines a check which will be called after any clean but before any build actions take place.
	    fn should be a functor that takes a context and raises a BuildException if the check fails. """
    from buildcontext import getBuildInitializationContext
    getBuildInitializationContext().registerPreBuildCheck(fn)