Add AppendUnique() and PrependUnique() Environment methods. Fix using the qt Tool...
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Mon, 16 Feb 2004 06:09:44 +0000 (06:09 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Mon, 16 Feb 2004 06:09:44 +0000 (06:09 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@899 fdb21ef1-2011-0410-befe-b5e4ea1792b1

doc/man/scons.1
src/CHANGES.txt
src/engine/SCons/Environment.py
src/engine/SCons/EnvironmentTests.py
src/engine/SCons/Tool/qt.py
test/QT.py

index f5c0a705b81785d62ed5013fbaa627186ed53f0b..0b0756ad22beca4133f03e9389323679dba50cec 100644 (file)
@@ -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()
index e6c3b536f5f3018bf59b835271c615e6c80bd013..e75d50da239cefac01df25de2c98b8026225fd4c 100644 (file)
@@ -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.
index 46897ef9bd5ea6ff65c10ddb0f920e52630abc2c..900b1e1fa9d5c5795945eb23217cee64cb60e02b 100644 (file)
@@ -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.
index f81a10270fb2e733785faed67c5d2a13bd6d113e..0887ae33098aad1ed674c13a461efbc2d496be4f 100644 (file)
@@ -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
 
index 4be7a6540b571cc404a46f229f4279c99835939f..9969e024d72c4d232acbd7078e52097788964a47 100644 (file)
@@ -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)
index 0a2505e26c627665c301e84ca90d94dd1c6da434..3eb5af46cfca8ae090104b0ce568cee45b36f9f9 100644 (file)
@@ -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 <stdio.h>
+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 <qobject.h>
 #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 <qobject.h>
 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'],"""
 <!DOCTYPE UI><UI>
 <class>MyWidget</class>
 <widget>
@@ -437,7 +467,7 @@ void mocFromH() {
 </UI>
 """)
 
-    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)."