diff --git a/v2/build/generators.py b/v2/build/generators.py index 6c02a6359..bae7e54d9 100644 --- a/v2/build/generators.py +++ b/v2/build/generators.py @@ -412,7 +412,7 @@ class Generator: pre = pre[1:] post = post[1:] - targets.append(virtual_target.FileTarget(generated_name, False, t, project, a)) + targets.append(virtual_target.FileTarget(generated_name, t, project, a)) return [ project.manager().virtual_targets().register(t) for t in targets ] diff --git a/v2/build/project.py b/v2/build/project.py index d1c720c04..77d745b77 100644 --- a/v2/build/project.py +++ b/v2/build/project.py @@ -794,8 +794,9 @@ class ProjectRules: self.rules = {} self.local_names = [x for x in self.__class__.__dict__ if x not in ["__init__", "init_project", "add_rule", - "error_reporting_wrapper", "add_rule_for_type"]] + "error_reporting_wrapper", "add_rule_for_type", "reverse"]] self.all_names_ = [x for x in self.local_names] + self.reverse = {} def _import_rule(self, bjam_module, name, callable): if hasattr(callable, "bjam_signature"): @@ -1002,6 +1003,7 @@ attribute is allowed only for top-level 'project' invocations""") v = m.__dict__[f] if callable(v): self._import_rule(jamfile_module, name + "." + f, v) + self.reverse.setdefault(jamfile_module, {})[name + "." + f] = v if names_to_import: if not local_names: @@ -1028,3 +1030,11 @@ attribute is allowed only for top-level 'project' invocations""") return [c + r for r in requirements] else: return [c + ":" + r for r in requirements] + + def reverse_lookup(self, jamfile_module, name_in_jamfile_modue): + """Return callable that we've previously imported to jam.""" + + if self.reverse.has_key(jamfile_module): + return self.reverse[jamfile_module].get(name_in_jamfile_modue, None) + + return None diff --git a/v2/build/property.py b/v2/build/property.py index 9a59c61a2..f0ebe2145 100644 --- a/v2/build/property.py +++ b/v2/build/property.py @@ -226,11 +226,10 @@ def translate_indirect(properties, context_module): # will conflict. m = context_module + "." + m - v = m - #v = indirect.make(m, context_module) - get_manager().engine().register_bjam_action(v) + v = context_module + '%' + m + get_manager().engine().register_bjam_action(m) - result.append(Property(p.feature(), "@" + m, p.condition())) + result.append(Property(p.feature(), "@" + v, p.condition())) else: result.append(p) diff --git a/v2/build/virtual_target.py b/v2/build/virtual_target.py index 61706ddf9..5ef3a49b7 100644 --- a/v2/build/virtual_target.py +++ b/v2/build/virtual_target.py @@ -156,7 +156,7 @@ class VirtualTargetRegistry: file_type = type.type (file) - result = FileTarget (file, False, file_type, project, + result = FileTarget (file, file_type, project, None, file_location) self.files_ [path] = result @@ -366,7 +366,7 @@ class AbstractFileTarget (VirtualTarget): type: optional type of this target. """ - def __init__ (self, name, exact, type, project, action = None): + def __init__ (self, name, type, project, action = None, exact=False): VirtualTarget.__init__ (self, name, project) self.type_ = type @@ -607,14 +607,14 @@ class FileTarget (AbstractFileTarget): - the value passed to the 'suffix' method, if any, or - the suffix which correspond to the target's type. """ - def __init__ (self, name, exact, type, project, action = None, path=None): - AbstractFileTarget.__init__ (self, name, exact, type, project, action) + def __init__ (self, name, type, project, action = None, path=None, exact=False): + AbstractFileTarget.__init__ (self, name, type, project, action, exact) self.path_ = path def clone_with_different_type(self, new_type): - return FileTarget(self.name_, 1, new_type, self.project_, - self.action_, self.path_) + return FileTarget(self.name_, new_type, self.project_, + self.action_, self.path_, exact=True) def actualize_location (self, target): engine = self.project_.manager_.engine () @@ -791,7 +791,8 @@ class Action: if i.type (): scanner = type.get_scanner (i.type (), prop_set) - result.append (i.actualize (scanner)) + r = i.actualize (scanner) + result.append (r) return result @@ -857,11 +858,14 @@ class NonScanningAction(Action): def __init__(self, sources, action_name, property_set): #FIXME: should the manager parameter of Action.__init__ #be removed? -- Steven Watanabe - Action.__init__(b2.manager.get_manager(), sources, action_name, property_set) + Action.__init__(self, b2.manager.get_manager(), sources, action_name, property_set) def actualize_source_type(self, sources, property_set): - - return [x for source in sources for x in i.actualize()] + + result = [] + for s in sources: + result.append(s.actualize()) + return result def traverse (target, include_roots = False, include_sources = False): """ Traverses the dependency graph of 'target' and return all targets that will @@ -915,8 +919,8 @@ def clone_action (action, new_project, new_action_name, new_properties): n = target.name() # Don't modify the name of the produced targets. Strip the directory f - cloned_target = FileTarget(n, 1, target.type(), new_project, - cloned_action) + cloned_target = FileTarget(n, target.type(), new_project, + cloned_action, exact=True) d = target.dependencies() if d: diff --git a/v2/example/generate/gen.jam b/v2/example/generate/gen.jam new file mode 100644 index 000000000..73232aab5 --- /dev/null +++ b/v2/example/generate/gen.jam @@ -0,0 +1,26 @@ + +import "class" : new ; +import common ; + +rule generate-example ( project name : property-set : sources * ) +{ + local result ; + for local s in $(sources) + { + #local source-name = [ $(s).name ] ; + #local source-action = [ $(s).action ] ; + #local source-properties = [ $(source-action).properties ] ; + + # Create a new action, that takes the source target and runs the + # 'common.copy' command on it. + local a = [ new non-scanning-action $(s) : common.copy : $(property-set) + ] ; + + # Create a target to represent the action result. Uses the target name + # passed here via the 'name' parameter and the same type and project as + # the source. + result += [ new file-target $(name) : [ $(s).type ] : $(project) : $(a) + ] ; + } + return $(result) ; +} \ No newline at end of file diff --git a/v2/example/generate/gen.py b/v2/example/generate/gen.py new file mode 100644 index 000000000..09ee15b43 --- /dev/null +++ b/v2/example/generate/gen.py @@ -0,0 +1,16 @@ + +from b2.build.virtual_target import NonScanningAction, FileTarget + +def generate_example(project, name, ps, sources): + + result = [] + for s in sources: + + a = NonScanningAction([s], "common.copy", ps) + + # Create a target to represent the action result. Uses the target name + # passed here via the 'name' parameter and the same type and project as + # the source. + result.append(FileTarget(name, s.type(), project, a)) + + return result diff --git a/v2/example/generate/jamroot.jam b/v2/example/generate/jamroot.jam index a244f65fc..07b8623b4 100644 --- a/v2/example/generate/jamroot.jam +++ b/v2/example/generate/jamroot.jam @@ -2,30 +2,8 @@ # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) -import "class" : new ; -import common ; +import generate ; -rule generate-example ( project name : property-set : sources * ) -{ - local result ; - for local s in $(sources) - { - #local source-name = [ $(s).name ] ; - #local source-action = [ $(s).action ] ; - #local source-properties = [ $(source-action).properties ] ; +import gen ; - # Create a new action, that takes the source target and runs the - # 'common.copy' command on it. - local a = [ new non-scanning-action $(s) : common.copy : $(property-set) - ] ; - - # Create a target to represent the action result. Uses the target name - # passed here via the 'name' parameter and the same type and project as - # the source. - result += [ new file-target $(name) : [ $(s).type ] : $(project) : $(a) - ] ; - } - return $(result) ; -} - -generate a2 : a.cpp : @generate-example ; +generate a2 : a.cpp : @gen.generate_example ; diff --git a/v2/tools/builtin.py b/v2/tools/builtin.py index bf2bb85b5..1cd30a9d2 100644 --- a/v2/tools/builtin.py +++ b/v2/tools/builtin.py @@ -316,7 +316,7 @@ register_globals () class SearchedLibTarget (virtual_target.AbstractFileTarget): def __init__ (self, name, project, shared, real_name, search, action): - virtual_target.AbstractFileTarget.__init__ (self, name, False, 'SEARCHED_LIB', project, action) + virtual_target.AbstractFileTarget.__init__ (self, name, 'SEARCHED_LIB', project, action) self.shared_ = shared self.real_name_ = real_name diff --git a/v2/tools/make.py b/v2/tools/make.py index 97fa81283..a6d476269 100644 --- a/v2/tools/make.py +++ b/v2/tools/make.py @@ -16,17 +16,24 @@ from b2.build import type from b2.manager import get_manager import b2.build.property_set +# FIXME: copy-paste from generate.py +import re +_extract_jamfile_and_rule = re.compile("@(Jamfile<.*>)%(.*)") + class MakeTarget(BasicTarget): def construct(self, name, source_targets, property_set): action_name = property_set.get("")[0] assert action_name[0] == '@' - action_name = action_name[1:] + (jamfile, rule) = _extract_jamfile_and_rule.match(action_name).groups() + # This is very bad. We need to call rule inside the proper module, + # not at global scope, where it might not be available at all. + action_name = rule action = Action(get_manager(), source_targets, action_name, property_set) - target = FileTarget(self.name(), 1, type.type(self.name()), - self.project(), action) + target = FileTarget(self.name(), type.type(self.name()), + self.project(), action, exact=True) return [ b2.build.property_set.empty(), [self.project().manager().virtual_targets().register(target)]]