From: stevenknight Date: Mon, 16 Feb 2004 06:09:44 +0000 (+0000) Subject: Add AppendUnique() and PrependUnique() Environment methods. Fix using the qt Tool... X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=94eae19906b2cd336db69f2ff67b00fa61cc4f4a;p=scons.git Add AppendUnique() and PrependUnique() Environment methods. Fix using the qt Tool from a copied construction environment. git-svn-id: http://scons.tigris.org/svn/scons/trunk@899 fdb21ef1-2011-0410-befe-b5e4ea1792b1 --- diff --git a/doc/man/scons.1 b/doc/man/scons.1 index f5c0a705..0b0756ad 100644 --- a/doc/man/scons.1 +++ b/doc/man/scons.1 @@ -2033,6 +2033,24 @@ before: /foo:/biz after: /biz:/foo/bar:/foo .EE +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI env.AppendUnique( key = val ", [...])" +Appends the specified keyword arguments +to the end of construction variables in the environment. +If the Environment does not have +the specified construction variable, +it is simply added to the environment. +If the construction variable being appended to is a list, +then any value(s) that already exist in the +construction variable will +.I not +be added again to the list. + +.ES +env.AppendUnique(CCFLAGS = '-g', FOO = ['foo.yyy']) +.EE + '\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .TP env.BitKeeper() @@ -2939,6 +2957,24 @@ before: /biz:/foo after: /foo/bar:/foo:/biz .EE +'\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.TP +.RI env.AppendUnique( key = val ", [...])" +Appends the specified keyword arguments +to the beginning of construction variables in the environment. +If the Environment does not have +the specified construction variable, +it is simply added to the environment. +If the construction variable being appended to is a list, +then any value(s) that already exist in the +construction variable will +.I not +be added again to the list. + +.ES +env.PrependUnique(CCFLAGS = '-g', FOO = ['foo.yyy']) +.EE + '\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .TP env.RCS() diff --git a/src/CHANGES.txt b/src/CHANGES.txt index e6c3b536..e75d50da 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -173,6 +173,15 @@ RELEASE 0.95 - XXX - Save memory at build time by allowing Nodes to delete their build environments after they've been built. + - Add AppendUnique() and PrependUnique() Environment methods, which + add values to construction variables like Append() and Prepend() + do, but suppress any duplicate elements in the list. + + - Allow the 'qt' tool to still be used successfully from a copied + Environment. The include and library directories previously ended up + having the same string re-appended to the end, yielding an incorrect + path name. + From Vincent Risi: - Add support for the bcc32, ilink32 and tlib Borland tools. diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py index 46897ef9..900b1e1f 100644 --- a/src/engine/SCons/Environment.py +++ b/src/engine/SCons/Environment.py @@ -454,6 +454,31 @@ class Base: self._dict[envname][name] = nv + def AppendUnique(self, **kw): + """Append values to existing construction variables + in an Environment, if they're not already there. + """ + kw = our_deepcopy(kw) + for key, val in kw.items(): + if not self._dict.has_key(key): + self._dict[key] = val + elif SCons.Util.is_Dict(self._dict[key]) and \ + SCons.Util.is_Dict(val): + self._dict[key].update(val) + elif SCons.Util.is_List(val): + dk = self._dict[key] + if not SCons.Util.is_List(dk): + dk = [dk] + val = filter(lambda x, dk=dk: x not in dk, val) + self._dict[key] = dk + val + else: + dk = self._dict[key] + if SCons.Util.is_List(dk): + if not val in dk: + self._dict[key] = dk + val + else: + self._dict[key] = self._dict[key] + val + def Copy(self, tools=None, toolpath=[], **kw): """Return a copy of a construction Environment. The copy is like a Python "deep copy"--that is, independent @@ -623,6 +648,31 @@ class Base: self._dict[envname][name] = nv + def PrependUnique(self, **kw): + """Append values to existing construction variables + in an Environment, if they're not already there. + """ + kw = our_deepcopy(kw) + for key, val in kw.items(): + if not self._dict.has_key(key): + self._dict[key] = val + elif SCons.Util.is_Dict(self._dict[key]) and \ + SCons.Util.is_Dict(val): + self._dict[key].update(val) + elif SCons.Util.is_List(val): + dk = self._dict[key] + if not SCons.Util.is_List(dk): + dk = [dk] + val = filter(lambda x, dk=dk: x not in dk, val) + self._dict[key] = val + dk + else: + dk = self._dict[key] + if SCons.Util.is_List(dk): + if not val in dk: + self._dict[key] = val + dk + else: + self._dict[key] = val + dk + def Replace(self, **kw): """Replace existing construction variables in an Environment with new construction variables and/or values. diff --git a/src/engine/SCons/EnvironmentTests.py b/src/engine/SCons/EnvironmentTests.py index f81a1027..0887ae33 100644 --- a/src/engine/SCons/EnvironmentTests.py +++ b/src/engine/SCons/EnvironmentTests.py @@ -587,9 +587,9 @@ class EnvironmentTestCase(unittest.TestCase): RDirs=RDirs) flags = env.subst_list('$_LIBFLAGS', 1)[0] assert len(flags) == 3, flags - assert flags[0] == 'foofoobar', \ + assert flags[0] == 'foobar', \ flags[0] - assert flags[1] == 'foobarbar', \ + assert flags[1] == 'foobar', \ flags[1] assert flags[2] == 'foobazbar', \ flags[2] @@ -611,7 +611,7 @@ class EnvironmentTestCase(unittest.TestCase): flags[2] assert flags[3] == os.path.normpath('foo'), \ flags[3] - assert flags[4] == os.path.normpath('xx/baz/barbar'), \ + assert flags[4] == os.path.normpath('xx/baz/bar'), \ flags[4] assert flags[5] == os.path.normpath('foo'), \ flags[5] @@ -635,7 +635,7 @@ class EnvironmentTestCase(unittest.TestCase): flags[2] assert flags[3] == os.path.normpath('foo'), \ flags[3] - assert flags[4] == os.path.normpath('xx/baz/barbar'), \ + assert flags[4] == os.path.normpath('xx/baz/bar'), \ flags[4] assert flags[5] == os.path.normpath('foo'), \ flags[5] @@ -900,6 +900,30 @@ class EnvironmentTestCase(unittest.TestCase): assert(env1['ENV']['PATH'] == r'C:\dir\num\one;C:\dir\num\two;C:\dir\num\three') assert(env1['MYENV']['MYPATH'] == r'C:\mydir\num\two;C:\mydir\num\three;C:\mydir\num\one') + def test_AppendUnique(self): + """Test appending to unique values to construction variables + + This strips values that are already present when lists are + involved.""" + env = Environment(AAA1 = 'a1', + AAA2 = 'a2', + AAA3 = 'a3', + BBB1 = ['b1'], + BBB2 = ['b2'], + BBB3 = ['b3']) + env.AppendUnique(AAA1 = 'a1', + AAA2 = ['a2'], + AAA3 = ['a3', 'b', 'c', 'a3'], + BBB1 = 'b1', + BBB2 = ['b2'], + BBB3 = ['b3', 'c', 'd', 'b3']) + assert env['AAA1'] == 'a1a1', env['AAA1'] + assert env['AAA2'] == ['a2'], env['AAA2'] + assert env['AAA3'] == ['a3', 'b', 'c'], env['AAA3'] + assert env['BBB1'] == ['b1'], env['BBB1'] + assert env['BBB2'] == ['b2'], env['BBB2'] + assert env['BBB3'] == ['b3', 'c', 'd'], env['BBB3'] + def test_Copy(self): """Test construction Environment copying @@ -1189,6 +1213,30 @@ class EnvironmentTestCase(unittest.TestCase): assert(env1['ENV']['PATH'] == r'C:\dir\num\three;C:\dir\num\two;C:\dir\num\one') assert(env1['MYENV']['MYPATH'] == r'C:\mydir\num\one;C:\mydir\num\three;C:\mydir\num\two') + def test_PrependUnique(self): + """Test prepending unique values to construction variables + + This strips values that are already present when lists are + involved.""" + env = Environment(AAA1 = 'a1', + AAA2 = 'a2', + AAA3 = 'a3', + BBB1 = ['b1'], + BBB2 = ['b2'], + BBB3 = ['b3']) + env.PrependUnique(AAA1 = 'a1', + AAA2 = ['a2'], + AAA3 = ['a3', 'b', 'c', 'a3'], + BBB1 = 'b1', + BBB2 = ['b2'], + BBB3 = ['b3', 'b', 'c', 'b3']) + assert env['AAA1'] == 'a1a1', env['AAA1'] + assert env['AAA2'] == ['a2'], env['AAA2'] + assert env['AAA3'] == ['b', 'c', 'a3'], env['AAA3'] + assert env['BBB1'] == ['b1'], env['BBB1'] + assert env['BBB2'] == ['b2'], env['BBB2'] + assert env['BBB3'] == ['b', 'c', 'b3'], env['BBB3'] + def test_Replace(self): """Test replacing construction variables in an Environment diff --git a/src/engine/SCons/Tool/qt.py b/src/engine/SCons/Tool/qt.py index 4be7a654..9969e024 100644 --- a/src/engine/SCons/Tool/qt.py +++ b/src/engine/SCons/Tool/qt.py @@ -210,9 +210,9 @@ def generate(env): env['LIBEMITTER'] = _Automoc('StaticObject', uicDeclBld,mocFromHBld,mocFromCppBld) # Of course, we need to link against the qt libraries - env.Append(CPPPATH=os.path.join('$QTDIR', 'include')) - env.Append(LIBPATH=os.path.join('$QTDIR', 'lib')) - env.Append(LIBS='$QT_LIB') + env.AppendUnique(CPPPATH=[os.path.join('$QTDIR', 'include')]) + env.AppendUnique(LIBPATH=[os.path.join('$QTDIR', 'lib')]) + env.AppendUnique(LIBS=['$QT_LIB']) def exists(env): return _detect(env) diff --git a/test/QT.py b/test/QT.py index 0a2505e2..3eb5af46 100644 --- a/test/QT.py +++ b/test/QT.py @@ -126,7 +126,7 @@ QT_MOC = '%s %s' % (python, test.workpath('qt','bin','mymoc.py')) QT_UIC = '%s %s' % (python, test.workpath('qt','bin','myuic.py')) ############################################################################## -# 4 test cases with 4 different operation modes +# Test cases with different operation modes def createSConstruct(test,place): test.write(place, """ @@ -148,7 +148,7 @@ Export("env") SConscript( sconscript ) """ % (QT, QT_LIB, QT_MOC, QT_UIC)) -test.subdir( 'work1', 'work2', 'work3', 'work4', 'work5' ) +test.subdir( 'work1', 'work2', 'work3', 'work4', 'work5', 'work6' ) ############################################################################## # 1. create a moc file from a header file. @@ -335,15 +335,45 @@ if not MYLIB_IMPL: print test.stdout() test.fail_test() +############################################################################## +# 5. Test creation from a copied environment. + +createSConstruct(test, ['work5', 'SConstruct']) +test.write( ['work5', 'SConscript'], """ +Import("env") +env = env.Copy(tools=['qt']) +env.Program('main', 'main.cpp', CXXFLAGS=['-g']) +""") -# look if qt is installed, and try out all builders +test.write(['work5', 'main.cpp'], r""" +#include "foo5.h" +int main() { foo5(); return 0; } +""") + +test.write(['qt', 'include', 'foo5.h'], """\ +#include +void +foo5(void) +{ + printf("qt/include/foo5.h\\n"); +} +""") + +test.run(chdir='work5') + +main_exe = 'main' + _exe +test.run(program = test.workpath('work5', main_exe), + stdout = 'qt/include/foo5.h\n') + +############################################################################## +# 6. look if qt is installed, and try out all builders if os.environ.get('QTDIR', None): QTDIR=os.environ['QTDIR'] - test.write( ['work5', 'SConstruct'],""" + test.write( ['work6', 'SConstruct'],""" import os dummy_env = Environment() ENV = dummy_env['ENV'] @@ -379,11 +409,11 @@ env.Program('test_realqt', ['mocFromCpp.cpp', 'main.cpp']) """) - test.write( ['work5', 'mocFromCpp.h'],""" + test.write( ['work6', 'mocFromCpp.h'],""" void mocFromCpp(); """) - test.write( ['work5', 'mocFromCpp.cpp'],""" + test.write( ['work6', 'mocFromCpp.cpp'],""" #include #include "mocFromCpp.h" class MyClass1 : public QObject { @@ -399,7 +429,7 @@ void mocFromCpp() { #include "moc_mocFromCpp.cpp" """) - test.write( ['work5', 'mocFromH.h'],""" + test.write( ['work6', 'mocFromH.h'],""" #include class MyClass2 : public QObject { Q_OBJECT; @@ -411,7 +441,7 @@ class MyClass2 : public QObject { void mocFromH(); """) - test.write( ['work5', 'mocFromH.cpp'],""" + test.write( ['work6', 'mocFromH.cpp'],""" #include "mocFromH.h" MyClass2::MyClass2() : QObject() {} @@ -421,7 +451,7 @@ void mocFromH() { } """) - test.write( ['work5', 'anUiFile.ui'],""" + test.write( ['work6', 'anUiFile.ui'],""" MyWidget @@ -437,7 +467,7 @@ void mocFromH() { """) - test.write( ['work5', 'main.cpp'], """ + test.write( ['work6', 'main.cpp'], """ #include "mocFromCpp.h" #include "mocFromH.h" #include "anUiFile.h" @@ -448,13 +478,13 @@ int main() { } """) - test.run(chdir='work5', arguments="test_realqt" + _exe) + test.run(chdir='work6', arguments="test_realqt" + _exe) QTDIR=os.environ['QTDIR'] del os.environ['QTDIR'] - test.run(chdir='work5', arguments="-c test_realqt" + _exe) - test.run(chdir='work5', arguments="PATH=%s/bin test_realqt%s"%(QTDIR,_exe)) + test.run(chdir='work6', arguments="-c test_realqt" + _exe) + test.run(chdir='work6', arguments="PATH=%s/bin test_realqt%s"%(QTDIR,_exe)) else: print "Could not find QT, skipping test(s)."