summaryrefslogtreecommitdiff
path: root/tools/build/src/build/scanner.jam
diff options
context:
space:
mode:
Diffstat (limited to 'tools/build/src/build/scanner.jam')
-rw-r--r--tools/build/src/build/scanner.jam163
1 files changed, 163 insertions, 0 deletions
diff --git a/tools/build/src/build/scanner.jam b/tools/build/src/build/scanner.jam
new file mode 100644
index 000000000..ed5507029
--- /dev/null
+++ b/tools/build/src/build/scanner.jam
@@ -0,0 +1,163 @@
+# Copyright 2003 Dave Abrahams
+# Copyright 2002, 2003, 2004, 2005 Vladimir Prus
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+# Implements scanners: objects computing implicit dependencies for files, such
+# as includes in C++.
+#
+# A scanner has a regular expression used to find the dependencies, some data
+# needed to interpret those dependencies (e.g., include paths), and code which
+# establishing needed relationships between actual jam targets.
+#
+# Scanner objects are created by actions when they try to actualize virtual
+# targets, passed to the virtual-target.actualize() method and are then
+# associated with actual targets. It is possible to use several scanners for a
+# single virtual-target. For example, a single source file might be compiled
+# twice - each time using a different include path. In this case, two separate
+# actual targets will be created, each having a scanner of its own.
+#
+# Typically, scanners are created from target type and the action's properties,
+# using the rule 'get' in this module. Directly creating scanners is not
+# recommended, as it might create multiple equvivalent but different instances,
+# and lead to unnecessary actual target duplication. However, actions can also
+# create scanners in a special way, instead of relying on just the target type.
+
+import "class" : new ;
+import property ;
+import property-set ;
+import virtual-target ;
+
+# Base scanner class.
+#
+class scanner
+{
+ rule __init__ ( )
+ {
+ }
+
+ # Returns a pattern to use for scanning.
+ #
+ rule pattern ( )
+ {
+ import errors : error : errors.error ;
+ errors.error "method must be overriden" ;
+ }
+
+ # Establish necessary relationship between targets, given an actual target
+ # beeing scanned and a list of pattern matches in that file.
+ #
+ rule process ( target : matches * )
+ {
+ import errors : error : errors.error ;
+ errors.error "method must be overriden" ;
+ }
+}
+
+
+# Registers a new generator class, specifying a set of properties relevant to
+# this scanner. Constructor for that class should have one parameter: a list of
+# properties.
+#
+rule register ( scanner-class : relevant-properties * )
+{
+ .registered += $(scanner-class) ;
+ .relevant-properties.$(scanner-class) = $(relevant-properties) ;
+}
+
+
+# Common scanner class, usable when there is only one kind of includes (unlike
+# C, where "" and <> includes have different search paths).
+#
+class common-scanner : scanner
+{
+ import scanner ;
+
+ rule __init__ ( includes * )
+ {
+ scanner.__init__ ;
+ self.includes = $(includes) ;
+ }
+
+ rule process ( target : matches * : binding )
+ {
+ local target_path = [ NORMALIZE_PATH $(binding:D) ] ;
+
+ NOCARE $(matches) ;
+ INCLUDES $(target) : $(matches) ;
+ SEARCH on $(matches) = $(target_path) $(self.includes:G=) ;
+ ISFILE $(matches) ;
+
+ scanner.propagate $(__name__) : $(matches) : $(target) ;
+ }
+}
+
+
+# Returns an instance of a previously registered scanner, with the specified
+# properties.
+#
+rule get ( scanner-class : property-set )
+{
+ if ! $(scanner-class) in $(.registered)
+ {
+ import errors ;
+ errors.error "attempt to get an unregisted scanner" ;
+ }
+
+ local r = $(.rv-cache.$(property-set)) ;
+ if ! $(r)
+ {
+ r = [ property-set.create
+ [ property.select $(.relevant-properties.$(scanner-class)) :
+ [ $(property-set).raw ] ] ] ;
+ .rv-cache.$(property-set) = $(r) ;
+ }
+
+ if ! $(scanner.$(scanner-class).$(r:J=-))
+ {
+ local s = [ new $(scanner-class) [ $(r).raw ] ] ;
+ scanner.$(scanner-class).$(r:J=-) = $(s) ;
+ }
+ return $(scanner.$(scanner-class).$(r:J=-)) ;
+}
+
+
+# Installs the specified scanner on the actual target 'target'.
+#
+rule install ( scanner : target )
+{
+ HDRSCAN on $(target) = [ $(scanner).pattern ] ;
+ SCANNER on $(target) = $(scanner) ;
+ HDRRULE on $(target) = scanner.hdrrule ;
+
+ # Scanner reflects differences in properties affecting binding of 'target',
+ # which will be known when processing includes for it, and give information
+ # on how to interpret different include types (e.g. quoted vs. those in
+ # angle brackets in C files).
+ HDRGRIST on $(target) = $(scanner) ;
+}
+
+
+# Propagate scanner settings from 'including-target' to 'targets'.
+#
+rule propagate ( scanner : targets * : including-target )
+{
+ HDRSCAN on $(targets) = [ on $(including-target) return $(HDRSCAN) ] ;
+ SCANNER on $(targets) = $(scanner) ;
+ HDRRULE on $(targets) = scanner.hdrrule ;
+ HDRGRIST on $(targets) = [ on $(including-target) return $(HDRGRIST) ] ;
+}
+
+
+rule hdrrule ( target : matches * : binding )
+{
+ local scanner = [ on $(target) return $(SCANNER) ] ;
+ $(scanner).process $(target) : $(matches) : $(binding) ;
+}
+
+
+# hdrrule must be available at global scope so it can be invoked by header
+# scanning.
+#
+IMPORT scanner : hdrrule : : scanner.hdrrule ;