Example #1
0
def expand_composites (properties):
    """ Expand all composite properties in the set so that all components
        are explicitly expressed.
    """
    explicit_features = get_grist (properties)

    result = []

    # now expand composite features
    for p in properties:
        expanded = expand_composite (p)

        for x in expanded:
            if not x in result:
                f = get_grist (x)

                if f in __free_features:
                    result.append (x)
                elif not x in properties:  # x is the result of expansion
                    if not f in explicit_features:  # not explicitly-specified
                        if f in get_grist (result):
                            raise FeatureConflict ("expansions of composite features result in "
                            "conflicting values for '%s'\nvalues: '%s'\none contributing composite property was '%s'" % (f, 
                            get_values (f, result) + [replace_grist (x, '')], p))
                        else:
                            result.append (x)
                elif f in get_grist (result):
                    raise FeatureConflict ("explicitly-specified values of non-free feature '%s' conflict\n"
                    "existing values: '%s'\nvalue from expanding '%s': '%s'" % (f, 
                    get_values (f, properties), p, replace_grist (x, '')))
                else:
                    result.append (x)

    return result
Example #2
0
def __expand_subfeatures_aux(feature, value, dont_validate=False):
    """ Helper for expand_subfeatures.
        Given a feature and value, or just a value corresponding to an
        implicit feature, returns a property set consisting of all component
        subfeatures and their values. For example:
        
          expand_subfeatures <toolset>gcc-2.95.2-linux-x86
              -> <toolset>gcc <toolset-version>2.95.2 <toolset-os>linux <toolset-cpu>x86
          equivalent to:
              expand_subfeatures gcc-2.95.2-linux-x86

        feature:        The name of the feature, or empty if value corresponds to an implicit property
        value:          The value of the feature.
        dont_validate:  If True, no validation of value string will be done.
    """
    if not feature:
        feature = implied_feature(value)
    else:
        validate_feature(feature)

    if not dont_validate:
        validate_value_string(feature, value)

    components = value.split("-")

    # get the top-level feature's value
    value = replace_grist(components[0], '')

    result = [replace_grist(components[0], feature)]

    subvalues = components[1:]

    while len(subvalues) > 0:
        subvalue = subvalues[0]  # pop the head off of subvalues
        subvalues = subvalues[1:]

        subfeature = __find_implied_subfeature(feature, subvalue, value)

        # If no subfeature was found, reconstitute the value string and use that
        if not subfeature:
            result = '-'.join(components)
            result = replace_grist(result, feature)
            return [result]

        f = ungrist(feature)
        # FIXME: why grist includes '<>'?
        result.append(replace_grist(subvalue,
                                    '<' + f + '-' + subfeature + '>'))

    return result
Example #3
0
def __expand_subfeatures_aux (feature, value, dont_validate = False):
    """ Helper for expand_subfeatures.
        Given a feature and value, or just a value corresponding to an
        implicit feature, returns a property set consisting of all component
        subfeatures and their values. For example:
        
          expand_subfeatures <toolset>gcc-2.95.2-linux-x86
              -> <toolset>gcc <toolset-version>2.95.2 <toolset-os>linux <toolset-cpu>x86
          equivalent to:
              expand_subfeatures gcc-2.95.2-linux-x86

        feature:        The name of the feature, or empty if value corresponds to an implicit property
        value:          The value of the feature.
        dont_validate:  If True, no validation of value string will be done.
    """
    if not feature:
        feature = implied_feature(value)
    else:
        validate_feature(feature)

    if not dont_validate:
        validate_value_string(feature, value)
    
    components = value.split ("-")
    
    # get the top-level feature's value
    value = replace_grist(components[0], '')

    result = [ replace_grist(components[0], feature) ]
    
    subvalues = components[1:]

    while len(subvalues) > 0:
        subvalue = subvalues [0]    # pop the head off of subvalues
        subvalues = subvalues [1:]
        
        subfeature = __find_implied_subfeature (feature, subvalue, value)
        
        # If no subfeature was found, reconstitute the value string and use that
        if not subfeature:
            result = '-'.join(components)
            result = replace_grist (result, feature)
            return [result]
            
        f = ungrist (feature)
        # FIXME: why grist includes '<>'?
        result.append (replace_grist (subvalue, '<' + f + '-' + subfeature + '>'))
    
    return result
Example #4
0
    def actualize (self, scanner = None):
        """ Generates all the actual targets and sets up build actions for
            this target.
            
            If 'scanner' is specified, creates an additional target
            with the same location as actual target, which will depend on the
            actual target and be associated with 'scanner'. That additional
            target is returned. See the docs (#dependency_scanning) for rationale.
            Target must correspond to a file if 'scanner' is specified.
            
            If scanner is not specified, then actual target is returned.
        """
        actual_name = self.actualize_no_scanner ()

        if not scanner:
            return actual_name

        else:
            # Add the scanner instance to the grist for name.
            g = '-'.join ([ungrist(get_grist(actual_name)), str(id(scanner))])

            name = replace_grist (actual_name, '<' + g + '>')

            if not self.made_.has_key (name):
                self.made_ [name] = True

                self.project_.manager ().engine ().add_dependency (name, actual_name)

                self.actualize_location (name)

                self.project_.manager ().scanners ().install (scanner, name, str (self))

            return name
Example #5
0
def is_subfeature_of (parent_property, f):
    """ Return true iff f is an ordinary subfeature of the parent_property's
        feature, or if f is a subfeature of the parent_property's feature
        specific to the parent_property's value.
    """
    if not valid (f) or not 'subfeature' in __all_features [f]['attributes']:
        return False

    specific_subfeature = __re_split_subfeatures.match (f)

    if specific_subfeature:
        # The feature has the form
        # <topfeature-topvalue:subfeature>,
        # e.g. <toolset-msvc:version>
        feature_value = split_top_feature(specific_subfeature.group(1))
        if replace_grist (feature_value [1], '<' + feature_value [0] + '>') == parent_property:
            return True
    else:
        # The feature has the form <topfeature-subfeature>,
        # e.g. <toolset-version>
        top_sub = split_top_feature (ungrist (f))

        if top_sub [1] and add_grist (top_sub [0]) == get_grist (parent_property):
            return True

    return False
Example #6
0
def is_subfeature_of(parent_property, f):
    """ Return true iff f is an ordinary subfeature of the parent_property's
        feature, or if f is a subfeature of the parent_property's feature
        specific to the parent_property's value.
    """
    if not valid(f) or not 'subfeature' in __all_features[f]['attributes']:
        return False

    specific_subfeature = __re_split_subfeatures.match(f)

    if specific_subfeature:
        # The feature has the form
        # <topfeature-topvalue:subfeature>,
        # e.g. <toolset-msvc:version>
        feature_value = split_top_feature(specific_subfeature.group(1))
        if replace_grist(feature_value[1],
                         '<' + feature_value[0] + '>') == parent_property:
            return True
    else:
        # The feature has the form <topfeature-subfeature>,
        # e.g. <toolset-version>
        top_sub = split_top_feature(ungrist(f))

        if top_sub[1] and add_grist(top_sub[0]) == get_grist(parent_property):
            return True

    return False
Example #7
0
def expand_subfeatures (properties, dont_validate = False):
    """
    Make all elements of properties corresponding to implicit features
    explicit, and express all subfeature values as separate properties
    in their own right. For example, the property
    
       gcc-2.95.2-linux-x86
    
    might expand to
    
      <toolset>gcc <toolset-version>2.95.2 <toolset-os>linux <toolset-cpu>x86

    properties:     A sequence with elements of the form
                    <feature>value-string or just value-string in the
                    case of implicit features.
  : dont_validate:  If True, no validation of value string will be done.
    """
    result = []
    for p in properties:
        p_grist = get_grist (p)
        # Don't expand subfeatures in subfeatures
        if ':' in p_grist:
            result.append (p)
        else:
            result.extend (__expand_subfeatures_aux (p_grist, replace_grist (p, ''), dont_validate))

    return result
Example #8
0
    def __init__ (self, main_target, prop_set, sources, build_properties, sources_usage_requirements, created_targets):
        """ 
        main_target:                 The instance of MainTarget class
        prop_set:                    Properties requested for this target
        sources:
        build_properties:            Actually used properties
        sources_usage_requirements:  Properties propagated from sources
        created_targets:             Top-level created targets
        """
        self.main_target_ = main_target
        self.properties_ = prop_set
        self.sources_ = sources
        self.build_properties_ = build_properties
        self.sources_usage_requirements_ = sources_usage_requirements
        self.created_targets_ = created_targets

        self.usage_requirements_ = None
        
        # Pre-compose the list of other dependency graphs, on which this one
        # depends
        deps = build_properties.get ('<implicit-dependency>')
        
        self.other_dg_ = []
        for d in deps:
            # FIXME: the property must have the actual object here, not a string.
            value = replace_grist (d, '')
            self.other_dg_.append (value.creating_subvariant ())

        self.other_dg_ = unique (self.other_dg_)

        self.implicit_includes_cache_ = {}
        self.target_directories_ = None
Example #9
0
def expand_subfeatures(properties, dont_validate=False):
    """
    Make all elements of properties corresponding to implicit features
    explicit, and express all subfeature values as separate properties
    in their own right. For example, the property
    
       gcc-2.95.2-linux-x86
    
    might expand to
    
      <toolset>gcc <toolset-version>2.95.2 <toolset-os>linux <toolset-cpu>x86

    properties:     A sequence with elements of the form
                    <feature>value-string or just value-string in the
                    case of implicit features.
  : dont_validate:  If True, no validation of value string will be done.
    """
    result = []
    for p in properties:
        p_grist = get_grist(p)
        # Don't expand subfeatures in subfeatures
        if ':' in p_grist:
            result.append(p)
        else:
            result.extend(
                __expand_subfeatures_aux(p_grist, replace_grist(p, ''),
                                         dont_validate))

    return result
Example #10
0
    def __init__ (self, main_target, prop_set, sources, build_properties, sources_usage_requirements, created_targets):
        """ 
        main_target:                 The instance of MainTarget class
        prop_set:                    Properties requested for this target
        sources:
        build_properties:            Actually used properties
        sources_usage_requirements:  Properties propagated from sources
        created_targets:             Top-level created targets
        """
        self.main_target_ = main_target
        self.properties_ = prop_set
        self.sources_ = sources
        self.build_properties_ = build_properties
        self.sources_usage_requirements_ = sources_usage_requirements
        self.created_targets_ = created_targets

        self.usage_requirements_ = None
        
        # Pre-compose the list of other dependency graphs, on which this one
        # depends
        deps = build_properties.get ('<implicit-dependency>')
        
        self.other_dg_ = []
        for d in deps:
            # FIXME: the property must have the actual object here, not a string.
            value = replace_grist (d, '')
            self.other_dg_.append (value.creating_subvariant ())

        self.other_dg_ = unique (self.other_dg_)

        self.implicit_includes_cache_ = {}
        self.target_directories_ = None
Example #11
0
    def actualize (self, scanner = None):
        """ Generates all the actual targets and sets up build actions for
            this target.
            
            If 'scanner' is specified, creates an additional target
            with the same location as actual target, which will depend on the
            actual target and be associated with 'scanner'. That additional
            target is returned. See the docs (#dependency_scanning) for rationale.
            Target must correspond to a file if 'scanner' is specified.
            
            If scanner is not specified, then actual target is returned.
        """
        actual_name = self.actualize_no_scanner ()

        if not scanner:
            return actual_name

        else:
            # Add the scanner instance to the grist for name.
            g = '-'.join ([ungrist(get_grist(actual_name)), str(id(scanner))])

            name = replace_grist (actual_name, '<' + g + '>')

            if not self.made_.has_key (name):
                self.made_ [name] = True

                self.project_.manager ().engine ().add_dependency (name, actual_name)

                self.actualize_location (name)

                self.project_.manager ().scanners ().install (scanner, name, str (self))

            return name
Example #12
0
def register(type, suffixes=[], base_type=None):
    """ Registers a target type, possibly derived from a 'base-type'.
        If 'suffixes' are provided, they list all the suffixes that mean a file is of 'type'.
        Also, the first element gives the suffix to be used when constructing and object of
        'type'.
        type: a string
        suffixes: None or a sequence of strings
        base_type: None or a string
    """
    # Type names cannot contain hyphens, because when used as
    # feature-values they will be interpreted as composite features
    # which need to be decomposed.
    if __re_hyphen.search(type):
        raise BaseException('type name "%s" contains a hyphen' % type)

    # it's possible for a type to be registered with a
    # base type that hasn't been registered yet. in the
    # check for base_type below and the following calls to setdefault()
    # the key `type` will be added to __types. When the base type
    # actually gets registered, it would fail after the simple check
    # of "type in __types"; thus the check for "'base' in __types[type]"
    if type in __types and 'base' in __types[type]:
        raise BaseException('Type "%s" is already registered.' % type)

    entry = __types.setdefault(type, {})
    entry['base'] = base_type
    entry.setdefault('derived', [])
    entry.setdefault('scanner', None)

    if base_type:
        __types.setdefault(base_type, {}).setdefault('derived',
                                                     []).append(type)

    if len(suffixes) > 0:
        # Generated targets of 'type' will use the first of 'suffixes'
        # (this may be overridden)
        set_generated_target_suffix(type, [], suffixes[0])

        # Specify mapping from suffixes to type
        register_suffixes(suffixes, type)

    feature.extend('target-type', [type])
    feature.extend('main-target-type', [type])
    feature.extend('base-target-type', [type])

    if base_type:
        feature.compose('<target-type>' + type,
                        [replace_grist(base_type, '<base-target-type>')])
        feature.compose('<base-target-type>' + type,
                        ['<base-target-type>' + base_type])

    import b2.build.generators as generators
    # Adding a new derived type affects generator selection so we need to
    # make the generator selection module update any of its cached
    # information related to a new derived type being defined.
    generators.update_cached_information_with_a_new_type(type)

    # FIXME: resolving recursive dependency.
    from b2.manager import get_manager
    get_manager().projects().project_rules().add_rule_for_type(type)
Example #13
0
def register(type, suffixes=[], base_type=None):
    """ Registers a target type, possibly derived from a 'base-type'.
        If 'suffixes' are provided, they list all the suffixes that mean a file is of 'type'.
        Also, the first element gives the suffix to be used when constructing and object of
        'type'.
        type: a string
        suffixes: None or a sequence of strings
        base_type: None or a string
    """
    # Type names cannot contain hyphens, because when used as
    # feature-values they will be interpreted as composite features
    # which need to be decomposed.
    if __re_hyphen.search(type):
        raise BaseException('type name "%s" contains a hyphen' % type)

    # it's possible for a type to be registered with a
    # base type that hasn't been registered yet. in the
    # check for base_type below and the following calls to setdefault()
    # the key `type` will be added to __types. When the base type
    # actually gets registered, it would fail after the simple check
    # of "type in __types"; thus the check for "'base' in __types[type]"
    if type in __types and "base" in __types[type]:
        raise BaseException('Type "%s" is already registered.' % type)

    entry = __types.setdefault(type, {})
    entry["base"] = base_type
    entry.setdefault("derived", [])
    entry.setdefault("scanner", None)

    if base_type:
        __types.setdefault(base_type, {}).setdefault("derived", []).append(type)

    if len(suffixes) > 0:
        # Generated targets of 'type' will use the first of 'suffixes'
        # (this may be overriden)
        set_generated_target_suffix(type, [], suffixes[0])

        # Specify mapping from suffixes to type
        register_suffixes(suffixes, type)

    feature.extend("target-type", [type])
    feature.extend("main-target-type", [type])
    feature.extend("base-target-type", [type])

    if base_type:
        feature.compose("<target-type>" + type, [replace_grist(base_type, "<base-target-type>")])
        feature.compose("<base-target-type>" + type, ["<base-target-type>" + base_type])

    import b2.build.generators as generators

    # Adding a new derived type affects generator selection so we need to
    # make the generator selection module update any of its cached
    # information related to a new derived type being defined.
    generators.update_cached_information_with_a_new_type(type)

    # FIXME: resolving recursive dependency.
    from b2.manager import get_manager

    get_manager().projects().project_rules().add_rule_for_type(type)
Example #14
0
def get_values (feature, properties):
    """ Returns all values of the given feature specified by the given property set.
    """
    result = []
    for p in properties:
        if get_grist (p) == feature:
            result.append (replace_grist (p, ''))
    
    return result
Example #15
0
def get_values(feature, properties):
    """ Returns all values of the given feature specified by the given property set.
    """
    result = []
    for p in properties:
        if get_grist(p) == feature:
            result.append(replace_grist(p, ''))

    return result
Example #16
0
def register(type, suffixes=[], base_type=None):
    """ Registers a target type, possibly derived from a 'base-type'. 
        If 'suffixes' are provided, they list all the suffixes that mean a file is of 'type'.
        Also, the first element gives the suffix to be used when constructing and object of
        'type'.
        type: a string
        suffixes: None or a sequence of strings
        base_type: None or a string
    """
    # Type names cannot contain hyphens, because when used as
    # feature-values they will be interpreted as composite features
    # which need to be decomposed.
    if __re_hyphen.search(type):
        raise BaseException('type name "%s" contains a hyphen' % type)

    if __types.has_key(type):
        raise BaseException('Type "%s" is already registered.' % type)

    entry = {}
    entry['base'] = base_type
    entry['derived'] = []
    entry['scanner'] = None
    __types[type] = entry

    if base_type:
        __types[base_type]['derived'].append(type)

    if len(suffixes) > 0:
        # Generated targets of 'type' will use the first of 'suffixes'
        # (this may be overriden)
        set_generated_target_suffix(type, [], suffixes[0])

        # Specify mapping from suffixes to type
        register_suffixes(suffixes, type)

    feature.extend('target-type', [type])
    feature.extend('main-target-type', [type])
    feature.extend('base-target-type', [type])

    if base_type:
        feature.compose('<target-type>' + type,
                        replace_grist(base_type, '<base-target-type>'))
        feature.compose('<base-target-type>' + type,
                        '<base-target-type>' + base_type)

    import b2.build.generators as generators
    # Adding a new derived type affects generator selection so we need to
    # make the generator selection module update any of its cached
    # information related to a new derived type being defined.
    generators.update_cached_information_with_a_new_type(type)

    # FIXME: resolving recursive dependency.
    from b2.manager import get_manager
    get_manager().projects().project_rules().add_rule_for_type(type)
Example #17
0
def register(type, suffixes=[], base_type=None):
    """ Registers a target type, possibly derived from a 'base-type'. 
        If 'suffixes' are provided, they list all the suffixes that mean a file is of 'type'.
        Also, the first element gives the suffix to be used when constructing and object of
        'type'.
        type: a string
        suffixes: None or a sequence of strings
        base_type: None or a string
    """
    # Type names cannot contain hyphens, because when used as
    # feature-values they will be interpreted as composite features
    # which need to be decomposed.
    if __re_hyphen.search(type):
        raise BaseException('type name "%s" contains a hyphen' % type)

    if __types.has_key(type):
        raise BaseException('Type "%s" is already registered.' % type)

    entry = {}
    entry["base"] = base_type
    entry["derived"] = []
    entry["scanner"] = None
    __types[type] = entry

    if base_type:
        __types[base_type]["derived"].append(type)

    if len(suffixes) > 0:
        # Generated targets of 'type' will use the first of 'suffixes'
        # (this may be overriden)
        set_generated_target_suffix(type, [], suffixes[0])

        # Specify mapping from suffixes to type
        register_suffixes(suffixes, type)

    feature.extend("target-type", [type])
    feature.extend("main-target-type", [type])
    feature.extend("base-target-type", [type])

    if base_type:
        feature.compose("<target-type>" + type, replace_grist(base_type, "<base-target-type>"))
        feature.compose("<base-target-type>" + type, "<base-target-type>" + base_type)

    import b2.build.generators as generators

    # Adding a new derived type affects generator selection so we need to
    # make the generator selection module update any of its cached
    # information related to a new derived type being defined.
    generators.update_cached_information_with_a_new_type(type)

    # FIXME: resolving recursive dependency.
    from b2.manager import get_manager

    get_manager().projects().project_rules().add_rule_for_type(type)
Example #18
0
def defaults(features):
    """ Returns the default property values for the given features.
    """
    result = []
    for f in features:
        attributes = __all_features[f]['attributes']
        if not 'free' in attributes and not 'optional' in attributes:
            defaults = __all_features[f]['default']
            if defaults:
                result.append(replace_grist(defaults, f))

    return result
Example #19
0
def defaults (features):
    """ Returns the default property values for the given features.
    """
    result = []
    for f in features:
        attributes = __all_features [f]['attributes']
        if not 'free' in attributes and not 'optional' in attributes:
            defaults = __all_features [f]['default']
            if defaults:
                result.append (replace_grist (defaults, f))

    return result
Example #20
0
def add_defaults(properties):
    """ Given a set of properties, add default values for features not
        represented in the set. 
        Note: if there's there's ordinary feature F1 and composite feature
        F2, which includes some value for F1, and both feature have default values,
        then the default value of F1 will be added, not the value in F2. This might
        not be right idea: consider
        
          feature variant : debug ... ;
               <variant>debug : .... <runtime-debugging>on
          feature <runtime-debugging> : off on ;
          
          Here, when adding default for an empty property set, we'll get
        
            <variant>debug <runtime_debugging>off
         
          and that's kind of strange.        
    """
    result = [x for x in properties]

    for v in replace_grist(properties, ''):
        if v in properties:
            raise BaseException(
                "'add_defaults' requires explicitly specified features, but '%s' appears to be the value of an un-expanded implicit feature"
                % v)

    # We don't add default for elements with ":" inside. This catches:
    # 1. Conditional properties --- we don't want <variant>debug:<define>DEBUG
    #    to be takes as specified value for <variant>
    # 2. Free properties with ":" in values. We don't care, since free properties
    #    don't have defaults.
    xproperties = [
        property for property in properties if __re_no_hyphen.match(property)
    ]
    missing_top = set.difference(__all_top_features, get_grist(xproperties))
    more = defaults(missing_top)
    result += more
    xproperties += more

    # Add defaults for subfeatures of features which are present
    for p in xproperties:
        gp = get_grist(p)
        s = []
        if __all_features.has_key(gp):
            s = __all_features[gp]['subfeatures']
        f = ungrist(gp)

        xbase = ['<%s-%s>' % (f, xs) for xs in s]

        missing_subs = set.difference(xbase, get_grist(result))
        result += defaults(__select_subfeatures(p, missing_subs))

    return result
Example #21
0
    def process(self, target, matches, binding):
        # create a single string so that findall
        # can be used since it returns a list of
        # all grouped matches
        match_str = ' '.join(matches)
        # the question mark makes the regexes non-greedy
        angles = re.findall(r'<(.*?)>', match_str)
        quoted = re.findall(r'"(.*?)"', match_str)

        # CONSIDER: the new scoping rules seem to defeat "on target" variables.
        g = ENGINE.get_target_variable(target, 'HDRGRIST')
        b = os.path.normpath(os.path.dirname(binding))

        # Attach binding of including file to included targets. When a target is
        # directly created from a virtual target this extra information is
        # unnecessary. But in other cases, it allows us to distinguish between
        # two headers of the same name included from different places. We do not
        # need this extra information for angle includes, since they should not
        # depend on the including file (we can not get literal "." in the
        # include path).
        # local g2 = $(g)"#"$(b) ;
        g2 = g + '#' + b

        angles = [replace_grist(angle, g) for angle in angles]
        quoted = [replace_grist(quote, g2) for quote in quoted]

        includes = angles + quoted

        bjam.call('INCLUDES', target, includes)
        bjam.call('NOCARE', includes)
        ENGINE.set_target_variable(angles, 'SEARCH', self.includes)
        ENGINE.set_target_variable(quoted, 'SEARCH', [b] + self.includes)

        # Just propagate the current scanner to includes, in hope that includes
        # do not change scanners.
        SCANNERS.propagate(self, includes)

        bjam.call('ISFILE', includes)
Example #22
0
    def process(self, target, matches, binding):
        # create a single string so that findall
        # can be used since it returns a list of
        # all grouped matches
        match_str = ' '.join(matches)
        # the question mark makes the regexes non-greedy
        angles = re.findall(r'<(.*?)>', match_str)
        quoted = re.findall(r'"(.*?)"', match_str)

        # CONSIDER: the new scoping rules seem to defeat "on target" variables.
        g = ENGINE.get_target_variable(target, 'HDRGRIST')
        b = os.path.normpath(os.path.dirname(binding))

        # Attach binding of including file to included targets. When a target is
        # directly created from a virtual target this extra information is
        # unnecessary. But in other cases, it allows us to distinguish between
        # two headers of the same name included from different places. We do not
        # need this extra information for angle includes, since they should not
        # depend on the including file (we can not get literal "." in the
        # include path).
        # local g2 = $(g)"#"$(b) ;
        g2 = g + '#' + b

        angles = [replace_grist(angle, g) for angle in angles]
        quoted = [replace_grist(quote, g2) for quote in quoted]

        includes = angles + quoted

        bjam.call('INCLUDES', target, includes)
        bjam.call('NOCARE', includes)
        ENGINE.set_target_variable(angles, 'SEARCH', self.includes)
        ENGINE.set_target_variable(quoted, 'SEARCH', [b] + self.includes)

        # Just propagate the current scanner to includes, in hope that includes
        # do not change scanners.
        SCANNERS.propagate(self, includes)

        bjam.call('ISFILE', includes)
Example #23
0
def add_defaults (properties):
    """ Given a set of properties, add default values for features not
        represented in the set. 
        Note: if there's there's ordinary feature F1 and composite feature
        F2, which includes some value for F1, and both feature have default values,
        then the default value of F1 will be added, not the value in F2. This might
        not be right idea: consider
        
          feature variant : debug ... ;
               <variant>debug : .... <runtime-debugging>on
          feature <runtime-debugging> : off on ;
          
          Here, when adding default for an empty property set, we'll get
        
            <variant>debug <runtime_debugging>off
         
          and that's kind of strange.        
    """
    result = [ x for x in properties ]
    
    for v in replace_grist (properties, ''):
        if v in properties:
            raise BaseException ("'add_defaults' requires explicitly specified features, but '%s' appears to be the value of an un-expanded implicit feature" % v)

    # We don't add default for elements with ":" inside. This catches:
    # 1. Conditional properties --- we don't want <variant>debug:<define>DEBUG
    #    to be takes as specified value for <variant>
    # 2. Free properties with ":" in values. We don't care, since free properties
    #    don't have defaults.
    xproperties = [ property for property in properties if __re_no_hyphen.match (property) ]
    missing_top = set.difference (__all_top_features, get_grist (xproperties))
    more =  defaults (missing_top)
    result += more
    xproperties += more
    
    # Add defaults for subfeatures of features which are present
    for p in xproperties:
        gp = get_grist (p)
        s = []
        if __all_features.has_key (gp):
            s = __all_features [gp]['subfeatures']
        f = ungrist (gp)
        
        xbase = ['<%s-%s>' % (f, xs) for xs in s]
            
        missing_subs = set.difference (xbase, get_grist (result))
        result += defaults (__select_subfeatures (p, missing_subs))
    
    return result
Example #24
0
def minimize (properties):
    """ Given an expanded property set, eliminate all redundancy: properties
        which are elements of other (composite) properties in the set will
        be eliminated. Non-symmetric properties equal to default values will be
        eliminated, unless the override a value from some composite property.
        Implicit properties will be expressed without feature
        grist, and sub-property values will be expressed as elements joined
        to the corresponding main property.
    """    
# FXIME: the code below was in the original feature.jam file, however 'p' is not defined.
#       # Precondition checking
#       local implicits = [ set.intersection $(p:G=) : $(p:G) ] ;
#       if $(implicits)
#       {
#           error minimize requires an expanded property set, but \"$(implicits[1])\"
#             appears to be the value of an un-expanded implicit feature ;
#       }
           
    # remove properties implied by composite features
    components = []
    for property in properties:
        if __composite_properties.has_key (property):
            components.extend (__composite_properties [property]['components'])
    
    x = set.difference (properties, components)
    
    # handle subfeatures and implicit features
    x = __move_subfeatures_to_the_end (x)
    
    result = []
    while x:
        fullp = x [0]
        p = fullp
        f = get_grist (p)
        v = replace_grist (p, '')
        
        # eliminate features in implicit properties.
        if 'implicit' in __all_features [f]['attributes']:
            p = v

        # locate all subproperties of $(x[1]) in the property set
        subproperties = __select_subproperties (fullp, x)
        
        if subproperties:
            # reconstitute the joined property name
            subproperties.sort ()
            joined = p + '-' + '-'.join (replace_grist (subproperties, ''))
            result.append (joined)

            x = set.difference (x [1:], subproperties)

        else:
            # eliminate properties whose value is equal to feature's
            # default and which are not symmetric and which do not
            # contradict values implied by composite properties.
            
            # since all component properties of composites in the set
            # have been eliminated, any remaining property whose
            # feature is the same as a component of a composite in the
            # set must have a non-redundant value.
            if [fullp] != defaults ([f]) or 'symmetric' in attributes (f)\
                   or get_grist (fullp) in get_grist (components):
                result.append (p)

            x = x [1:]

    return result
Example #25
0
 def __init__(self, includes):
     scanner.Scanner.__init__(self)
     self.includes = []
     for include in includes:
         self.includes.extend(replace_grist(include, '').split('&&'))
Example #26
0
 def __init__(self, includes):
     scanner.Scanner.__init__(self)
     self.includes = []
     for include in includes:
         self.includes.extend(replace_grist(include, '').split('&&'))
Example #27
0
def minimize(properties):
    """ Given an expanded property set, eliminate all redundancy: properties
        which are elements of other (composite) properties in the set will
        be eliminated. Non-symmetric properties equal to default values will be
        eliminated, unless the override a value from some composite property.
        Implicit properties will be expressed without feature
        grist, and sub-property values will be expressed as elements joined
        to the corresponding main property.
    """
    # FXIME: the code below was in the original feature.jam file, however 'p' is not defined.
    #       # Precondition checking
    #       local implicits = [ set.intersection $(p:G=) : $(p:G) ] ;
    #       if $(implicits)
    #       {
    #           error minimize requires an expanded property set, but \"$(implicits[1])\"
    #             appears to be the value of an un-expanded implicit feature ;
    #       }

    # remove properties implied by composite features
    components = []
    for property in properties:
        if __composite_properties.has_key(property):
            components.extend(__composite_properties[property]['components'])

    x = set.difference(properties, components)

    # handle subfeatures and implicit features
    x = __move_subfeatures_to_the_end(x)

    result = []
    while x:
        fullp = x[0]
        p = fullp
        f = get_grist(p)
        v = replace_grist(p, '')

        # eliminate features in implicit properties.
        if 'implicit' in __all_features[f]['attributes']:
            p = v

        # locate all subproperties of $(x[1]) in the property set
        subproperties = __select_subproperties(fullp, x)

        if subproperties:
            # reconstitute the joined property name
            subproperties.sort()
            joined = p + '-' + '-'.join(replace_grist(subproperties, ''))
            result.append(joined)

            x = set.difference(x[1:], subproperties)

        else:
            # eliminate properties whose value is equal to feature's
            # default and which are not symmetric and which do not
            # contradict values implied by composite properties.

            # since all component properties of composites in the set
            # have been eliminated, any remaining property whose
            # feature is the same as a component of a composite in the
            # set must have a non-redundant value.
            if [fullp] != defaults ([f]) or 'symmetric' in attributes (f)\
                   or get_grist (fullp) in get_grist (components):
                result.append(p)

            x = x[1:]

    return result