summaryrefslogtreecommitdiff
path: root/jam-files/boost-build/build/property_set.py
diff options
context:
space:
mode:
authorChris Dyer <cdyer@cs.cmu.edu>2012-10-11 14:06:32 -0400
committerChris Dyer <cdyer@cs.cmu.edu>2012-10-11 14:06:32 -0400
commit07ea7b64b6f85e5798a8068453ed9fd2b97396db (patch)
tree644496a1690d84d82a396bbc1e39160788beb2cd /jam-files/boost-build/build/property_set.py
parent37b9e45e5cb29d708f7249dbe0b0fb27685282a0 (diff)
parenta36fcc5d55c1de84ae68c1091ebff2b1c32dc3b7 (diff)
Merge branch 'master' of https://github.com/redpony/cdec
Diffstat (limited to 'jam-files/boost-build/build/property_set.py')
-rw-r--r--jam-files/boost-build/build/property_set.py449
1 files changed, 0 insertions, 449 deletions
diff --git a/jam-files/boost-build/build/property_set.py b/jam-files/boost-build/build/property_set.py
deleted file mode 100644
index f12eb90c..00000000
--- a/jam-files/boost-build/build/property_set.py
+++ /dev/null
@@ -1,449 +0,0 @@
-# Status: ported.
-# Base revision: 40480
-
-# Copyright (C) Vladimir Prus 2002. Permission to copy, use, modify, sell and
-# distribute this software is granted provided this copyright notice appears in
-# all copies. This software is provided "as is" without express or implied
-# warranty, and with no claim as to its suitability for any purpose.
-
-from b2.util.utility import *
-import property, feature, string
-import b2.build.feature
-from b2.exceptions import *
-from b2.util.sequence import unique
-from b2.util.set import difference
-from b2.util import cached
-
-from b2.manager import get_manager
-
-
-def reset ():
- """ Clear the module state. This is mainly for testing purposes.
- """
- global __cache
-
- # A cache of property sets
- # TODO: use a map of weak refs?
- __cache = {}
-
-reset ()
-
-
-def create (raw_properties = []):
- """ Creates a new 'PropertySet' instance for the given raw properties,
- or returns an already existing one.
- """
- # FIXME: propagate to callers.
- if len(raw_properties) > 0 and isinstance(raw_properties[0], property.Property):
- x = raw_properties
- else:
- x = [property.create_from_string(ps) for ps in raw_properties]
- x.sort()
- x = unique (x)
-
- # FIXME: can we do better, e.g. by directly computing
- # has value of the list?
- key = tuple(x)
-
- if not __cache.has_key (key):
- __cache [key] = PropertySet(x)
-
- return __cache [key]
-
-def create_with_validation (raw_properties):
- """ Creates new 'PropertySet' instances after checking
- that all properties are valid and converting incidental
- properties into gristed form.
- """
- properties = [property.create_from_string(s) for s in raw_properties]
- property.validate(properties)
-
- return create(properties)
-
-def empty ():
- """ Returns PropertySet with empty set of properties.
- """
- return create ()
-
-def create_from_user_input(raw_properties, jamfile_module, location):
- """Creates a property-set from the input given by the user, in the
- context of 'jamfile-module' at 'location'"""
-
- properties = property.create_from_strings(raw_properties, True)
- properties = property.translate_paths(properties, location)
- properties = property.translate_indirect(properties, jamfile_module)
-
- project_id = get_manager().projects().attributeDefault(jamfile_module, 'id', None)
- if not project_id:
- project_id = os.path.abspath(location)
- properties = property.translate_dependencies(properties, project_id, location)
- properties = property.expand_subfeatures_in_conditions(properties)
- return create(properties)
-
-
-def refine_from_user_input(parent_requirements, specification, jamfile_module,
- location):
- """Refines requirements with requirements provided by the user.
- Specially handles "-<property>value" syntax in specification
- to remove given requirements.
- - parent-requirements -- property-set object with requirements
- to refine
- - specification -- string list of requirements provided by the use
- - project-module -- the module to which context indirect features
- will be bound.
- - location -- the path to which path features are relative."""
-
-
- if not specification:
- return parent_requirements
-
-
- add_requirements = []
- remove_requirements = []
-
- for r in specification:
- if r[0] == '-':
- remove_requirements.append(r[1:])
- else:
- add_requirements.append(r)
-
- if remove_requirements:
- # Need to create property set, so that path features
- # and indirect features are translated just like they
- # are in project requirements.
- ps = create_from_user_input(remove_requirements,
- jamfile_module, location)
-
- parent_requirements = create(difference(parent_requirements.all(),
- ps.all()))
- specification = add_requirements
-
- requirements = create_from_user_input(specification,
- jamfile_module, location)
-
- return parent_requirements.refine(requirements)
-
-class PropertySet:
- """ Class for storing a set of properties.
- - there's 1<->1 correspondence between identity and value. No
- two instances of the class are equal. To maintain this property,
- the 'PropertySet.create' rule should be used to create new instances.
- Instances are immutable.
-
- - each property is classified with regard to it's effect on build
- results. Incidental properties have no effect on build results, from
- Boost.Build point of view. Others are either free, or non-free, which we
- call 'base'. Each property belong to exactly one of those categories and
- it's possible to get list of properties in each category.
-
- In addition, it's possible to get list of properties with specific
- attribute.
-
- - several operations, like and refine and as_path are provided. They all use
- caching whenever possible.
- """
- def __init__ (self, properties = []):
-
-
- raw_properties = []
- for p in properties:
- raw_properties.append(p.to_raw())
-
- self.all_ = properties
- self.all_raw_ = raw_properties
- self.all_set_ = set(properties)
-
- self.incidental_ = []
- self.free_ = []
- self.base_ = []
- self.dependency_ = []
- self.non_dependency_ = []
- self.conditional_ = []
- self.non_conditional_ = []
- self.propagated_ = []
- self.link_incompatible = []
-
- # A cache of refined properties.
- self.refined_ = {}
-
- # A cache of property sets created by adding properties to this one.
- self.added_ = {}
-
- # Cache for the default properties.
- self.defaults_ = None
-
- # Cache for the expanded properties.
- self.expanded_ = None
-
- # Cache for the expanded composite properties
- self.composites_ = None
-
- # Cache for property set with expanded subfeatures
- self.subfeatures_ = None
-
- # Cache for the property set containing propagated properties.
- self.propagated_ps_ = None
-
- # A map of features to its values.
- self.feature_map_ = None
-
- # A tuple (target path, is relative to build directory)
- self.target_path_ = None
-
- self.as_path_ = None
-
- # A cache for already evaluated sets.
- self.evaluated_ = {}
-
- for p in raw_properties:
- if not get_grist (p):
- raise BaseException ("Invalid property: '%s'" % p)
-
- att = feature.attributes (get_grist (p))
-
- if 'propagated' in att:
- self.propagated_.append (p)
-
- if 'link_incompatible' in att:
- self.link_incompatible.append (p)
-
- for p in properties:
-
- # A feature can be both incidental and free,
- # in which case we add it to incidental.
- if p.feature().incidental():
- self.incidental_.append(p)
- elif p.feature().free():
- self.free_.append(p)
- else:
- self.base_.append(p)
-
- if p.condition():
- self.conditional_.append(p)
- else:
- self.non_conditional_.append(p)
-
- if p.feature().dependency():
- self.dependency_.append (p)
- else:
- self.non_dependency_.append (p)
-
-
- def all(self):
- return self.all_
-
- def raw (self):
- """ Returns the list of stored properties.
- """
- return self.all_raw_
-
- def __str__(self):
- return ' '.join(str(p) for p in self.all_)
-
- def base (self):
- """ Returns properties that are neither incidental nor free.
- """
- return self.base_
-
- def free (self):
- """ Returns free properties which are not dependency properties.
- """
- return self.free_
-
- def non_free(self):
- return self.base_ + self.incidental_
-
- def dependency (self):
- """ Returns dependency properties.
- """
- return self.dependency_
-
- def non_dependency (self):
- """ Returns properties that are not dependencies.
- """
- return self.non_dependency_
-
- def conditional (self):
- """ Returns conditional properties.
- """
- return self.conditional_
-
- def non_conditional (self):
- """ Returns properties that are not conditional.
- """
- return self.non_conditional_
-
- def incidental (self):
- """ Returns incidental properties.
- """
- return self.incidental_
-
- def refine (self, requirements):
- """ Refines this set's properties using the requirements passed as an argument.
- """
- assert isinstance(requirements, PropertySet)
- if not self.refined_.has_key (requirements):
- r = property.refine(self.all_, requirements.all_)
-
- self.refined_[requirements] = create(r)
-
- return self.refined_[requirements]
-
- def expand (self):
- if not self.expanded_:
- expanded = feature.expand(self.all_)
- self.expanded_ = create(expanded)
- return self.expanded_
-
- def expand_subfeatures(self):
- if not self.subfeatures_:
- self.subfeatures_ = create(feature.expand_subfeatures(self.all_))
- return self.subfeatures_
-
- def evaluate_conditionals(self, context=None):
- if not context:
- context = self
-
- if not self.evaluated_.has_key(context):
- # FIXME: figure why the call messes up first parameter
- self.evaluated_[context] = create(
- property.evaluate_conditionals_in_context(self.all(), context))
-
- return self.evaluated_[context]
-
- def propagated (self):
- if not self.propagated_ps_:
- self.propagated_ps_ = create (self.propagated_)
- return self.propagated_ps_
-
- def add_defaults (self):
- # FIXME: this caching is invalidated when new features
- # are declare inside non-root Jamfiles.
- if not self.defaults_:
- expanded = feature.add_defaults(self.all_)
- self.defaults_ = create(expanded)
- return self.defaults_
-
- def as_path (self):
- if not self.as_path_:
-
- def path_order (p1, p2):
-
- i1 = p1.feature().implicit()
- i2 = p2.feature().implicit()
-
- if i1 != i2:
- return i2 - i1
- else:
- return cmp(p1.feature().name(), p2.feature().name())
-
- # trim redundancy
- properties = feature.minimize(self.base_)
-
- # sort according to path_order
- properties.sort (path_order)
-
- components = []
- for p in properties:
- if p.feature().implicit():
- components.append(p.value())
- else:
- components.append(p.feature().name() + "-" + p.value())
-
- self.as_path_ = '/'.join (components)
-
- return self.as_path_
-
- def target_path (self):
- """ Computes the target path that should be used for
- target with these properties.
- Returns a tuple of
- - the computed path
- - if the path is relative to build directory, a value of
- 'true'.
- """
- if not self.target_path_:
- # The <location> feature can be used to explicitly
- # change the location of generated targets
- l = self.get ('<location>')
- if l:
- computed = l[0]
- is_relative = False
-
- else:
- p = self.as_path ()
-
- # Really, an ugly hack. Boost regression test system requires
- # specific target paths, and it seems that changing it to handle
- # other directory layout is really hard. For that reason,
- # we teach V2 to do the things regression system requires.
- # The value o '<location-prefix>' is predended to the path.
- prefix = self.get ('<location-prefix>')
-
- if prefix:
- if len (prefix) > 1:
- raise AlreadyDefined ("Two <location-prefix> properties specified: '%s'" % prefix)
-
- computed = os.path.join(prefix[0], p)
-
- else:
- computed = p
-
- if not computed:
- computed = "."
-
- is_relative = True
-
- self.target_path_ = (computed, is_relative)
-
- return self.target_path_
-
- def add (self, ps):
- """ Creates a new property set containing the properties in this one,
- plus the ones of the property set passed as argument.
- """
- if not self.added_.has_key(ps):
- self.added_[ps] = create(self.all_ + ps.all())
- return self.added_[ps]
-
- def add_raw (self, properties):
- """ Creates a new property set containing the properties in this one,
- plus the ones passed as argument.
- """
- return self.add (create (properties))
-
-
- def get (self, feature):
- """ Returns all values of 'feature'.
- """
- if type(feature) == type([]):
- feature = feature[0]
- if not isinstance(feature, b2.build.feature.Feature):
- feature = b2.build.feature.get(feature)
-
- if not self.feature_map_:
- self.feature_map_ = {}
-
- for v in self.all_:
- if not self.feature_map_.has_key(v.feature()):
- self.feature_map_[v.feature()] = []
- self.feature_map_[v.feature()].append(v.value())
-
- return self.feature_map_.get(feature, [])
-
- @cached
- def get_properties(self, feature):
- """Returns all contained properties associated with 'feature'"""
-
- if not isinstance(feature, b2.build.feature.Feature):
- feature = b2.build.feature.get(feature)
-
- result = []
- for p in self.all_:
- if p.feature() == feature:
- result.append(p)
- return result
-
- def __contains__(self, item):
- return item in self.all_set_
-