From: stevenknight Date: Tue, 31 Aug 2004 23:29:36 +0000 (+0000) Subject: Add a SetDefault() method and a kinder, gentler qt.py that uses it. (Christoph Wiede... X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=76e30dd3eaa660b845d233b85763acaa0e4c182b;p=scons.git Add a SetDefault() method and a kinder, gentler qt.py that uses it. (Christoph Wiedemann) git-svn-id: http://scons.tigris.org/svn/scons/trunk@1052 fdb21ef1-2011-0410-befe-b5e4ea1792b1 --- diff --git a/doc/man/scons.1 b/doc/man/scons.1 index 6b94453e..931a46f3 100644 --- a/doc/man/scons.1 +++ b/doc/man/scons.1 @@ -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. diff --git a/src/CHANGES.txt b/src/CHANGES.txt index f1d85300..617b38f8 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -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 diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py index 03f2e38a..aeae2729 100644 --- a/src/engine/SCons/Environment.py +++ b/src/engine/SCons/Environment.py @@ -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) diff --git a/src/engine/SCons/EnvironmentTests.py b/src/engine/SCons/EnvironmentTests.py index a6b86455..de09fd78 100644 --- a/src/engine/SCons/EnvironmentTests.py +++ b/src/engine/SCons/EnvironmentTests.py @@ -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') diff --git a/src/engine/SCons/Tool/qt.py b/src/engine/SCons/Tool/qt.py index ee55051b..c6237d36 100644 --- a/src/engine/SCons/Tool/qt.py +++ b/src/engine/SCons/Tool/qt.py @@ -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): diff --git a/test/QTFLAGS.py b/test/QTFLAGS.py index 46c54dfd..a07c2c6b 100644 --- a/test/QTFLAGS.py +++ b/test/QTFLAGS.py @@ -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()