Analagous to the previously-described Builder
objects, SCons
supplies (and uses) Scanner
objects to search the contents of
a file for implicit dependency files:
CScan | scan .{c,C,cc,cxx,cpp} files for #include dependencies |
A construction environment can be explicitly initialized with
associated Scanner
objects:
env = Environment(SCANNERS = ['CScan', 'M4Scan'])
Scanner
objects bound to a construction environment can be
associated directly with specified files:
env.CScan('foo.c', 'bar.c') env.M4Scan('input.m4')
A user may define a Scanner
object to scan a type of file for
implicit dependencies:
def scanner1(file_contents): # search for dependencies return dependency_list FirstScan = Scanner(function = scanner1)
The scanner function must return a list of dependencies that its finds based on analyzing the file contents it is passed as an argument.
The scanner function, when invoked, will be passed the calling environment. The scanner function can use construction environments from the passed environment to affect how it performs its dependency scan--the canonical example being to use some sort of search-path construction variable to look for dependency files in other directories:
def scanner2(file_contents, env): path = env.{'SCANNERPATH'} # XXX # search for dependencies using 'path' return dependency_list SecondScan = Scanner(function = scanner2)
The user may specify an additional argument when the Scanner
object
is created. When the scanner is invoked, the additional argument
will be passed to the scanner funciton, which can be used in any way
the scanner function sees fit:
def scanner3(file_contents, env, arg): # skip 'arg' lines, then search for dependencies return dependency_list Skip_3_Lines_Scan = Scanner(function = scanner2, argument = 3) Skip_6_Lines_Scan = Scanner(function = scanner2, argument = 6)
A method exists to return a copy of an existing Scanner
object,
with any overridden values specified as keyword arguments to the
method:
scan = Scanner(function = my_scan) scan_path = scan.Copy(path = '%SCANNERPATH')
Typically, Scanner
objects will be supplied by a tool-master or
administrator through a shared construction environment.
Each construction environment has a SCANNERMAP
, a dictionary that associates
different file suffixes with a scanner object that can be used to
generate a list of dependencies from the contents of that file. This
SCANNERMAP
can be initialized at instantiation:
env = Environment(SCANNERMAP = { '.c' : CScan, '.cc' : CScan, '.m4' : M4Scan, })
Scanner
objects referenced in the SCANNERMAP
do not need to
be listed separately in the SCANNERS
variable. The construction environment
will bind the union of the Scanner
objects listed
in both variables.