Commits

Anonymous committed 405ac4d

Document the necessity of passing in "target" to and "source" to env.subst() calls that want to expand ${TARGET,TARGETS,SOURCE,SOURCES}. Also, speed up the Variable_Method_Caller class.

  • Participants
  • Parent commits 98ce325

Comments (0)

Files changed (3)

 
 '\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .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
 
 '\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
     --  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
 
         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
 
         "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
 
     --  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

src/engine/SCons/Defaults.py

     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'      : {},