From 52fc82f32622b801534126370a1f47f9b851c9be Mon Sep 17 00:00:00 2001 From: Du Bois Eloi Date: Wed, 1 Feb 2012 18:55:22 +0100 Subject: [PATCH 01/22] sconsProject: added precompiled header feature (to check) --- __init__.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/__init__.py b/__init__.py index 396c67b..4337233 100755 --- a/__init__.py +++ b/__init__.py @@ -944,7 +944,7 @@ def ObjectLibrary( self, target, libraries=[], includes=[], envFlags={}, sources return dstLibChecker - def StaticLibrary( self, target, sources=[], dirs=[], env=None, libraries=[], includes=[], localEnvFlags={}, replaceLocalEnvFlags={}, + def StaticLibrary( self, target, sources=[], precsrc='', precinc='', dirs=[], env=None, libraries=[], includes=[], localEnvFlags={}, replaceLocalEnvFlags={}, externEnvFlags={}, globalEnvFlags={}, dependencies=[], installDir=None, install=True, accept=['*.cpp', '*.cc', '*.c'], reject=['@', '_qrc', '_ui', '.moc.cpp'], shared=False ): ''' @@ -992,7 +992,13 @@ def StaticLibrary( self, target, sources=[], dirs=[], env=None, libraries=[], in sourcesFiles = sourcesFiles + localEnv['ADDSRC'] sourcesFiles = self.getAbsoluteCwd( sourcesFiles ) - + + #adding precompiled headers + if precinc: + localEnv['PCHSTOP'] = self.dir + '/' + precinc + localEnv.Append( CPPFLAGS = [ '/FI' + self.dir + '/' + precinc, '/Zm135' ] ) + localEnv['PCH'] = localEnv.PCH( precsrc )[0] + # create the target dstLib = localEnv.StaticLibrary( target=target, source=sourcesFiles ) @@ -1016,7 +1022,7 @@ def StaticLibrary( self, target, sources=[], dirs=[], env=None, libraries=[], in return dstLibInstall - def SharedLibrary( self, target, sources=[], dirs=[], env=None, libraries=[], includes=[], localEnvFlags={}, replaceLocalEnvFlags={}, + def SharedLibrary( self, target, sources=[], precsrc='', precinc='', dirs=[], env=None, libraries=[], includes=[], localEnvFlags={}, replaceLocalEnvFlags={}, externEnvFlags={}, globalEnvFlags={}, dependencies=[], installDir=None, install=True, accept=['*.cpp', '*.cc', '*.c'], reject=['@', '_qrc', '_ui', '.moc.cpp'] ): ''' @@ -1059,6 +1065,12 @@ def SharedLibrary( self, target, sources=[], dirs=[], env=None, libraries=[], in sourcesFiles = self.getAbsoluteCwd( sourcesFiles ) + #adding precompiled headers + if precinc: + localEnv['PCHSTOP'] = self.dir + '/' + precinc + localEnv.Append( CPPFLAGS = [ '/FI' + self.dir + '/' + precinc, '/Zm135' ] ) + localEnv['PCH'] = localEnv.PCH( precsrc )[0] + # create the target dstLib = localEnv.SharedLibrary( target=target, source=sourcesFiles ) @@ -1244,4 +1256,3 @@ def subdirsContaining(self, directory, patterns): __all__ = ['SConsProject'] - From 268c10b6258dc07e4e1d6c2c4288ea3a26c4b688 Mon Sep 17 00:00:00 2001 From: Du Bois Eloi Date: Thu, 2 Feb 2012 00:47:55 +0100 Subject: [PATCH 02/22] sconsProject: improvment on precompiled header path --- __init__.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/__init__.py b/__init__.py index 4337233..fb9a1ac 100755 --- a/__init__.py +++ b/__init__.py @@ -995,8 +995,8 @@ def StaticLibrary( self, target, sources=[], precsrc='', precinc='', dirs=[], en #adding precompiled headers if precinc: - localEnv['PCHSTOP'] = self.dir + '/' + precinc - localEnv.Append( CPPFLAGS = [ '/FI' + self.dir + '/' + precinc, '/Zm135' ] ) + localEnv['PCHSTOP'] = self.getRealAbsoluteCwd() + '/' + precinc + localEnv.Append( CPPFLAGS = [ '/FI' + self.getRealAbsoluteCwd() + '/' + precinc, '/Zm135' ] ) localEnv['PCH'] = localEnv.PCH( precsrc )[0] # create the target @@ -1067,8 +1067,8 @@ def SharedLibrary( self, target, sources=[], precsrc='', precinc='', dirs=[], en #adding precompiled headers if precinc: - localEnv['PCHSTOP'] = self.dir + '/' + precinc - localEnv.Append( CPPFLAGS = [ '/FI' + self.dir + '/' + precinc, '/Zm135' ] ) + localEnv['PCHSTOP'] = self.getRealAbsoluteCwd() + '/' + precinc + localEnv.Append( CPPFLAGS = [ '/FI' + self.getRealAbsoluteCwd() + '/' + precinc, '/Zm135' ] ) localEnv['PCH'] = localEnv.PCH( precsrc )[0] # create the target From 2db29df192becf696226fbff835c03e220af826c Mon Sep 17 00:00:00 2001 From: Eloi du Bois Date: Thu, 2 Feb 2012 16:30:50 +0100 Subject: [PATCH 03/22] sconsProject: disabled WIN64 constant. --- autoconf/sconsProject.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoconf/sconsProject.py b/autoconf/sconsProject.py index 92b2342..b7d73e3 100755 --- a/autoconf/sconsProject.py +++ b/autoconf/sconsProject.py @@ -30,7 +30,7 @@ def configure(self, project, env): env.AppendUnique( CPPDEFINES = 'WINDOWS' ) env.AppendUnique( CPPDEFINES = '_WINDOWS' ) env.AppendUnique( CPPDEFINES = '__WINDOWS__' ) - env.AppendUnique( CPPDEFINES = 'WIN'+str(env['osbits']) ) +# env.AppendUnique( CPPDEFINES = 'WIN'+str(env['osbits']) ) else: env.AppendUnique( CPPDEFINES = 'UNIX' ) env.AppendUnique( CPPDEFINES = '__UNIX__' ) From b704ffe0d7c5a7b806b45de2d8030809a176456f Mon Sep 17 00:00:00 2001 From: Du Bois Date: Thu, 2 Feb 2012 18:15:12 +0100 Subject: [PATCH 04/22] sconsProject: gcc compilation fixes. --- __init__.py | 4 ++-- compiler/gcc.py | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/__init__.py b/__init__.py index fb9a1ac..22a739b 100755 --- a/__init__.py +++ b/__init__.py @@ -994,7 +994,7 @@ def StaticLibrary( self, target, sources=[], precsrc='', precinc='', dirs=[], en sourcesFiles = self.getAbsoluteCwd( sourcesFiles ) #adding precompiled headers - if precinc: + if precinc and self.windows: localEnv['PCHSTOP'] = self.getRealAbsoluteCwd() + '/' + precinc localEnv.Append( CPPFLAGS = [ '/FI' + self.getRealAbsoluteCwd() + '/' + precinc, '/Zm135' ] ) localEnv['PCH'] = localEnv.PCH( precsrc )[0] @@ -1066,7 +1066,7 @@ def SharedLibrary( self, target, sources=[], precsrc='', precinc='', dirs=[], en sourcesFiles = self.getAbsoluteCwd( sourcesFiles ) #adding precompiled headers - if precinc: + if precinc and self.windows: localEnv['PCHSTOP'] = self.getRealAbsoluteCwd() + '/' + precinc localEnv.Append( CPPFLAGS = [ '/FI' + self.getRealAbsoluteCwd() + '/' + precinc, '/Zm135' ] ) localEnv['PCH'] = localEnv.PCH( precsrc )[0] diff --git a/compiler/gcc.py b/compiler/gcc.py index 28a614f..0786293 100755 --- a/compiler/gcc.py +++ b/compiler/gcc.py @@ -29,6 +29,8 @@ def version( bin = 'gcc' ): CC['define'] = '-D' +CC['multithreadedlib'] = '' +CC['singlethreadedlib'] = '' CC['optimize'] = ['-O2']#, #'-finline-limit=700', From 1f0103ab5e943b5a5d470c93e5b56ea724ea2b84 Mon Sep 17 00:00:00 2001 From: Du Bois Date: Thu, 12 Apr 2012 19:57:00 +0200 Subject: [PATCH 05/22] sconsProject: added qtmain.py (windows non console application). --- autoconf/qtmain.py | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 autoconf/qtmain.py diff --git a/autoconf/qtmain.py b/autoconf/qtmain.py new file mode 100644 index 0000000..fae35ff --- /dev/null +++ b/autoconf/qtmain.py @@ -0,0 +1,3 @@ +from _external import * + +qtmain = LibChecker( 'qtmain' ) From 2bb8524b3d2c7e050bcd39fcacbe75cb69ac385f Mon Sep 17 00:00:00 2001 From: Du Bois Eloi Date: Fri, 13 Apr 2012 14:07:17 +0200 Subject: [PATCH 06/22] sconsProject: fixed wrong merge. --- autoconf/qtmain.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/autoconf/qtmain.py b/autoconf/qtmain.py index a6b8184..0b2d334 100644 --- a/autoconf/qtmain.py +++ b/autoconf/qtmain.py @@ -1,9 +1,3 @@ -<<<<<<< HEAD from _external import * qtmain = LibChecker( 'qtmain' ) -======= -from _external import * - -qtmain = LibChecker( 'qtmain' ) ->>>>>>> 1f0103ab5e943b5a5d470c93e5b56ea724ea2b84 From 876d2467c9f5cd590c8e9735758823ea6a2fc11d Mon Sep 17 00:00:00 2001 From: Du Bois Date: Sat, 28 Apr 2012 16:32:24 +0200 Subject: [PATCH 07/22] qtmain: unix compatibility --- autoconf/qtmain.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/autoconf/qtmain.py b/autoconf/qtmain.py index 0b2d334..5c85ec4 100644 --- a/autoconf/qtmain.py +++ b/autoconf/qtmain.py @@ -1,3 +1,7 @@ from _external import * -qtmain = LibChecker( 'qtmain' ) +if windows: + qtmain = LibChecker( 'qtmain' ) +else: + qtmain = ObjectChecker( 'qtmain' ) + From 08d679a1a696059e8c87352c3ec0cf5604c2bc65 Mon Sep 17 00:00:00 2001 From: Du Bois Eloi Date: Thu, 5 Jul 2012 14:34:59 +0200 Subject: [PATCH 08/22] sconsProject update for precompiled headers. --- __init__.py | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/__init__.py b/__init__.py index b43c8c0..77683d0 100755 --- a/__init__.py +++ b/__init__.py @@ -277,6 +277,8 @@ def getRealAbsoluteCwd(self, relativePath=None): if relativePath: if isinstance(relativePath, SCons.Node.FS.Dir): return relativePath.srcnode().abspath + elif not isinstance(relativePath, str): + return relativePath elif relativePath.startswith('#'): return os.path.join(self.dir, relativePath[1:]) elif os.path.isabs(relativePath): @@ -991,10 +993,10 @@ def MSVSProject(self, targetName, buildTarget, l_env.Replace( CPPPATH = self.convertSconsPathToStr(l_env['CPPPATH']) ) visualProject = l_env.MSVSProject( - target = os.path.normpath( self.getRealAbsoluteCwd(visualProjectFile) ), - srcs = [ os.path.normpath( self.getRealAbsoluteCwd(i) ) for i in sources], - incs = [ os.path.normpath( self.getRealAbsoluteCwd(i) ) for i in headers], - localincs = [ os.path.normpath( self.getRealAbsoluteCwd(i) ) for i in localHeaders], + target = self.normpath( self.getRealAbsoluteCwd(visualProjectFile) ), + srcs = [ self.normpath( self.getRealAbsoluteCwd(i) ) for i in sources], + incs = [ self.normpath( self.getRealAbsoluteCwd(i) ) for i in headers], + localincs = [ self.normpath( self.getRealAbsoluteCwd(i) ) for i in localHeaders], resources = resources, misc = misc, buildtarget = buildTarget[0], @@ -1004,6 +1006,11 @@ def MSVSProject(self, targetName, buildTarget, self.allVisualProjects.append( visualProject ) self.env.Alias( 'visualProject-'+targetName, visualProject ) + def normpath( self, s ): + if ( isinstance(s, str) ): + return os.path.normpath( s ) + return s + def ObjectLibrary( self, target, libraries=[], includes=[], envFlags={}, sources=[], public=True, publicName=None, @@ -1272,7 +1279,7 @@ def SharedLibrary( self, target, return dstLibInstall def Program( self, target, - sources=[], dirs=[], libraries=[], includes=[], + sources=[], dirs=[], libraries=[], includes=[], rc_files = [], precsrc = [], precinc = [], env=None, localEnvFlags={}, replaceLocalEnvFlags={}, externEnvFlags={}, globalEnvFlags={}, dependencies=[], installDir=None, install=True, headers=[], localHeaders=[], @@ -1315,7 +1322,7 @@ def Program( self, target, localEnv = None localLibraries = l_libraries if env: - localEnv = env.Clone() + localEnv = env self.appendLibsToEnv(localEnv, localLibraries) if 'SconsProjectLibraries' in localEnv: localLibraries += localEnv['SconsProjectLibraries'] @@ -1334,10 +1341,20 @@ def Program( self, target, localEnv.AppendUnique( **globalEnvFlags ) sourcesFiles = self.getAbsoluteCwd( sourcesFiles ) + + # Add rc files (windows only) + if self.windows: + for rc in rc_files: + print rc +# sourcesFiles.append( localEnv.RES( rc ) ); + + if precinc and self.windows: + localEnv['PCHSTOP'] = self.getRealAbsoluteCwd() + '/' + precinc + localEnv.Append( CPPFLAGS = [ '/FI' + self.getRealAbsoluteCwd() + '/' + precinc, '/Zm135' ] ) + localEnv['PCH'] = localEnv.PCH( precsrc )[0] # create the target dst = localEnv.Program( target=target, source=sourcesFiles ) - dstInstall = localEnv.Install( installDir if installDir else self.inOutputBin(), dst ) if install else dst localEnv.Alias( target, dstInstall ) localEnv.Alias( 'all', target ) From f9c10a87b61f35c93f2137e1f978a8bf92ac600a Mon Sep 17 00:00:00 2001 From: Du Bois Eloi Date: Tue, 13 Nov 2012 22:36:49 +0100 Subject: [PATCH 09/22] sconsProject: added /bigobj for visual C++ higher dlls' segments size. --- compiler/gcc.py | 1 + compiler/visual.py | 1 + 2 files changed, 2 insertions(+) diff --git a/compiler/gcc.py b/compiler/gcc.py index 88d1b8e..0e6106b 100755 --- a/compiler/gcc.py +++ b/compiler/gcc.py @@ -29,6 +29,7 @@ def version( bin = ccBin ): CC['define'] = '-D' +CC['bigobj'] = '' CC['multithreadedlib'] = '' CC['singlethreadedlib'] = '' diff --git a/compiler/visual.py b/compiler/visual.py index 48eada7..73e00b9 100755 --- a/compiler/visual.py +++ b/compiler/visual.py @@ -12,6 +12,7 @@ CC['multithreadedlib'] = '/MD' CC['singlethreadedlib'] = '/ML' +CC['bigobj'] = '/bigobj' CC['optimize'] =['/O2','/Ox','/GA','/GL'] CC['nooptimize'] =['/Od'] From b04220e2bc2d1e47435f756b60c4d2db8a7effb2 Mon Sep 17 00:00:00 2001 From: Du Bois Eloi Date: Tue, 21 May 2013 23:43:49 +0200 Subject: [PATCH 10/22] sconsProject: added multithreaded_static_lib to compile with /MT (vc++ only) --- compiler/gcc.py | 1 + compiler/visual.py | 1 + 2 files changed, 2 insertions(+) diff --git a/compiler/gcc.py b/compiler/gcc.py index 0e6106b..d5e5f2b 100755 --- a/compiler/gcc.py +++ b/compiler/gcc.py @@ -31,6 +31,7 @@ def version( bin = ccBin ): CC['bigobj'] = '' CC['multithreadedlib'] = '' +CC['multithreaded_static_lib'] = '' CC['singlethreadedlib'] = '' CC['optimize'] = ['-O2']#, diff --git a/compiler/visual.py b/compiler/visual.py index 73e00b9..b112129 100755 --- a/compiler/visual.py +++ b/compiler/visual.py @@ -11,6 +11,7 @@ CC['exceptionsEnabled'] = '/EHsc' #'/GX' CC['multithreadedlib'] = '/MD' +CC['multithreaded_static_lib'] = '/MT' CC['singlethreadedlib'] = '/ML' CC['bigobj'] = '/bigobj' From afa65e30d45e7df6a2d52dd348e1d65b1653dee8 Mon Sep 17 00:00:00 2001 From: Eloi du Bois Date: Mon, 27 May 2013 21:43:53 +0200 Subject: [PATCH 11/22] sconsProject: some improvments * deal with "path too long" issues (disabled until it works) * qt.py updated solving moc.exe that generates too long include paths * qt.py updated to deal with translations --- __init__.py | 28 ++- tools/qt.py | 577 ++++++++++++++++++++++++++++------------------------ 2 files changed, 335 insertions(+), 270 deletions(-) diff --git a/__init__.py b/__init__.py index 1c18846..2b2f8b4 100755 --- a/__init__.py +++ b/__init__.py @@ -31,6 +31,27 @@ def join_if_basedir_not_empty( *dirs ): return '' return os.path.join(*dirs) +class VisualCSpawn: + def visualcspawn(self, sh, escape, cmd, args, env): + newargs = ' '.join(args[1:]) + cmdline = cmd + " " + newargs + startupinfo = subprocess.STARTUPINFO() + startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW + proc = subprocess.Popen(cmdline, stdin=subprocess.PIPE, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, startupinfo=startupinfo, shell = False, env = env) + data, err = proc.communicate() + rv = proc.wait() + if rv: + print "=====" + print err + print "=====" + return rv + +def setupSpawn( env ): + if sys.platform == 'win32': + buf = VisualCSpawn() + buf.visualCSpawnEnv = env + env['SPAWN'] = buf.visualcspawn class SConsProject: ''' @@ -111,7 +132,7 @@ def createCustomPlugins( self, sources=[], libs=[] ): 'scripttest', ] + (['msvs'] if windows else []), toolpath=[os.path.join(dir_sconsProject,'tools')] ) - + allVisualProjects = [] def __init__(self): @@ -170,6 +191,8 @@ def __init__(self): #if self.windows: self.env['ENV']['PATH'] = os.environ['PATH'] # access to the compiler (if not in '/usr/bin') +# setupSpawn( self.env ); + # scons optimizations... # http://www.scons.org/wiki/GoFastButton # @@ -669,7 +692,6 @@ def applyOptionsOnEnv(self, env): for c in ['color_clear', 'color_red', 'color_redB', 'color_green', 'color_blue', 'color_blueB', 'color_yellow', 'color_brown', 'color_violet', 'color_autoconf', 'color_header', 'color_title', 'color_compile', 'color_link', 'color_install', 'color_info', 'color_success', 'color_warning', 'color_fail', 'color_error']: env[c] = '' - def SConscript(self, dirs=[], exports=[]): ''' To include SConscript from SConstruct, this automatically defines variantdirs. @@ -1281,7 +1303,7 @@ def SharedLibrary( self, target, sourcesFiles = sourcesFiles + localEnv['ADDSRC'] sourcesFiles = self.getAbsoluteCwd( sourcesFiles ) - + #adding precompiled headers if precinc and self.windows: localEnv['PCHSTOP'] = self.getRealAbsoluteCwd() + '/' + precinc diff --git a/tools/qt.py b/tools/qt.py index f72a048..6e6a6d3 100644 --- a/tools/qt.py +++ b/tools/qt.py @@ -10,7 +10,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,10 +32,11 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/qt.py 5023 2010/06/14 22:05:46 scons" +__revision__ = "src/engine/SCons/Tool/qt.py 2013/03/03 09:48:35 garyo" -import os.path +import os import re +import sys import SCons.Action import SCons.Builder @@ -45,298 +46,340 @@ import SCons.Util class ToolQtWarning(SCons.Warnings.Warning): - pass + pass class GeneratedMocFileNotIncluded(ToolQtWarning): - pass + pass class QtdirNotFound(ToolQtWarning): - pass + pass SCons.Warnings.enableWarningClass(ToolQtWarning) header_extensions = [".h", ".hxx", ".hpp", ".hh"] if SCons.Util.case_sensitive_suffixes('.h', '.H'): - header_extensions.append('.H') -# TODO: The following two lines will work when integrated back to SCons -# TODO: Meanwhile the third line will do the work -#cplusplus = __import__('SCons.Tool.c++', globals(), locals(), []) + header_extensions.append('.H') +#cplusplus = __import__('c++', globals(), locals(), []) #cxx_suffixes = cplusplus.CXXSuffixes cxx_suffixes = [".c", ".cxx", ".cpp", ".cc"] +def fileReplace(fname, pat, s_after): + # first, see if the pattern is even in the file. + with open(fname) as f: + if not any(re.search(pat, line) for line in f): + return # pattern does not occur in file so we are done. + + # pattern is in the file, so perform replace operation. + with open(fname) as f: + out_fname = fname + ".tmp" + out = open(out_fname, "w") + for line in f: + out.write(re.sub(pat, s_after, line)) + out.close() + f.close(); + os.remove(fname) + os.rename(out_fname, fname) + +def simplifyInclude(target, source, env): + fileReplace(target[0].rstr(), "#include\s+\"(\.\./)+", "#include \"" + os.getcwd().replace("\\", "/") + "/" ); + return None + def checkMocIncluded(target, source, env): - moc = target[0] - cpp = source[0] - # looks like cpp.includes is cleared before the build stage :-( - # not really sure about the path transformations (moc.cwd? cpp.cwd?) :-/ - path = SCons.Defaults.CScan.path(env, moc.cwd) - includes = SCons.Defaults.CScan(cpp, env, path) - if not moc in includes: - SCons.Warnings.warn( - GeneratedMocFileNotIncluded, - "Generated moc file '%s' is not included by '%s'" % - (str(moc), str(cpp))) + moc = target[0] + cpp = source[0] + # looks like cpp.includes is cleared before the build stage :-( + # not really sure about the path transformations (moc.cwd? cpp.cwd?) :-/ + path = SCons.Defaults.CScan.path(env, moc.cwd) + includes = SCons.Defaults.CScan(cpp, env, path) + if not moc in includes: + SCons.Warnings.warn( + GeneratedMocFileNotIncluded, + "Generated moc file '%s' is not included by '%s'" % + (str(moc), str(cpp))) def find_file(filename, paths, node_factory): - for dir in paths: - node = node_factory(filename, dir) - if node.rexists(): - return node - return None + for dir in paths: + node = node_factory(filename, dir) + if node.rexists(): + return node + return None class _Automoc(object): - """ - Callable class, which works as an emitter for Programs, SharedLibraries and - StaticLibraries. - """ - - def __init__(self, objBuilderName): - self.objBuilderName = objBuilderName - - def __call__(self, target, source, env): - """ - Smart autoscan function. Gets the list of objects for the Program - or Lib. Adds objects and builders for the special qt files. - """ - try: - if int(env.subst('$QT_AUTOSCAN')) == 0: - return target, source - except ValueError: - pass - try: - debug = int(env.subst('$QT_DEBUG')) - except ValueError: - debug = 0 - - # some shortcuts used in the scanner - splitext = SCons.Util.splitext - objBuilder = getattr(env, self.objBuilderName) + """ + Callable class, which works as an emitter for Programs, SharedLibraries and + StaticLibraries. + """ + + def __init__(self, objBuilderName): + self.objBuilderName = objBuilderName + + def __call__(self, target, source, env): + """ + Smart autoscan function. Gets the list of objects for the Program + or Lib. Adds objects and builders for the special qt files. + """ + try: + if int(env.subst('$QT_AUTOSCAN')) == 0: + return target, source + except ValueError: + pass + try: + debug = int(env.subst('$QT_DEBUG')) + except ValueError: + debug = 0 + + # some shortcuts used in the scanner + splitext = SCons.Util.splitext + objBuilder = getattr(env, self.objBuilderName) - # some regular expressions: - # Q_OBJECT detection - q_object_search = re.compile(r'[^A-Za-z0-9]Q_OBJECT[^A-Za-z0-9]') - # cxx and c comment 'eater' - #comment = re.compile(r'(//.*)|(/\*(([^*])|(\*[^/]))*\*/)') - # CW: something must be wrong with the regexp. See also bug #998222 - # CURRENTLY THERE IS NO TEST CASE FOR THAT - - # The following is kind of hacky to get builders working properly (FIXME) - objBuilderEnv = objBuilder.env - objBuilder.env = env - mocBuilderEnv = env.Moc.env - env.Moc.env = env - - # make a deep copy for the result; MocH objects will be appended - out_sources = source[:] - - for obj in SCons.Util.flatten(source): - if not obj.has_builder(): - # binary obj file provided - if debug: - print "scons: qt: '%s' seems to be a binary. Discarded." % str(obj) - continue - cpp = obj.sources[0] - if not splitext(str(cpp))[1] in cxx_suffixes: - if debug: - print "scons: qt: '%s' is no cxx file. Discarded." % str(cpp) - # c or fortran source - continue - #cpp_contents = comment.sub('', cpp.get_text_contents()) - cpp_contents = cpp.get_text_contents() - h=None - for h_ext in header_extensions: - # try to find the header file in the corresponding source - # directory - hname = splitext(cpp.name)[0] + h_ext - h = find_file(hname, (cpp.get_dir(),), env.File) - if h: - if debug: - print "scons: qt: Scanning '%s' (header of '%s')" % (str(h), str(cpp)) - #h_contents = comment.sub('', h.get_text_contents()) - h_contents = h.get_text_contents() - break - if not h and debug: - print "scons: qt: no header for '%s'." % (str(cpp)) - if h and q_object_search.search(h_contents): - # h file with the Q_OBJECT macro found -> add moc_cpp - moc_cpp = env.Moc(h) - moc_o = objBuilder(moc_cpp) - out_sources.append(moc_o) - #moc_cpp.target_scanner = SCons.Defaults.CScan - if debug: - print "scons: qt: found Q_OBJECT macro in '%s', moc'ing to '%s'" % (str(h), str(moc_cpp)) - if cpp and q_object_search.search(cpp_contents): - # cpp file with Q_OBJECT macro found -> add moc - # (to be included in cpp) - moc = env.Moc(cpp) - env.Ignore(moc, moc) - if debug: - print "scons: qt: found Q_OBJECT macro in '%s', moc'ing to '%s'" % (str(cpp), str(moc)) - #moc.source_scanner = SCons.Defaults.CScan - # restore the original env attributes (FIXME) - objBuilder.env = objBuilderEnv - env.Moc.env = mocBuilderEnv - - return (target, out_sources) + # some regular expressions: + # Q_OBJECT detection + q_object_search = re.compile(r'[^A-Za-z0-9]Q_OBJECT[^A-Za-z0-9]') + # cxx and c comment 'eater' + #comment = re.compile(r'(//.*)|(/\*(([^*])|(\*[^/]))*\*/)') + # CW: something must be wrong with the regexp. See also bug #998222 + # CURRENTLY THERE IS NO TEST CASE FOR THAT + + # The following is kind of hacky to get builders working properly (FIXME) + objBuilderEnv = objBuilder.env + objBuilder.env = env + mocBuilderEnv = env.Moc.env + env.Moc.env = env + + # make a deep copy for the result; MocH objects will be appended + out_sources = source[:] + + for obj in source: + if not obj.has_builder(): + # binary obj file provided + if debug: + print "scons: qt: '%s' seems to be a binary. Discarded." % str(obj) + continue + cpp = obj.sources[0] + if not splitext(str(cpp))[1] in cxx_suffixes: + if debug: + print "scons: qt: '%s' is no cxx file. Discarded." % str(cpp) + # c or fortran source + continue + #cpp_contents = comment.sub('', cpp.get_text_contents()) + cpp_contents = cpp.get_text_contents() + h=None + for h_ext in header_extensions: + # try to find the header file in the corresponding source + # directory + hname = splitext(cpp.name)[0] + h_ext + h = find_file(hname, (cpp.get_dir(),), env.File) + if h: + if debug: + print "scons: qt: Scanning '%s' (header of '%s')" % (str(h), str(cpp)) + #h_contents = comment.sub('', h.get_text_contents()) + h_contents = h.get_text_contents() + break + if not h and debug: + print "scons: qt: no header for '%s'." % (str(cpp)) + if h and q_object_search.search(h_contents): + # h file with the Q_OBJECT macro found -> add moc_cpp + moc_cpp = env.Moc(h) + moc_o = objBuilder(moc_cpp) + out_sources.append(moc_o) + #moc_cpp.target_scanner = SCons.Defaults.CScan + if debug: + print "scons: qt: found Q_OBJECT macro in '%s', moc'ing to '%s'" % (str(h), str(moc_cpp)) + if cpp and q_object_search.search(cpp_contents): + # cpp file with Q_OBJECT macro found -> add moc + # (to be included in cpp) + moc = env.Moc(cpp) + env.Ignore(moc, moc) + if debug: + print "scons: qt: found Q_OBJECT macro in '%s', moc'ing to '%s'" % (str(cpp), str(moc)) + #moc.source_scanner = SCons.Defaults.CScan + # restore the original env attributes (FIXME) + objBuilder.env = objBuilderEnv + env.Moc.env = mocBuilderEnv + + return (target, out_sources) AutomocShared = _Automoc('SharedObject') AutomocStatic = _Automoc('StaticObject') +def _detect(env): + """Not really safe, but fast method to detect the QT library""" + QTDIR = None + if not QTDIR: + QTDIR = env.get('QTDIR',None) + if not QTDIR: + QTDIR = os.environ.get('QTDIR',None) + if not QTDIR: + moc = env.WhereIs('moc') + if moc: + QTDIR = os.path.dirname(os.path.dirname(moc)) + SCons.Warnings.warn( + QtdirNotFound, + "Could not detect qt, using moc executable as a hint (QTDIR=%s)" % QTDIR) + else: + QTDIR = None + SCons.Warnings.warn( + QtdirNotFound, + "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( - #env.File( - adjustixes( - bs, - env.subst('$QT_UICIMPLPREFIX'), - env.subst('$QT_UICIMPLSUFFIX') - ) - #) - ) - #if len(target) < 3: - # # third target is moc file - # target.append( - # #env.File( - # adjustixes( - # bs, - # env.subst('$QT_MOCHPREFIX')+'ui_',#+env.subst('$QT_UICIMPLPREFIX'), # to check - # env.subst('$QT_MOCHSUFFIX')#+env.subst('$QT_UICIMPLSUFFIX') - # ) - # #) - # ) - #print '-- uicEmitter --' - #for i in range(len(target)): - # if not isinstance( target[i], str ): - # print 'target['+str(i)+']', target[i].str_for_display() - # else: - # print 'target['+str(i)+']', target[i] - #for i in range(len(source)): - # if not isinstance( source[i], str ): - # print 'source['+str(i)+']', source[i].str_for_display() - # else: - # print 'source['+str(i)+']', source[i] - #print '-- uicEmitter --' - return target, source + 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 uicScannerFunc(node, env, path): - lookout = [] - lookout.extend(env['CPPPATH']) - lookout.append(str(node.rfile().dir)) - includes = re.findall("(.*?)", node.get_text_contents()) - result = [] - for incFile in includes: - dep = env.FindFile(incFile,lookout) - if dep: - result.append(dep) - #print 'uicScannerFunc: ', result - return result - -uicScanner = SCons.Scanner.Base( - uicScannerFunc, - name = "UicScanner", - node_class = SCons.Node.FS.File, - node_factory = SCons.Node.FS.File, - recursive = 0 - ) + lookout = [] + lookout.extend(env['CPPPATH']) + lookout.append(str(node.rfile().dir)) + includes = re.findall("(.*?)", node.get_text_contents()) + result = [] + for incFile in includes: + dep = env.FindFile(incFile,lookout) + if dep: + result.append(dep) + return result + +uicScanner = SCons.Scanner.Base(uicScannerFunc, + name = "UicScanner", + node_class = SCons.Node.FS.File, + node_factory = SCons.Node.FS.File, + recursive = 0) def generate(env): - """Add Builders and construction variables for qt to an Environment.""" - CLVar = SCons.Util.CLVar - Action = SCons.Action.Action - Builder = SCons.Builder.Builder - - env.SetDefault( - 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 = '', #'ui_', - QT_UICDECLSUFFIX = '.h', - QT_UICIMPLPREFIX = '', #'ui_', - 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 = SCons.Action.Action('$QT_UICCOM', '$QT_UICCOMSTR'), - emitter = uicEmitter, - src_suffix = '$QT_UISUFFIX', - suffix = '$QT_UICDECLSUFFIX', - prefix = '$QT_UICDECLPREFIX', - source_scanner = uicScanner, - ) - - mocBld = Builder(action={}, prefix={}, suffix={}) - for h in header_extensions: - act = SCons.Action.Action('$QT_MOCFROMHCOM', '$QT_MOCFROMHCOMSTR') - mocBld.add_action(h, act) - mocBld.prefix[h] = '$QT_MOCHPREFIX' - mocBld.suffix[h] = '$QT_MOCHSUFFIX' - for cxx in cxx_suffixes: - act = SCons.Action.Action('$QT_MOCFROMCXXCOM', '$QT_MOCFROMCXXCOMSTR') - mocBld.add_action(cxx, act) - mocBld.prefix[cxx] = '$QT_MOCCXXPREFIX' - mocBld.suffix[cxx] = '$QT_MOCCXXSUFFIX' - - # register the builders - env['BUILDERS']['Uic'] = uicBld - env['BUILDERS']['Moc'] = mocBld - static_obj, shared_obj = SCons.Tool.createObjBuilders(env) - static_obj.add_src_builder('Uic') - shared_obj.add_src_builder('Uic') - - env.AddMethod( enableQtEmmitters, "EnableQtEmmitters") - + """Add Builders and construction variables for qt to an Environment.""" + CLVar = SCons.Util.CLVar + Action = SCons.Action.Action + Builder = SCons.Builder.Builder + + 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', + QT4_LUPDATE = os.path.join('$QT_BINPATH','lupdate'), + QT4_LRELEASE = os.path.join('$QT_BINPATH','lrelease'), + QT4_LUPDATECOM = '$QT4_LUPDATE $SOURCE -ts $TARGET', + QT4_LRELEASECOM = '$QT4_LRELEASE $SOURCE', + + # 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 = [ + CLVar('$QT_MOC $QT_MOCFROMHFLAGS -o ${TARGETS[0]} $SOURCE'), Action(simplifyInclude) ], + # 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), Action(simplifyInclude)] + ) + + # ... and the corresponding builders + uicBld = Builder(action=SCons.Action.Action('$QT_UICCOM', '$QT_UICCOMSTR'), + emitter=uicEmitter, + src_suffix='$QT_UISUFFIX', + suffix='$QT_UICDECLSUFFIX', + prefix='$QT_UICDECLPREFIX', + source_scanner=uicScanner) + mocBld = Builder(action={}, prefix={}, suffix={}) + for h in header_extensions: + act = SCons.Action.Action('$QT_MOCFROMHCOM', '$QT_MOCFROMHCOMSTR') + mocBld.add_action(h, act) + mocBld.prefix[h] = '$QT_MOCHPREFIX' + mocBld.suffix[h] = '$QT_MOCHSUFFIX' + for cxx in cxx_suffixes: + act = SCons.Action.Action('$QT_MOCFROMCXXCOM', '$QT_MOCFROMCXXCOMSTR') + mocBld.add_action(cxx, act) + mocBld.prefix[cxx] = '$QT_MOCCXXPREFIX' + mocBld.suffix[cxx] = '$QT_MOCCXXSUFFIX' + + # register the builders + # Translation builder + tsbuilder = Builder( + action = SCons.Action.Action('$QT4_LUPDATECOM'), #,'$QT4_LUPDATECOMSTR'), + multi=1 + ) + qmbuilder = Builder( + action = SCons.Action.Action('$QT4_LRELEASECOM'),# , '$QT4_LRELEASECOMSTR'), + src_suffix = '.ts', + suffix = '.qm', + single_source = True + ) + + env['BUILDERS']['Ts'] = tsbuilder + env['BUILDERS']['Qm'] = qmbuilder + env['BUILDERS']['Uic'] = uicBld + env['BUILDERS']['Uic'] = uicBld + env['BUILDERS']['Moc'] = mocBld + static_obj, shared_obj = SCons.Tool.createObjBuilders(env) + static_obj.add_src_builder('Uic') + shared_obj.add_src_builder('Uic') + + # We use the emitters of Program / StaticLibrary / SharedLibrary + # to scan for moc'able files + # We can't refer to the builders directly, we have to fetch them + # as Environment attributes because that sets them up to be called + # correctly later by our emitter. + env.AppendUnique(PROGEMITTER =[AutomocStatic], + SHLIBEMITTER=[AutomocShared], + LIBEMITTER =[AutomocStatic], + # Of course, we need to link against the qt libraries + CPPPATH=["$QT_CPPPATH"], + LIBPATH=["$QT_LIBPATH"]) + env.AddMethod( enableQtEmmitters, "EnableQtEmmitters") def enableQtEmmitters(self): - # We use the emitters of Program / StaticLibrary / SharedLibrary - # to scan for moc'able files - # We can't refer to the builders directly, we have to fetch them - # as Environment attributes because that sets them up to be called - # correctly later by our emitter. - self.AppendUnique( - PROGEMITTER = [AutomocStatic], - SHLIBEMITTER = [AutomocShared], - LIBEMITTER = [AutomocStatic], - ) + # We use the emitters of Program / StaticLibrary / SharedLibrary + # to scan for moc'able files + # We can't refer to the builders directly, we have to fetch them + # as Environment attributes because that sets them up to be called + # correctly later by our emitter. + self.AppendUnique( + PROGEMITTER = [AutomocStatic], + SHLIBEMITTER = [AutomocShared], + LIBEMITTER = [AutomocStatic], + ) def exists(env): - return True - + return _detect(env) From 7ab39b8ddd083889d5f4b93a9b9b23ca244c2dd8 Mon Sep 17 00:00:00 2001 From: Du Bois Date: Tue, 9 Jul 2013 21:54:02 +0200 Subject: [PATCH 12/22] sconsProject: experimental branch comments * added comments for win32 commands spawn * added comments for qt.py include simplifier --- __init__.py | 9 +++++++-- tools/qt.py | 3 +++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/__init__.py b/__init__.py index 8287959..0678fa1 100755 --- a/__init__.py +++ b/__init__.py @@ -31,8 +31,11 @@ def join_if_basedir_not_empty( *dirs ): return '' return os.path.join(*dirs) +# taken from http://scons.org/wiki/LongCmdLinesOnWin32 +# this is used to avoid 'command line too long' issues on MS windows OS class VisualCSpawn: def visualcspawn(self, sh, escape, cmd, args, env): + # run processes with Popen, this avoid to get 'command line too long' issues newargs = ' '.join(args[1:]) cmdline = cmd + " " + newargs startupinfo = subprocess.STARTUPINFO() @@ -48,6 +51,7 @@ def visualcspawn(self, sh, escape, cmd, args, env): return rv def setupSpawn( env ): + # only use spawn on win32 environments if sys.platform == 'win32': buf = VisualCSpawn() buf.visualCSpawnEnv = env @@ -191,6 +195,7 @@ def __init__(self): #if self.windows: self.env['ENV']['PATH'] = os.environ['PATH'] # access to the compiler (if not in '/usr/bin') +# disabled win32 command line spawn until having a better test case. # setupSpawn( self.env ); # scons optimizations... @@ -205,6 +210,8 @@ def __init__(self): self.env.Decider('MD5-timestamp') # This option tells SCons to intelligently cache implicit dependencies. It attempts to determine if the implicit dependencies have changed since the last build, and if so it will recalculate them. This is usually slower than using --implicit-deps-unchanged, but is also more accurate. SetOption('implicit_cache', 1) + # This option tells SCons to intelligently cache implicit dependencies. It attempts to determine if the implicit dependencies have changed since the last build, and if so it will recalculate them. This is usually slower than using --implicit-deps-unchanged, but is also more accurate. + SetOption('implicit_cache', 1) # By default SCons will calculate the MD5 checksum of every source file in your build each time it is run, and will only cache the checksum after the file is 2 days old. This default of 2 days is to protect from clock skew from NFS or revision control systems. You can tweak this delay using --max-drift=SECONDS where SECONDS is some number of seconds. Decreasing SECONDS can improve build speed by eliminating superfluous MD5 checksum calculations. SetOption('max_drift', 60 * 15) # cache the checksum after max_drift seconds # Normally you tell Scons about include directories by setting the CPPPATH construction variable, which causes SCons to search those directories when doing implicit dependency scans and also includes those directories in the compile command line. If you have header files that never or rarely change (e.g. system headers, or C run-time headers), then you can exclude them from CPPPATH and include them in the CCFLAGS construction variable instead, which causes SCons to ignore those include directories when scanning for implicit dependencies. Carefully tuning the include directories in this way can usually result in a dramatic speed increase with very little loss of accuracy. @@ -1702,5 +1709,3 @@ def subdirsContaining(self, directory, patterns): dirs.sort() return dirs - -__all__ = ['SConsProject'] diff --git a/tools/qt.py b/tools/qt.py index 6e6a6d3..7a36d37 100644 --- a/tools/qt.py +++ b/tools/qt.py @@ -63,6 +63,7 @@ class QtdirNotFound(ToolQtWarning): #cxx_suffixes = cplusplus.CXXSuffixes cxx_suffixes = [".c", ".cxx", ".cpp", ".cc"] +# this function replace a given pattern (pat) by s_after inside the file fname def fileReplace(fname, pat, s_after): # first, see if the pattern is even in the file. with open(fname) as f: @@ -80,6 +81,8 @@ def fileReplace(fname, pat, s_after): os.remove(fname) os.rename(out_fname, fname) +# simplify very long useless includes such as #include "../../../../foo.hpp" with #include "./foo.hpp" +# this is useful because moc generates very long relative includes that implies issues on windows OS. def simplifyInclude(target, source, env): fileReplace(target[0].rstr(), "#include\s+\"(\.\./)+", "#include \"" + os.getcwd().replace("\\", "/") + "/" ); return None From a7fcc3ace5cd6651cb1bd14e7ab1c897c7e678a5 Mon Sep 17 00:00:00 2001 From: Du Bois Eloi Date: Tue, 5 Nov 2013 20:52:53 +0100 Subject: [PATCH 13/22] sconsProject: qt5 compilation. --- autoconf/qt5.py | 148 ++++++++++++ autoconf/qxorm.py | 4 +- tools/qt.py | 573 +++++++++++++++++++++++----------------------- 3 files changed, 434 insertions(+), 291 deletions(-) create mode 100644 autoconf/qt5.py mode change 100755 => 100644 autoconf/qxorm.py diff --git a/autoconf/qt5.py b/autoconf/qt5.py new file mode 100644 index 0000000..3e04dc4 --- /dev/null +++ b/autoconf/qt5.py @@ -0,0 +1,148 @@ +from _external import * +import os +import SCons.Util + +def unique(list): + return dict.fromkeys(list).keys() + +def subdirs(files): + dirs = unique(map(os.path.dirname, files)) + dirs.sort() + return dirs + +def locateQt5Command(env, command, bindir): + #print 'locateQt5Command:', command + suffixes = [ + '-qt5', + '5', + '', + ] + progs = [command+s for s in suffixes] + for prog in progs: + path = env.WhereIs(prog, path=bindir) + if path: + return path + for prog in progs: + path = env.WhereIs(prog) + if path: + return path + + msg = 'Qt5 command "' + command + '" not found. Tried: ' + str(progs) + '.' + #raise Exception(msg) + print 'Warning: ', msg + return command + +class Qt5Checker(LibWithHeaderChecker): + ''' + Qt5 checker + ''' + allUiFiles = [] + + def __init__( self, + modules = [ + 'QtCore', + 'QtGui', + 'QtOpenGL', + 'QtWidgets', + 'QtPrintSuppport', + ], + uiFiles = [], + defines = ['QT_NO_KEYWORDS'], + useLocalIncludes = True ): + self.name = 'qt5' + postfix = '' if not windows else '5' + self.libs = [ m + postfix for m in modules] + self.uiFiles =self.getAbsoluteCwd(uiFiles) + self.defines = defines[:] + self.useLocalIncludes = useLocalIncludes + + def setModules(self, modules): + self.libs = modules[:] + + def declareUiFiles(self, uiFiles): + self.uiFiles.extend( self.getAbsoluteCwd(uiFiles) ) + + def initEnv(self, project, env): + # use qt scons tool + env.Tool('qt') + + def initOptions(self, project, opts): + LibWithHeaderChecker.initOptions(self, project, opts) + opts.Add( 'bindir_'+self.name, 'Base directory for '+self.name, '${_join_if_basedir_not_empty( dir_'+self.name+ ', "bin" )}' ) + return True + + def configure(self, project, env): + env.EnableQtEmmitters() + + bindir = '$bindir_'+self.name + moc = locateQt5Command(env, 'moc', bindir) + uic = locateQt5Command(env, 'uic', bindir) + rcc = locateQt5Command(env, 'rcc', bindir) + lupdate = locateQt5Command(env, 'lupdate', bindir) + lrelease = locateQt5Command(env, 'lrelease', bindir) + + # specific part for Qt5 + env.Replace( + # suffixes/prefixes for the headers / sources to generate + QT_UICDECLPREFIX = 'ui_', + QT_UICDECLSUFFIX = '.h', + QT_UICIMPLPREFIX = 'ui_', + QT_UICIMPLSUFFIX = '$CXXFILESUFFIX', + QT_MOCHPREFIX = 'moc_', + QT_MOCHSUFFIX = '$CXXFILESUFFIX', + QT_MOCCXXPREFIX = '', + QT_MOCCXXSUFFIX = '.moc', + QT_UISUFFIX = '.ui', + + # Qt commands + # command to generate header from a .ui file + QT_UICCOM = [ + SCons.Util.CLVar('$QT_UIC $QT_UICDECLFLAGS -o ${TARGETS[0]} $SOURCE'), + ], + ) + + env.SetDefault( + QT_MOC = moc, + QT_UIC = uic, + QT5_RCC = rcc, + QT5_LUPDATE = lupdate, + QT5_LRELEASE = lrelease, + ) + + # don't need emitter with qt5 + env['BUILDERS']['Uic'].emitter = None + + if env['mode'] != 'debug' : + env.AppendUnique( CPPDEFINES = 'QMLJSDEBUGGER' ) + env.AppendUnique( CPPDEFINES = 'QT_DECLARATIVE_DEBUG' ) # QtQuick 1 + #env.AppendUnique( CPPDEFINES = 'QT_QML_DEBUG' ) # QtQuick 2 + + return BaseLibChecker.configure(self, project, env) + + def check(self, project, conf): + conf.env.AppendUnique( CPPDEFINES = self.defines ) + result = True + for mod in self.getLibs(conf.env): + r = self.CheckLibWithHeader( conf, [mod], header=[mod+'/'+mod], language='c++' ) + if not r: + print 'error: ',mod + result &= r + return result + + def postconfigure(self, project, env, level): + ''' + Add things for ui files after all libs check. + ''' + if len(self.uiFiles): + for ui in self.uiFiles: + # do not redeclare a ui file + if ui not in Qt5Checker.allUiFiles: + env.Uic( ui ) + Qt5Checker.allUiFiles.append( ui ) + if self.useLocalIncludes: + env.AppendUnique( CPPPATH=subdirs(self.uiFiles) ) + return True + +qt5 = Qt5Checker + + diff --git a/autoconf/qxorm.py b/autoconf/qxorm.py old mode 100755 new mode 100644 index 0048aae..1c0f36a --- a/autoconf/qxorm.py +++ b/autoconf/qxorm.py @@ -1,13 +1,13 @@ from _external import * from boost import * from boost_serialization import * -from qt4 import * +from qt5 import * qxorm = LibWithHeaderChecker( 'QxOrm', 'QxOrm.h', 'c++', name='qxorm', - dependencies= [ boost, boost_serialization, qt4(modules=[ 'QtCore', 'QtGui', 'QtSql' ] ) ], + dependencies= [ boost, boost_serialization, qt5(modules=[ 'QtCore', 'QtGui', 'QtSql' ] ) ], ) diff --git a/tools/qt.py b/tools/qt.py index 7a36d37..86dbe84 100644 --- a/tools/qt.py +++ b/tools/qt.py @@ -10,7 +10,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,11 +32,10 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/qt.py 2013/03/03 09:48:35 garyo" +__revision__ = "src/engine/SCons/Tool/qt.py 5023 2010/06/14 22:05:46 scons" -import os +import os.path import re -import sys import SCons.Action import SCons.Builder @@ -46,20 +45,22 @@ import SCons.Util class ToolQtWarning(SCons.Warnings.Warning): - pass + pass class GeneratedMocFileNotIncluded(ToolQtWarning): - pass + pass class QtdirNotFound(ToolQtWarning): - pass + pass SCons.Warnings.enableWarningClass(ToolQtWarning) header_extensions = [".h", ".hxx", ".hpp", ".hh"] if SCons.Util.case_sensitive_suffixes('.h', '.H'): - header_extensions.append('.H') -#cplusplus = __import__('c++', globals(), locals(), []) + header_extensions.append('.H') +# TODO: The following two lines will work when integrated back to SCons +# TODO: Meanwhile the third line will do the work +#cplusplus = __import__('SCons.Tool.c++', globals(), locals(), []) #cxx_suffixes = cplusplus.CXXSuffixes cxx_suffixes = [".c", ".cxx", ".cpp", ".cc"] @@ -88,301 +89,295 @@ def simplifyInclude(target, source, env): return None def checkMocIncluded(target, source, env): - moc = target[0] - cpp = source[0] - # looks like cpp.includes is cleared before the build stage :-( - # not really sure about the path transformations (moc.cwd? cpp.cwd?) :-/ - path = SCons.Defaults.CScan.path(env, moc.cwd) - includes = SCons.Defaults.CScan(cpp, env, path) - if not moc in includes: - SCons.Warnings.warn( - GeneratedMocFileNotIncluded, - "Generated moc file '%s' is not included by '%s'" % - (str(moc), str(cpp))) + moc = target[0] + cpp = source[0] + # looks like cpp.includes is cleared before the build stage :-( + # not really sure about the path transformations (moc.cwd? cpp.cwd?) :-/ + path = SCons.Defaults.CScan.path(env, moc.cwd) + includes = SCons.Defaults.CScan(cpp, env, path) + if not moc in includes: + SCons.Warnings.warn( + GeneratedMocFileNotIncluded, + "Generated moc file '%s' is not included by '%s'" % + (str(moc), str(cpp))) def find_file(filename, paths, node_factory): - for dir in paths: - node = node_factory(filename, dir) - if node.rexists(): - return node - return None + for dir in paths: + node = node_factory(filename, dir) + if node.rexists(): + return node + return None class _Automoc(object): - """ - Callable class, which works as an emitter for Programs, SharedLibraries and - StaticLibraries. - """ - - def __init__(self, objBuilderName): - self.objBuilderName = objBuilderName - - def __call__(self, target, source, env): - """ - Smart autoscan function. Gets the list of objects for the Program - or Lib. Adds objects and builders for the special qt files. - """ - try: - if int(env.subst('$QT_AUTOSCAN')) == 0: - return target, source - except ValueError: - pass - try: - debug = int(env.subst('$QT_DEBUG')) - except ValueError: - debug = 0 - - # some shortcuts used in the scanner - splitext = SCons.Util.splitext - objBuilder = getattr(env, self.objBuilderName) + """ + Callable class, which works as an emitter for Programs, SharedLibraries and + StaticLibraries. + """ + + def __init__(self, objBuilderName): + self.objBuilderName = objBuilderName + + def __call__(self, target, source, env): + """ + Smart autoscan function. Gets the list of objects for the Program + or Lib. Adds objects and builders for the special qt files. + """ + try: + if int(env.subst('$QT_AUTOSCAN')) == 0: + return target, source + except ValueError: + pass + try: + debug = int(env.subst('$QT_DEBUG')) + except ValueError: + debug = 0 + + # some shortcuts used in the scanner + splitext = SCons.Util.splitext + objBuilder = getattr(env, self.objBuilderName) - # some regular expressions: - # Q_OBJECT detection - q_object_search = re.compile(r'[^A-Za-z0-9]Q_OBJECT[^A-Za-z0-9]') - # cxx and c comment 'eater' - #comment = re.compile(r'(//.*)|(/\*(([^*])|(\*[^/]))*\*/)') - # CW: something must be wrong with the regexp. See also bug #998222 - # CURRENTLY THERE IS NO TEST CASE FOR THAT - - # The following is kind of hacky to get builders working properly (FIXME) - objBuilderEnv = objBuilder.env - objBuilder.env = env - mocBuilderEnv = env.Moc.env - env.Moc.env = env - - # make a deep copy for the result; MocH objects will be appended - out_sources = source[:] - - for obj in source: - if not obj.has_builder(): - # binary obj file provided - if debug: - print "scons: qt: '%s' seems to be a binary. Discarded." % str(obj) - continue - cpp = obj.sources[0] - if not splitext(str(cpp))[1] in cxx_suffixes: - if debug: - print "scons: qt: '%s' is no cxx file. Discarded." % str(cpp) - # c or fortran source - continue - #cpp_contents = comment.sub('', cpp.get_text_contents()) - cpp_contents = cpp.get_text_contents() - h=None - for h_ext in header_extensions: - # try to find the header file in the corresponding source - # directory - hname = splitext(cpp.name)[0] + h_ext - h = find_file(hname, (cpp.get_dir(),), env.File) - if h: - if debug: - print "scons: qt: Scanning '%s' (header of '%s')" % (str(h), str(cpp)) - #h_contents = comment.sub('', h.get_text_contents()) - h_contents = h.get_text_contents() - break - if not h and debug: - print "scons: qt: no header for '%s'." % (str(cpp)) - if h and q_object_search.search(h_contents): - # h file with the Q_OBJECT macro found -> add moc_cpp - moc_cpp = env.Moc(h) - moc_o = objBuilder(moc_cpp) - out_sources.append(moc_o) - #moc_cpp.target_scanner = SCons.Defaults.CScan - if debug: - print "scons: qt: found Q_OBJECT macro in '%s', moc'ing to '%s'" % (str(h), str(moc_cpp)) - if cpp and q_object_search.search(cpp_contents): - # cpp file with Q_OBJECT macro found -> add moc - # (to be included in cpp) - moc = env.Moc(cpp) - env.Ignore(moc, moc) - if debug: - print "scons: qt: found Q_OBJECT macro in '%s', moc'ing to '%s'" % (str(cpp), str(moc)) - #moc.source_scanner = SCons.Defaults.CScan - # restore the original env attributes (FIXME) - objBuilder.env = objBuilderEnv - env.Moc.env = mocBuilderEnv - - return (target, out_sources) + # some regular expressions: + # Q_OBJECT detection + q_object_search = re.compile(r'[^A-Za-z0-9]Q_OBJECT[^A-Za-z0-9]') + # cxx and c comment 'eater' + #comment = re.compile(r'(//.*)|(/\*(([^*])|(\*[^/]))*\*/)') + # CW: something must be wrong with the regexp. See also bug #998222 + # CURRENTLY THERE IS NO TEST CASE FOR THAT + + # The following is kind of hacky to get builders working properly (FIXME) + objBuilderEnv = objBuilder.env + objBuilder.env = env + mocBuilderEnv = env.Moc.env + env.Moc.env = env + + # make a deep copy for the result; MocH objects will be appended + out_sources = source[:] + + for obj in SCons.Util.flatten(source): + if not obj.has_builder(): + # binary obj file provided + if debug: + print "scons: qt: '%s' seems to be a binary. Discarded." % str(obj) + continue + cpp = obj.sources[0] + if not splitext(str(cpp))[1] in cxx_suffixes: + if debug: + print "scons: qt: '%s' is no cxx file. Discarded." % str(cpp) + # c or fortran source + continue + #cpp_contents = comment.sub('', cpp.get_text_contents()) + cpp_contents = cpp.get_text_contents() + h=None + for h_ext in header_extensions: + # try to find the header file in the corresponding source + # directory + hname = splitext(cpp.name)[0] + h_ext + h = find_file(hname, (cpp.get_dir(),), env.File) + if h: + if debug: + print "scons: qt: Scanning '%s' (header of '%s')" % (str(h), str(cpp)) + #h_contents = comment.sub('', h.get_text_contents()) + h_contents = h.get_text_contents() + break + if not h and debug: + print "scons: qt: no header for '%s'." % (str(cpp)) + if h and q_object_search.search(h_contents): + # h file with the Q_OBJECT macro found -> add moc_cpp + moc_cpp = env.Moc(h) + moc_o = objBuilder(moc_cpp) + out_sources.append(moc_o) + #moc_cpp.target_scanner = SCons.Defaults.CScan + if debug: + print "scons: qt: found Q_OBJECT macro in '%s', moc'ing to '%s'" % (str(h), str(moc_cpp)) + if cpp and q_object_search.search(cpp_contents): + # cpp file with Q_OBJECT macro found -> add moc + # (to be included in cpp) + moc = env.Moc(cpp) + env.Ignore(moc, moc) + if debug: + print "scons: qt: found Q_OBJECT macro in '%s', moc'ing to '%s'" % (str(cpp), str(moc)) + #moc.source_scanner = SCons.Defaults.CScan + # restore the original env attributes (FIXME) + objBuilder.env = objBuilderEnv + env.Moc.env = mocBuilderEnv + + return (target, out_sources) AutomocShared = _Automoc('SharedObject') AutomocStatic = _Automoc('StaticObject') -def _detect(env): - """Not really safe, but fast method to detect the QT library""" - QTDIR = None - if not QTDIR: - QTDIR = env.get('QTDIR',None) - if not QTDIR: - QTDIR = os.environ.get('QTDIR',None) - if not QTDIR: - moc = env.WhereIs('moc') - if moc: - QTDIR = os.path.dirname(os.path.dirname(moc)) - SCons.Warnings.warn( - QtdirNotFound, - "Could not detect qt, using moc executable as a hint (QTDIR=%s)" % QTDIR) - else: - QTDIR = None - SCons.Warnings.warn( - QtdirNotFound, - "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 + 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( + #env.File( + adjustixes( + bs, + env.subst('$QT_UICIMPLPREFIX'), + env.subst('$QT_UICIMPLSUFFIX') + ) + #) + ) + #if len(target) < 3: + # # third target is moc file + # target.append( + # #env.File( + # adjustixes( + # bs, + # env.subst('$QT_MOCHPREFIX')+'ui_',#+env.subst('$QT_UICIMPLPREFIX'), # to check + # env.subst('$QT_MOCHSUFFIX')#+env.subst('$QT_UICIMPLSUFFIX') + # ) + # #) + # ) + #print '-- uicEmitter --' + #for i in range(len(target)): + # if not isinstance( target[i], str ): + # print 'target['+str(i)+']', target[i].str_for_display() + # else: + # print 'target['+str(i)+']', target[i] + #for i in range(len(source)): + # if not isinstance( source[i], str ): + # print 'source['+str(i)+']', source[i].str_for_display() + # else: + # print 'source['+str(i)+']', source[i] + #print '-- uicEmitter --' + return target, source def uicScannerFunc(node, env, path): - lookout = [] - lookout.extend(env['CPPPATH']) - lookout.append(str(node.rfile().dir)) - includes = re.findall("(.*?)", node.get_text_contents()) - result = [] - for incFile in includes: - dep = env.FindFile(incFile,lookout) - if dep: - result.append(dep) - return result - -uicScanner = SCons.Scanner.Base(uicScannerFunc, - name = "UicScanner", - node_class = SCons.Node.FS.File, - node_factory = SCons.Node.FS.File, - recursive = 0) + lookout = [] + lookout.extend(env['CPPPATH']) + lookout.append(str(node.rfile().dir)) + includes = re.findall("(.*?)", node.get_text_contents()) + result = [] + for incFile in includes: + dep = env.FindFile(incFile,lookout) + if dep: + result.append(dep) + #print 'uicScannerFunc: ', result + return result + +uicScanner = SCons.Scanner.Base( + uicScannerFunc, + name = "UicScanner", + node_class = SCons.Node.FS.File, + node_factory = SCons.Node.FS.File, + recursive = 0 + ) def generate(env): - """Add Builders and construction variables for qt to an Environment.""" - CLVar = SCons.Util.CLVar - Action = SCons.Action.Action - Builder = SCons.Builder.Builder - - 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', - QT4_LUPDATE = os.path.join('$QT_BINPATH','lupdate'), - QT4_LRELEASE = os.path.join('$QT_BINPATH','lrelease'), - QT4_LUPDATECOM = '$QT4_LUPDATE $SOURCE -ts $TARGET', - QT4_LRELEASECOM = '$QT4_LRELEASE $SOURCE', - - # 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 = [ - CLVar('$QT_MOC $QT_MOCFROMHFLAGS -o ${TARGETS[0]} $SOURCE'), Action(simplifyInclude) ], - # 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), Action(simplifyInclude)] - ) - - # ... and the corresponding builders - uicBld = Builder(action=SCons.Action.Action('$QT_UICCOM', '$QT_UICCOMSTR'), - emitter=uicEmitter, - src_suffix='$QT_UISUFFIX', - suffix='$QT_UICDECLSUFFIX', - prefix='$QT_UICDECLPREFIX', - source_scanner=uicScanner) - mocBld = Builder(action={}, prefix={}, suffix={}) - for h in header_extensions: - act = SCons.Action.Action('$QT_MOCFROMHCOM', '$QT_MOCFROMHCOMSTR') - mocBld.add_action(h, act) - mocBld.prefix[h] = '$QT_MOCHPREFIX' - mocBld.suffix[h] = '$QT_MOCHSUFFIX' - for cxx in cxx_suffixes: - act = SCons.Action.Action('$QT_MOCFROMCXXCOM', '$QT_MOCFROMCXXCOMSTR') - mocBld.add_action(cxx, act) - mocBld.prefix[cxx] = '$QT_MOCCXXPREFIX' - mocBld.suffix[cxx] = '$QT_MOCCXXSUFFIX' - - # register the builders - # Translation builder - tsbuilder = Builder( - action = SCons.Action.Action('$QT4_LUPDATECOM'), #,'$QT4_LUPDATECOMSTR'), - multi=1 - ) - qmbuilder = Builder( - action = SCons.Action.Action('$QT4_LRELEASECOM'),# , '$QT4_LRELEASECOMSTR'), - src_suffix = '.ts', - suffix = '.qm', - single_source = True - ) - - env['BUILDERS']['Ts'] = tsbuilder - env['BUILDERS']['Qm'] = qmbuilder - env['BUILDERS']['Uic'] = uicBld - env['BUILDERS']['Uic'] = uicBld - env['BUILDERS']['Moc'] = mocBld - static_obj, shared_obj = SCons.Tool.createObjBuilders(env) - static_obj.add_src_builder('Uic') - shared_obj.add_src_builder('Uic') - - # We use the emitters of Program / StaticLibrary / SharedLibrary - # to scan for moc'able files - # We can't refer to the builders directly, we have to fetch them - # as Environment attributes because that sets them up to be called - # correctly later by our emitter. - env.AppendUnique(PROGEMITTER =[AutomocStatic], - SHLIBEMITTER=[AutomocShared], - LIBEMITTER =[AutomocStatic], - # Of course, we need to link against the qt libraries - CPPPATH=["$QT_CPPPATH"], - LIBPATH=["$QT_LIBPATH"]) - env.AddMethod( enableQtEmmitters, "EnableQtEmmitters") + """Add Builders and construction variables for qt to an Environment.""" + CLVar = SCons.Util.CLVar + Action = SCons.Action.Action + Builder = SCons.Builder.Builder + + env.SetDefault( + 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 = '', #'ui_', + QT_UICDECLSUFFIX = '.h', + QT_UICIMPLPREFIX = '', #'ui_', + QT_UICIMPLSUFFIX = '$CXXFILESUFFIX', + QT_MOCHPREFIX = 'moc_', + QT_MOCHSUFFIX = '$CXXFILESUFFIX', + QT_MOCCXXPREFIX = '', + QT_MOCCXXSUFFIX = '.moc', + QT_UISUFFIX = '.ui', + QT4_LUPDATE = os.path.join('$QT_BINPATH','lupdate'), + QT4_LRELEASE = os.path.join('$QT_BINPATH','lrelease'), + QT4_LUPDATECOM = '$QT4_LUPDATE $SOURCE -ts $TARGET', + QT4_LRELEASECOM = '$QT4_LRELEASE $SOURCE', + + # 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), Action(simplifyInclude)] + ) + + # ... and the corresponding builders + uicBld = Builder( + action = SCons.Action.Action('$QT_UICCOM', '$QT_UICCOMSTR'), + emitter = uicEmitter, + src_suffix = '$QT_UISUFFIX', + suffix = '$QT_UICDECLSUFFIX', + prefix = '$QT_UICDECLPREFIX', + source_scanner = uicScanner, + ) + + mocBld = Builder(action={}, prefix={}, suffix={}) + for h in header_extensions: + act = SCons.Action.Action('$QT_MOCFROMHCOM', '$QT_MOCFROMHCOMSTR') + mocBld.add_action(h, act) + mocBld.prefix[h] = '$QT_MOCHPREFIX' + mocBld.suffix[h] = '$QT_MOCHSUFFIX' + for cxx in cxx_suffixes: + act = SCons.Action.Action('$QT_MOCFROMCXXCOM', '$QT_MOCFROMCXXCOMSTR') + mocBld.add_action(cxx, act) + mocBld.prefix[cxx] = '$QT_MOCCXXPREFIX' + mocBld.suffix[cxx] = '$QT_MOCCXXSUFFIX' + + # register the builders + # Translation builder + tsbuilder = Builder( + action = SCons.Action.Action('$QT4_LUPDATECOM'), #,'$QT4_LUPDATECOMSTR'), + multi=1 + ) + qmbuilder = Builder( + action = SCons.Action.Action('$QT4_LRELEASECOM'),# , '$QT4_LRELEASECOMSTR'), + src_suffix = '.ts', + suffix = '.qm', + single_source = True + ) + + env['BUILDERS']['Ts'] = tsbuilder + env['BUILDERS']['Qm'] = qmbuilder + env['BUILDERS']['Uic'] = uicBld + env['BUILDERS']['Moc'] = mocBld + static_obj, shared_obj = SCons.Tool.createObjBuilders(env) + static_obj.add_src_builder('Uic') + shared_obj.add_src_builder('Uic') + + env.AddMethod( enableQtEmmitters, "EnableQtEmmitters") + def enableQtEmmitters(self): - # We use the emitters of Program / StaticLibrary / SharedLibrary - # to scan for moc'able files - # We can't refer to the builders directly, we have to fetch them - # as Environment attributes because that sets them up to be called - # correctly later by our emitter. - self.AppendUnique( - PROGEMITTER = [AutomocStatic], - SHLIBEMITTER = [AutomocShared], - LIBEMITTER = [AutomocStatic], - ) + # We use the emitters of Program / StaticLibrary / SharedLibrary + # to scan for moc'able files + # We can't refer to the builders directly, we have to fetch them + # as Environment attributes because that sets them up to be called + # correctly later by our emitter. + self.AppendUnique( + PROGEMITTER = [AutomocStatic], + SHLIBEMITTER = [AutomocShared], + LIBEMITTER = [AutomocStatic], + ) def exists(env): - return _detect(env) + return True + From 97c21116a9468fcb21196170c15321e69604c4c7 Mon Sep 17 00:00:00 2001 From: Du Bois Eloi Date: Mon, 9 Dec 2013 22:29:14 +0100 Subject: [PATCH 14/22] sconsProject: fixed compilation issues * Fixed issue with qt5 on MACOSX using framework: library where added with -lQtCore and -framework QtCore * Fixed issue with qt5 that was making modules dependencies wrongly added * Fixed issue with poco libraries --- autoconf/_external.py | 1 - autoconf/poco_foundation.py | 2 +- autoconf/poco_net.py | 4 ++-- autoconf/poco_xml.py | 2 +- autoconf/qt5.py | 10 ++++++++-- 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/autoconf/_external.py b/autoconf/_external.py index 4a054a2..1cf8a11 100644 --- a/autoconf/_external.py +++ b/autoconf/_external.py @@ -86,7 +86,6 @@ def postconfigure(self, project, env, level): ''' Particular case, which allow to add things after all libraries checks. ''' - env.AppendUnique( LIBS = self.getLibs(env) ) return True def check(self, project, conf): diff --git a/autoconf/poco_foundation.py b/autoconf/poco_foundation.py index 42782ef..3915cb5 100644 --- a/autoconf/poco_foundation.py +++ b/autoconf/poco_foundation.py @@ -1,5 +1,5 @@ from _external import * from poco_xml import * -poco_foundation = HeaderChecker( 'poco_foundation', 'Poco/Foundation.h', 'c++', dependencies=[poco_xml] ) +poco_foundation = LibWithHeaderChecker( 'poco_foundation', ['Poco/Foundation.h'], 'c++', dependencies=[poco_xml] ) diff --git a/autoconf/poco_net.py b/autoconf/poco_net.py index 2d0737e..c5e7c59 100644 --- a/autoconf/poco_net.py +++ b/autoconf/poco_net.py @@ -6,7 +6,7 @@ windows = os.name.lower() == "nt" and sys.platform.lower().startswith("win") if windows: - poco_net = HeaderChecker( 'poco_net', 'Poco/Net/Net.h', 'c++', dependencies=[poco_foundation, winsock2] ) + poco_net = LibWithHeaderChecker( 'poco_net', 'Poco/Net/Net.h', 'c++', dependencies=[poco_foundation, winsock2] ) else: - poco_net = HeaderChecker( 'poco_net', 'Poco/Net/Net.h', 'c++', dependencies=[poco_foundation] ) + poco_net = LibWithHeaderChecker( 'poco_net', 'Poco/Net/Net.h', 'c++', dependencies=[poco_foundation] ) diff --git a/autoconf/poco_xml.py b/autoconf/poco_xml.py index 5b4416d..93fa0d9 100644 --- a/autoconf/poco_xml.py +++ b/autoconf/poco_xml.py @@ -1,4 +1,4 @@ from _external import * -poco_xml = HeaderChecker( 'poco_xml', 'Poco/XML/XML.h', 'c++' ) +poco_xml = LibWithHeaderChecker( 'poco_xml', 'Poco/XML/XML.h', 'c++' ) diff --git a/autoconf/qt5.py b/autoconf/qt5.py index 3e04dc4..8660cf5 100644 --- a/autoconf/qt5.py +++ b/autoconf/qt5.py @@ -44,14 +44,20 @@ def __init__( self, 'QtGui', 'QtOpenGL', 'QtWidgets', - 'QtPrintSuppport', + 'QtNetwork', + 'QtPrintSupport', + 'QtWebKit', + 'QtWebKitWidgets', ], uiFiles = [], defines = ['QT_NO_KEYWORDS'], useLocalIncludes = True ): self.name = 'qt5' postfix = '' if not windows else '5' - self.libs = [ m + postfix for m in modules] + for m in modules: + realName = m + postfix + if realName not in self.libs: + self.libs.append( realName ) self.uiFiles =self.getAbsoluteCwd(uiFiles) self.defines = defines[:] self.useLocalIncludes = useLocalIncludes From dc422ca0f8f6a1a9b6d7c1e0219fcf0e4226ec10 Mon Sep 17 00:00:00 2001 From: Eloi du Bois Date: Fri, 27 Dec 2013 19:13:43 +0100 Subject: [PATCH 15/22] Added CC['wchar'] option because Qt5 binaries are compiled with /Zc:wchar_t- option --- compiler/gcc.py | 3 +++ compiler/visual.py | 2 ++ 2 files changed, 5 insertions(+) diff --git a/compiler/gcc.py b/compiler/gcc.py index 7ed67c2..b96eb91 100755 --- a/compiler/gcc.py +++ b/compiler/gcc.py @@ -74,6 +74,9 @@ CC['cover'] = ['-fprofile-arcs', '-ftest-coverage'] CC['linkcover'] = ['-lgcov'] +# @see visual.py +CC['wchar'] = [] + ##### -fprofile-arcs # Instrument arcs during compilation. For each function of your program, GCC creates a program flow graph, then finds a spanning tree for the graph. Only arcs that are not on the spanning tree have to be instrumented: the compiler adds code to count the number of times that these arcs are executed. When an arc is the only exit or only entrance to a block, the instrumentation code can be added to the block; otherwise, a new basic block must be created to hold the instrumentation code. # diff --git a/compiler/visual.py b/compiler/visual.py index ecb8389..04f0a53 100755 --- a/compiler/visual.py +++ b/compiler/visual.py @@ -70,6 +70,8 @@ CC['ssse3'] = ['/arch:SSSE3'] CC['sse4'] = ['/arch:SSE4'] +# needed for compatibility with qt5 precompiled library +CC['wchar'] = ['/Zc:wchar_t-'] def retrieveVersion(ccBinArg): import subprocess From c1454d9525f9eb9029e82fb0616c2f14b74ea3d0 Mon Sep 17 00:00:00 2001 From: Eloi du Bois Date: Fri, 27 Dec 2013 19:14:46 +0100 Subject: [PATCH 16/22] Fixed scons compilation issue on Windows. --- tools/qt.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/tools/qt.py b/tools/qt.py index 86dbe84..618ce1a 100644 --- a/tools/qt.py +++ b/tools/qt.py @@ -131,7 +131,7 @@ def __call__(self, target, source, env): debug = int(env.subst('$QT_DEBUG')) except ValueError: debug = 0 - + # some shortcuts used in the scanner splitext = SCons.Util.splitext objBuilder = getattr(env, self.objBuilderName) @@ -154,16 +154,16 @@ def __call__(self, target, source, env): out_sources = source[:] for obj in SCons.Util.flatten(source): - if not obj.has_builder(): - # binary obj file provided - if debug: - print "scons: qt: '%s' seems to be a binary. Discarded." % str(obj) - continue - cpp = obj.sources[0] + if not isinstance(obj, SCons.Node.Node) or not obj.has_builder(): + # binary obj file provided + if debug: + print "scons: qt: '%s' seems to be a binary. Discarded." % str(obj) + continue + cpp = obj.sources[0] if not splitext(str(cpp))[1] in cxx_suffixes: if debug: print "scons: qt: '%s' is no cxx file. Discarded." % str(cpp) - # c or fortran source + # c or fortran source continue #cpp_contents = comment.sub('', cpp.get_text_contents()) cpp_contents = cpp.get_text_contents() @@ -194,8 +194,7 @@ def __call__(self, target, source, env): # (to be included in cpp) moc = env.Moc(cpp) env.Ignore(moc, moc) - if debug: - print "scons: qt: found Q_OBJECT macro in '%s', moc'ing to '%s'" % (str(cpp), str(moc)) + print "scons: qt: found Q_OBJECT macro in '%s', moc'ing to '%s'" % (str(cpp), str(moc)) #moc.source_scanner = SCons.Defaults.CScan # restore the original env attributes (FIXME) objBuilder.env = objBuilderEnv From 78b2b4f3256125fad56538d660b8912ebcae9420 Mon Sep 17 00:00:00 2001 From: Eloi du Bois Date: Fri, 27 Dec 2013 19:15:16 +0100 Subject: [PATCH 17/22] Minor fix --- tools/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/__init__.py b/tools/__init__.py index 069c93c..17dad70 100755 --- a/tools/__init__.py +++ b/tools/__init__.py @@ -1,4 +1,4 @@ -import qt4 +import qt5 From e1f068e96e0c9b506af97c971e54277f150e3fca Mon Sep 17 00:00:00 2001 From: Du Bois Date: Thu, 8 May 2014 03:08:08 +0200 Subject: [PATCH 18/22] sconsProject: added option to override shared library suffix, which is useful when cross-compiling (eg. android). * name of the option: SHLIBSUFFIX --- __init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/__init__.py b/__init__.py index 80ea2a7..05250b3 100755 --- a/__init__.py +++ b/__init__.py @@ -556,6 +556,7 @@ def help_format(env, opt, help, default, actual, aliases): opts.Add('aliases', 'A list of custom aliases.', []) opts.Add('jobs', 'Parallel jobs', '1') opts.Add(BoolVariable('check_libs', 'Enable/Disable lib checking', True)) + opts.Add('SHLIBSUFFIX', 'Specify the shared libraries suffix', '.dll' if self.windows else( '.dylib' if self.macos else '.so' ) ) opts.Add('CC', 'Specify the C Compiler', self.compiler.ccBin) opts.Add('CXX', 'Specify the C++ Compiler', self.compiler.cxxBin) @@ -1296,7 +1297,7 @@ def SharedLibrary( self, target, else: # if no environment we create a new one localEnv = self.createEnv( localLibraries, name=target ) - + # apply arguments to env localIncludes = self.prepareIncludes(l_includes) localEnv.AppendUnique( CPPPATH = localIncludes ) From 7eafdd05d5e074bacd63701140d3acd0ada08694 Mon Sep 17 00:00:00 2001 From: Du Bois Date: Thu, 8 May 2014 03:09:51 +0200 Subject: [PATCH 19/22] sconsProject: added an option to specify ranlib and ar binaries (useful for android compilation) --- __init__.py | 2 ++ compiler/clang.py | 2 ++ compiler/gcc.py | 2 ++ compiler/visual.py | 2 ++ 4 files changed, 8 insertions(+) diff --git a/__init__.py b/__init__.py index 05250b3..167f2c7 100755 --- a/__init__.py +++ b/__init__.py @@ -559,6 +559,8 @@ def help_format(env, opt, help, default, actual, aliases): opts.Add('SHLIBSUFFIX', 'Specify the shared libraries suffix', '.dll' if self.windows else( '.dylib' if self.macos else '.so' ) ) opts.Add('CC', 'Specify the C Compiler', self.compiler.ccBin) opts.Add('CXX', 'Specify the C++ Compiler', self.compiler.cxxBin) + opts.Add('AR', 'Specify the C Compiler', self.compiler.arBin) + opts.Add('RANLIB', 'Specify the C++ Compiler', self.compiler.ranlibBin) opts.Add('SCRIPTTESTXX', 'Specify the script test binary', "nosetests") opts.Add('SCRIPTTESTFLAGS', 'Specify the script test flags', "") diff --git a/compiler/clang.py b/compiler/clang.py index c75cd45..335e99c 100755 --- a/compiler/clang.py +++ b/compiler/clang.py @@ -5,6 +5,8 @@ name = 'clang' ccBin = 'clang' cxxBin = 'clang++' +arBin = 'ar' +ranlibBin = 'ranlib' linkBin = ccBin linkxxBin = cxxBin diff --git a/compiler/gcc.py b/compiler/gcc.py index 17ac84b..5be33b8 100755 --- a/compiler/gcc.py +++ b/compiler/gcc.py @@ -11,6 +11,8 @@ cxxBin = 'g++' linkBin = ccBin linkxxBin = cxxBin +arBin = 'ar' +ranlibBin = 'ranlib' ccVersionStr = 'unknown' ccVersion = [0,0,0] diff --git a/compiler/visual.py b/compiler/visual.py index 04f0a53..4bf408c 100755 --- a/compiler/visual.py +++ b/compiler/visual.py @@ -4,6 +4,8 @@ cxxBin = 'cl' linkBin = 'link' linkxxBin = 'link' +arBin = '' +ranlibBin = '' ccVersionStr = 'unknown' ccVersion = [0,0,0] From c5f665cf33fec368916e1de84fe4ac9626670c2a Mon Sep 17 00:00:00 2001 From: Du Bois Date: Sun, 30 Nov 2014 19:34:22 +0100 Subject: [PATCH 20/22] sconsProject: added ncurses libraries (ncurses and CDK framework) --- autoconf/cdk.py | 3 +++ autoconf/ncurses.py | 3 +++ 2 files changed, 6 insertions(+) create mode 100755 autoconf/cdk.py create mode 100755 autoconf/ncurses.py diff --git a/autoconf/cdk.py b/autoconf/cdk.py new file mode 100755 index 0000000..89a9e4f --- /dev/null +++ b/autoconf/cdk.py @@ -0,0 +1,3 @@ +from _external import * + +jpeg = LibWithHeaderChecker('jpeg', ['stdio.h','jpeglib.h'], 'c') diff --git a/autoconf/ncurses.py b/autoconf/ncurses.py new file mode 100755 index 0000000..89a9e4f --- /dev/null +++ b/autoconf/ncurses.py @@ -0,0 +1,3 @@ +from _external import * + +jpeg = LibWithHeaderChecker('jpeg', ['stdio.h','jpeglib.h'], 'c') From 84d08cee0dc894d2223335c356b2b889c8ef103a Mon Sep 17 00:00:00 2001 From: Du Bois Date: Sun, 30 Nov 2014 21:36:32 +0100 Subject: [PATCH 21/22] sconsProject: ncurses updates. --- autoconf/cdk.py | 3 ++- autoconf/ncurses.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) mode change 100755 => 100644 autoconf/cdk.py mode change 100755 => 100644 autoconf/ncurses.py diff --git a/autoconf/cdk.py b/autoconf/cdk.py old mode 100755 new mode 100644 index 89a9e4f..d56e11c --- a/autoconf/cdk.py +++ b/autoconf/cdk.py @@ -1,3 +1,4 @@ from _external import * -jpeg = LibWithHeaderChecker('jpeg', ['stdio.h','jpeglib.h'], 'c') +# CDK is a framework for ncurses +cdk = LibWithHeaderChecker('cdk', ['cdk.h'], 'c') diff --git a/autoconf/ncurses.py b/autoconf/ncurses.py old mode 100755 new mode 100644 index 89a9e4f..72fd889 --- a/autoconf/ncurses.py +++ b/autoconf/ncurses.py @@ -1,3 +1,3 @@ from _external import * -jpeg = LibWithHeaderChecker('jpeg', ['stdio.h','jpeglib.h'], 'c') +ncurses = LibWithHeaderChecker('ncurses', ['ncurses.h'], 'c') From 64792a81caa911b4f8b201d18ef3e18c1d9200a6 Mon Sep 17 00:00:00 2001 From: Du Bois Date: Sun, 30 Nov 2014 21:36:43 +0100 Subject: [PATCH 22/22] sconsProject: added fmod. --- autoconf/fmod.py | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 autoconf/fmod.py diff --git a/autoconf/fmod.py b/autoconf/fmod.py new file mode 100644 index 0000000..1ff0791 --- /dev/null +++ b/autoconf/fmod.py @@ -0,0 +1,5 @@ +from _external import * + +fmod = LibWithHeaderChecker( 'fmod', 'fmod.h', 'c' ) + +