From 75a074d126ff285d21033ea39a962023f785089f Mon Sep 17 00:00:00 2001 From: Steven Knight Date: Thu, 31 Jul 2003 19:02:45 +0000 Subject: Don't Split() SConscript file name strings on white space. --- doc/man/scons.1 | 55 ++++++++++++++++++++++++++----- src/CHANGES.txt | 6 ++++ src/RELEASE.txt | 30 ++++++++++++----- src/engine/SCons/Script/SConscript.py | 33 ++++++++++--------- src/engine/SCons/Util.py | 3 -- test/SConscript.py | 62 ++++++++++++++++++++++------------- 6 files changed, 132 insertions(+), 57 deletions(-) diff --git a/doc/man/scons.1 b/doc/man/scons.1 index c2adf48..a0a08d1 100644 --- a/doc/man/scons.1 +++ b/doc/man/scons.1 @@ -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 diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 8c8f08a..f966b79 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -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 diff --git a/src/RELEASE.txt b/src/RELEASE.txt index 3cf87ca..f8c29d5 100644 --- a/src/RELEASE.txt +++ b/src/RELEASE.txt @@ -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 - a 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 diff --git a/src/engine/SCons/Script/SConscript.py b/src/engine/SCons/Script/SConscript.py index 8987908..ee53a63 100644 --- a/src/engine/SCons/Script/SConscript.py +++ b/src/engine/SCons/Script/SConscript.py @@ -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) diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py index 2a96d25..cba61e5 100644 --- a/src/engine/SCons/Util.py +++ b/src/engine/SCons/Util.py @@ -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 diff --git a/test/SConscript.py b/test/SConscript.py index 810017d..7ebffc3 100644 --- a/test/SConscript.py +++ b/test/SConscript.py @@ -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() -- cgit v0.12