Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER
on a one-time uuid to make a path to the file.
- Clarify VariantDir behavior when switching to not duplicate sources
and tweak wording a bit.
- Update documentation of the three file-finding functions in the API
(FindFile, FindInstalledFiles, FindSourceFilse) as well as FindPathDirs.
Also add a test for FindFile to be sure it locates non-existing
derived files as advertised.


RELEASE 4.10.1 - Sun, 16 Nov 2025 10:51:57 -0700
Expand Down
5 changes: 4 additions & 1 deletion RELEASE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ IMPROVEMENTS
- Simplified and sped up compilation database generation. No longer requires
each entry to have a dedicated node that's always built; instead, the database
*itself* is set to always build.

- Switch remaining "original style" docstring parameter listings to Google style.

- Additional small tweaks to Environment.py type hints, fold some overly
Expand Down Expand Up @@ -118,6 +118,9 @@ DOCUMENTATION
- Clarify VariantDir behavior when switching to not duplicate sources
and tweak wording a bit.

- Update documentation of the three file-finding functions in the API
(FindFile, FindInstalledFiles, FindSourceFilse) as well as FindPathDirs.

DEVELOPMENT
-----------

Expand Down
41 changes: 19 additions & 22 deletions SCons/Environment.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1974,6 +1974,7 @@ Example:
</para>

<example_commands>
# Searches for 'foo' in 'dir1' and 'dir2', returning the node if found
foo = env.FindFile('foo', ['dir1', 'dir2'])
</example_commands>
</summary>
Expand All @@ -1985,16 +1986,16 @@ foo = env.FindFile('foo', ['dir1', 'dir2'])
</arguments>
<summary>
<para>
Returns the list of targets set up by the
Return the list of targets set up by the
&b-link-Install;
or
and
&b-link-InstallAs;
builders.
</para>

<para>
This function serves as a convenient method to select the contents of
a binary package.
The list is populated as &b-Install; and &b-InstallAs; are executed -
that is, the return reflects builder calls already seen
but not any calls that may occur later.
</para>

<para>
Expand All @@ -2004,13 +2005,13 @@ Example:
<example_commands>
Install('/bin', ['executable_a', 'executable_b'])

# will return the file node list
# Returns the file node list
# ['/bin/executable_a', '/bin/executable_b']
FindInstalledFiles()

Install('/lib', ['some_library'])

# will return the file node list
# Returns the file node list
# ['/bin/executable_a', '/bin/executable_b', '/lib/some_library']
FindInstalledFiles()
</example_commands>
Expand All @@ -2019,22 +2020,17 @@ FindInstalledFiles()

<scons_function name="FindSourceFiles">
<arguments>
(node='"."')
([node])
</arguments>
<summary>
<para>
Returns the list of nodes which serve as the source of the built files.
It does so by inspecting the dependency tree starting at the optional
argument
<parameter>node</parameter>
which defaults to the '"."'-node. It will then return all leaves of
<parameter>node</parameter>.
These are all children which have no further children.
</para>

<para>
This function is a convenient method to select the contents of a Source
Package.
Return the list of nodes which represent the sources of the built files.
It does so by recursively inspecting the dependency tree starting at the optional
argument <parameter>node</parameter>,
which defaults to the current directory (<literal>"."</literal>).
It returns all leaf nodes (files with no further dependencies) from the tree.
This function serves as a convenient method to select the contents of
a source package.
</para>

<para>
Expand All @@ -2054,8 +2050,9 @@ FindSourceFiles('src')
</example_commands>

<para>
As you can see, build support files (&SConstruct; in the above example)
will also be returned by this function.
Notice that build support files in the tree
(&SConstruct; in the above example)
are also returned.
</para>
</summary>
</scons_function>
Expand Down
64 changes: 25 additions & 39 deletions SCons/Scanner/Scanner.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,46 +31,32 @@ This file is processed by the bin/SConsDoc.py module.
</arguments>
<summary>
<para>
Returns a function
(actually a callable Python object)
intended to be used as the
<varname>path_function</varname>
of a Scanner object.
The returned object will look up the specified
<varname>variable</varname>
in a construction environment
and treat the construction variable's value as a list of
directory paths that should be searched
(like
&cv-link-CPPPATH;,
&cv-link-LIBPATH;,
etc.).
Return a callable object for use as the
<varname>path_function</varname> of a
<link linkend='scanner_objects'>Scanner object</link>.
When called, it looks up the specified
<varname>variable</varname> in the &consenv;
and treats its value as a list of
directory paths to search
(like &cv-link-CPPPATH; or &cv-link-LIBPATH;).
</para>

<para>
Note that use of
&f-FindPathDirs;
is generally preferable to
writing your own
Using &f-FindPathDirs;
is generally preferable to writing your own
<varname>path_function</varname>
for the following reasons:
1) The returned list will contain all appropriate directories
found in source trees
(when
&f-link-VariantDir;
is used)
or in code repositories
(when
&f-Repository;
or the
<option>-Y</option>
option are used).
2) scons will identify expansions of
<varname>variable</varname>
that evaluate to the same list of directories as,
in fact, the same list,
and avoid re-scanning the directories for files,
when possible.
because it handles common &SCons;
scanning cases correctly and efficiently:
(1) it returns all appropriate directories
from source trees when a variant directory is used,
and from repositories when
&f-link-Repository; or the
<link linkend="opt-repository"><option>-Y/--repository</option></link>
option is in effect.
(2) it detects when different values of
<varname>variable</varname> resolve to the same directory list and
reuses that result instead of rescanning the same directories,
avoiding redundant work.
</para>

<para>
Expand All @@ -82,9 +68,9 @@ def my_scan(node, env, path, arg):
# Code to scan file contents goes here...
return include_files

scanner = Scanner(name = 'myscanner',
function = my_scan,
path_function = FindPathDirs('MYPATH'))
scanner = Scanner(
name='myscanner', function=my_scan, path_function=FindPathDirs('MYPATH')
)
</example_commands>
</summary>
</scons_function>
Expand Down
40 changes: 24 additions & 16 deletions test/FindFile.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,33 +35,41 @@
test.write(['foo', 'testfile2'], 'test 2\n')
test.write(['bar', 'testfile1'], 'test 3\n')
test.write(['bar', 'baz', 'testfile2'], 'test 4\n')
test.write('source.txt', 'source content\n')

test.write('SConstruct', """
env = Environment(FILE = 'file', BAR = 'bar')
file1 = FindFile('testfile1', [ 'foo', '.', 'bar', 'bar/baz' ])
env = Environment(FILE='file', BAR='bar')
file1 = FindFile('testfile1', ['foo', '.', 'bar', 'bar/baz'])
with open(file1, 'r') as f:
print(f.read())
file2 = env.FindFile('test${FILE}1', [ 'bar', 'foo', '.', 'bar/baz' ])
print(f.read(), end='')
file2 = env.FindFile('test${FILE}1', ['bar', 'foo', '.', 'bar/baz'])
with open(file2, 'r') as f:
print(f.read())
file3 = FindFile('testfile2', [ 'foo', '.', 'bar', 'bar/baz' ])
print(f.read(), end='')
file3 = FindFile('testfile2', ['foo', '.', 'bar', 'bar/baz'])
with open(file3, 'r') as f:
print(f.read())
file4 = env.FindFile('testfile2', [ '$BAR/baz', 'foo', '.', 'bar' ])
print(f.read(), end='')
file4 = env.FindFile('testfile2', ['$BAR/baz', 'foo', '.', 'bar'])
with open(file4, 'r') as f:
print(f.read())
""")
print(f.read(), end='')

expect = test.wrap_stdout(read_str = """test 1
# Test finding unbuilt derived files
derived = env.Command('derived.txt', 'source.txt', Copy('$TARGET', '$SOURCE'))
found_derived = FindFile('derived.txt', ['.'])
print('Found derived:', str(found_derived))
""")

expect = test.wrap_stdout(
read_str="""\
test 1
test 3

test 2

test 4
Found derived: derived.txt
""",
build_str="""Copy("derived.txt", "source.txt")
""",
)

""", build_str = "scons: `.' is up to date.\n")

test.run(arguments = ".", stdout = expect)
test.run(arguments=".", stdout=expect)

test.pass_test()
Loading