# Copyright David Abrahams 2004. # Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus # Copyright 2010 Rene Rivera # 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 type ; import scanner ; class c-scanner : scanner { import path ; import regex ; import scanner ; import sequence ; import virtual-target ; rule __init__ ( includes * ) { scanner.__init__ ; for local i in $(includes) { self.includes += [ sequence.transform path.native : [ regex.split $(i:G=) "&&" ] ] ; } } rule pattern ( ) { return "#[ \t]*include[ ]*(<(.*)>|\"(.*)\")" ; } rule process ( target : matches * : binding ) { local angle = [ regex.transform $(matches) : "<(.*)>" ] ; angle = [ sequence.transform path.native : $(angle) ] ; local quoted = [ regex.transform $(matches) : "\"(.*)\"" ] ; quoted = [ sequence.transform path.native : $(quoted) ] ; # CONSIDER: the new scoping rule seem to defeat "on target" variables. local g = [ on $(target) return $(HDRGRIST) ] ; local b = [ NORMALIZE_PATH $(binding:D) ] ; # Attach binding of including file to included targets. When a target is # directly created from virtual target this extra information is # unnecessary. But in other cases, it allows us to distinguish between # two headers of the same name included from different places. We do not # need this extra information for angle includes, since they should not # depend on including file (we can not get literal "." in include path). local g2 = $(g)"#"$(b) ; angle = $(angle:G=$(g)) ; quoted = $(quoted:G=$(g2)) ; local all = $(angle) $(quoted) ; INCLUDES $(target) : $(all) ; NOCARE $(all) ; SEARCH on $(angle) = $(self.includes:G=) ; SEARCH on $(quoted) = $(b) $(self.includes:G=) ; # Just propagate the current scanner to includes in hope that includes # do not change scanners. scanner.propagate $(__name__) : $(angle) $(quoted) : $(target) ; ISFILE $(angle) $(quoted) ; } } scanner.register c-scanner : include ; type.register CPP : cpp cxx cc ; type.register H : h ; type.register HPP : hpp : H ; type.register C : c ; # It most cases where a CPP file or a H file is a source of some action, we # should rebuild the result if any of files included by CPP/H are changed. One # case when this is not needed is installation, which is handled specifically. type.set-scanner CPP : c-scanner ; type.set-scanner C : c-scanner ; # One case where scanning of H/HPP files is necessary is PCH generation -- if # any header included by HPP being precompiled changes, we need to recompile the # header. type.set-scanner H : c-scanner ; type.set-scanner HPP : c-scanner ;