Don't Split() SConscript file name strings on white space.
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Thu, 31 Jul 2003 19:02:45 +0000 (19:02 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Thu, 31 Jul 2003 19:02:45 +0000 (19:02 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@754 fdb21ef1-2011-0410-befe-b5e4ea1792b1

doc/man/scons.1
src/CHANGES.txt
src/RELEASE.txt
src/engine/SCons/Script/SConscript.py
src/engine/SCons/Util.py
test/SConscript.py

index c2adf4831e7c31ac16ebf31fb969902b0c6bc8ae..a0a08d1bbeda7d5900c37b7799087a916241ec49 100644 (file)
@@ -4491,20 +4491,53 @@ SetOption('max_drift', 1)
 .EE
 
 .TP
-.RI SConscript( script ", [" exports ", " build_dir ", " src_dir ", " duplicate ])
+.RI SConscript( scripts ", [" exports ", " build_dir ", " src_dir ", " duplicate ])
+.TP
+.RI SConscript(dirs= subdirs ", [name=" script ", " exports ", " build_dir ", " src_dir ", " duplicate ])
 This tells
 .B scons
 to execute
-.I script
-as a SConscript (configuration) file.
+one or more subsidiary SConscript (configuration) files.
+There are two ways to call the
+.BR SConscript ()
+function.
+
+The first way you can call
+.BR SConscript ()
+is to explicitly specify one or more
+.I scripts
+as the first argument.
+A single script may be specified as a string;
+multiple scripts must be specified as a list
+(either explicitly or as created by
+a function like
+.BR Split ()).
+
+The second way you can call
+.BR SConscript ()
+is to specify a list of (sub)directory names
+as a
+.RI dirs= subdirs
+keyword argument.
+In this case,
+.B scons
+will, by default,
+execute a subsidiary configuration file named
+.B SConscript
+in each of the specified directories.
+You may specify a name other than
+.B SConscript
+by supplying an optional
+.RI name= script
+keyword argument.
 
 The optional 
 .I exports
 argument provides a list of variable names or a dictionary of
-named values to export to
-.IR script ". "
+named values to export to the
+.IR script(s) ". "
 These variables are locally exported only to the specified
-.IR script ,
+.IR script(s) ,
 and do not affect the
 global pool of variables used by
 the
@@ -4513,8 +4546,8 @@ function.
 '\"If multiple dirs are provided,
 '\"each script gets a fresh export.
 The subsidiary
-.I script
-file must use the
+.I script(s)
+must use the
 .BR Import ()
 function to import the variables.
 
@@ -4527,6 +4560,7 @@ that would normally be built in the subdirectory in which
 resides should actually
 be built in
 .IR build_dir .
+
 The optional
 .I src_dir
 argument specifies that the
@@ -4534,6 +4568,7 @@ source files from which
 the target files should be built
 can be found in
 .IR src_dir .
+
 By default,
 .B scons
 will link or copy (depending on the platform)
@@ -4571,7 +4606,9 @@ SConscript('subdir/SConscript')
 foo = SConscript('sub/SConscript', exports='env')
 SConscript('dir/SConscript', exports=['env', 'variable'])
 SConscript('src/SConscript', build_dir='build', duplicate=0)
-SConscript('bld/SConscript', src_dir='src', exports='env')
+SConscript('bld/SConscript', src_dir='src', exports='env variable')
+SConscript(dirs=['sub1', 'sub2'])
+SConscript(dirs=['sub3', 'sub4'], name='MySConscript')
 .EE
 
 .TP
index 8c8f08a3b5f464c2e955141e502bd8949a6d9a78..f966b79c7bb95b99e47952f58580ad0cca3f1d28 100644 (file)
@@ -68,6 +68,12 @@ RELEASE 0.XX - XXX
   - Refactor the creation of the Program, *Object and *Library Builders
     so that they're moved out of SCons.Defaults and created on demand.
 
+  - Don't split SConscript file names on white space.
+
+  - Document the SConscript function's "dirs" and "name" keywords.
+
+  - Remove the internal (and superfluous) SCons.Util.argmunge() function.
+
   From Gary Oberbrunner:
 
   - Report the target being built in error messages when building
index 3cf87ca7f659e58394b48d5beaed9792272076bc..f8c29d563089a47731aaacd4e5556105d0c8cf31 100644 (file)
@@ -7,7 +7,7 @@
                             Release Notes
 
 
-This is an alpha release of SCons, a tool for building software (and
+This is an beta release of SCons, a tool for building software (and
 other files).  SCons is implemented in Python, and its "configuration
 files" are actually Python scripts, allowing you to use the full power
 of a real scripting language to solve build problems.  You do not,
@@ -32,19 +32,32 @@ RELEASE 0.XX - XXX
     spelling still works but has been deprecated and generates a
     warning.
 
+  - The SConscript() function no longer splits its first argument on
+    white space into a list of SConscript file names.  You must now
+    explicitly enclose the file names in a list:
+
+        SConscript(['sub1/SConscript', 'sub2/SConscript'])
+
+    Or use the Split() function (or something similar) to create a list:
+
+        SConscript(Split('sub1/SConscript sub2/SConscript'))
+
+    This makes the SConscript() function's handling of file names
+    consistent with the rest of SCons.
+
   Please note the following important changes since release 0.14:
 
   - SCons now tries to verify that Microsoft Visual Studio (including
-    Visual C++) is actually installed before using it, by checking that
-    the program directory exists.  If SCons cannot find your copy of
-    Visual Studio, it is probably because it installed itself itself in
-    default directory that we have not seen before.  If this is the
+    Visual C++) is actually installed before using it, by checking
+    that the program directory exists.  If SCons cannot find your copy
+    of Visual Studio, it is probably because it installed itself in a
+    default directory that we have not seen before.  If this is the
     case, please let us know so that we can update future versions.
 
   SCons is developed with an extensive regression test suite, and a
   rigorous development methodology for continually improving that suite.
   Because of this, SCons is of sufficient quality that you can use it
-  for real work.  The "alpha" status of the release reflects that we
+  for real work.  The "beta" status of the release reflects that we
   still may change interfaces in future releases, which may require
   modifications to your SConscript files.  We strive to hold these
   changes to a minimum.
@@ -143,12 +156,12 @@ RELEASE 0.XX - XXX
       an infinite loop.
 
     - When using SourceSignatures('timestamp'), changes to Python
-      Value() do not cause rebuilds.
+      Value() Nodes do not cause rebuilds.
 
     - No support yet for the following planned command-line options:
 
          -d -e -l --list-actions --list-derived --list-where
-         -o --override -p -r -R --random -w --write-filenames
+         -o --override -p -r -R -w --write-filenames
          -W --warn-undefined-variables
 
 
@@ -164,6 +177,7 @@ With plenty of help from the SCons Development team:
         Chad Austin
         Charles Crain
         Steve Leblanc
+        Gary Oberbrunner
         Anthony Roach
         Greg Spencer
         Christoph Wiedemann
index 89879082343d62590a8592818c53be39927fedef..ee53a63ae78c77b5295030e58a48fd0cdbaef34d 100644 (file)
@@ -91,7 +91,8 @@ def get_calling_namespaces():
 def compute_exports(exports):
     """Compute a dictionary of exports given one of the parameters
     to the Export() function or the exports argument to SConscript()."""
-    exports = SCons.Util.argmunge(exports)
+
+    exports = SCons.Util.Split(exports)
     loc, glob = get_calling_namespaces()
 
     retval = {}
@@ -149,41 +150,43 @@ def Return(*vars):
 # exports.
 
 def GetSConscriptFilenames(ls, kw):
-    files = []
     exports = []
 
     if len(ls) == 0:
         try:
-            dirs = map(str, SCons.Util.argmunge(kw["dirs"]))
+            dirs = kw["dirs"]
         except KeyError:
             raise SCons.Errors.UserError, \
                   "Invalid SConscript usage - no parameters"
 
-        name = kw.get('name', 'SConscript')
+        if not SCons.Util.is_List(dirs):
+            dirs = [ dirs ]
+        dirs = map(str, dirs)
 
-        if kw.get('exports'):
-            exports = SCons.Util.argmunge(kw['exports'])
+        name = kw.get('name', 'SConscript')
 
         files = map(lambda n, name = name: os.path.join(n, name), dirs)
 
     elif len(ls) == 1:
 
-        files = SCons.Util.argmunge(ls[0])
-        if kw.get('exports'):
-            exports = SCons.Util.argmunge(kw['exports'])
+        files = ls[0]
 
     elif len(ls) == 2:
 
-        files   = SCons.Util.argmunge(ls[0])
-        exports = SCons.Util.argmunge(ls[1])
-
-        if kw.get('exports'):
-            exports.extend(SCons.Util.argmunge(kw['exports']))
+        files   = ls[0]
+        exports = SCons.Util.Split(ls[1])
 
     else:
+
         raise SCons.Errors.UserError, \
               "Invalid SConscript() usage - too many arguments"
 
+    if not SCons.Util.is_List(files):
+        files = [ files ]
+
+    if kw.get('exports'):
+        exports.extend(SCons.Util.Split(kw['exports']))
+
     build_dir = kw.get('build_dir')
     if build_dir:
         if len(files) != 1:
@@ -398,7 +401,7 @@ def Export(*vars):
 def Import(*vars):
     try:
         for var in vars:
-            var = SCons.Util.argmunge(var)
+            var = SCons.Util.Split(var)
             for v in var:
                 if v == '*':
                     stack[-1].globals.update(global_exports)
index 2a96d25bc60a2fd34cd748a8fce6b55bb9712f6d..cba61e5ec09a041167a849fe0946cc3ac2b7d4a4 100644 (file)
@@ -619,9 +619,6 @@ def is_Dict(e):
 def is_List(e):
     return type(e) is types.ListType or isinstance(e, UserList.UserList)
 
-def argmunge(arg):
-    return Split(arg)
-
 def Split(arg):
     """This function converts a string or list into a list of strings
     or Nodes.  This makes things easier for users by allowing files to
index 810017da6f0d1585f0edba46b4d5517d0cfc2662..7ebffc3214897c1757431b82fea20a6ebdb281c3 100644 (file)
@@ -28,10 +28,10 @@ import TestSCons
 
 test = TestSCons.TestSCons()
 
-test.write('foo.py', """
-foo = 4""")
+test.write('foo.py', "foo = 4\n")
 
-test.write('SConstruct', """
+
+test.write('SConstruct', """\
 import os
 import foo
 
@@ -46,7 +46,6 @@ x3,x4 = SConscript('SConscript1', "x1 x2")
 assert x3 == "SConscript1 x3"
 assert x4 == "SConscript1 x4"
 
-
 (x3,x4) = SConscript('SConscript2', ["x1","x2"])
 assert x3 == "SConscript2 x3"
 assert x4 == "SConscript2 x4"
@@ -81,8 +80,8 @@ assert x9 == "SConscript6 x9"
 SConscript('SConscript7')
 """)
 
-test.write('SConscript', """
 
+test.write('SConscript', """\
 # os should not be automajically imported:
 assert not globals().has_key("os")
 
@@ -101,7 +100,7 @@ Return("x3 x4")
 """)
 
 
-test.write('SConscript2', """
+test.write('SConscript2', """\
 Import("x1","x2")
 assert x1 == "SConstruct x1"
 assert x2 == "SConstruct x2"
@@ -110,7 +109,8 @@ x4 = "SConscript2 x4"
 Return("x3","x4")
 """)
 
-test.write('SConscript3', """
+
+test.write('SConscript3', """\
 Import("x1 x2")
 assert x1 == "SConstruct x1"
 assert x2 == "SConstruct x2"
@@ -123,11 +123,10 @@ assert x5 == "SConscript31 x5"
 assert x6 == "SConscript31 x6"
 
 Export("x1 x2")
-
-
 """)
 
-test.write('SConscript31', """
+
+test.write('SConscript31', """\
 Import("x1 x2")
 assert x1 == "SConscript3 x1"
 assert x2 == "SConstruct x2"
@@ -138,7 +137,7 @@ Return("x5")
 """)
 
 
-test.write('SConscript4', """
+test.write('SConscript4', """\
 Import("x1", "x2")
 assert x1 == "SConstruct x1"
 assert x2 == "SConstruct x2"
@@ -147,14 +146,15 @@ x2 = "SConscript4 x2"
 Export("x1", "x2")
 """)
 
+
 test.subdir('subdir')
-test.write(['subdir', 'SConscript'], """
+test.write(['subdir', 'SConscript'], """\
 foo = 'subdir/SConscript foo'
 Return('foo')
 """)
 
 
-test.write('SConscript5', """
+test.write('SConscript5', """\
 B = Builder(action = 'B')
 def scan():
     pass
@@ -163,7 +163,7 @@ A = Action("A")
 """)
 
 
-test.write('SConscript6', """
+test.write('SConscript6', """\
 Import("x7 x8")
 assert x7 == "SConstruct x7"
 assert x8 == "SConstruct x8"
@@ -171,18 +171,21 @@ x9 = "SConscript6 x9"
 Return("x9")
 """)
 
-test.write('SConscript7', """
+
+test.write('SConscript7', """\
 result1 = ((1, 3), -4)
 result2 = ((2, 3), -4)
-assert result1 == SConscript('foo/SConscript bar/SConscript')
+assert result1 == SConscript(Split('foo/SConscript bar/SConscript'))
 assert result1 == SConscript(['foo/SConscript', 'bar/SConscript'])
 assert result1 == SConscript([File('foo/SConscript'), File('bar/SConscript')])
-assert result1 == SConscript(dirs = 'foo bar')
+assert result1 == SConscript(dirs = Split('foo bar'))
 assert result1 == SConscript(dirs = ['foo', 'bar'])
-assert result2 == SConscript(dirs = 'foo bar', name = 'subscript')
+assert result2 == SConscript(dirs = Split('foo bar'), name = 'subscript')
 assert result2 == SConscript(dirs = ['foo', 'bar'], name = 'subscript')
 assert result1 == SConscript(dirs = ['foo', Dir('bar')])
 assert result2 == SConscript(dirs = [Dir('foo'), 'bar'], name = 'subscript')
+assert 5 == SConscript('w s/SConscript')
+assert (-4, 5) == SConscript(['bar/SConscript', 'w s/SConscript'])
 
 x1 = 3
 x2 = 2
@@ -191,19 +194,20 @@ assert (3, 2) == SConscript('baz/SConscript', 'x1', exports = 'x2')
 assert (3, 2) == SConscript('baz/SConscript', exports = 'x1 x2')
 """)
 
-fooscript = "x = %d; y = 3; Return('x y')"
-barscript = "x = -4; Return('x')"
+fooscript = "x = %d; y = 3; Return('x y')\n"
+barscript = "x = -4; Return('x')\n"
 
-test.subdir('foo', 'bar', 'baz')
+test.subdir('foo', 'bar', 'baz', 'w s')
 test.write(['foo', 'SConscript'], fooscript % 1)
 test.write(['foo', 'subscript'],  fooscript % 2)
 test.write(['bar', 'SConscript'], barscript)
 test.write(['bar', 'subscript'],  barscript)
-test.write(['baz', 'SConscript'], """
+test.write(['baz', 'SConscript'], """\
 Import("x1 x2")
 result = (x1, x2)
 Return("result")
 """)
+test.write(['w s', 'SConscript'], "x = 5; Return('x')\n")
 
 
 wpath = test.workpath()
@@ -345,4 +349,18 @@ assert y == 'zoom'
 
 test.run(arguments = ".")
 
+# Test white space
+test.subdir('white space')
+test.write("SConstruct", """\
+SConscript('white space/SConscript')
+""")
+
+test.write(['white space', 'SConscript'], """\
+print "`white space/SConscript'"
+""")
+
+test.run(arguments = ".",
+         stdout = test.wrap_stdout(read_str = "`white space/SConscript'\n",
+                                   build_str = "scons: `.' is up to date.\n"))
+
 test.pass_test()