]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/tools/build/src/build/scanner.py
4 # Copyright 2003 Dave Abrahams
5 # Copyright 2002, 2003, 2004, 2005 Vladimir Prus
6 # Distributed under the Boost Software License, Version 1.0.
7 # (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
9 # Implements scanners: objects that compute implicit dependencies for
10 # files, such as includes in C++.
12 # Scanner has a regular expression used to find dependencies, some
13 # data needed to interpret those dependencies (for example, include
14 # paths), and a code which actually established needed relationship
15 # between actual jam targets.
17 # Scanner objects are created by actions, when they try to actualize
18 # virtual targets, passed to 'virtual-target.actualize' method and are
19 # then associated with actual targets. It is possible to use
20 # several scanners for a virtual-target. For example, a single source
21 # might be used by to compile actions, with different include paths.
22 # In this case, two different actual targets will be created, each
23 # having scanner of its own.
25 # Typically, scanners are created from target type and action's
26 # properties, using the rule 'get' in this module. Directly creating
27 # scanners is not recommended, because it might create many equvivalent
28 # but different instances, and lead in unneeded duplication of
29 # actual targets. However, actions can also create scanners in a special
30 # way, instead of relying on just target type.
34 from b2
.manager
import get_manager
35 from b2
.util
import is_iterable_typed
39 """ Clear the module state. This is mainly for testing purposes.
41 global __scanners
, __rv_cache
, __scanner_cache
43 # Maps registered scanner classes to relevant properties
46 # A cache of scanners.
47 # The key is: class_name.properties_tag, where properties_tag is the concatenation
48 # of all relevant properties, separated by '-'
54 def register(scanner_class
, relevant_properties
):
55 """ Registers a new generator class, specifying a set of
56 properties relevant to this scanner. Ctor for that class
57 should have one parameter: list of properties.
59 assert issubclass(scanner_class
, Scanner
)
60 assert isinstance(relevant_properties
, basestring
)
61 __scanners
[str(scanner_class
)] = relevant_properties
63 def registered(scanner_class
):
64 """ Returns true iff a scanner of that class is registered
66 return str(scanner_class
) in __scanners
68 def get(scanner_class
, properties
):
69 """ Returns an instance of previously registered scanner
70 with the specified properties.
72 assert issubclass(scanner_class
, Scanner
)
73 assert is_iterable_typed(properties
, basestring
)
74 scanner_name
= str(scanner_class
)
76 if not registered(scanner_name
):
77 raise BaseException ("attempt to get unregistered scanner: %s" % scanner_name
)
79 relevant_properties
= __scanners
[scanner_name
]
80 r
= property.select(relevant_properties
, properties
)
82 scanner_id
= scanner_name
+ '.' + '-'.join(r
)
84 if scanner_id
not in __scanner_cache
:
85 __scanner_cache
[scanner_id
] = scanner_class(r
)
87 return __scanner_cache
[scanner_id
]
90 """ Base scanner class.
96 """ Returns a pattern to use for scanning.
98 raise BaseException ("method must be overridden")
100 def process (self
, target
, matches
, binding
):
101 """ Establish necessary relationship between targets,
102 given actual target being scanned, and a list of
103 pattern matches in that file.
105 raise BaseException ("method must be overridden")
108 # Common scanner class, which can be used when there's only one
109 # kind of includes (unlike C, where "" and <> includes have different
111 class CommonScanner(Scanner
):
113 def __init__ (self
, includes
):
114 Scanner
.__init
__(self
)
115 self
.includes
= includes
117 def process(self
, target
, matches
, binding
):
119 target_path
= os
.path
.normpath(os
.path
.dirname(binding
[0]))
120 bjam
.call("mark-included", target
, matches
)
122 get_manager().engine().set_target_variable(matches
, "SEARCH",
123 [target_path
] + self
.includes
)
124 get_manager().scanners().propagate(self
, matches
)
126 class ScannerRegistry
:
128 def __init__ (self
, manager
):
129 self
.manager_
= manager
131 self
.exported_scanners_
= {}
133 def install (self
, scanner
, target
, vtarget
):
134 """ Installs the specified scanner on actual target 'target'.
135 vtarget: virtual target from which 'target' was actualized.
137 assert isinstance(scanner
, Scanner
)
138 assert isinstance(target
, basestring
)
139 assert isinstance(vtarget
, basestring
)
140 engine
= self
.manager_
.engine()
141 engine
.set_target_variable(target
, "HDRSCAN", scanner
.pattern())
142 if scanner
not in self
.exported_scanners_
:
143 exported_name
= "scanner_" + str(self
.count_
)
144 self
.count_
= self
.count_
+ 1
145 self
.exported_scanners_
[scanner
] = exported_name
146 bjam
.import_rule("", exported_name
, scanner
.process
)
148 exported_name
= self
.exported_scanners_
[scanner
]
150 engine
.set_target_variable(target
, "HDRRULE", exported_name
)
152 # scanner reflects difference in properties affecting
153 # binding of 'target', which will be known when processing
154 # includes for it, will give information on how to
155 # interpret quoted includes.
156 engine
.set_target_variable(target
, "HDRGRIST", str(id(scanner
)))
159 def propagate(self
, scanner
, targets
):
160 assert isinstance(scanner
, Scanner
)
161 assert is_iterable_typed(targets
, basestring
) or isinstance(targets
, basestring
)
162 engine
= self
.manager_
.engine()
163 engine
.set_target_variable(targets
, "HDRSCAN", scanner
.pattern())
164 engine
.set_target_variable(targets
, "HDRRULE",
165 self
.exported_scanners_
[scanner
])
166 engine
.set_target_variable(targets
, "HDRGRIST", str(id(scanner
)))