From 9198503d21ac99352629e8d8dfb7c14b11f34401 Mon Sep 17 00:00:00 2001 From: Steven Knight Date: Sat, 29 Dec 2001 08:04:42 +0000 Subject: Add duplicate (defaults to true) option to BuildDir() --- doc/man/scons.1 | 220 ++++++++++++++++++++++++---------- etc/TestCmd.py | 7 +- src/CHANGES.txt | 5 + src/engine/SCons/Node/FS.py | 56 +++++---- src/engine/SCons/Node/FSTests.py | 14 +++ src/engine/SCons/Script/SConscript.py | 37 +++--- src/engine/SCons/Util.py | 23 +++- src/engine/SCons/UtilTests.py | 10 +- test/BuildDir.py | 47 +++++--- test/CPPPATH.py | 33 ++++- test/SConscript.py | 9 ++ 11 files changed, 325 insertions(+), 136 deletions(-) diff --git a/doc/man/scons.1 b/doc/man/scons.1 index 100710f..38b196d 100644 --- a/doc/man/scons.1 +++ b/doc/man/scons.1 @@ -78,23 +78,29 @@ is normally executed in a top-level directory containing a file, specifying the target or targets to be built as command-line arguments. The command -.RS +.IP +.nf scons . -.RE +.PP +.fi will build all target files in or below the current directory .RI ( . ")." -.RS +.IP +.nf scons / -.RE +.PP +.fi will build all target files in or below the root directory (i.e., all files). Specific targets may be supplied: -.RS +.IP +.nf scons foo bar -.RE +.PP +.fi Targets may be omitted from the command line, in which case the targets specified @@ -102,9 +108,11 @@ in the configuration file(s) as .B Default targets will be built: -.RS +.IP +.nf scons -.RE +.PP +.fi Specifying "cleanup" targets in configuration files is not necessary. The @@ -112,12 +120,16 @@ necessary. The flag removes all files necessary to build the specified target: .IP +.nf scons -c . .PP +.fi to remove all target files, or: .IP +.nf scons -c build export .PP +.fi to remove target files under build and export. A subset of a hierarchical tree may be built by @@ -126,9 +138,11 @@ remaining at the top-level directory (where the file lives) and specifying the subdirectory as the target to be built: -.RS +.IP +.nf scons src/subdir -.RE +.PP +.fi .\" or changing directory and invoking scons with the .\" .B -u @@ -151,18 +165,22 @@ supports building multiple targets in parallel via a option that takes, as its argument, the number of simultaneous tasks that may be spawned: -.RS +.IP +.nf scons -j 4 -.RE +.PP +.fi builds four targets in parallel, for example. .\" Values of variables to be passed to the configuration file(s) .\" may be specified on the command line: .\" -.\" .RS +.\" .IP +.\" .nf .\" scons debug=1 . -.\" .RE +.\" .PP +.\" .fi .\" .\" These variables can be used in the configuration file(s) to modify .\" the build in any way. @@ -375,9 +393,11 @@ any out-of-date target files, but do not execute the commands. .\" option. .\" .\" To print the database without performing a build do: -.\" .RS +.\" .IP +.\" .nf .\" scons -p -q -.\" .RE +.\" .PP +.\" .fi .\" .\" .IP "-q, --question" .\" Do not run any commands, or print anything. Just return an exit @@ -469,9 +489,11 @@ A new construction environment is created using the .B Environment function: -.RS +.IP +.nf env = Environment() -.RE +.PP +.fi Build rules are specified by calling builder methods on a construction environment. The arguments to the builder methods are target (a list of @@ -481,15 +503,13 @@ for target or source, then interprets it as a space delimited list of files. The following are examples of calling a builder: -.RS +.IP +.nf env.Program(target = 'bar', source = 'bar.c foo.c') -.RE -.RS env.Program('bar', 'bar.c foo.c') -.RE -.RS env.Program('bar', ['bar.c', 'foo.c']) -.RE +.PP +.fi .B scons provides the following builders: @@ -498,30 +518,33 @@ Builds an object file from one or more C/C++ source files. Source files must have one of the following extensions: .c, .C, .cc, .cpp, .cxx, .c++, .C++. The target object file prefix and suffix (if any) are automatically added. Example: - -.RS +.IP +.nf env.Object(target = 'bar', source = 'bar.c') -.RE +.PP +.fi .IP Program Builds an executable given one or more object files or C/C++ source files. If any C/C++ source files are given, then they will be automatically compiled to object files. The executable prefix and suffix (if any) are automatically added to the target. Example: - -.RS +.IP +.nf env.Program(target = 'bar', source = 'bar.c foo.o') -.RE +.PP +.fi .IP Library Builds a library given one or more object files or C/C++ source files. If any C/C++ source files are given, then they will be automatically compiled to object files. The library prefix and suffix (if any) are automatically added to the target. Example: - -.RS +.IP +.nf env.Library(target = 'bar', source = 'bar.c foo.o') -.RE +.PP +.fi .LP @@ -533,9 +556,11 @@ be specified using the .B Depends method of a construction environment: -.RS +.IP +.nf env.Depends('foo.c', 'foo.h') -.RE +.PP +.fi When .B scons @@ -544,18 +569,22 @@ line. Default targets can be specified using the .B Default function: -.RS +.IP +.nf Default('foo', 'bar', 'baz') -.RE +.PP +.fi A configuration file can specify other configuration files to execute using the .B SConscript function: -.RS +.IP +.nf SConscript('dir/SConscript') -.RE +.PP +.fi A construction environment has an associated dictionary of construction variables that are used by built-in or user-supplied build rules. A number @@ -587,7 +616,28 @@ The list of directories that the C preprocessor will search for include directories. The C/C++ implicit dependency scanner will search these directories for include files. Don't explicitly put include directory arguments in CCFLAGS or CXXFLAGS because the result will be non-portable -and the directories will not be searched by the depedency scanner. +and the directories will not be searched by the depedency scanner. Note: +directory names in CPPPATH will be looked-up relative to the SConscript +directory when they are used in a command. To force +.B scons +to look-up a directory relative to the root of the source tree use #: +.IP +.nf +env.Environment(CPPPATH='#/include') +.PP +.fi +.RS +The directory look-up can also be forced using the +.BR Dir () +function: +.RE +.IP +.nf +include = Dir('include') +env.Environment(CPPPATH=include) +.PP +.fi +.RE .IP LINK The linker. @@ -660,27 +710,31 @@ Construction variables can be retrieved and set using the .B Dictionary method of the construction environment: -.RS +.IP +.nf dict = env.Dictionary() -.RE -.RS dict["CC"] = "cc" -.RE +.PP +.fi Construction variables can also be passed to the construction environment constructor: -.RS +.IP +.nf env = Environment(CC="cc") -.RE +.PP +.fi or when copying a construction environment using the .B Copy method: -.RS +.IP +.nf env2 = env.Copy(CC="cl.exe") -.RE +.PP +.fi .B scons also provides various function not associated with a construction @@ -708,9 +762,11 @@ will be returned by the call to .BR SConscript (). Example: -.RS +.IP +.nf foo = SConscript('subdir/SConscript', "env") -.RE +.PP +.fi .TP .RI Export( vars ) @@ -724,9 +780,11 @@ Multiple variable names can be passed to .BR Export () in a space delimited string or as seperate arguments. Example: -.RS +.IP +.nf Export("env") -.RE +.PP +.fi .TP .RI Import( vars ) @@ -745,9 +803,11 @@ have precedence. Multiple variable names can be passed to .BR Import () in a space delimited string or as seperate arguments. Example: -.RS +.IP +.nf Import("env") -.RE +.PP +.fi .TP .RI Return( vars ) @@ -761,9 +821,11 @@ Multiple variable names can be passed to .BR Return () in a space delimited string or as seperate arguments. Example: -.RS +.IP +.nf Return("foo") -.RE +.PP +.fi .TP .RI Default( targets ) @@ -786,7 +848,7 @@ argument is given to will exit after printing out the help text. .TP -.RI BuildDir( build_dir ", " src_dir ) +.RI BuildDir( build_dir ", " src_dir ", [" duplicate ]) This specifies a build directory to use for all derived files. .I build_dir specifies the build directory to be used for all derived files that would @@ -796,12 +858,38 @@ Multiple build directories can be set up for multiple build variants, for example. .B scons will link or copy (depending on the platform) all the source files into the -build directory, so the build commands will not be modifed if -.BR BuildDir () -is used. +build directory if +.I duplicate +is set to 1 (the default). If +.I duplicate +is set to 0, then +.B scons +will not copy or link any source files, which may cause build problems in +certain situations (e.g. C source files that are generated by the +build). +.IR duplicate =0 +is usually safe, and is always more efficient than +.IR duplicate =1. +.TP +.RI Dir( name ", [" directory ]) +This returns an object that represents a given directory +.IR name . +.I name +can be a relative or absolute path. +.I directory +is an optional directory that will be used as the parent directory. +.TP +.RI File( name ", [" directory ]) +This returns an object that represents a given file +.IR name . +.I name +can be a relative or absolute path. +.I directory +is an optional directory that will be used as the parent directory. + .SH EXTENDING .B scons @@ -860,15 +948,19 @@ The file names of the sources of the build command. For example, given the construction variable CC='cc', targets=['foo'], and sources=['foo.c', 'bar.c']: -.RS +.IP +.nf action='$CC -c -o $TARGET $SOURCES' -.RE +.PP +.fi would produce the command line: -.RS +.IP +.nf cc -c -o foo foo.c bar.c -.RE +.PP +.fi .\" XXX document how to add user defined scanners. diff --git a/etc/TestCmd.py b/etc/TestCmd.py index d09d35d..8df039e 100644 --- a/etc/TestCmd.py +++ b/etc/TestCmd.py @@ -564,8 +564,11 @@ class TestCmd: f = _mode_writable else: f = _mode_non_writable - os.path.walk(top, _walk_chmod, f) - + try: + os.path.walk(top, _walk_chmod, f) + except: + pass # ignore any problems changing modes + def write(self, file, content, mode = 'wb'): """Writes the specified content text (second argument) to the specified file name (first argument). The file name may be diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 52671cb..c84d0cb 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -15,6 +15,11 @@ RELEASE 0.03 - - Search both /usr/lib and /usr/local/lib for scons directories by adding them both to sys.path, with whichever is in sys.prefix first. + From Anthony Roach: + + - Add a "duplicate" keyword argument to BuildDir() that can be set + to prevent linking/copying source files into build directories. + RELEASE 0.02 - Sun, 23 Dec 2001 19:05:09 -0600 diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py index adfd440..98b6b02 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -279,18 +279,20 @@ class FS: name, directory = self.__transformPath(name, directory) return self.__doLookup(Dir, name, directory) - def BuildDir(self, build_dir, src_dir): + def BuildDir(self, build_dir, src_dir, duplicate=1): """Link the supplied build directory to the source directory for purposes of building files.""" self.__setTopLevelDir() - dirSrc = self.Dir(src_dir) - dirBuild = self.Dir(build_dir) - if not dirSrc.is_under(self.Top) or not dirBuild.is_under(self.Top): + if not isinstance(src_dir, SCons.Node.Node): + src_dir = self.Dir(src_dir) + if not isinstance(build_dir, SCons.Node.Node): + build_dir = self.Dir(build_dir) + build_dir.duplicate = duplicate + if not src_dir.is_under(self.Top) or not build_dir.is_under(self.Top): raise UserError, "Both source and build directories must be under top of build tree." - if dirSrc.is_under(dirBuild): + if src_dir.is_under(build_dir): raise UserError, "Source directory cannot be under build directory." - dirBuild.link(dirSrc) - + build_dir.link(src_dir, duplicate) class Entry(SCons.Node.Node): """A generic class for file system entries. This class if for @@ -309,6 +311,7 @@ class Entry(SCons.Node.Node): self.name = name if directory: + self.duplicate = directory.duplicate self.abspath = os.path.join(directory.abspath, name) if str(directory.path) == '.': self.path = name @@ -316,16 +319,18 @@ class Entry(SCons.Node.Node): self.path = os.path.join(directory.path, name) else: self.abspath = self.path = name + self.duplicate = 1 self.path_ = self.path self.abspath_ = self.abspath self.dir = directory self.use_signature = 1 - self.__doSrcpath() + self.__doSrcpath(self.duplicate) - def adjust_srcpath(self): - self.__doSrcpath() + def adjust_srcpath(self, duplicate): + self.__doSrcpath(duplicate) - def __doSrcpath(self): + def __doSrcpath(self, duplicate): + self.duplicate = duplicate if self.dir: if str(self.dir.srcpath) == '.': self.srcpath = self.name @@ -336,7 +341,10 @@ class Entry(SCons.Node.Node): def __str__(self): """A FS node's string representation is its path name.""" - return self.path + if self.duplicate or self.builder: + return self.path + else: + return self.srcpath def __cmp__(self, other): if type(self) != types.StringType and type(other) != types.StringType: @@ -351,7 +359,7 @@ class Entry(SCons.Node.Node): return hash(self.abspath_) def exists(self): - return os.path.exists(self.abspath) + return os.path.exists(str(self)) def current(self): """If the underlying path doesn't exist, we know the node is @@ -411,20 +419,20 @@ class Dir(Entry): self.builder = 1 self._sconsign = None - def __doReparent(self): + def __doReparent(self, duplicate): for ent in self.entries.values(): if not ent is self and not ent is self.dir: - ent.adjust_srcpath() + ent.adjust_srcpath(duplicate) - def adjust_srcpath(self): - Entry.adjust_srcpath(self) - self.__doReparent() + def adjust_srcpath(self, duplicate): + Entry.adjust_srcpath(self, duplicate) + self.__doReparent(duplicate) - def link(self, srcdir): + def link(self, srcdir, duplicate): """Set this directory as the build directory for the supplied source directory.""" self.srcpath = srcdir.path - self.__doReparent() + self.__doReparent(duplicate) def up(self): return self.entries['..'] @@ -526,7 +534,7 @@ class File(Entry): def get_timestamp(self): if self.exists(): - return os.path.getmtime(self.path) + return os.path.getmtime(str(self)) else: return 0 @@ -556,12 +564,12 @@ class File(Entry): if self.env: for scn in self.scanners: if not self.scanned.has_key(scn): - self.add_implicit(scn.scan(self.path, self.env), - scn) + deps = scn.scan(str(self), self.env) + self.add_implicit(deps,scn) self.scanned[scn] = 1 def exists(self): - if not self.created: + if self.duplicate and not self.created: self.created = 1 if self.srcpath != self.path and \ os.path.exists(self.srcpath): diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py index f2130d7..4801dae 100644 --- a/src/engine/SCons/Node/FSTests.py +++ b/src/engine/SCons/Node/FSTests.py @@ -86,6 +86,20 @@ class BuildDirTestCase(unittest.TestCase): assert f1.srcpath == os.path.normpath('src/test1'), f1.srcpath assert f2.srcpath == os.path.normpath('src/test1'), f2.srcpath + fs = SCons.Node.FS.FS() + fs.BuildDir('build/var1', 'src', duplicate=0) + fs.BuildDir('build/var2', 'src') + f1 = fs.File('build/var1/test1') + f1out = fs.File('build/var1/test1.out') + f1out.builder = 1 + f2 = fs.File('build/var2/test1') + assert f1.srcpath == os.path.normpath('src/test1'), f1.srcpath + assert f1out.srcpath == os.path.normpath('src/test1.out'), f1out.srcpath + assert str(f1) == os.path.normpath('src/test1'), str(f1) + assert str(f1out) == os.path.normpath('build/var1/test1.out'), str(f1out) + assert f2.srcpath == os.path.normpath('src/test1'), str(f2) + assert str(f2) == os.path.normpath('build/var2/test1'), str(f2) + # Test to see if file_link() works... test=TestCmd(workdir='') test.subdir('src','build') diff --git a/src/engine/SCons/Script/SConscript.py b/src/engine/SCons/Script/SConscript.py index 924fd29..7085547 100644 --- a/src/engine/SCons/Script/SConscript.py +++ b/src/engine/SCons/Script/SConscript.py @@ -89,22 +89,23 @@ def SConscript(script, exports=[]): # push: stack.append(Frame(exports)) - # call: - if script == "-": - exec sys.stdin in stack[-1].globals - else: - f = SCons.Node.FS.default_fs.File(script) - if f.exists(): - file = open(str(f), "r") - SCons.Node.FS.default_fs.chdir(f.dir) - exec file in stack[-1].globals + try: + # call: + if script == "-": + exec sys.stdin in stack[-1].globals else: - sys.stderr.write("Ignoring missing SConscript '%s'\n" % f.path) - - - # pop: - frame = stack.pop() - SCons.Node.FS.default_fs.chdir(frame.prev_dir) + if not isinstance(script, SCons.Node.Node): + script = SCons.Node.FS.default_fs.File(script) + if script.exists(): + file = open(str(script), "r") + SCons.Node.FS.default_fs.chdir(script.dir) + exec file in stack[-1].globals + else: + sys.stderr.write("Ignoring missing SConscript '%s'\n" % script.path) + finally: + # pop: + frame = stack.pop() + SCons.Node.FS.default_fs.chdir(frame.prev_dir) return frame.retval @@ -122,8 +123,8 @@ def Help(text): print "Use scons -H for help about command-line options." sys.exit(0) -def BuildDir(build_dir, src_dir): - SCons.Node.FS.default_fs.BuildDir(build_dir, src_dir) +def BuildDir(build_dir, src_dir, duplicate=1): + SCons.Node.FS.default_fs.BuildDir(build_dir, src_dir, duplicate) def GetBuildPath(files): nodes = SCons.Util.scons_str2nodes(files, @@ -173,4 +174,6 @@ def BuildDefaultGlobals(): globals['Export'] = Export globals['Import'] = Import globals['Return'] = Return + globals['Dir'] = SCons.Node.FS.default_fs.Dir + globals['File'] = SCons.Node.FS.default_fs.File return globals diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py index 0d05498..262762e 100644 --- a/src/engine/SCons/Util.py +++ b/src/engine/SCons/Util.py @@ -37,6 +37,7 @@ import re from UserList import UserList import SCons.Node.FS import copy +import SCons.Node def scons_str2nodes(arg, node_factory=SCons.Node.FS.default_fs.File): """This function converts a string or list into a list of Node instances. @@ -199,7 +200,7 @@ def scons_subst_list(strSubst, locals, globals): n = 1 # Tokenize the original string... - strSubst = _space_sep.sub('\0', strSubst) + strSubst = _space_sep.sub('\0', str(strSubst)) # Now, do the substitution while n != 0: @@ -266,7 +267,14 @@ class VarInterpolator: src = dict[self.src] if not type(src) is types.ListType and not isinstance(src, UserList): src = [ src ] - return map(lambda x, d=dict: scons_subst(x, {}, d), src) + + def prepare(x, dict=dict): + if isinstance(x, SCons.Node.Node): + return x + else: + return scons_subst(x, {}, dict) + + return map(prepare, src) def generate(self, dict): if not dict.has_key(self.src): @@ -300,9 +308,14 @@ class DirVarInterp(VarInterpolator): def prepareSrc(self, dict): src = VarInterpolator.prepareSrc(self, dict) - return map(lambda x, fs=self.fs, d=self.dir: \ - fs.Dir(str(x), directory = d).path, - src) + + def prepare(x, self=self): + if not isinstance(x, SCons.Node.Node): + return self.fs.Dir(str(x), directory=self.dir) + else: + return x + + return map(prepare, src) def instance(self, dir, fs): try: diff --git a/src/engine/SCons/UtilTests.py b/src/engine/SCons/UtilTests.py index 9eebc85..a7c9e70 100644 --- a/src/engine/SCons/UtilTests.py +++ b/src/engine/SCons/UtilTests.py @@ -165,9 +165,10 @@ class UtilTestCase(unittest.TestCase): test = TestCmd.TestCmd(workdir = '') test.write('./foo', 'Some file\n') fs = SCons.Node.FS.FS(test.workpath("")) + os.chdir(test.workpath("")) # FS doesn't like the cwd to be something other than it's root node_derived = fs.File(test.workpath('./bar/baz')) node_derived.builder_set(1) # Any non-zero value. - paths = map(lambda x, fs=fs: fs.Dir(x), ['.', './bar']) + paths = map(fs.Dir, ['.', './bar']) nodes = find_files(['foo', 'baz'], paths, fs.File) file_names = map(str, nodes) file_names = map(os.path.normpath, file_names) @@ -188,12 +189,13 @@ class UtilTestCase(unittest.TestCase): assert dict['_LIBFLAGS'][2] == 'foobazbar', \ dict['_LIBFLAGS'][2] - dict = {'CPPPATH' : [ 'foo', 'bar', 'baz', '$FOO/bar' ], + blat = SCons.Node.FS.default_fs.File('blat') + dict = {'CPPPATH' : [ 'foo', 'bar', 'baz', '$FOO/bar', blat], 'INCPREFIX' : 'foo', 'INCSUFFIX' : 'bar', 'FOO' : 'baz' } autogenerate(dict, dir = SCons.Node.FS.default_fs.Dir('/xx')) - assert len(dict['_INCFLAGS']) == 4, dict['_INCFLAGS'] + assert len(dict['_INCFLAGS']) == 5, dict['_INCFLAGS'] assert dict['_INCFLAGS'][0] == os.path.normpath('foo/xx/foobar'), \ dict['_INCFLAGS'][0] assert dict['_INCFLAGS'][1] == os.path.normpath('foo/xx/barbar'), \ @@ -203,6 +205,8 @@ class UtilTestCase(unittest.TestCase): assert dict['_INCFLAGS'][3] == os.path.normpath('foo/xx/baz/barbar'), \ dict['_INCFLAGS'][3] + assert dict['_INCFLAGS'][4] == os.path.normpath('fooblatbar'), \ + dict['_INCFLAGS'][4] if __name__ == "__main__": suite = unittest.makeSuite(UtilTestCase, 'test_') diff --git a/test/BuildDir.py b/test/BuildDir.py index 8f7c149..ef11760 100644 --- a/test/BuildDir.py +++ b/test/BuildDir.py @@ -36,17 +36,29 @@ else: test = TestSCons.TestSCons() -foo1 = test.workpath('build/var1/foo1' + _exe) -foo2 = test.workpath('build/var1/foo2' + _exe) -foo3 = test.workpath('build/var2/foo1' + _exe) -foo4 = test.workpath('build/var2/foo2' + _exe) +foo11 = test.workpath('build', 'var1', 'foo1' + _exe) +foo12 = test.workpath('build', 'var1', 'foo2' + _exe) +foo21 = test.workpath('build', 'var2', 'foo1' + _exe) +foo22 = test.workpath('build', 'var2', 'foo2' + _exe) +foo31 = test.workpath('build', 'var3', 'foo1' + _exe) +foo32 = test.workpath('build', 'var3', 'foo2' + _exe) test.write('SConstruct', """ -BuildDir('build/var1', 'src') -BuildDir('build/var2', 'src') -SConscript('build/var1/SConscript') -SConscript('build/var2/SConscript') -""") +src = Dir('src') +var2 = Dir('build/var2') +var3 = Dir('build/var3') + +BuildDir('build/var1', src) +BuildDir(var2, src) +BuildDir(var3, src, duplicate=0) + +env = Environment() +SConscript('build/var1/SConscript', "env") +SConscript('build/var2/SConscript', "env") + +env = Environment(CPPPATH=src) +SConscript('build/var3/SConscript', "env") +""") test.subdir('src') test.write('src/SConscript', """ @@ -62,8 +74,7 @@ def buildIt(target, source, env): f2.close() f1.close() return 0 - -env = Environment() +Import("env") env.Command(target='f2.c', source='f2.in', action=buildIt) env.Program(target='foo2', source='f2.c') env.Program(target='foo1', source='f1.c') @@ -103,9 +114,15 @@ test.write('src/f2.h', r""" test.run(arguments = '.') -test.run(program = foo1, stdout = "f1.c\n") -test.run(program = foo2, stdout = "f2.c\n") -test.run(program = foo3, stdout = "f1.c\n") -test.run(program = foo4, stdout = "f2.c\n") +test.run(program = foo11, stdout = "f1.c\n") +test.run(program = foo12, stdout = "f2.c\n") +test.run(program = foo21, stdout = "f1.c\n") +test.run(program = foo22, stdout = "f2.c\n") +test.run(program = foo31, stdout = "f1.c\n") +test.run(program = foo32, stdout = "f2.c\n") + +# Make sure we didn't duplicate the source files in build/var3. +test.fail_test(os.path.exists(test.workpath('build', 'var3', 'f1.c'))) +test.fail_test(os.path.exists(test.workpath('build', 'var3', 'f2.in'))) test.pass_test() diff --git a/test/CPPPATH.py b/test/CPPPATH.py index fb21426..af7bdd8 100644 --- a/test/CPPPATH.py +++ b/test/CPPPATH.py @@ -35,8 +35,9 @@ else: prog = 'prog' + _exe subdir_prog = os.path.join('subdir', 'prog' + _exe) +variant_prog = os.path.join('variant', 'prog' + _exe) -args = prog + ' ' + subdir_prog +args = prog + ' ' + subdir_prog + ' ' + variant_prog test = TestSCons.TestSCons() @@ -47,6 +48,11 @@ env = Environment(CPPPATH = ['include']) obj = env.Object(target='prog', source='subdir/prog.c') env.Program(target='prog', source=obj) SConscript('subdir/SConscript', "env") + +BuildDir('variant', 'subdir', 0) +include = Dir('include') +env = Environment(CPPPATH=[include]) +SConscript('variant/SConscript', "env") """) test.write(['subdir', 'SConscript'], """ @@ -93,7 +99,7 @@ r""" -test.run(arguments = args, stderr = None) +test.run(arguments = args) test.run(program = test.workpath(prog), stdout = "subdir/prog.c\ninclude/foo.h 1\ninclude/bar.h 1\n") @@ -101,9 +107,13 @@ test.run(program = test.workpath(prog), test.run(program = test.workpath(subdir_prog), stdout = "subdir/prog.c\nsubdir/include/foo.h 1\nsubdir/include/bar.h 1\n") -test.up_to_date(arguments = args) +test.run(program = test.workpath(variant_prog), + stdout = "subdir/prog.c\ninclude/foo.h 1\ninclude/bar.h 1\n") +# Make sure we didn't duplicate the source file in the variant subdirectory. +test.fail_test(os.path.exists(test.workpath('variant', 'prog.c'))) +test.up_to_date(arguments = args) test.unlink('include/foo.h') test.write('include/foo.h', @@ -120,8 +130,13 @@ test.run(program = test.workpath(prog), test.run(program = test.workpath(subdir_prog), stdout = "subdir/prog.c\nsubdir/include/foo.h 1\nsubdir/include/bar.h 1\n") -test.up_to_date(arguments = args) +test.run(program = test.workpath(variant_prog), + stdout = "subdir/prog.c\ninclude/foo.h 2\ninclude/bar.h 1\n") +# Make sure we didn't duplicate the source file in the variant subdirectory. +test.fail_test(os.path.exists(test.workpath('variant', 'prog.c'))) + +test.up_to_date(arguments = args) test.unlink('include/bar.h') @@ -130,7 +145,7 @@ r""" #define BAR_STRING "include/bar.h 2\n" """) -test.run(arguments = prog) +test.run(arguments = args) test.run(program = test.workpath(prog), stdout = "subdir/prog.c\ninclude/foo.h 2\ninclude/bar.h 2\n") @@ -138,6 +153,12 @@ test.run(program = test.workpath(prog), test.run(program = test.workpath(subdir_prog), stdout = "subdir/prog.c\nsubdir/include/foo.h 1\nsubdir/include/bar.h 1\n") -test.up_to_date(arguments = prog) +test.run(program = test.workpath(variant_prog), + stdout = "subdir/prog.c\ninclude/foo.h 2\ninclude/bar.h 2\n") + +# Make sure we didn't duplicate the source file in the variant subdirectory. +test.fail_test(os.path.exists(test.workpath('variant', 'prog.c'))) + +test.up_to_date(arguments = args) test.pass_test() diff --git a/test/SConscript.py b/test/SConscript.py index 5172040..496624d 100644 --- a/test/SConscript.py +++ b/test/SConscript.py @@ -59,6 +59,10 @@ Import("x1"," x2") assert x1 == "SConscript4 x1" assert x2 == "SConscript4 x2" +subdir = Dir('subdir') +script = File('SConscript', subdir) +foo = SConscript(script) +assert foo == "subdir/SConscript foo" """) test.write('SConscript', """ @@ -128,6 +132,11 @@ x2 = "SConscript4 x2" Export("x1", "x2") """) +test.subdir('subdir') +test.write(['subdir', 'SConscript'], """ +foo = 'subdir/SConscript foo' +Return('foo') +""") wpath = test.workpath() -- cgit v0.12