1# Copyright 2004 David Abrahams
2# Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus
3# Copyright 2010 Rene Rivera
4# Distributed under the Boost Software License, Version 1.0.
5# (See accompanying file LICENSE_1_0.txt or copy at
6# http://www.boost.org/LICENSE_1_0.txt)
7
8import scanner ;
9import type ;
10
11
12class c-scanner : scanner
13{
14    import path ;
15    import regex ;
16    import scanner ;
17    import sequence ;
18    import toolset ;
19    import virtual-target ;
20
21    rule __init__ ( includes * )
22    {
23        scanner.__init__ ;
24
25        # toolset.handle-flag-value is a bit of overkill, but it
26        # does correctly handle the topological sort of && separated
27        # include paths
28        self.includes = [ toolset.handle-flag-value <include> : $(includes) ] ;
29    }
30
31    rule pattern ( )
32    {
33        return "#[ \t]*include[ \t]*(<(.*)>|\"(.*)\")" ;
34    }
35
36    rule process ( target : matches * : binding )
37    {
38        local angle = [ regex.transform $(matches) : "<(.*)>" ] ;
39        angle = [ sequence.transform path.native : $(angle) ] ;
40        local quoted = [ regex.transform $(matches) : "\"(.*)\"" ] ;
41        quoted = [ sequence.transform path.native : $(quoted) ] ;
42
43        # CONSIDER: the new scoping rules seem to defeat "on target" variables.
44        local g = [ on $(target) return $(HDRGRIST) ] ;
45        local b = [ NORMALIZE_PATH $(binding:D) ] ;
46
47        # Attach binding of including file to included targets. When a target is
48        # directly created from a virtual target this extra information is
49        # unnecessary. But in other cases, it allows us to distinguish between
50        # two headers of the same name included from different places. We do not
51        # need this extra information for angle includes, since they should not
52        # depend on the including file (we can not get literal "." in the
53        # include path).
54        local g2 = $(g)"#"$(b) ;
55
56        angle = $(angle:G=$(g)) ;
57        quoted = $(quoted:G=$(g2)) ;
58
59        local all = $(angle) $(quoted) ;
60
61        INCLUDES $(target) : $(all) ;
62        NOCARE $(all) ;
63        SEARCH on $(angle) = $(self.includes:G=) ;
64        SEARCH on $(quoted) = $(b) $(self.includes:G=) ;
65
66        # Just propagate the current scanner to includes, in hope that includes
67        # do not change scanners.
68        scanner.propagate $(__name__) : $(all) : $(target) ;
69
70        ISFILE $(all) ;
71    }
72}
73
74scanner.register c-scanner : include ;
75
76type.register CPP : cpp cxx cc ;
77type.register H   : h ;
78type.register HPP : hpp : H ;
79type.register C   : c ;
80
81# It most cases where a CPP file or a H file is a source of some action, we
82# should rebuild the result if any of files included by CPP/H are changed. One
83# case when this is not needed is installation, which is handled specifically.
84type.set-scanner CPP : c-scanner ;
85type.set-scanner C   : c-scanner ;
86# One case where scanning of H/HPP files is necessary is PCH generation -- if
87# any header included by HPP being precompiled changes, we need to recompile the
88# header.
89type.set-scanner H   : c-scanner ;
90type.set-scanner HPP : c-scanner ;
91