From: stevenknight Date: Wed, 19 Dec 2001 00:22:35 +0000 (+0000) Subject: Bug fixes from Charles Crain. X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=307155b217abac8a762e043ca0c121f8474ad521;p=scons.git Bug fixes from Charles Crain. git-svn-id: http://scons.tigris.org/svn/scons/trunk@163 fdb21ef1-2011-0410-befe-b5e4ea1792b1 --- diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 41a5ba7d..9a112df8 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -13,19 +13,31 @@ RELEASE 0.02 - - Fixed the version comment in the scons.bat (the UNIX geek used # instead of @rem). - - Added support for the Install method (courtesy Charles Crain). + - Fix to setup.py so it doesn't require a sys.argv[1] argument. - - Added support for the BuildDir method (courtesy Charles Crain). + From Charles Crain: - - Added the Export method (courtesy Charles Crain). + - Added support for the Install method. - - Documented CXXFLAGS, CXXCOM, and CPPPATH (courtesy Anthony Roach). + - Added support for the BuildDir method. - - Fixed SCONS_LIB_DIR to work as documented (courtesy Anthony Roach). + - Added the Export method. - - Made Default() accept Nodes as arguments (courtesy Anthony Roach). + - Fix the -C option by delaying setting the top of the FS tree. - - Fix to setup.py so it doesn't require a sys.argv[1] argument. + - Avoid putting the directory path on the libraries in the LIBS + construction variable. + + - Added a GetBuildPath() method to return the full path to the + Node for a specified string. + + From Anthony Roach: + + - Documented CXXFLAGS, CXXCOM, and CPPPATH. + + - Fixed SCONS_LIB_DIR to work as documented. + + - Made Default() accept Nodes as arguments. diff --git a/src/engine/SCons/BuilderTests.py b/src/engine/SCons/BuilderTests.py index 6590daf2..5beee1a9 100644 --- a/src/engine/SCons/BuilderTests.py +++ b/src/engine/SCons/BuilderTests.py @@ -297,7 +297,7 @@ class BuilderTestCase(unittest.TestCase): # to the other module via a direct import. kw['dir'] = SCons.Node.FS.default_fs.Dir('d') contents = apply(b4.get_contents, (), kw) - expect = os.path.normpath("-ld/l1 -ld/l2 -Ld/libX -Id/c -Id/p") + expect = os.path.normpath("-ll1 -ll2 -Ld/libX -Id/c -Id/p") assert contents == expect, contents + " != " + expect def test_name(self): diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py index 303db61d..6a7fcc89 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -127,15 +127,32 @@ class FS: The path argument must be a valid absolute path. """ if path == None: - path = os.getcwd() + self.pathTop = os.getcwd() + else: + self.pathTop = path self.Root = PathDict() - self.Top = self.__doLookup(Dir, path) - self.Top.path = '.' - self.Top.srcpath = '.' - self.Top.path_ = os.path.join('.', '') - self.cwd = self.Top + self.Top = None + + def set_toplevel_dir(self, path): + assert not self.Top, "You can only set the top-level path on an FS object that has not had its File, Dir, or Entry methods called yet." + self.pathTop = path + + def __setTopLevelDir(self): + if not self.Top: + self.Top = self.__doLookup(Dir, self.pathTop) + self.Top.path = '.' + self.Top.srcpath = '.' + self.Top.path_ = os.path.join('.', '') + self.cwd = self.Top + + def __hash__(self): + self.__setTopLevelDir() + return hash(self.Top) def __cmp__(self, other): + self.__setTopLevelDir() + if isinstance(other, FS): + other.__setTopLevelDir() return cmp(self.__dict__, other.__dict__) def __doLookup(self, fsclass, name, directory=None): @@ -206,6 +223,7 @@ class FS: If directory is None, and name is a relative path, then the same applies. """ + self.__setTopLevelDir() if name[0] == '#': directory = self.Top name = os.path.join(os.path.normpath('./'), name[1:]) @@ -216,6 +234,7 @@ class FS: def chdir(self, dir): """Change the current working directory for lookups. """ + self.__setTopLevelDir() if not dir is None: self.cwd = dir @@ -258,6 +277,7 @@ class FS: def BuildDir(self, build_dir, src_dir): """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): diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py index 0f6b8b72..6851e5ec 100644 --- a/src/engine/SCons/Node/FSTests.py +++ b/src/engine/SCons/Node/FSTests.py @@ -372,7 +372,7 @@ class FSTestCase(unittest.TestCase): os.chdir('..') fs3 = SCons.Node.FS.FS() assert fs1 == fs2 - assert fs1 == fs3 + assert fs1 != fs3 # Test comparison of Entry objects e1 = fs3.Entry('cmp/entry') diff --git a/src/engine/SCons/Script.py b/src/engine/SCons/Script.py index 15abb48e..1298a9e4 100644 --- a/src/engine/SCons/Script.py +++ b/src/engine/SCons/Script.py @@ -58,6 +58,7 @@ from SCons.Errors import * import SCons.Sig import SCons.Sig.MD5 from SCons.Taskmaster import Taskmaster +import SCons.Util # # Modules and classes that we don't use directly in this script, but @@ -182,6 +183,14 @@ def Help(text): def BuildDir(build_dir, src_dir): SCons.Node.FS.default_fs.BuildDir(build_dir, src_dir) +def GetBuildPath(files): + nodes = SCons.Util.scons_str2nodes(files, + SCons.Node.FS.default_fs.Entry) + ret = map(str, nodes) + if len(ret) == 1: + return ret[0] + return ret + def Export(**kw): # A convenient shorthand to pass exports to the SConscript function. return kw @@ -361,6 +370,7 @@ def options_init(): def opt_C(opt, arg): try: os.chdir(arg) + SCons.Node.FS.default_fs.set_toplevel_dir(os.getcwd()) except: sys.stderr.write("Could not change directory to 'arg'\n") diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py index b2850c09..1cd51d71 100644 --- a/src/engine/SCons/Util.py +++ b/src/engine/SCons/Util.py @@ -36,7 +36,7 @@ import string import re from UserList import UserList import SCons.Node.FS -import cStringIO +import copy 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. @@ -255,20 +255,77 @@ def find_files(filenames, paths, return nodes +class VarInterpolator: + def __init__(self, dest, src, prefix, suffix): + self.dest = dest + self.src = src + self.prefix = prefix + self.suffix = suffix + def prepareSrc(self, dict): + src = dict[self.src] + if not type(src) is types.ListType and not isinstance(src, UserList): + src = [ src ] + return src + + def generate(self, dict): + if not dict.has_key(self.src): + dict[self.dest] = '' + return + src = self.prepareSrc(dict) + + try: + prefix = str(dict[self.prefix]) + except KeyError: + prefix='' -AUTO_GEN_VARS = ( ( '_LIBFLAGS', - 'LIBS', - 'LIBLINKPREFIX', - 'LIBLINKSUFFIX' ), - ( '_LIBDIRFLAGS', - 'LIBPATH', - 'LIBDIRPREFIX', - 'LIBDIRSUFFIX' ), - ( '_INCFLAGS', - 'CPPPATH', - 'INCPREFIX', - 'INCSUFFIX' ) ) + try: + suffix = str(dict[self.suffix]) + except KeyError: + suffix ='' + + dict[self.dest] = map(lambda x, suff=suffix, pref=prefix: \ + pref + os.path.normpath(str(x)) + suff, + src) + + def instance(self, dir, fs): + return self + +class DirVarInterp(VarInterpolator): + def __init__(self, dest, src, prefix, suffix): + VarInterpolator.__init__(self, dest, src, prefix, suffix) + self.fs = None + self.Dir = None + self.dictInstCache = {} + + 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 instance(self, dir, fs): + try: + ret = self.dictInstCache[(dir, fs)] + except KeyError: + ret = copy.copy(self) + ret.fs = fs + ret.dir = dir + self.dictInstCache[(dir, fs)] = ret + return ret + +AUTO_GEN_VARS = ( VarInterpolator('_LIBFLAGS', + 'LIBS', + 'LIBLINKPREFIX', + 'LIBLINKSUFFIX'), + DirVarInterp('_LIBDIRFLAGS', + 'LIBPATH', + 'LIBDIRPREFIX', + 'LIBDIRSUFFIX' ), + DirVarInterp('_INCFLAGS', + 'CPPPATH', + 'INCPREFIX', + 'INCSUFFIX') ) def autogenerate(dict, fs = SCons.Node.FS.default_fs, dir = None): """Autogenerate the "interpolated" environment variables. @@ -287,28 +344,6 @@ def autogenerate(dict, fs = SCons.Node.FS.default_fs, dir = None): is a string, with the prefix and suffix concatenated.""" - for strVarAuto, strSrc, strPref, strSuff, in AUTO_GEN_VARS: - if not dict.has_key(strSrc): - dict[strVarAuto] = '' - continue - - src = dict[strSrc] - if not type(src) is types.ListType and not isinstance(src, UserList): - src = [ src ] - src = map(lambda x, fs=fs, d=dir: \ - fs.Dir(str(x), directory = d).path, - src) - - try: - prefix = str(dict[strPref]) - except KeyError: - prefix='' - - try: - suffix = str(dict[strSuff]) - except KeyError: - suffix ='' + for interp in AUTO_GEN_VARS: + interp.instance(dir, fs).generate(dict) - dict[strVarAuto] = map(lambda x, suff=suffix, pref=prefix: \ - pref + os.path.normpath(str(x)) + suff, - src) diff --git a/src/engine/SCons/UtilTests.py b/src/engine/SCons/UtilTests.py index 2952fc43..615e29f8 100644 --- a/src/engine/SCons/UtilTests.py +++ b/src/engine/SCons/UtilTests.py @@ -179,7 +179,7 @@ class UtilTestCase(unittest.TestCase): dict = {'LIBS' : [ 'foo', 'bar', 'baz' ], 'LIBLINKPREFIX' : 'foo', 'LIBLINKSUFFIX' : 'bar'} - autogenerate(dict) + autogenerate(dict, dir = SCons.Node.FS.default_fs.Dir('/xx')) assert len(dict['_LIBFLAGS']) == 3, dict('_LIBFLAGS') assert dict['_LIBFLAGS'][0] == 'foofoobar', \ dict['_LIBFLAGS'][0] diff --git a/test/LIBS.py b/test/LIBS.py index dec523df..8dac7be0 100644 --- a/test/LIBS.py +++ b/test/LIBS.py @@ -25,14 +25,54 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import TestSCons +import sys + +if sys.platform == 'win32': + _exe = '.exe' +else: + _exe = '' test = TestSCons.TestSCons() -test.pass_test() #XXX Short-circuit until this is implemented. +foo_exe = test.workpath('subdir/foo' + _exe) test.write('SConstruct', """ +SConscript('subdir/SConscript') +""") + +test.subdir('subdir') + +test.write('subdir/foo.c', r""" +void do_it(); + +int main(void) +{ + do_it(); + return 0; +} +""") + +test.write('subdir/bar.c', r""" +#include + +void do_it() +{ + printf("bar.c\n"); +} +""") + +test.write('subdir/SConscript', r""" +env = Environment(LIBS=['bar'], LIBPATH = [ '#subdir' ]) +env.Library(target='bar', source='bar.c') +env.Program(target='foo', source='foo.c') """) test.run(arguments = '.') +test.run(program=foo_exe, stdout='bar.c\n') + test.pass_test() + + + + diff --git a/test/option--C.py b/test/option--C.py index ffff484f..cb8c01ca 100644 --- a/test/option--C.py +++ b/test/option--C.py @@ -43,27 +43,27 @@ print "SConstruct", os.getcwd() test.write(['sub', 'SConstruct'], """ import os -print "sub/SConstruct", os.getcwd() +print GetBuildPath('..') """) test.write(['sub', 'dir', 'SConstruct'], """ import os -print "sub/dir/SConstruct", os.getcwd() +print GetBuildPath('..') """) test.run(arguments = '-C sub', - stdout = "sub/SConstruct %s\n" % wpath_sub) + stdout = "%s\n" % wpath) test.run(arguments = '-C sub -C dir', - stdout = "sub/dir/SConstruct %s\n" % wpath_sub_dir) + stdout = "%s\n" % wpath_sub) test.run(stdout = "SConstruct %s\n" % wpath) test.run(arguments = '--directory=sub/dir', - stdout = "sub/dir/SConstruct %s\n" % wpath_sub_dir) + stdout = "%s\n" % wpath_sub) test.run(arguments = '-C %s -C %s' % (wpath_sub_dir, wpath_sub), - stdout = "sub/SConstruct %s\n" % wpath_sub) + stdout = "%s\n" % wpath) test.pass_test()