Skip to content

Commit fb03ae9

Browse files
authored
Merge pull request #3811 from mwichmann/doc-subst-attrs
Update manpage on variable substitution
2 parents 7a32c41 + bcad36f commit fb03ae9

File tree

1 file changed

+87
-59
lines changed

1 file changed

+87
-59
lines changed

doc/man/scons.xml

Lines changed: 87 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -6182,14 +6182,25 @@ env.Command('marker', 'input_file', action=[MyBuildAction, Touch('$TARGET')])
61826182

61836183
<para>Before executing a command,
61846184
&scons;
6185-
performs &consvar; substitution on the string that makes up
6186-
the command line of the builder.
6187-
&Consvars; to be interpolated are indicated in the
6185+
performs variable substitution on the string that makes up
6186+
the action part of the builder.
6187+
Variables to be interpolated are indicated in the
61886188
string with a leading
61896189
<literal>$</literal>, to distinguish them from plain text
61906190
which is not to be substituted.
6191+
The name may be surrounded by curly braces
6192+
(<literal>${}</literal>)
6193+
to separate the name from surrounding characters if necessary.
6194+
Curly braces are required when you use
6195+
Python list subscripting/slicing notation on a variable
6196+
to select one or more items from a list,
6197+
or access a variable's special attributes,
6198+
or use Python expression substitution.
6199+
</para>
6200+
6201+
<para>
61916202
Besides regular &consvars;, scons provides the following
6192-
special variables for each command execution:</para>
6203+
special variables for use in expanding commands:</para>
61936204

61946205
<variablelist>
61956206
<varlistentry>
@@ -6261,45 +6272,39 @@ changed since the target was last built.</para>
62616272
</varlistentry>
62626273
</variablelist>
62636274

6264-
<para>Note that the above variables are reserved
6265-
and may not be assigned to in the &consenv;.</para>
6275+
<para>These names are reserved
6276+
and may not be assigned to or used as &consvars;.</para>
62666277

6267-
<para>For example, given the &consvars;
6268-
<literal>CC='cc'</literal>,
6269-
<literal>targets=['foo']</literal>
6270-
and
6271-
<literal>sources=['foo.c', 'bar.c']</literal>:
6278+
<para>For example, the following builder call:
62726279
</para>
62736280

62746281
<programlisting language="python">
6275-
action='$CC -c -o $TARGET $SOURCES'
6282+
env = Environment(CC='cc')
6283+
env.Command(
6284+
target=['foo'],
6285+
source=['foo.c', 'bar.c'],
6286+
action='@echo $CC -c -o $TARGET $SOURCES'
6287+
)
62766288
</programlisting>
62776289

6278-
<para>would produce the command line:</para>
6290+
<para>would produce the following output:</para>
62796291

62806292
<screen>
62816293
cc -c -o foo foo.c bar.c
62826294
</screen>
62836295

6284-
<para>Variable names may be surrounded by curly braces
6285-
(<emphasis role="bold">{}</emphasis>)
6286-
to separate the name from surrounding characters which
6287-
are not part of the name.
6288-
Within the curly braces, a variable name may use
6289-
Python list subscripting/slicing notation to select one
6290-
or more items from a list.
6291-
In the previous example, the string:
6296+
<para>
6297+
In the previous example, a string
62926298
<code>${SOURCES[1]}</code>
6293-
would produce:</para>
6294-
6295-
<screen>
6296-
bar.c
6297-
</screen>
6299+
would expand to: <computeroutput>bar.c</computeroutput>.
6300+
</para>
62986301

6299-
<para>Additionally, a variable name may
6302+
<para>A variable name may
63006303
have the following
63016304
modifiers appended within the enclosing curly braces
6302-
to access properties of the interpolated string:</para>
6305+
to access properties of the interpolated string.
6306+
These are known as <firstterm>special attributes</firstterm>.
6307+
</para>
63036308

63046309
<simplelist>
63056310
<member><parameter>base</parameter> -
@@ -6378,23 +6383,18 @@ ${SOURCE.rsrcdir} =&gt; /usr/repository/src
63786383
</literallayout>
63796384

63806385
<para>
6381-
Modifiers can be combined, like
6382-
<literal>${TARGET.base.windows}</literal>,
6386+
Some modifiers can be combined, like
63836387
<literal>${TARGET.srcpath.base)</literal>,
63846388
<literal>${TARGET.file.suffix}</literal>, etc.
63856389
</para>
63866390

6387-
<para>Note that curly braces braces may also be used
6388-
to enclose arbitrary Python code to be evaluated.
6389-
(In fact, this is how the above modifiers are substituted,
6390-
they are simply attributes of the Python objects
6391-
that represent &cv-TARGET;, &cv-SOURCES;, etc.)
6391+
<para>The curly brace notation may also be used
6392+
to enclose a Python expression to be evaluated.
63926393
See <xref linkend='python_code_substitution'/> below
6393-
for more thorough examples of
6394-
how this can be used.</para>
6394+
for a description.</para>
63956395

6396-
<para>Lastly, a variable name
6397-
may be a callable Python function
6396+
<para>A variable name
6397+
may also be a Python function
63986398
associated with a
63996399
&consvar; in the environment.
64006400
The function should
@@ -6425,6 +6425,12 @@ def foo(target, source, env, for_signature):
64256425
env=Environment(FOO=foo, BAR="$FOO baz")
64266426
</programlisting>
64276427

6428+
<para>As a reminder, this evaluation happens when
6429+
<literal>$BAR</literal> is actually used in a
6430+
builder action. The value of <literal>env['BAR']</literal>
6431+
will be exactly as it was set: <literal>"$FOO baz"</literal>.
6432+
</para>
6433+
64286434
<para>You can use this feature to pass arguments to a
64296435
Python function by creating a callable class
64306436
that stores one or more arguments in an object,
@@ -6496,19 +6502,20 @@ echo Last build occurred . &gt; $TARGET
64966502
<title>Python Code Substitution</title>
64976503

64986504
<para>
6499-
Any Python code within curly braces
6500-
(<emphasis role="bold">{}</emphasis>)
6501-
and introduced by the variable prefix <literal>$</literal>
6502-
will be evaluated using the Python <function>eval</function> statement,
6503-
with the Python globals set to
6504-
the current environment's set of &consvars;, and the result
6505-
substituted in.
6505+
If a substitutable expression using the notation
6506+
<literal>${something}</literal> does not appear to match one of
6507+
the other substitution patterns,
6508+
it is evaluated as a Python expression.
6509+
This uses Python's <function>eval</function> function,
6510+
with the <parameter>globals</parameter> parameter set to
6511+
the current environment's set of &consvars;,
6512+
and the result substituted in.
65066513
So in the following case:</para>
65076514

65086515
<programlisting language="python">
6509-
env['COND'] = 0
6510-
env.Command('foo.out', 'foo.in',
6511-
'''echo ${COND==1 and 'FOO' or 'BAR'} &gt; $TARGET''')
6516+
env.Command(
6517+
'foo.out', 'foo.in', "echo ${COND==1 and 'FOO' or 'BAR'} &gt; $TARGET"
6518+
)
65126519
</programlisting>
65136520

65146521
<para>the command executed will be either</para>
@@ -6530,7 +6537,7 @@ built, not when the SConscript is being read. So if
65306537
<literal>env['COND']</literal> is changed
65316538
later in the SConscript, the final value will be used.</para>
65326539

6533-
<para>Here's a more interesting example. Note that all of
6540+
<para>Here's a more complete example. Note that all of
65346541
<envar>COND</envar>,
65356542
<envar>FOO</envar>,
65366543
and
@@ -6541,17 +6548,29 @@ separated by spaces.</para>
65416548

65426549
<programlisting language="python">
65436550
env=Environment()
6544-
env['COND'] = 0
6551+
env['COND'] = 1
65456552
env['FOO'] = ['foo1', 'foo2']
65466553
env['BAR'] = 'barbar'
6547-
env.Command('foo.out', 'foo.in',
6548-
'echo ${COND==1 and FOO or BAR} &gt; $TARGET')
6549-
6550-
# Will execute this:
6551-
# echo foo1 foo2 &gt; foo.out
6554+
env.Command(
6555+
'foo.out', 'foo.in', "echo ${COND==1 and FOO or BAR} &gt; $TARGET"
6556+
)
65526557
</programlisting>
65536558

6554-
<para>SCons uses the following rules when converting &consvars; into
6559+
<para>will execute:</para>
6560+
<screen>
6561+
echo foo1 foo2 &gt; foo.out
6562+
</screen>
6563+
6564+
<para>
6565+
In point of fact, Python expression evaluation is
6566+
how the special attributes are substituted:
6567+
they are simply attributes of the Python objects
6568+
that represent &cv-TARGET;, &cv-SOURCES;, etc.,
6569+
which &SCons; passes to <function>eval</function> which
6570+
returns the value.
6571+
</para>
6572+
6573+
<para>&SCons; uses the following rules when converting &consvars; into
65556574
command lines:</para>
65566575

65576576
<variablelist>
@@ -6589,6 +6608,16 @@ contain embedded newline characters.</para>
65896608
</listitem>
65906609
</varlistentry>
65916610
</variablelist>
6611+
6612+
<note><para>
6613+
Use of the Python <function>eval</function> function
6614+
is considered to have security implications, since,
6615+
depending on input sources,
6616+
arbitrary unchecked strings of code can be executed by the Python interpreter.
6617+
Although &SCons; makes use of it in a somewhat restricted context,
6618+
you should be aware of this issue when using the
6619+
<literal>${python-expression-for-subst}</literal> form.
6620+
</para></note>
65926621
</refsect2>
65936622

65946623
<refsect2 id='scanner_objects'>
@@ -6613,8 +6642,7 @@ a Python function that will process
66136642
the Node (file)
66146643
and return a list of File Nodes
66156644
representing the implicit
6616-
dependencies (file names) found in the contents;
6617-
or:
6645+
dependencies (file names) found in the contents.
66186646
</para></listitem>
66196647
<listitem><para>
66206648
a dictionary that maps keys

0 commit comments

Comments
 (0)