diff options
author | Mats Wichmann <mats@linux.com> | 2024-12-13 14:20:23 (GMT) |
---|---|---|
committer | Mats Wichmann <mats@linux.com> | 2024-12-16 17:04:36 (GMT) |
commit | 3ee18c08c72fe8a6ce6cc2c39c355a880472213e (patch) | |
tree | 1cba5ff89e4a15f1195664f17f9b6d35d341f7f9 | |
parent | 0c21de9c4bd366eeec88e93f1323c1e5dc6a9825 (diff) | |
download | SCons-3ee18c08c72fe8a6ce6cc2c39c355a880472213e.zip SCons-3ee18c08c72fe8a6ce6cc2c39c355a880472213e.tar.gz SCons-3ee18c08c72fe8a6ce6cc2c39c355a880472213e.tar.bz2 |
Update docs on special method evaluation
The User Guide uses an example (in the Command chapter) of making a target
name out of the source name, a special attribute, and concatenation
with a new suffix. The special attribute part is not something that has
been introduced. Some searching suggests it's never actually described in
the User Guide, though .file, .abspath and .srcdir are used in examples.
The attribute used, .basename, doesn't actually exist - there's a
.base and a .filebase. Furthermore, the substitution suggested doesn't
work. Expansion of special variables like $SOURCE into nodes is deferred -
see the docstring of SCons.Subst.NLWrapper - so the internal expansion
ends up trying to lookup the attribute on a string, which fails with
an AttributeError. The way the user guide entry is written, it was
not actually evaluated: it was described as an <scons_example>, but
an incomplete one, and since there was no corresponding <scons_output>
the problem was not detected.
The changes fix up the example to have it use an existing attribute
(.base) and do File() on the source, and add a sidebar to provide a
bit of an explanation so this isn't just "magic". A subsequent example
(ex4, which I added) is dropped as it doesn't add enough value by itself,
and the final example (formerly ex5, renamed to ex3) now includes this
substitution so it's actually run by the doc machinery, and can be
seen to be working correctly.
This finally fixes #2905, which was closed in 2018 as having been addressed,
though the non-working example actually remained. The issue is
also mentioned in #4660, which is not resolved by changing the docs -
leaving that open, at least for the time being.
Signed-off-by: Mats Wichmann <mats@linux.com>
-rw-r--r-- | CHANGES.txt | 3 | ||||
-rw-r--r-- | RELEASE.txt | 4 | ||||
-rw-r--r-- | doc/generated/examples/builderscommands_ex3_1.xml (renamed from doc/generated/examples/builderscommands_ex5_1.xml) | 0 | ||||
-rw-r--r-- | doc/user/builders-commands.xml | 64 | ||||
-rw-r--r-- | doc/user/environments.xml | 2 | ||||
-rw-r--r-- | doc/user/nodes.xml | 14 |
6 files changed, 54 insertions, 33 deletions
diff --git a/CHANGES.txt b/CHANGES.txt index 5383cb7..285dcda 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -186,6 +186,9 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER and other attributes rather than indexing into stat return. - The update-release-info test is adapted to accept changed help output introduced in Python 3.12.8/3.13.1. + - Update the User Guide Command() example which now shows a target name + being created from '${SOURCE.base}.out' to use a valid special + attribute and to explain what's being done in the example. RELEASE 4.8.1 - Tue, 03 Sep 2024 17:22:20 -0700 diff --git a/RELEASE.txt b/RELEASE.txt index d386cb3..25d4862 100644 --- a/RELEASE.txt +++ b/RELEASE.txt @@ -211,6 +211,10 @@ DOCUMENTATION - Improved Variables documentation. +- Update the User Guide Command() example which now shows a target name + being created from '${SOURCE.base}.out' to use a valid special + attribute and to explain what's being done in the example. + DEVELOPMENT ----------- diff --git a/doc/generated/examples/builderscommands_ex5_1.xml b/doc/generated/examples/builderscommands_ex3_1.xml index 67659c1..67659c1 100644 --- a/doc/generated/examples/builderscommands_ex5_1.xml +++ b/doc/generated/examples/builderscommands_ex3_1.xml diff --git a/doc/user/builders-commands.xml b/doc/user/builders-commands.xml index d7e8c34..697193c 100644 --- a/doc/user/builders-commands.xml +++ b/doc/user/builders-commands.xml @@ -142,37 +142,49 @@ foo.in <para> - Note that &cv-link-SOURCE; and &cv-link-TARGET; are expanded - in the source and target as well, so you can write: + &cv-link-SOURCE; and &cv-link-TARGET; are expanded + in the source and target as well: </para> - <scons_example name="builderscommands_ex3"> - <file name="SConstruct" printme="1"> -env.Command('${SOURCE.basename}.out', 'foo.in', build) - </file> - </scons_example> - - <para> - - which does the same thing as the previous example, but allows you - to avoid repeating yourself. - - </para> + <!-- NOTE: this used to be an scons_example, but was not complete and + didn't have a matching scons_output, which meant problems were not + detected. The style of this line is now reused in the last example + of the section to make sure it's actually tested + (see issue #2905 - which was closed prematurely). + --> + <sconstruct> +env.Command('${SOURCE.base}.out', File('foo.in'), build) + </sconstruct> <para> - It may be helpful to use the <parameter>action</parameter> - keyword to specify the action, is this makes things more clear - to the reader: + Which does the same thing as the previous example, but allows you + to write a more generic rule for transforming the source filename + to the target filename, since unlike regular Builders, + &Command; does not have any built-in rules for that. </para> - <scons_example name="builderscommands_ex4"> - <file name="SConstruct" printme="1"> -env.Command('${SOURCE.basename}.out', 'foo.in', action=build) - </file> - </scons_example> + <tip><para> + + The example uses a <firstterm>Node special attribute</firstterm> + (<literal>.base</literal>, the file without its suffix), + a concept which has not been introduced yet, + but will appear in several subsequent examples + (see details in the Reference Manual section + <emphasis>Substitution: Special Attributes</emphasis>). + Due to the quirks of &SCons;' deferred evaluation scheme, + node special attribues do not currently work + in source and target arguments <emphasis>if</emphasis> the + replacement is a string (like <literal>'foo.in'</literal>). + They do work fine in strings describing actions. + You can give &SCons; a little help by + manually converting the filename string to a Node + (see <xref linkend="sect-creating-nodes"/>), + which is the approach used in the example. + + </para></tip> <para> @@ -187,11 +199,13 @@ env.Command('${SOURCE.basename}.out', 'foo.in', action=build) which include a message based on the type of action. However, you can also construct the &Action; object yourself to pass to &f-Command;, which gives you much more control. + Using the <parameter>action</parameter> keyword can also help + make such lines easier to read. Here's an evolution of the example from above showing this approach: </para> - <scons_example name="builderscommands_ex5"> + <scons_example name="builderscommands_ex3"> <file name="SConstruct" printme="1"> env = Environment() @@ -200,7 +214,7 @@ def build(target, source, env): return None act = Action(build, cmdstr="Building ${TARGET}") -env.Command('foo.out', 'foo.in', action=act) +env.Command('${SOURCE.base}.out', File('foo.in'), action=act) </file> <file name="foo.in"> foo.in @@ -213,7 +227,7 @@ foo.in </para> - <scons_output example="builderscommands_ex5" suffix="1"> + <scons_output example="builderscommands_ex3" suffix="1"> <scons_output_command>scons -Q</scons_output_command> </scons_output> diff --git a/doc/user/environments.xml b/doc/user/environments.xml index 6807694..ac99608 100644 --- a/doc/user/environments.xml +++ b/doc/user/environments.xml @@ -1876,9 +1876,9 @@ env = Environment() env.Command('foo', [], '__ROOT__/usr/bin/printenv.py') </file> <file name="__ROOT__/usr/bin/printenv.py" chmod="0o755"> -#!/usr/bin/env python import os import sys + if len(sys.argv) > 1: keys = sys.argv[1:] else: diff --git a/doc/user/nodes.xml b/doc/user/nodes.xml index a652e79..eba6014 100644 --- a/doc/user/nodes.xml +++ b/doc/user/nodes.xml @@ -40,7 +40,7 @@ This file is processed by the bin/SConsDoc.py module. </para> - <section> + <section id="sect-builder-nodelists"> <title>Builder Methods Return Lists of Target Nodes</title> <para> @@ -150,7 +150,7 @@ int main() { printf("Goodbye, world!\n"); } </section> - <section> + <section id="sect-creating-nodes"> <title>Explicitly Creating File and Directory Nodes</title> <para> @@ -228,7 +228,7 @@ xyzzy = Entry('xyzzy') </section> - <section> + <section id="sect-printing-nodes"> <title>Printing &Node; File Names</title> <para> @@ -290,7 +290,7 @@ int main() { printf("Hello, world!\n"); } </section> - <section> + <section id="sect-node-names"> <title>Using a &Node;'s File Name as a String</title> <para> @@ -337,7 +337,7 @@ int main() { printf("Hello, world!\n"); } </section> - <section> + <section id="sect-node-paths"> <title>&GetBuildPath;: Getting the Path From a &Node; or String</title> <para> @@ -384,7 +384,7 @@ print(env.GetBuildPath([n, "sub/dir/$VAR"])) <!-- - <section> + <section id="sect-node-contents"> <title>Fetching the Contents of a &Node;</title> <para> @@ -422,7 +422,7 @@ int main() { printf("Hello, world!\n"); } <!-- - <section> + <section id="sect-value-nodes"> <title>Python Value &Node;</title> <para> |