Document the necessity of passing in "target" to and "source" to env.subst() calls...
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Wed, 21 Sep 2005 13:02:57 +0000 (13:02 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Wed, 21 Sep 2005 13:02:57 +0000 (13:02 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@1347 fdb21ef1-2011-0410-befe-b5e4ea1792b1

doc/man/scons.1
src/RELEASE.txt
src/engine/SCons/Defaults.py

index 14a0bf2e7774517ba6c8b5e6f04dd4713946d6b6..cf60e6c72fc7520cc8f7a96ae25c51c72b61d026 100644 (file)
@@ -4283,15 +4283,71 @@ env.SourceCode('no_source.c', None)
 
 '\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .TP
-.RI env.subst( string )
+.RI env.subst( string ", [" raw ", " target ", " source ", " conv ])
 Performs construction variable interpolation
 on the specified string argument.
 
+By default,
+any
+.B $(
+and
+.B $)
+will be stripped from the returned string.
+The optional
+.I raw
+target may be set to
+.B 1
+if you want to preserve these,
+although there is usually
+no reason to do this.
+
+The optional
+.I target
+and
+.I source
+keyword arguments
+must be set to lists of
+target and source nodes, respectively,
+if you want the
+.BR $TARGET ,
+.BR $TARGETS ,
+.BR $SOURCE
+and
+.BR $SOURCES
+to be available for expansion.
+This is usually necessary if you are
+calling
+.BR env.subst ()
+from within a Python function used
+as an SCons action.
+
+By default,
+all returned values are converted
+to their string representation.
+The optional
+.I conv
+argument
+may specify a conversion function
+that will be used in place of
+the default.
+For example, if you want Python objects
+(including SCons Nodes)
+to be returned as Python objects,
+you can use the Python
+.B lambda
+idiom to pass in an unnamed function
+that simply returns its unconverted argument.
+
 .ES
 print env.subst("The C compiler is: $CC")
 
 def compile(target, source, env):
-    sourceDir = env.subst("${SOURCE.srcdir}")
+    sourceDir = env.subst("${SOURCE.srcdir}",
+                          target=target,
+                          source=source)
+
+source_nodes = env.subst('$EXPAND_TO_NODELIST',
+                         conv=lambda x: x)
 .EE
 
 '\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
index a6b10c3c00e62842edbabb003165329ccba3c51a..7e61b616d3606a988131978694bffc4340f74b2c 100644 (file)
@@ -31,12 +31,12 @@ RELEASE 0.97 - XXX
     --  DIRECTORY TREES ARE NO LONGER AUTOMATICALLY SCANNED FOR CHANGES
 
         Custom builders and Command() calls that accept directories as
-        source arguments no longer scan entire on-disk directory trees
-        by default.  This means that their targets will not be
-        automatically rebuilt if a file changes on disk, and SCons does
-        *not* already know about.  Note that the targets will still be
-        rebuilt correctly if a file changes that SCons already knows
-        about due to a Builder or other call.
+        source arguments no longer scan entire on-disk directory trees by
+        default.  This means that their targets will not be automatically
+        rebuilt if a file changes on disk *unless* SCons already knows
+        about the file from a specific Builder or File() call.  Note that
+        the targets will still be rebuilt correctly if a file changes
+        that SCons already knows about due to a Builder or other call.
 
         The existing behavior of scanning on-disk directory trees for
         any changed file can be maintained by passing the new DirScanner
@@ -77,12 +77,12 @@ RELEASE 0.97 - XXX
 
         in any SConscript file.
 
-        If you are using the Repository feature, are not already using
-        the SConsignFile() function in your build, you *must* add
-        SConsignFile(None) to your build to keep interoperating with an
-        existing Repository that uses the old behavior of a .sconsign
-        file in each directory.  Alternatively, you can rebuild the
-        Repository with the new default behavior.
+        If you are using the Repository feature, and are not already
+        using the SConsignFile() function in your build, you *must*
+        add "SConsignFile(None)" to your build configuration to keep
+        interoperating with an existing Repository that uses the old
+        behavior of a .sconsign file in each directory.  Alternatively,
+        you can rebuild the Repository with the new default behavior.
 
     --  OTHER SIGNATURE CHANGES WILL CAUSE LIKELY REBUILDS AFTER UPGRADE
 
@@ -186,6 +186,26 @@ RELEASE 0.97 - XXX
         "sconsign.1" man pages on UNIX and Linux systems.  A
         new --no-install-man
 
+    --  env.subst() NO LONGER EXPANDS $TARGET, $SOURCES, etc. BY DEFAULT
+
+        Calls to the env.subst() method to interpolate construction
+        variables in strings no longer automatically expand the special
+        variables $TARGET, $TARGETS, $SOURCE and $SOURCES.  The keyword
+        variables "target" and "source" must now be set to the lists
+        of target and source files to be used in expansion of those
+        variables, when desired.
+
+        This is most likely necessary for any env.subst() calls within
+        a Python function being used as an SCons action for a Builder:
+
+            def build_it(env, target, source):
+                env.subst('$STRING', target=targets, source=sources)
+            MyBuilder = Builder(action=build_it)
+
+        The "target" and "source" keyword arguments are backwards
+        compatible and can be added to SConscript files without breaking
+        builds on systems using older SCons releases.
+
     --  ParseConfig() METHOD ADDS LIBRARY FILE NAMES TO THE $LIBS VARIABLE
 
         The ParseConfig() method now adds library file names returned
@@ -218,20 +238,21 @@ RELEASE 0.97 - XXX
 
     --  BUILDERS RETURN A LIST-LIKE OBJECT, NOT A REGULAR LIST
 
-        Builders calls now return an object that behaves like a list
+        Builder calls now return an object that behaves like a list
         (and which provides some other functionality), not an underlying
         Python list.  In general, this should not cause any problems,
         although it introduces a subtle change in the following behavior:
 
                 obj += env.Object('foo.c')
 
-        If "obj" is a list, Python will no longer update the "obj" in
-        place, because the return value from env.Object() is no longer
-        the same type.  Python will instead allocate a new object and
-        assign the local variable "obj" to it.  If "obj" is defined in
-        an SConscript file that calls another SConscript file containing
-        the above code, "obj" in the first SConscript file will not
-        contain the objects.
+        If "obj" is a regular Python list, Python will no longer update
+        the "obj" in place, because the return value from env.Object()
+        is no longer the same type.  Python will instead allocate a
+        new object and assign the local variable "obj" to it.  If "obj"
+        is defined in an SConscript file that calls another SConscript
+        file containing the above code, "obj" in the first SConscript
+        file will not contain the object file nodes created by the
+        env.Object() call.
 
         You can guarantee that a list will be updated in place regardless
         of which SConscript file defines it and which adds to it by
index c1b9d3f4afb1df2999c182636d32067250a33f9d..5c9d5e7eb22a026733777c21f47305927e7de21c 100644 (file)
@@ -332,17 +332,15 @@ class Variable_Method_Caller:
     def __call__(self, *args, **kw):
         try: 1/0
         except ZeroDivisionError: frame = sys.exc_info()[2].tb_frame
-        variable = None
+        variable = self.variable
         while frame:
-            try:
-                variable = frame.f_locals[self.variable]
-            except KeyError:
-                pass
+            if frame.f_locals.has_key(variable):
+                v = frame.f_locals[variable]
+                if v:
+                    method = getattr(v, self.method)
+                    return apply(method, args, kw)
             frame = frame.f_back
-        if variable is None:
-            return None
-        method = getattr(variable, self.method)
-        return apply(method, args, kw)
+        return None
 
 ConstructionEnvironment = {
     'BUILDERS'      : {},