Imported Upstream version 1.51.0
[platform/upstream/boost.git] / tools / build / v2 / build / scanner.jam
1 # Copyright 2003 Dave Abrahams 
2 # Copyright 2002, 2003, 2004, 2005 Vladimir Prus 
3 # Distributed under the Boost Software License, Version 1.0. 
4 # (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) 
5
6 #  Implements scanners: objects that compute implicit dependencies for
7 #  files, such as includes in C++.
8 #
9 #  Scanner has a regular expression used to find dependencies, some
10 #  data needed to interpret those dependencies (for example, include
11 #  paths), and a code which actually established needed relationship
12 #  between actual jam targets.
13 #
14 #  Scanner objects are created by actions, when they try to actualize
15 #  virtual targets, passed to 'virtual-target.actualize' method and are
16 #  then associated with actual targets. It is possible to use
17 #  several scanners for a virtual-target. For example, a single source
18 #  might be used by to compile actions, with different include paths.
19 #  In this case, two different actual targets will be created, each 
20 #  having scanner of its own.
21 #
22 #  Typically, scanners are created from target type and action's 
23 #  properties, using the rule 'get' in this module. Directly creating
24 #  scanners is not recommended, because it might create many equvivalent
25 #  but different instances, and lead in unneeded duplication of
26 #  actual targets. However, actions can also create scanners in a special
27 #  way, instead of relying on just target type.
28
29 import "class" : new ;
30 import property virtual-target property-set ;
31 import errors : error ;
32
33 #  Base scanner class. 
34 class scanner 
35 {
36     rule __init__ ( )
37     {
38     }
39     
40     # Returns a pattern to use for scanning
41     rule pattern ( )
42     {
43         error "method must be overriden" ;
44     }
45
46     # Establish necessary relationship between targets,
47     # given actual target beeing scanned, and a list of
48     # pattern matches in that file.
49     rule process ( target : matches * )
50     {
51         error "method must be overriden" ;
52     }        
53 }
54
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.
58 rule register ( scanner-class : relevant-properties * )
59 {
60     .registered += $(scanner-class) ;
61     .relevant-properties.$(scanner-class) = $(relevant-properties) ;
62 }
63
64 # Common scanner class, which can be used when there's only one
65 # kind of includes (unlike C, where "" and <> includes have different
66 # search paths).
67 class common-scanner : scanner 
68 {
69     import scanner ;
70     rule __init__ ( includes * )
71     {
72         scanner.__init__ ;
73         self.includes = $(includes) ;
74     }
75             
76     rule process ( target : matches * : binding )
77     {
78         local target_path = [ NORMALIZE_PATH $(binding:D) ] ;
79
80         NOCARE $(matches) ;
81         INCLUDES $(target) : $(matches) ;
82         SEARCH on $(matches) = $(target_path) $(self.includes:G=) ;
83         ISFILE $(matches) ;
84     
85         scanner.propagate $(__name__) : $(matches) : $(target) ;     
86     }
87 }
88
89
90 # Returns an instance of previously registered scanner,
91 # with the specified properties.
92 rule get ( scanner-class : property-set ) 
93 {
94     if ! $(scanner-class) in $(.registered)
95     {
96         error "attempt to get unregisted scanner" ;
97     }
98     
99     local r = $(.rv-cache.$(property-set)) ;
100     if ! $(r)
101     {
102         r = [ property-set.create 
103             [ property.select $(.relevant-properties.$(scanner-class)) :
104               [ $(property-set).raw ] ] ] ;        
105         .rv-cache.$(property-set) = $(r) ;
106     }
107         
108     if ! $(scanner.$(scanner-class).$(r:J=-))
109     {
110         scanner.$(scanner-class).$(r:J=-) = [ new $(scanner-class) [ $(r).raw ] ] ;
111     }
112     return $(scanner.$(scanner-class).$(r:J=-)) ;    
113 }
114
115
116 # Installs the specified scanner on actual target 'target'. 
117 rule install ( scanner : target 
118     vtarget # virtual target from which 'target' was actualized
119 )
120 {
121     HDRSCAN on $(target) = [ $(scanner).pattern ] ;
122     SCANNER on $(target) = $(scanner) ;
123     HDRRULE on $(target) = scanner.hdrrule ;
124     
125     # scanner reflects difference in properties affecting    
126     # binding of 'target', which will be known when processing
127     # includes for it, will give information on how to
128     # interpret quoted includes.
129     HDRGRIST on $(target) = $(scanner) ;
130 }
131
132 # Propagate scanner setting from 'including-target' to 'targets'.
133 rule propagate ( scanner : targets * : including-target )
134 {
135     HDRSCAN on $(targets) = [ on $(including-target) return $(HDRSCAN) ] ;
136     SCANNER on $(targets) = $(scanner) ;
137     HDRRULE on $(targets) = scanner.hdrrule ;
138     HDRGRIST on $(targets) = [ on $(including-target) return $(HDRGRIST) ] ;
139 }
140
141
142 rule hdrrule ( target : matches * : binding )
143 {
144     local scanner = [ on $(target) return $(SCANNER) ] ;
145     $(scanner).process $(target) : $(matches) : $(binding) ;
146 }
147 # hdrrule must be available at global scope so that it can be invoked
148 # by header scanning
149 IMPORT scanner : hdrrule : : scanner.hdrrule ;
150
151
152
153