Here are a few things I learned that don’t appear to be in the documentation.
Passing variables to SConscripts
The documentation states two ways to make variables available for import:
SConscript('build/src/SConscript', exports = 'env')
which exports a variable for just this SConscript to import, or
which adds to a global export list that all SConscripts can import from. They can be combined, and variables exported in the SConscript line take precedence over ones in the global list.
However, there is a third way to do this that is undocumented as far as I can tell
which is the same as the first method, just sans the export keyword. And of course, it can be a list of variables, and they can be remapped.
This are not documented, but is useful. Detect (or env.Detect) is the call that is used to find an executable. It’s called Detect() because it’s used by the tool config system to see if a tool is installed. It searches through the paths in the PATH environment variable.
The scalar version returns the path to the executable, if the executable can be found in the system:
path = env.Detect('protoc')
The list version returns the path to the first executable that can be found. This is useful if there’s a single conceptual tool that might have multiple names:
path = env.Detect(['protoc', 'protoc9', 'protoc10'])
The latter would only be used for cases where each variant is equivalent in functionality, because it will just pick the first one found. Alternatively, there could be a case for listing from superset to subset tool, if your usage code can detect and handle fallbacks, but it’s probably better to do that with individual Detect() calls.
You can pass in the file with extension, if you only want to find that exact name. Otherwise, SCons will add the extension appropriate to the operating system (on Windows, it will iterate through PATHEXT).
The idiom is to do this in your tool’s exists() function, if your tool is a wrapper around an installed program.