20.2. Adding a search path to a Scanner: FindPathDirs

If the build tool in question will use a path variable to search for included files or other dependencies, then the Scanner will need to take that path variable into account as well - the same way $CPPPATH is used for files processed by the C Preprocessor (used for C, C++, Fortran and others). Path variables may be lists of nodes or semicolon-separated strings (SCons uses a semicolon here irrespective of the pathlist separator used by the native operating system), and may contain construction variables to be expanded. A Scanner can take a path_function to process such a path variable; the function produces a tuple of paths that is passed to the scanner function as its path parameter.

To make this easy, SCons provides the premade FindPathDirs function which returns a callable to expand a given path variable (given as an SCons construction variable name) to a tuple of paths at the time the Scanner is called. Deferring evaluation until that point allows, for instance, the path to contain $TARGET references which differ for each file scanned.

Using FindPathDirs is easy. Continuing the above example, using $KPATH as the construction variable to hold the paths (analogous to $CPPPATH), we just modify the call to the Scanner factory function to include a path_function keyword argument:

kscan = Scanner(
    function=kfile_scan,
    skeys=['.k'],
    path_function=FindPathDirs('KPATH'),
)
      

FindPathDirs is called when the Scanner is created, and the callable object it returns is stored as an attribute in the scanner. When the scanner is invoked, it calls that object, which processes the $KPATH from the current construction environment, doing necessary expansions and, if necessary, adds related repository and variant directories, producing a (possibly empty) tuple of paths that is passed on to the scanner function. The scanner function is then responsible for using that list of paths to locate the include files identified by the scan. The next section will show an example of that.

As a side note, the returned method stores the path in an efficient way so lookups are fast even when variable substitutions may be needed. This is important since many files get scanned in a typical build.