Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r64610 - in trunk/tools/build/v2: . build engine/src kernel test util
From: ghost_at_[hidden]
Date: 2010-08-05 02:28:12


Author: vladimir_prus
Date: 2010-08-05 02:22:58 EDT (Thu, 05 Aug 2010)
New Revision: 64610
URL: http://svn.boost.org/trac/boost/changeset/64610

Log:
Port build/configure.jam.

Also allow to expose Python class to Jam, which fixes
tag.py and inline.py testcases.

Added:
   trunk/tools/build/v2/build/configure.py (contents, props changed)
Text files modified:
   trunk/tools/build/v2/build/alias.py | 2
   trunk/tools/build/v2/build/engine.py | 6 +
   trunk/tools/build/v2/build/project.py | 3
   trunk/tools/build/v2/build/property.py | 10 --
   trunk/tools/build/v2/build/property_set.py | 10 +-
   trunk/tools/build/v2/build/targets.py | 129 ++++++++++++++++++++-------------------
   trunk/tools/build/v2/build/virtual_target.py | 26 +++++--
   trunk/tools/build/v2/build_system.py | 23 ++++---
   trunk/tools/build/v2/engine/src/compile.c | 28 +++++++
   trunk/tools/build/v2/kernel/bootstrap.jam | 9 ++
   trunk/tools/build/v2/manager.py | 22 ------
   trunk/tools/build/v2/test/BoostBuild.py | 3
   trunk/tools/build/v2/test/test_all.py | 4 +
   trunk/tools/build/v2/util/__init__.py | 59 +++++++++++++++++
   14 files changed, 210 insertions(+), 124 deletions(-)

Modified: trunk/tools/build/v2/build/alias.py
==============================================================================
--- trunk/tools/build/v2/build/alias.py (original)
+++ trunk/tools/build/v2/build/alias.py 2010-08-05 02:22:58 EDT (Thu, 05 Aug 2010)
@@ -55,7 +55,7 @@
 
     targets.main_target_alternative(AliasTarget(
         name, project,
- targets.main_target_sources(sources, name),
+ targets.main_target_sources(sources, name, no_renaming=True),
         targets.main_target_requirements(requirements or [], project),
         targets.main_target_default_build(default_build, project),
         targets.main_target_usage_requirements(usage_requirements or [], project)))

Added: trunk/tools/build/v2/build/configure.py
==============================================================================
--- (empty file)
+++ trunk/tools/build/v2/build/configure.py 2010-08-05 02:22:58 EDT (Thu, 05 Aug 2010)
@@ -0,0 +1,157 @@
+# Status: ported.
+# Base revison: 64488
+#
+# Copyright (c) 2010 Vladimir Prus.
+#
+# Use, modification and distribution is subject to the Boost Software
+# License Version 1.0. (See accompanying file LICENSE_1_0.txt or
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# This module defines function to help with two main tasks:
+#
+# - Discovering build-time configuration for the purposes of adjusting
+# build process.
+# - Reporting what is built, and how it is configured.
+
+import b2.build.property as property
+import b2.build.property_set as property_set
+
+import b2.build.targets
+
+from b2.manager import get_manager
+from b2.util.sequence import unique
+from b2.util import bjam_signature, value_to_jam
+
+import bjam
+import os
+
+__width = 30
+
+def set_width(width):
+ global __width
+ __width = 30
+
+__components = []
+__built_components = []
+__component_logs = {}
+__announced_checks = False
+
+__log_file = None
+__log_fd = -1
+
+def register_components(components):
+ """Declare that the components specified by the parameter exist."""
+ __components.extend(components)
+
+def components_building(components):
+ """Declare that the components specified by the parameters will be build."""
+ __built_components.extend(components)
+
+def log_component_configuration(component, message):
+ """Report something about component configuration that the user should better know."""
+ __component_logs.setdefault(component, []).append(message)
+
+def log_check_result(result):
+ global __announced_checks
+ if not __announced_checks:
+ print "Performing configuration checks"
+ __announced_checks = True
+
+ print result
+
+def log_library_search_result(library, result):
+ log_check_result((" - %(library)s : %(result)s" % locals()).rjust(width))
+
+
+def print_component_configuration():
+
+ print "\nComponent configuration:"
+ for c in __components:
+ if c in __built_components:
+ s = "building"
+ else:
+ s = "not building"
+ message = " - %s)" % c
+ message = message.rjust(__width)
+ message += " : " + s
+ for m in __component_logs.get(c, []):
+ print " -" + m
+ print ""
+
+__builds_cache = {}
+
+def builds(metatarget_reference, project, ps, what):
+ # Attempt to build a metatarget named by 'metatarget-reference'
+ # in context of 'project' with properties 'ps'.
+ # Returns non-empty value if build is OK.
+
+ result = []
+
+ existing = __builds_cache.get((what, ps), None)
+ if existing is None:
+
+ result = False
+ __builds_cache[(what, ps)] = False
+
+ targets = b2.build.targets.generate_from_reference(
+ metatarget_reference, project, ps).targets()
+ jam_targets = []
+ for t in targets:
+ jam_targets.append(t.actualize())
+
+ x = (" - %s" % what).rjust(__width)
+ if bjam.call("UPDATE_NOW", jam_targets, str(__log_fd), "ignore-minus-n"):
+ __builds_cache[(what, ps)] = True
+ result = True
+ log_check_result("%s: yes" % x)
+ else:
+ log_check_result("%s: no" % x)
+
+ return result
+ else:
+ return existing
+
+def set_log_file(log_file_name):
+ # Called by Boost.Build startup code to specify name of a file
+ # that will receive results of configure checks. This
+ # should never be called by users.
+ global __log_file, __log_fd
+ dirname = os.path.dirname(log_file_name)
+ if not os.path.exists(dirname):
+ os.makedirs(dirname)
+ # Make sure to keep the file around, so that it's not
+ # garbage-collected and closed
+ __log_file = open(log_file_name, "w")
+ __log_fd = __log_file.fileno()
+
+# Frontend rules
+
+class CheckTargetBuildsWorker:
+
+ def __init__(self, target, true_properties, false_properties):
+ self.target = target
+ self.true_properties = property.create_from_strings(true_properties)
+ self.false_properties = property.create_from_strings(false_properties)
+
+ def check(self, ps):
+
+ # FIXME: this should not be hardcoded. Other checks might
+ # want to consider different set of features as relevant.
+ toolset = ps.get_properties('toolset')[0]
+ ps = property_set.create([toolset])
+ t = get_manager().targets().current()
+ p = t.project()
+ if builds(self.target, p, ps, "%s builds" % self.target):
+ return self.true_properties
+ else:
+ return self.false_properties
+
+@bjam_signature((["target"], ["true_properties", "*"], ["false_properties", "*"]))
+def check_target_builds(target, true_properties, false_properties):
+ worker = CheckTargetBuildsWorker(target, true_properties, false_properties)
+ value = value_to_jam(worker.check)
+ return "<conditional>" + value
+
+get_manager().projects().add_rule("check-target-builds", check_target_builds)
+
+

Modified: trunk/tools/build/v2/build/engine.py
==============================================================================
--- trunk/tools/build/v2/build/engine.py (original)
+++ trunk/tools/build/v2/build/engine.py 2010-08-05 02:22:58 EDT (Thu, 05 Aug 2010)
@@ -50,7 +50,7 @@
         if property_set:
             p = property_set.raw()
 
- b2.util.call_jam_function(self.action_name, targets, sources, p)
+ b2.util.set_jam_action(self.action_name, targets, sources, p)
         
 action_modifiers = {"updated": 0x01,
                     "together": 0x02,
@@ -144,6 +144,10 @@
             # Rule is already in indirect format
             return action_name
         else:
+ ix = action_name.find('.')
+ if ix != -1 and action_name[:ix] == context_module:
+ return context_module + '%' + action_name[ix+1:]
+
             return context_module + '%' + action_name
 
     def register_bjam_action (self, action_name, function=None):

Modified: trunk/tools/build/v2/build/project.py
==============================================================================
--- trunk/tools/build/v2/build/project.py (original)
+++ trunk/tools/build/v2/build/project.py 2010-08-05 02:22:58 EDT (Thu, 05 Aug 2010)
@@ -650,7 +650,8 @@
         modules = sys.modules
         for class_name in modules:
             parts = class_name.split('.')
- if name is class_name or parts[0] == "b2" and parts[-1] == name:
+ if name is class_name or parts[0] == "b2" \
+ and parts[-1] == name.replace("-", "_"):
                 module = modules[class_name]
                 self.loaded_tool_modules_[name] = module
                 return module

Modified: trunk/tools/build/v2/build/property.py
==============================================================================
--- trunk/tools/build/v2/build/property.py (original)
+++ trunk/tools/build/v2/build/property.py 2010-08-05 02:22:58 EDT (Thu, 05 Aug 2010)
@@ -273,14 +273,6 @@
 
     return None
 
-# FIXME: this should go
-def is_conditional (property):
- """ Returns True if a property is conditional.
- """
- if __re_colon.search (replace_grist (property, '')):
- return True
- else:
- return False
 
 def select (features, properties):
     """ Selects properties which correspond to any of the given features.
@@ -310,7 +302,7 @@
         else:
             base.append (p)
 
- result = base
+ result = base[:]
     for p in conditional:
 
         # Evaluate condition

Modified: trunk/tools/build/v2/build/property_set.py
==============================================================================
--- trunk/tools/build/v2/build/property_set.py (original)
+++ trunk/tools/build/v2/build/property_set.py 2010-08-05 02:22:58 EDT (Thu, 05 Aug 2010)
@@ -303,9 +303,9 @@
             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_raw_,
- context.raw()))
+ property.evaluate_conditionals_in_context(self.all(), context))
 
         return self.evaluated_[context]
 
@@ -412,6 +412,8 @@
     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)
         
@@ -439,9 +441,5 @@
         return result
     
     def __contains__(self, item):
- for p in self.all_set_:
- if p.feature().name() == "toolset":
- print "EXISTING", hash(p), hash(p._feature), hash(p._value), "--", hash(item._feature), has(item._value)
- print self.all_set_
         return item in self.all_set_
     

Modified: trunk/tools/build/v2/build/targets.py
==============================================================================
--- trunk/tools/build/v2/build/targets.py (original)
+++ trunk/tools/build/v2/build/targets.py 2010-08-05 02:22:58 EDT (Thu, 05 Aug 2010)
@@ -87,7 +87,6 @@
 import b2.build.build_request as build_request
 
 import b2.util.set
-
 _re_separate_target_from_properties = re.compile (r'^([^<]*)(/(<.*))?$')
 
 class TargetRegistry:
@@ -111,7 +110,7 @@
         target.project ().add_alternative (target)
         return target
 
- def main_target_sources (self, sources, main_target_name, no_remaning=0):
+ def main_target_sources (self, sources, main_target_name, no_renaming=0):
         """Return the list of sources to use, if main target rule is invoked
         with 'sources'. If there are any objects in 'sources', they are treated
         as main target instances, and the name of such targets are adjusted to
@@ -120,17 +119,20 @@
         result = []
 
         for t in sources:
+
+ t = b2.util.jam_to_value_maybe(t)
+
             if isinstance (t, AbstractTarget):
                 name = t.name ()
 
                 if not no_renaming:
- new_name = main_target_name + '__' + name
- t.rename (new_name)
+ name = main_target_name + '__' + name
+ t.rename (name)
 
                 # Inline targets are not built by default.
                 p = t.project()
                 p.mark_target_as_explicit(name)
- result.append (new_name)
+ result.append(name)
 
             else:
                 result.append (t)
@@ -776,6 +778,50 @@
 
         return self.file_location_
 
+def resolve_reference(target_reference, project):
+ """ Given a target_reference, made in context of 'project',
+ returns the AbstractTarget instance that is referred to, as well
+ as properties explicitly specified for this reference.
+ """
+ # Separate target name from properties override
+ split = _re_separate_target_from_properties.match (target_reference)
+ if not split:
+ raise BaseException ("Invalid reference: '%s'" % target_reference)
+
+ id = split.group (1)
+
+ sproperties = []
+
+ if split.group (3):
+ sproperties = property.create_from_strings(feature.split(split.group(3)))
+ sproperties = feature.expand_composites(sproperties)
+
+ # Find the target
+ target = project.find (id)
+
+ return (target, property_set.create(sproperties))
+
+def generate_from_reference(target_reference, project, property_set):
+ """ Attempts to generate the target given by target reference, which
+ can refer both to a main target or to a file.
+ Returns a list consisting of
+ - usage requirements
+ - generated virtual targets, if any
+ target_reference: Target reference
+ project: Project where the reference is made
+ property_set: Properties of the main target that makes the reference
+ """
+ target, sproperties = resolve_reference(target_reference, project)
+
+ # Take properties which should be propagated and refine them
+ # with source-specific requirements.
+ propagated = property_set.propagated()
+ rproperties = propagated.refine(sproperties)
+
+ return target.generate(rproperties)
+
+
+
 class BasicTarget (AbstractTarget):
     """ Implements the most standard way of constructing main target
         alternative from sources. Allows sources to be either file or
@@ -835,29 +881,6 @@
     def default_build (self):
         return self.default_build_
 
- def resolve_reference (self, target_reference, project):
- """ Given a target_reference, made in context of 'project',
- returns the AbstractTarget instance that is referred to, as well
- as properties explicitly specified for this reference.
- """
- # Separate target name from properties override
- split = _re_separate_target_from_properties.match (target_reference)
- if not split:
- raise BaseException ("Invalid reference: '%s'" % target_reference)
-
- id = split.group (1)
-
- sproperties = []
-
- if split.group (3):
- sproperties = property.create_from_strings(feature.split(split.group(3)))
- sproperties = feature.expand_composites(sproperties)
-
- # Find the target
- target = project.find (id)
-
- return (target, property_set.create(sproperties))
-
     def common_properties (self, build_request, requirements):
         """ Given build request and requirements, return properties
             common to dependency build request and target build
@@ -908,24 +931,23 @@
         #
         # might come from project's requirements.
         unconditional = feature.expand(requirements.non_conditional())
-
- raw = context.all()
- raw = property.refine(raw, unconditional)
+
+ context = context.refine(property_set.create(unconditional))
 
         # We've collected properties that surely must be present in common
         # properties. We now try to figure out what other properties
         # should be added in order to satisfy rules (4)-(6) from the docs.
     
- conditionals = requirements.conditional()
+ conditionals = property_set.create(requirements.conditional())
 
         # It's supposed that #conditionals iterations
         # should be enough for properties to propagate along conditions in any
         # direction.
- max_iterations = len(conditionals) +\
+ max_iterations = len(conditionals.all()) +\
                          len(requirements.get("<conditional>")) + 1
     
         added_requirements = []
- current = raw
+ current = context
     
         # It's assumed that ordinary conditional requirements can't add
         # <indirect-conditional> properties, and that rules referred
@@ -933,25 +955,24 @@
         # <indirect-conditional> properties. So the list of indirect conditionals
         # does not change.
         indirect = requirements.get("<conditional>")
- indirect = [s[1:] for s in indirect]
     
         ok = 0
         for i in range(0, max_iterations):
 
- e = property.evaluate_conditionals_in_context(conditionals, current)
+ e = conditionals.evaluate_conditionals(current).all()[:]
         
             # Evaluate indirect conditionals.
             for i in indirect:
+ i = b2.util.jam_to_value_maybe(i)
                 if callable(i):
                     # This is Python callable, yeah.
- e.extend(bjam.call(i, current))
+ e.extend(i(current))
                 else:
                     # Name of bjam function. Because bjam is unable to handle
                     # list of Property, pass list of strings.
- br = b2.util.call_jam_function(i, [str(p) for p in current])
+ br = b2.util.call_jam_function(i[1:], [str(p) for p in current.all()])
                     if br:
                         e.extend(property.create_from_strings(br))
-
 
             if e == added_requirements:
                 # If we got the same result, we've found final properties.
@@ -963,7 +984,7 @@
                 # Recompute 'current' using initial properties and conditional
                 # requirements.
                 added_requirements = e
- current = property.refine(raw, feature.expand(e))
+ current = context.refine(property_set.create(feature.expand(e)))
 
         if not ok:
             self.manager().errors()("Can't evaluate conditional properties "
@@ -973,7 +994,7 @@
         if what == "added":
             return property_set.create(unconditional + added_requirements)
         elif what == "refined":
- return property_set.create(current)
+ return current
         else:
             self.manager().errors("Invalid value of the 'what' parameter")
 
@@ -1029,7 +1050,7 @@
         usage_requirements = []
         for id in target_ids:
                     
- result = self.generate_from_reference(id, self.project_, property_set)
+ result = generate_from_reference(id, self.project_, property_set)
             targets += result.targets()
             usage_requirements += result.usage_requirements().all()
 
@@ -1046,7 +1067,7 @@
         usage_requirements = []
         for p in properties:
                    
- result = self.generate_from_reference(p.value(), self.project_, ps)
+ result = generate_from_reference(p.value(), self.project_, ps)
 
             for t in result.targets():
                 result_properties.append(property.Property(p.feature(), t))
@@ -1180,25 +1201,6 @@
         self.manager().targets().decrease_indent()
 
         return self.generated_[ps]
-
- def generate_from_reference (self, target_reference, project, property_set):
- """ Attempts to generate the target given by target reference, which
- can refer both to a main target or to a file.
- Returns a list consisting of
- - usage requirements
- - generated virtual targets, if any
- target_reference: Target reference
- project: Project where the reference is made
- property_set: Properties of the main target that makes the reference
- """
- target, sproperties = self.resolve_reference(target_reference, project)
-
- # Take properties which should be propagated and refine them
- # with source-specific requirements.
- propagated = property_set.propagated()
- rproperties = propagated.refine(sproperties)
-
- return target.generate(rproperties)
     
     def compute_usage_requirements (self, subvariant):
         """ Given the set of generated targets, and refined build
@@ -1276,6 +1278,9 @@
     def __init__ (self, name, project, type, sources, requirements, default_build, usage_requirements):
         BasicTarget.__init__ (self, name, project, sources, requirements, default_build, usage_requirements)
         self.type_ = type
+
+ def __jam_repr__(self):
+ return b2.util.value_to_jam(self)
     
     def type (self):
         return self.type_

Modified: trunk/tools/build/v2/build/virtual_target.py
==============================================================================
--- trunk/tools/build/v2/build/virtual_target.py (original)
+++ trunk/tools/build/v2/build/virtual_target.py 2010-08-05 02:22:58 EDT (Thu, 05 Aug 2010)
@@ -78,6 +78,7 @@
 import b2.build.property as property
 
 from b2.manager import get_manager
+from b2.util import bjam_signature
 
 __re_starts_with_at = re.compile ('^@(.*)')
 
@@ -533,16 +534,22 @@
         
         if tag:
 
- rule_names = [t[:1] for t in tag if t[0] == '@']
- if rule_names:
- if len(tag) > 1:
- self.manager_.errors()(
-"""<tag>@rulename is present but is not the only <tag> feature""")
+ if len(tag) > 1:
+ self.manager_.errors()(
+ """<tag>@rulename is present but is not the only <tag> feature""")
 
- self.name_ = bjam.call(rule_names[0], specified_name, self.type_, ps)
+ tag = tag[0]
+ if callable(tag):
+ self.name_ = tag(specified_name, self.type_, ps)
             else:
- self.manager_.errors()(
-"""The value of the <tag> feature must be '@rule-nane'""")
+ if not tag[0] == '@':
+ self.manager_.errors()("""The value of the <tag> feature must be '@rule-nane'""")
+
+ exported_ps = b2.util.value_to_jam(ps, methods=True)
+ self.name_ = b2.util.call_jam_function(
+ tag[1:], specified_name, self.type_, exported_ps)
+ if self.name_:
+ self.name_ = self.name_[0]
         
         # If there's no tag or the tag rule returned nothing.
         if not tag or not self.name_:
@@ -571,10 +578,13 @@
             
         return name
 
+@bjam_signature((["specified_name"], ["type"], ["property_set"]))
 def add_prefix_and_suffix(specified_name, type, property_set):
     """Appends the suffix appropriate to 'type/property-set' combination
     to the specified name and returns the result."""
 
+ property_set = b2.util.jam_to_value_maybe(property_set)
+
     suffix = ""
     if type:
         suffix = b2.build.type.generated_target_suffix(type, property_set)

Modified: trunk/tools/build/v2/build_system.py
==============================================================================
--- trunk/tools/build/v2/build_system.py (original)
+++ trunk/tools/build/v2/build_system.py 2010-08-05 02:22:58 EDT (Thu, 05 Aug 2010)
@@ -460,6 +460,8 @@
     global_build_dir = option.get("build-dir")
     manager = Manager(engine, global_build_dir)
 
+ import b2.build.configure as configure
+
     if "--version" in sys.argv:
 
         version.report()
@@ -587,17 +589,18 @@
     ## {
     ## generators.dump ;
     ## }
+
     
- ## # We wish to put config.log in the build directory corresponding
- ## # to Jamroot, so that the location does not differ depending on
- ## # directory where we do build. The amount of indirection necessary
- ## # here is scary.
- ## local first-project = [ $(targets[0]).project ] ;
- ## local first-project-root-location = [ $(first-project).get project-root ] ;
- ## local first-project-root-module = [ project.load $(first-project-root-location) ] ;
- ## local first-project-root = [ project.target $(first-project-root-module) ] ;
- ## local first-build-build-dir = [ $(first-project-root).build-dir ] ;
- ## configure.set-log-file $(first-build-build-dir)/config.log ;
+ # We wish to put config.log in the build directory corresponding
+ # to Jamroot, so that the location does not differ depending on
+ # directory where we do build. The amount of indirection necessary
+ # here is scary.
+ first_project = targets[0].project()
+ first_project_root_location = first_project.get('project-root')
+ first_project_root_module = manager.projects().load(first_project_root_location)
+ first_project_root = manager.projects().target(first_project_root_module)
+ first_build_build_dir = first_project_root.build_dir()
+ configure.set_log_file(os.path.join(first_build_build_dir, "config.log"))
 
     virtual_targets = []
 

Modified: trunk/tools/build/v2/engine/src/compile.c
==============================================================================
--- trunk/tools/build/v2/engine/src/compile.c (original)
+++ trunk/tools/build/v2/engine/src/compile.c 2010-08-05 02:22:58 EDT (Thu, 05 Aug 2010)
@@ -856,9 +856,31 @@
         }
         else
         {
- /* Do nothing. There are cases, e.g. feature.feature function that
- should return value for the benefit of Python code and which
- also can be called by Jam code. */
+ /* See if this is an instance that defines special __jam_repr__
+ method. */
+ if (PyInstance_Check(py_result)
+ && PyObject_HasAttrString(py_result, "__jam_repr__"))
+ {
+ PyObject* repr = PyObject_GetAttrString(py_result, "__jam_repr__");
+ if (repr)
+ {
+ PyObject* arguments2 = PyTuple_New(0);
+ PyObject* py_result2 = PyObject_Call(repr, arguments2, 0);
+ Py_DECREF(repr);
+ Py_DECREF(arguments2);
+ if (PyString_Check(py_result2))
+ {
+ result = list_new(0, newstr(PyString_AsString(py_result2)));
+ }
+ Py_DECREF(py_result2);
+ }
+ }
+
+ /* If 'result' is still empty, do nothing. There are cases, e.g.
+ feature.feature function that should return value for the benefit
+ of Python code and which also can be called by Jam code, where
+ no sensible value can be returned. We cannot even emit a warning,
+ since there will be a pile of them. */
         }
 
         Py_DECREF( py_result );

Modified: trunk/tools/build/v2/kernel/bootstrap.jam
==============================================================================
--- trunk/tools/build/v2/kernel/bootstrap.jam (original)
+++ trunk/tools/build/v2/kernel/bootstrap.jam 2010-08-05 02:22:58 EDT (Thu, 05 Aug 2010)
@@ -187,6 +187,15 @@
                 DEPENDS all : $(targets) ;
             }
             
+ rule call-in-module ( m : rulename : * )
+ {
+ module $(m)
+ {
+ return [ $(2) $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ] ;
+ }
+ }
+
+
             rule set-update-action ( action : targets * : sources * : properties * )
             {
                 $(action) $(targets) : $(sources) : $(properties) ;

Modified: trunk/tools/build/v2/manager.py
==============================================================================
--- trunk/tools/build/v2/manager.py (original)
+++ trunk/tools/build/v2/manager.py 2010-08-05 02:22:58 EDT (Thu, 05 Aug 2010)
@@ -38,12 +38,6 @@
         self.errors_ = Errors()
         self.command_line_free_features_ = property_set.empty()
         
- # Object Map.
- # TODO: This is a kludge: maps object names to the actual instances.
- # Sometimes, objects are stored in properties, along with some grist.
- # This map is used to store the value and return an id, which can be later on used to retriev it back.
- self.object_map_ = {}
-
         global the_manager
         the_manager = self
         
@@ -86,22 +80,6 @@
     def set_command_line_free_features(self, v):
         self.command_line_free_features_ = v
 
- def register_object (self, value):
- """ Stores an object in a map and returns a key that can be used to retrieve it.
- """
- key = 'object_registry_' + str (value)
- self.object_map_ [key] = value
- return key
-
- def get_object (self, key):
- """ Returns a previously registered object.
- """
- if not isinstance (key, str):
- # Probably it's the object itself.
- return key
-
- return self.object_map_ [key]
-
     def construct (self, properties = [], targets = []):
         """ Constructs the dependency graph.
             properties: the build properties.

Modified: trunk/tools/build/v2/test/BoostBuild.py
==============================================================================
--- trunk/tools/build/v2/test/BoostBuild.py (original)
+++ trunk/tools/build/v2/test/BoostBuild.py 2010-08-05 02:22:58 EDT (Thu, 05 Aug 2010)
@@ -46,6 +46,9 @@
         print_annotation(ann[0], ann[1], xml)
     annotations = []
 
+def clear_annotations():
+ global annotations
+ annotations = []
 
 defer_annotations = 0
 

Modified: trunk/tools/build/v2/test/test_all.py
==============================================================================
--- trunk/tools/build/v2/test/test_all.py (original)
+++ trunk/tools/build/v2/test/test_all.py 2010-08-05 02:22:58 EDT (Thu, 05 Aug 2010)
@@ -64,6 +64,10 @@
                 print "PASSED"
             else:
                 print "FAILED"
+
+ if i == "regression":
+ BoostBuild.flush_annotations()
+ BoostBuild.clear_annotations()
         else:
             rs = "succeed"
             if not passed:

Modified: trunk/tools/build/v2/util/__init__.py
==============================================================================
--- trunk/tools/build/v2/util/__init__.py (original)
+++ trunk/tools/build/v2/util/__init__.py 2010-08-05 02:22:58 EDT (Thu, 05 Aug 2010)
@@ -1,6 +1,7 @@
 
 import bjam
 import re
+import types
 
 # Decorator the specifies bjam-side prototype for a Python function
 def bjam_signature(s):
@@ -39,7 +40,7 @@
 
 _extract_jamfile_and_rule = re.compile("(Jamfile<.*>)%(.*)")
 
-def call_jam_function(name, *args):
+def set_jam_action(name, *args):
 
     m = _extract_jamfile_and_rule.match(name)
     if m:
@@ -49,6 +50,62 @@
 
     return bjam.call(*args)
 
+
+def call_jam_function(name, *args):
+
+ m = _extract_jamfile_and_rule.match(name)
+ if m:
+ args = ("call-in-module", m.group(1), m.group(2)) + args
+ return bjam.call(*args)
+ else:
+ return bjam.call(*((name,) + args))
+
+__value_id = 0
+__python_to_jam = {}
+__jam_to_python = {}
+
+def value_to_jam(value, methods=False):
+ """Makes a token to refer to a Python value inside Jam language code.
+
+ The token is merely a string that can be passed around in Jam code and
+ eventually passed back. For example, we might want to pass PropertySet
+ instance to a tag function and it might eventually call back
+ to virtual_target.add_suffix_and_prefix, passing the same instance.
+
+ For values that are classes, we'll also make class methods callable
+ from Jam.
+
+ Note that this is necessary to make a bit more of existing Jamfiles work.
+ This trick should not be used to much, or else the performance benefits of
+ Python port will be eaten.
+ """
+
+ global __value_id
+
+ r = __python_to_jam.get(value, None)
+ if r:
+ return r
+
+ exported_name = '###_' + str(__value_id)
+ __value_id = __value_id + 1
+ __python_to_jam[value] = exported_name
+ __jam_to_python[exported_name] = value
+
+ if methods and type(value) == types.InstanceType:
+ for field_name in dir(value):
+ field = getattr(value, field_name)
+ if callable(field) and not field_name.startswith("__"):
+ bjam.import_rule("", exported_name + "." + field_name, field)
+
+ return exported_name
+
+def jam_to_value_maybe(jam_value):
+
+ if type(jam_value) == type("") and jam_value.startswith("###"):
+ return __jam_to_python[jam_value]
+ else:
+ return jam_value
+
 def stem(filename):
     i = filename.find('.')
     if i != -1:


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk