Add a SetDefault() method and a kinder, gentler qt.py that uses it. (Christoph Wiede...
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Tue, 31 Aug 2004 23:29:36 +0000 (23:29 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Tue, 31 Aug 2004 23:29:36 +0000 (23:29 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@1052 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/QTFLAGS.py

index 6b94453ee9e9cf0930c07cb1167b168ae40dafc8..931a46f3d0635c288bef1545c123e5605b0d74c7 100644 (file)
@@ -3587,6 +3587,19 @@ SConsignFile("etc/scons-signatures")
 SConsignFile("/home/me/SCons/signatures")
 .EE
 
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+.RI env.SetDefault(key = val ", [...])"
+Sets construction variables to default values specified with the keyword
+arguments if (and only if) the variables are not already set.
+The following statements are equivalent:
+
+.ES
+env.SetDefault(FOO = 'foo')
+
+if not env.has_key('FOO'): env['FOO'] = 'foo'
+.EE
+
 '\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .TP
 .RI SetOption( name ", " value )
@@ -5624,14 +5637,16 @@ with python's os.path.join() method,
 but are listed here with the '/' separator
 for easier reading.)
 In addition, the construction environment
-variables CPPPATH, LIBPATH, LIBS, PROGEMITTER, SHLIBEMITTER and LIBEMITTER
+variables CPPPATH, LIBPATH and LIBS may be modified
+and the variables
+PROGEMITTER, SHLIBEMITTER and LIBEMITTER
 are modified. Because the build-performance is affected when using this tool,
 you have to explicitly specify it at Environment creation:
 
 .ES
 Environment(tools=['default','qt'])
 .EE
-
+.IP
 The qt tool supports the following operations:
 
 .B Automatic moc file generation from header files.
@@ -5665,14 +5680,31 @@ you may need to specify duplicate=1 in calls to BuildDir. See also the correspon
 Turn off scanning for mocable files. Use the Moc Builder to explicitely 
 specify files to run moc on.
 
+.IP QT_BINPATH
+The path where the qt binaries are installed.
+The default value is '$QTDIR/bin'.
+
+.IP QT_CPPPATH
+The path where the qt header files are installed.
+The default value is '$QTDIR/include'.
+Note: If you set this variable to None, the tool won't change the CPPPATH
+construction variable.
+
 .IP QT_DEBUG 
 Prints lots of debugging information while scanning for moc files.
 
+.IP QT_LIBPATH
+The path where the qt libraries are installed.
+The default value is '$QTDIR/lib'. 
+Note: If you set this variable to None, the tool won't change the LIBPATH
+construction variable.
+
 .IP QT_LIB
-Default value is 'qt'. You may want to set this to 'qt-mt'.
+Default value is 'qt'. You may want to set this to 'qt-mt'. Note: If you set
+this variable to None, the tool won't change the LIBS variable.
 
 .IP QT_MOC
-Default value is '$QTDIR/bin/moc'.
+Default value is '$QT_BINPATH/moc'.
 
 .IP QT_MOCCXXPREFIX
 Default value is ''. Prefix for moc output files, when source is a cxx file.
@@ -5703,7 +5735,7 @@ Default value is '$CXXFILESUFFIX'. Suffix for moc output files, when source is
 a header.
 
 .IP QT_UIC
-Default value is '$QTDIR/bin/uic'.
+Default value is '$QT_BINPATH/uic'.
 
 .IP QT_UICDECLCOM
 Command to generate header files from .ui files.
index f1d853006f7ccca0868a21ee810623663705ccb2..617b38f8a03f470a14176a827a47b27a893a4e93 100644 (file)
@@ -25,6 +25,17 @@ RELEASE 0.97 - XXX
   - Fix the Builder name returned from ListBuilders and other instances
     of subclasses of the BuilderBase class.
 
+  From Christoph Wiedemann:
+
+  - Add an Environment.SetDefault() method that only sets values if
+    they aren't already set.
+
+  - Have the qt.py Tool not override variables already set by the user.
+
+  - Add separate $QT_BINPATH, $QT_CPPPATH and $QT_LIBPATH variables
+    so these can be set individually, instead of being hard-wired
+    relative to $QTDIR.
+
 
 
 RELEASE 0.96.1 - XXX
index 03f2e38a1d62c67c8068135ac3ce600c9e70ea7f..aeae2729f9e9efb102088eb8ab34ca290eab656f 100644 (file)
@@ -919,6 +919,12 @@ class Base:
             name = name[:-len(old_suffix)]
         return os.path.join(dir, new_prefix+name+new_suffix)
 
+    def SetDefault(self, **kw):
+        for k in kw.keys():
+            if self._dict.has_key(k):
+                del kw[k]
+        apply(self.Replace, (), kw)
+
     def Tool(self, tool, toolpath=[]):
         tool = self.subst(tool)
         return SCons.Tool.Tool(tool, map(self.subst, toolpath))(self)
index a6b8645534ecacb982d91efd59c5b9b8ff969d60..de09fd7807203fb89b5cc2b672f4a8db0df5b4cd 100644 (file)
@@ -1580,6 +1580,16 @@ class EnvironmentTestCase(unittest.TestCase):
                                              'PREFIX', 'SUFFIX',
                                              'LIBPREFIX', 'LIBSUFFIX')
 
+    def test_SetDefault(self):
+        """Test the SetDefault method"""
+        env = Environment(tools = [])
+        env.SetDefault(V1 = 1)
+        env.SetDefault(V1 = 2)
+        assert env['V1'] == 1
+        env['V2'] = 2
+        env.SetDefault(V2 = 1)
+        assert env['V2'] == 2
+
     def test_Tool(self):
         """Test the Tool() method"""
         env = Environment(LINK='link', NONE='no-such-tool')
index ee55051bac8468420167d1599e2d1f4be428b8b5..c6237d36df615deea7c2086e48f53f86d3de2f3f 100644 (file)
@@ -201,6 +201,22 @@ def _detect(env):
                 "Could not detect qt, using empty QTDIR")
     return QTDIR
 
+def uicEmitter(target, source, env):
+    adjustixes = SCons.Util.adjustixes
+    bs = SCons.Util.splitext(str(source[0].name))[0]
+    bs = os.path.join(str(target[0].get_dir()),bs)
+    # first target (header) is automatically added by builder
+    if len(target) < 2:
+        # second target is implementation
+        target.append(adjustixes(bs,
+                                 env.subst('$QT_UICIMPLPREFIX'),
+                                 env.subst('$QT_UICIMPLSUFFIX')))
+    if len(target) < 3:
+        # third target is moc file
+        target.append(adjustixes(bs,
+                                 env.subst('$QT_MOCHPREFIX'),
+                                 env.subst('$QT_MOCHSUFFIX')))
+    return target, source
 
 def generate(env):
     """Add Builders and construction variables for qt to an Environment."""
@@ -209,66 +225,52 @@ def generate(env):
     Builder = SCons.Builder.Builder
     splitext = SCons.Util.splitext
 
-    # the basics
-    env['QTDIR']  = _detect(env)
-    env['QT_MOC'] = os.path.join('$QTDIR','bin','moc')
-    env['QT_UIC'] = os.path.join('$QTDIR','bin','uic')
-    env['QT_LIB'] = 'qt' # may be set to qt-mt
-
-    # Should the qt tool try to figure out, which sources are to be moc'ed ?
-    env['QT_AUTOSCAN'] = 1
-
-    # Some QT specific flags. I don't expect someone wants to
-    # manipulate those ...
-    env['QT_UICIMPLFLAGS'] = CLVar('')
-    env['QT_UICDECLFLAGS'] = CLVar('')
-    env['QT_MOCFROMHFLAGS'] = CLVar('')
-    env['QT_MOCFROMCXXFLAGS'] = CLVar('-i')
-
-    # suffixes/prefixes for the headers / sources to generate
-    env['QT_UICDECLPREFIX'] = ''
-    env['QT_UICDECLSUFFIX'] = '.h'
-    env['QT_UICIMPLPREFIX'] = 'uic_'
-    env['QT_UICIMPLSUFFIX'] = '$CXXFILESUFFIX'
-    env['QT_MOCHPREFIX'] = 'moc_'
-    env['QT_MOCHSUFFIX'] = '$CXXFILESUFFIX'
-    env['QT_MOCCXXPREFIX'] = ''
-    env['QT_MOCCXXSUFFIX'] = '.moc'
-    env['QT_UISUFFIX'] = '.ui'
-
-    def uicEmitter(target, source, env):
-        adjustixes = SCons.Util.adjustixes
-        bs = SCons.Util.splitext(str(source[0].name))[0]
-        bs = os.path.join(str(target[0].get_dir()),bs)
-        # first target (header) is automatically added by builder
-        if len(target) < 2:
-            # second target is implementation
-            target.append(adjustixes(bs,
-                                     env.subst('$QT_UICIMPLPREFIX'),
-                                     env.subst('$QT_UICIMPLSUFFIX')))
-        if len(target) < 3:
-            # third target is moc file
-            target.append(adjustixes(bs,
-                                     env.subst('$QT_MOCHPREFIX'),
-                                     env.subst('$QT_MOCHSUFFIX')))
-        return target, source
-
-    # Commands for the qt support ...
-    # command to generate header, implementation and moc-file from a .ui file
-    env['QT_UICCOM'] = [
-        CLVar('$QT_UIC $QT_UICDECLFLAGS -o ${TARGETS[0]} $SOURCE'),
-        CLVar('$QT_UIC $QT_UICIMPLFLAGS -impl ${TARGETS[0].file} '
-              '-o ${TARGETS[1]} $SOURCE'),
-        CLVar('$QT_MOC $QT_MOCFROMHFLAGS -o ${TARGETS[2]} ${TARGETS[0]}')]
-    # command to generate meta object information for a class declarated
-    # in a header
-    env['QT_MOCFROMHCOM'] = (
-        '$QT_MOC $QT_MOCFROMHFLAGS -o ${TARGETS[0]} $SOURCE')
-    # command to generate meta object information for a class declarated
-    # in a cpp file
-    env['QT_MOCFROMCXXCOM'] = [
-        CLVar('$QT_MOC $QT_MOCFROMCXXFLAGS -o ${TARGETS[0]} $SOURCE'),
-        Action(checkMocIncluded,None)]
+    env.SetDefault(QTDIR  = _detect(env),
+                   QT_BINPATH = os.path.join('$QTDIR', 'bin'),
+                   QT_CPPPATH = os.path.join('$QTDIR', 'include'),
+                   QT_LIBPATH = os.path.join('$QTDIR', 'lib'),
+                   QT_MOC = os.path.join('$QT_BINPATH','moc'),
+                   QT_UIC = os.path.join('$QT_BINPATH','uic'),
+                   QT_LIB = 'qt', # may be set to qt-mt
+
+                   QT_AUTOSCAN = 1, # scan for moc'able sources
+
+                   # Some QT specific flags. I don't expect someone wants to
+                   # manipulate those ...
+                   QT_UICIMPLFLAGS = CLVar(''),
+                   QT_UICDECLFLAGS = CLVar(''),
+                   QT_MOCFROMHFLAGS = CLVar(''),
+                   QT_MOCFROMCXXFLAGS = CLVar('-i'),
+
+                   # suffixes/prefixes for the headers / sources to generate
+                   QT_UICDECLPREFIX = '',
+                   QT_UICDECLSUFFIX = '.h',
+                   QT_UICIMPLPREFIX = 'uic_',
+                   QT_UICIMPLSUFFIX = '$CXXFILESUFFIX',
+                   QT_MOCHPREFIX = 'moc_',
+                   QT_MOCHSUFFIX = '$CXXFILESUFFIX',
+                   QT_MOCCXXPREFIX = '',
+                   QT_MOCCXXSUFFIX = '.moc',
+                   QT_UISUFFIX = '.ui',
+
+                   # Commands for the qt support ...
+                   # command to generate header, implementation and moc-file
+                   # from a .ui file
+                   QT_UICCOM = [
+                    CLVar('$QT_UIC $QT_UICDECLFLAGS -o ${TARGETS[0]} $SOURCE'),
+                    CLVar('$QT_UIC $QT_UICIMPLFLAGS -impl ${TARGETS[0].file} '
+                          '-o ${TARGETS[1]} $SOURCE'),
+                    CLVar('$QT_MOC $QT_MOCFROMHFLAGS -o ${TARGETS[2]} ${TARGETS[0]}')],
+                   # command to generate meta object information for a class
+                   # declarated in a header
+                   QT_MOCFROMHCOM = (
+                          '$QT_MOC $QT_MOCFROMHFLAGS -o ${TARGETS[0]} $SOURCE'),
+                   # command to generate meta object information for a class
+                   # declarated in a cpp file
+                   QT_MOCFROMCXXCOM = [
+                    CLVar('$QT_MOC $QT_MOCFROMCXXFLAGS -o ${TARGETS[0]} $SOURCE'),
+                    Action(checkMocIncluded,None)])
+
     # ... and the corresponding builders
     uicBld = Builder(action='$QT_UICCOM',
                      emitter=uicEmitter,
@@ -301,8 +303,8 @@ def generate(env):
                      SHLIBEMITTER=[AutomocShared],
                      LIBEMITTER  =[AutomocStatic],
                      # Of course, we need to link against the qt libraries
-                     CPPPATH=[os.path.join('$QTDIR', 'include')],
-                     LIBPATH=[os.path.join('$QTDIR', 'lib')],
+                     CPPPATH=["$QT_CPPPATH"],
+                     LIBPATH=["$QT_LIBPATH"],
                      LIBS=['$QT_LIB'])
 
 def exists(env):
index 46c54dfd162fa7ba9939447a68a5fc93f575b202..a07c2c6b342e410d8ccd2c3c8cc3a27859ffb632 100644 (file)
@@ -36,7 +36,8 @@ _exe = TestSCons._exe
 
 test = TestSCons.TestSCons()
 
-test.subdir( 'qt', ['qt', 'bin'], ['qt', 'include'], ['qt', 'lib'] )
+test.subdir( 'qt', ['qt', 'bin'], ['qt', 'include'], ['qt', 'lib'],
+             'work1', 'work2')
 
 # create a dummy qt installation
 
@@ -125,8 +126,6 @@ QT_LIB = 'myqt'
 QT_MOC = '%s %s' % (python, test.workpath('qt','bin','mymoc.py'))
 QT_UIC = '%s %s' % (python, test.workpath('qt','bin','myuic.py'))
 
-# 3 test cases with 3 different operation modes
-
 def createSConstruct(test,place,overrides):
     test.write(place, """
 env = Environment(QTDIR = r'%s',
@@ -149,7 +148,7 @@ SConscript( sconscript )
 """ % (QT, QT_LIB, QT_MOC, QT_UIC, overrides))
 
 
-createSConstruct(test, ['SConstruct'],
+createSConstruct(test, ['work1', 'SConstruct'],
                  """QT_UICIMPLFLAGS='-x',
                     QT_UICDECLFLAGS='-y',
                     QT_MOCFROMHFLAGS='-z',
@@ -163,7 +162,7 @@ createSConstruct(test, ['SConstruct'],
                     QT_MOCCXXPREFIX='moc',
                     QT_MOCCXXSUFFIX='.inl',
                     QT_UISUFFIX='.myui',""")
-test.write('SConscript',"""
+test.write(['work1', 'SConscript'],"""
 Import("env")
 env.Program('mytest', ['mocFromH.cpp',
                        'mocFromCpp.cpp',
@@ -172,34 +171,34 @@ env.Program('mytest', ['mocFromH.cpp',
                        'main.cpp'])
 """)
 
-test.write('mocFromH.hpp', """
+test.write(['work1', 'mocFromH.hpp'], """
 #include "my_qobject.h"
 void mocFromH() Q_OBJECT
 """)
 
-test.write('mocFromH.cpp', """
+test.write(['work1', 'mocFromH.cpp'], """
 #include "mocFromH.hpp"
 """)
 
-test.write('mocFromCpp.cpp', """
+test.write(['work1', 'mocFromCpp.cpp'], """
 #include "my_qobject.h"
 void mocFromCpp() Q_OBJECT
 #include "mocmocFromCpp.inl"
 """)
 
-test.write('an_ui_file.myui', """
+test.write(['work1', 'an_ui_file.myui'], """
 void an_ui_file()
 """)
 
-test.write('another_ui_file.myui', """
+test.write(['work1', 'another_ui_file.myui'], """
 void another_ui_file()
 """)
 
-test.write('another_ui_file.desc.hpp', """
+test.write(['work1', 'another_ui_file.desc.hpp'], """
 /* just a dependency checker */
 """)
 
-test.write('main.cpp', """
+test.write(['work1', 'main.cpp'], """
 #include "mocFromH.hpp"
 #include "uic-an_ui_file.hpp"
 #include "uic-another_ui_file.hpp"
@@ -213,21 +212,21 @@ int main() {
 }
 """)
 
-test.run( arguments = "mytest" + _exe )
+test.run(chdir = 'work1', arguments = "mytest" + _exe)
                        
-test.must_exist('mmmmocFromH.cxx',
-                'mocmocFromCpp.inl',
-                'an_ui_file.cxx',
-                'uic-an_ui_file.hpp',
-                'mmman_ui_file.cxx',
-                'another_ui_file.cxx',
-                'uic-another_ui_file.hpp',
-                'mmmanother_ui_file.cxx')
+test.must_exist(['work1', 'mmmmocFromH.cxx'],
+                ['work1', 'mocmocFromCpp.inl'],
+                ['work1', 'an_ui_file.cxx'],
+                ['work1', 'uic-an_ui_file.hpp'],
+                ['work1', 'mmman_ui_file.cxx'],
+                ['work1', 'another_ui_file.cxx'],
+                ['work1', 'uic-another_ui_file.hpp'],
+                ['work1', 'mmmanother_ui_file.cxx'])
 
 def _flagTest(test,fileToContentsStart):
     import string
     for f,c in fileToContentsStart.items():
-        if string.find(test.read(f), c) != 0:
+        if string.find(test.read(test.workpath('work1', f)), c) != 0:
             return 1
     return 0
 
@@ -237,4 +236,41 @@ test.fail_test(_flagTest(test, {'mmmmocFromH.cxx':'/* mymoc.py -z */',
                                 'uic-an_ui_file.hpp':'/* myuic.py -y */',
                                 'mmman_ui_file.cxx':'/* mymoc.py -z */'}))
 
+test.write(['work2', 'SConstruct'], """
+import os.path
+env1 = Environment(tools=['qt'],
+                   QTDIR = r'%(QTDIR)s',
+                   QT_BINPATH='$QTDIR/bin64',
+                   QT_LIBPATH='$QTDIR/lib64',
+                   QT_CPPPATH='$QTDIR/h64')
+
+if not env1.subst('$CPPPATH') == os.path.join(r'%(QTDIR)s', 'h64'):
+    print env1.subst('$CPPPATH')
+    Exit(1)
+if not env1.subst('$LIBPATH') == os.path.join(r'%(QTDIR)s', 'lib64'):
+    print env1.subst('$LIBPATH')
+    Exit(2)
+if not env1.subst('$QT_MOC') == os.path.join(r'%(QTDIR)s', 'bin64', 'moc'):
+    print env1.subst('$QT_MOC')
+    Exit(3)
+
+env2 = Environment(tools=['default', 'qt'],
+                   QTDIR = None,
+                   QT_LIB = None,
+                   QT_CPPPATH = None,
+                   QT_LIBPATH = None)
+
+env2.Program('main.cpp')
+""" % {'QTDIR':QT})
+
+test.write(['work2', 'main.cpp'], """
+int main() { return 0; }
+""")
+
+# Ignore stderr, because if Qt is not installed,
+# there may be a warning about an empty QTDIR on stderr.
+test.run(chdir='work2', stderr=None)
+
+test.must_exist(['work2', 'main' + _exe])
+
 test.pass_test()