From 3ee18c08c72fe8a6ce6cc2c39c355a880472213e Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Fri, 13 Dec 2024 07:20:23 -0700 Subject: [PATCH 1/2] 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 , but an incomplete one, and since there was no corresponding 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 --- CHANGES.txt | 3 + RELEASE.txt | 4 ++ ...s_ex5_1.xml => builderscommands_ex3_1.xml} | 0 doc/user/builders-commands.xml | 64 +++++++++++-------- doc/user/environments.xml | 2 +- doc/user/nodes.xml | 14 ++-- 6 files changed, 54 insertions(+), 33 deletions(-) rename doc/generated/examples/{builderscommands_ex5_1.xml => builderscommands_ex3_1.xml} (100%) diff --git a/CHANGES.txt b/CHANGES.txt index 5383cb7b5f..285dcda2f8 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 d386cb3397..25d4862abd 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 similarity index 100% rename from doc/generated/examples/builderscommands_ex5_1.xml rename to doc/generated/examples/builderscommands_ex3_1.xml diff --git a/doc/user/builders-commands.xml b/doc/user/builders-commands.xml index d7e8c34235..697193cbf5 100644 --- a/doc/user/builders-commands.xml +++ b/doc/user/builders-commands.xml @@ -142,37 +142,49 @@ foo.in - 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: - - -env.Command('${SOURCE.basename}.out', 'foo.in', build) - - - - - - which does the same thing as the previous example, but allows you - to avoid repeating yourself. - - + + +env.Command('${SOURCE.base}.out', File('foo.in'), build) + - It may be helpful to use the action - 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. - - -env.Command('${SOURCE.basename}.out', 'foo.in', action=build) - - + + + The example uses a Node special attribute + (.base, 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 + Substitution: Special Attributes). + Due to the quirks of &SCons;' deferred evaluation scheme, + node special attribues do not currently work + in source and target arguments if the + replacement is a string (like 'foo.in'). + 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 ), + which is the approach used in the example. + + @@ -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 action keyword can also help + make such lines easier to read. Here's an evolution of the example from above showing this approach: - + 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) foo.in @@ -213,7 +227,7 @@ foo.in - + scons -Q diff --git a/doc/user/environments.xml b/doc/user/environments.xml index 6807694ece..ac99608529 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') -#!/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 a652e79c79..eba601465e 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. -
+
Builder Methods Return Lists of Target Nodes @@ -150,7 +150,7 @@ int main() { printf("Goodbye, world!\n"); }
-
+
Explicitly Creating File and Directory Nodes @@ -228,7 +228,7 @@ xyzzy = Entry('xyzzy')
-
+
Printing &Node; File Names @@ -290,7 +290,7 @@ int main() { printf("Hello, world!\n"); }
-
+
Using a &Node;'s File Name as a String @@ -337,7 +337,7 @@ int main() { printf("Hello, world!\n"); }
-
+
&GetBuildPath;: Getting the Path From a &Node; or String @@ -384,7 +384,7 @@ print(env.GetBuildPath([n, "sub/dir/$VAR"]))