From 012ae9c2ca1ed17496f2f540f9d0067a19583eab Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Fri, 20 Feb 2026 13:06:24 -0700 Subject: [PATCH] Copy over qt3 files from main SCons Signed-off-by: Mats Wichmann --- sconscontrib/SCons/Tool/qt3/README | 9 + sconscontrib/SCons/Tool/qt3/__init__.py | 373 +++++++++++++ sconscontrib/SCons/Tool/qt3/docs/qt3.xml | 528 ++++++++++++++++++ .../SCons/Tool/qt3/test/.exclude_tests | 1 + .../SCons/Tool/qt3/test/CPPPATH-appended.py | 74 +++ sconscontrib/SCons/Tool/qt3/test/CPPPATH.py | 64 +++ sconscontrib/SCons/Tool/qt3/test/QTFLAGS.py | 214 +++++++ .../SCons/Tool/qt3/test/TestSCons_QT.py | 235 ++++++++ sconscontrib/SCons/Tool/qt3/test/Tool.py | 150 +++++ .../SCons/Tool/qt3/test/copied-env.py | 77 +++ sconscontrib/SCons/Tool/qt3/test/empty-env.py | 72 +++ .../SCons/Tool/qt3/test/generated-ui.py | 129 +++++ sconscontrib/SCons/Tool/qt3/test/installed.py | 214 +++++++ sconscontrib/SCons/Tool/qt3/test/manual.py | 142 +++++ .../SCons/Tool/qt3/test/moc-from-cpp.py | 108 ++++ .../SCons/Tool/qt3/test/moc-from-header.py | 103 ++++ .../SCons/Tool/qt3/test/qt_warnings.py | 98 ++++ sconscontrib/SCons/Tool/qt3/test/reentrant.py | 68 +++ .../SCons/Tool/qt3/test/source-from-ui.py | 155 +++++ .../SCons/Tool/qt3/test/up-to-date.py | 138 +++++ 20 files changed, 2952 insertions(+) create mode 100644 sconscontrib/SCons/Tool/qt3/README create mode 100644 sconscontrib/SCons/Tool/qt3/__init__.py create mode 100644 sconscontrib/SCons/Tool/qt3/docs/qt3.xml create mode 100644 sconscontrib/SCons/Tool/qt3/test/.exclude_tests create mode 100644 sconscontrib/SCons/Tool/qt3/test/CPPPATH-appended.py create mode 100644 sconscontrib/SCons/Tool/qt3/test/CPPPATH.py create mode 100644 sconscontrib/SCons/Tool/qt3/test/QTFLAGS.py create mode 100644 sconscontrib/SCons/Tool/qt3/test/TestSCons_QT.py create mode 100644 sconscontrib/SCons/Tool/qt3/test/Tool.py create mode 100644 sconscontrib/SCons/Tool/qt3/test/copied-env.py create mode 100644 sconscontrib/SCons/Tool/qt3/test/empty-env.py create mode 100644 sconscontrib/SCons/Tool/qt3/test/generated-ui.py create mode 100644 sconscontrib/SCons/Tool/qt3/test/installed.py create mode 100644 sconscontrib/SCons/Tool/qt3/test/manual.py create mode 100644 sconscontrib/SCons/Tool/qt3/test/moc-from-cpp.py create mode 100644 sconscontrib/SCons/Tool/qt3/test/moc-from-header.py create mode 100644 sconscontrib/SCons/Tool/qt3/test/qt_warnings.py create mode 100644 sconscontrib/SCons/Tool/qt3/test/reentrant.py create mode 100644 sconscontrib/SCons/Tool/qt3/test/source-from-ui.py create mode 100644 sconscontrib/SCons/Tool/qt3/test/up-to-date.py diff --git a/sconscontrib/SCons/Tool/qt3/README b/sconscontrib/SCons/Tool/qt3/README new file mode 100644 index 0000000..038563f --- /dev/null +++ b/sconscontrib/SCons/Tool/qt3/README @@ -0,0 +1,9 @@ +The qt3 tool module and tests are the ones removed from core SCons, +once there appeared to be no operating systems left supporting building +for Qt3. Provided here as a fallback in the unlikely case somebody still +needs them. Qt3 became officially unsupported in 2015; in reality quite +a bit earlier as various Linux and BSD distributions got rid of it in +the 2012-2013 timeframe (if not earlier). + +If you want to use qt3 with SCons, you'll have to build qt3 from source +yourself. This setup hasn't been tested as a standalone tool module. diff --git a/sconscontrib/SCons/Tool/qt3/__init__.py b/sconscontrib/SCons/Tool/qt3/__init__.py new file mode 100644 index 0000000..5ee0535 --- /dev/null +++ b/sconscontrib/SCons/Tool/qt3/__init__.py @@ -0,0 +1,373 @@ +# +# MIT License +# +# Copyright The SCons Foundation +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +"""Tool-specific initialization for Qt3. + +This is the long-time SCons tool module for Qt3 that was eventually +removed from the code due to lack of support for the technology in +any mainline systems - which at that point they had moved on to Qt6 +(usually only with backwards support for Qt5). There is no promise +that this module transplanted to contrib will work without some surgery, +or in fact - at all. + +There normally shouldn't be any need to import this module directly. +It will usually be imported through the generic SCons.Tool.Tool() +selection method. +""" + +import os.path +import re + +import SCons.Action +import SCons.Builder +import SCons.Defaults +import SCons.Scanner +import SCons.Tool +import SCons.Util +import SCons.Tool.cxx +import SCons.Warnings +cplusplus = SCons.Tool.cxx + +class ToolQtWarning(SCons.Warnings.SConsWarning): + pass + +class GeneratedMocFileNotIncluded(ToolQtWarning): + pass + +class QtdirNotFound(ToolQtWarning): + pass + +SCons.Warnings.enableWarningClass(ToolQtWarning) + +header_extensions = [".h", ".hxx", ".hpp", ".hh"] +if SCons.Util.case_sensitive_suffixes('.h', '.H'): + header_extensions.append('.H') + +cxx_suffixes = cplusplus.CXXSuffixes + + +def find_platform_specific_qt3_paths(): + """ + find non-standard QT paths + + If the platform does not put QT tools in standard search paths, + the path is expected to be set using QT3DIR. SCons violates + the normal rule of not pulling from the user's environment + in this case. However, some test cases try to validate what + happens when QT3DIR is unset, so we need to try to make a guess. + + :return: a guess at a path + """ + + # qt3_bin_dirs = [] + qt3_bin_dir = None + if os.path.isfile('/etc/redhat-release'): + with open('/etc/redhat-release','r') as rr: + lines = rr.readlines() + distro = lines[0].split()[0] + if distro == 'CentOS': + # Centos installs QT under /usr/{lib,lib64}/qt{4,5,-3.3}/bin + # so we need to handle this differently + # qt3_bin_dirs = glob.glob('/usr/lib64/qt*/bin') + # TODO: all current Fedoras do the same, need to look deeper here. + qt3_bin_dir = '/usr/lib64/qt-3.3/bin' + + return qt3_bin_dir + + +QT3_BIN_DIR = find_platform_specific_qt3_paths() + +def checkMocIncluded(target, source, env) -> None: + 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 moc not 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 + +class _Automoc: + """ + Callable class, which works as an emitter for Programs, SharedLibraries and + StaticLibraries. + """ + + def __init__(self, objBuilderName) -> None: + 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 qt3 files. + """ + try: + if int(env.subst('$QT3_AUTOSCAN')) == 0: + return target, source + except ValueError: + pass + try: + debug = int(env.subst('$QT3_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: qt3: '%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: qt3: '%s' is no cxx file. Discarded." % str(cpp)) + # c or fortran source + continue + #cpp_contents = comment.sub('', cpp.get_text_contents()) + if debug: + print("scons: qt3: Getting contents of %s" % cpp) + 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: qt3: 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: qt3: 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: qt3: 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: qt3: 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_qt3(env): + """Not really safe, but fast method to detect the QT library""" + + QT3DIR = env.get('QT3DIR',None) + if not QT3DIR: + QT3DIR = os.environ.get('QTDIR',None) + if not QT3DIR: + moc = env.WhereIs('moc') or env.WhereIs('moc',QT3_BIN_DIR) + if moc: + QT3DIR = os.path.dirname(os.path.dirname(moc)) + SCons.Warnings.warn( + QtdirNotFound, + "Could not detect qt3, using moc executable as a hint (QT3DIR=%s)" % QT3DIR) + else: + QT3DIR = None + SCons.Warnings.warn( + QtdirNotFound, + "Could not detect qt3, using empty QT3DIR") + return QT3DIR + +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('$QT3_UICIMPLPREFIX'), + env.subst('$QT3_UICIMPLSUFFIX'))) + if len(target) < 3: + # third target is moc file + target.append(adjustixes(bs, + env.subst('$QT3_MOCHPREFIX'), + env.subst('$QT3_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) + return result + +uicScanner = SCons.Scanner.ScannerBase(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 qt3 to an Environment.""" + CLVar = SCons.Util.CLVar + Action = SCons.Action.Action + Builder = SCons.Builder.Builder + + qt3path = _detect_qt3(env) + if qt3path is None: + return None + + env.SetDefault(QT3DIR = qt3path, + QT3_BINPATH = os.path.join('$QT3DIR', 'bin'), + QT3_CPPPATH = os.path.join('$QT3DIR', 'include'), + QT3_LIBPATH = os.path.join('$QT3DIR', 'lib'), + QT3_MOC = os.path.join('$QT3_BINPATH','moc'), + QT3_UIC = os.path.join('$QT3_BINPATH','uic'), + QT3_LIB = 'qt', # may be set to qt-mt + + QT3_AUTOSCAN = 1, # scan for moc'able sources + + # Some QT specific flags. I don't expect someone wants to + # manipulate those ... + QT3_UICIMPLFLAGS = CLVar(''), + QT3_UICDECLFLAGS = CLVar(''), + QT3_MOCFROMHFLAGS = CLVar(''), + QT3_MOCFROMCXXFLAGS = CLVar('-i'), + + # suffixes/prefixes for the headers / sources to generate + QT3_UICDECLPREFIX = '', + QT3_UICDECLSUFFIX = '.h', + QT3_UICIMPLPREFIX = 'uic_', + QT3_UICIMPLSUFFIX = '$CXXFILESUFFIX', + QT3_MOCHPREFIX = 'moc_', + QT3_MOCHSUFFIX = '$CXXFILESUFFIX', + QT3_MOCCXXPREFIX = '', + QT3_MOCCXXSUFFIX = '.moc', + QT3_UISUFFIX = '.ui', + + # Commands for the qt3 support ... + # command to generate header, implementation and moc-file + # from a .ui file + QT3_UICCOM = [ + CLVar('$QT3_UIC $QT3_UICDECLFLAGS -o ${TARGETS[0]} $SOURCE'), + CLVar('$QT3_UIC $QT3_UICIMPLFLAGS -impl ${TARGETS[0].file} ' + '-o ${TARGETS[1]} $SOURCE'), + CLVar('$QT3_MOC $QT3_MOCFROMHFLAGS -o ${TARGETS[2]} ${TARGETS[0]}')], + # command to generate meta object information for a class + # declarated in a header + QT3_MOCFROMHCOM = ( + '$QT3_MOC $QT3_MOCFROMHFLAGS -o ${TARGETS[0]} $SOURCE'), + # command to generate meta object information for a class + # declarated in a cpp file + QT3_MOCFROMCXXCOM = [ + CLVar('$QT3_MOC $QT3_MOCFROMCXXFLAGS -o ${TARGETS[0]} $SOURCE'), + Action(checkMocIncluded,None)]) + + # ... and the corresponding builders + uicBld = Builder(action=SCons.Action.Action('$QT3_UICCOM', '$QT3_UICCOMSTR'), + emitter=uicEmitter, + src_suffix='$QT3_UISUFFIX', + suffix='$QT3_UICDECLSUFFIX', + prefix='$QT3_UICDECLPREFIX', + source_scanner=uicScanner) + mocBld = Builder(action={}, prefix={}, suffix={}) + for h in header_extensions: + act = SCons.Action.Action('$QT3_MOCFROMHCOM', '$QT3_MOCFROMHCOMSTR') + mocBld.add_action(h, act) + mocBld.prefix[h] = '$QT3_MOCHPREFIX' + mocBld.suffix[h] = '$QT3_MOCHSUFFIX' + for cxx in cxx_suffixes: + act = SCons.Action.Action('$QT3_MOCFROMCXXCOM', '$QT3_MOCFROMCXXCOMSTR') + mocBld.add_action(cxx, act) + mocBld.prefix[cxx] = '$QT3_MOCCXXPREFIX' + mocBld.suffix[cxx] = '$QT3_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') + + # 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], + LDMODULEEMITTER=[AutomocShared], + LIBEMITTER =[AutomocStatic], + # Of course, we need to link against the qt3 libraries + CPPPATH=["$QT3_CPPPATH"], + LIBPATH=["$QT3_LIBPATH"], + LIBS=['$QT3_LIB']) + +def exists(env): + return _detect_qt3(env) diff --git a/sconscontrib/SCons/Tool/qt3/docs/qt3.xml b/sconscontrib/SCons/Tool/qt3/docs/qt3.xml new file mode 100644 index 0000000..4c75a88 --- /dev/null +++ b/sconscontrib/SCons/Tool/qt3/docs/qt3.xml @@ -0,0 +1,528 @@ + + + + +%scons; + +%builders-mod; + +%functions-mod; + +%tools-mod; + +%variables-mod; +]> + + + + + + +Sets &consvars; for building Qt3 applications. + + + +This tool is only suitable for building targeted to Qt3, +which is obsolete +(the tool is deprecated since 4.3, +and was renamed to qt3 in 4.5.0. +). +There are contributed tools for Qt4 and Qt5, see + +https://github.com/SCons/scons-contrib. +Qt4 has also passed end of life for standard support (in Dec 2015). + + + +Note paths for these &consvars; are assembled +using the os.path.join method +so they will have the appropriate separator at runtime, +but are listed here in the various +entries only with the '/' separator +for simplicity. + + + +In addition, the &consvars; +&cv-link-CPPPATH;, +&cv-link-LIBPATH; and +&cv-link-LIBS; may be modified +and the variables +&cv-link-PROGEMITTER;, &cv-link-SHLIBEMITTER; and &cv-link-LIBEMITTER; +are modified. Because the build-performance is affected when using this tool, +you have to explicitly specify it at Environment creation: + + + +Environment(tools=['default','qt3']) + + + +The &t-qt3; tool supports the following operations: + + + +Automatic moc file generation from header files. +You do not have to specify moc files explicitly, the tool does it for you. +However, there are a few preconditions to do so: Your header file must have +the same basename as your implementation file and must stay in the same +directory. It must have one of the suffixes +.h, +.hpp, +.H, +.hxx, +.hh. +You can turn off automatic moc file generation by setting +&cv-link-QT3_AUTOSCAN; to False. +See also the corresponding +&b-link-Moc; Builder. + + + +Automatic moc file generation from C++ files. +As described in the Qt documentation, include the moc file at the end of +the C++ file. Note that you have to include the file, which is generated +by the transformation +${QT3_MOCCXXPREFIX}<basename>${QT3_MOCCXXSUFFIX}, by default +<basename>.mo. A warning is generated after building the moc file if you +do not include the correct file. If you are using &f-link-VariantDir;, you may +need to specify duplicate=True. +You can turn off automatic moc file generation by setting &cv-QT3_AUTOSCAN; to +False. See also the corresponding +&b-link-Moc; Builder. + + + +Automatic handling of .ui files. +The implementation files generated from .ui +files are handled much the same as yacc or lex files. +Each .ui file given as a source of &b-link-Program;, +&b-link-Library; or &b-link-SharedLibrary; +will generate three files: the declaration file, the +implementation file and a moc file. Because there are also generated headers, +you may need to specify duplicate=True in calls to +&f-link-VariantDir;. +See also the corresponding +&b-link-Uic; Builder. + + + +QT3DIR +QT3_BINPATH +QT3_CPPPATH +QT3_LIBPATH +QT3_MOC +QT3_UIC +QT3_LIB +QT3_AUTOSCAN +QT3_UICIMPLFLAGS +QT3_UICDECLFLAGS +QT3_MOCFROMHFLAGS +QT3_MOCFROMCXXFLAGS +QT3_UICDECLPREFIX +QT3_UICDECLSUFFIX +QT3_UICIMPLPREFIX +QT3_UICIMPLSUFFIX +QT3_MOCHPREFIX +QT3_MOCHSUFFIX +QT3_MOCCXXPREFIX +QT3_MOCCXXSUFFIX +QT3_UISUFFIX +QT3_UICCOM +QT3_MOCFROMHCOM +QT3_MOCFROMCXXCOM + + +QT3DIR + + + + + + +Builds an output file from a moc input file. +moc input files are either header files or C++ files. +This builder is only available after using the +tool &t-link-qt3;. See the &cv-link-QT3DIR; variable for more information. +Example: + + + +env.Moc('foo.h') # generates moc_foo.cc +env.Moc('foo.cpp') # generates foo.moc + + + + + + + +Builds a header file, an implementation file and a moc file from an ui file. +and returns the corresponding nodes in the that order. +This builder is only available after using the tool &t-link-qt3;. +Note: you can specify .ui files directly as source +files to the &b-link-Program;, +&b-link-Library; and &b-link-SharedLibrary; builders +without using this builder. Using this builder lets you override the standard +naming conventions (be careful: prefixes are always prepended to names of +built files; if you don't want prefixes, you may set them to ``). +See the &cv-link-QT3DIR; variable for more information. +Example: + + + +env.Uic('foo.ui') # -> ['foo.h', 'uic_foo.cc', 'moc_foo.cc'] +env.Uic( + target=Split('include/foo.h gen/uicfoo.cc gen/mocfoo.cc'), + source='foo.ui' +) # -> ['include/foo.h', 'gen/uicfoo.cc', 'gen/mocfoo.cc'] + + + + + + + +The path to the Qt installation to build against. +If not already set, +&t-link-qt3; tool tries to obtain this from +os.environ; +if not found there, it tries to make a guess. + + +Changed in 4.5.0: renamed from QTDIR. + + + + + + + +Turn off scanning for mocable files. Use the &b-link-Moc; Builder to explicitly +specify files to run moc on. + + +Changed in 4.5.0: renamed from QT_AUTOSCAN. + + + + + + + +The path where the Qt binaries are installed. +The default value is '&cv-link-QT3DIR;/bin'. + + +Changed in 4.5.0: renamed from QT_BINPATH. + + + + + + + +The path where the Qt header files are installed. +The default value is '&cv-link-QT3DIR;/include'. +Note: If you set this variable to None, +the tool won't change the &cv-link-CPPPATH; +construction variable. + + +Changed in 4.5.0: renamed from QT_CPPPATH. + + + + + + + +Prints lots of debugging information while scanning for moc files. + + +Changed in 4.5.0: renamed from QT_DEBUG. + + + + + + + +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 &cv-link-LIBS; variable. + + +Changed in 4.5.0: renamed from QT_LIB. + + + + + + + +The path where the Qt libraries are installed. +The default value is '&cv-link-QT3DIR;/lib'. +Note: If you set this variable to None, +the tool won't change the &cv-link-LIBPATH; +construction variable. + + +Changed in 4.5.0: renamed from QT_LIBPATH. + + + + + + + +Default value is '&cv-link-QT3_BINPATH;/moc'. + + + + + + + +Default value is ''. +Prefix for moc output files when source is a C++ file. + + + + + + + +Default value is '.moc'. +Suffix for moc output files when source is a C++ file. + + +Changed in 4.5.0: renamed from QT_MOCCXXSUFFIX. + + + + + + + +Default value is '-i'. +These flags are passed to moc when moccing a C++ file. + + +Changed in 4.5.0: renamed from QT_MOCFROMCXXFLAGS. + + + + + + + +Command to generate a moc file from a C++ file. + + +Changed in 4.5.0: renamed from QT_MOCFROMCXXCOM. + + + + + + + +The string displayed when generating a moc file from a C++ file. +If this is not set, then &cv-link-QT3_MOCFROMCXXCOM; (the command line) is displayed. + + +Changed in 4.5.0: renamed from QT_MOCFROMCXXCOMSTR. + + + + + + + +Command to generate a moc file from a header. + + +Changed in 4.5.0: renamed from QT_MOCFROMSHCOM. + + + + + + + +The string displayed when generating a moc file from a C++ file. +If this is not set, then &cv-link-QT3_MOCFROMHCOM; (the command line) is displayed. + + +Changed in 4.5.0: renamed from QT_MOCFROMSHCOMSTR. + + + + + + + +Default value is ''. These flags are passed to moc +when moccing a header file. + + +Changed in 4.5.0: renamed from QT_MOCFROMSHFLAGS. + + + + + + + +Default value is 'moc_'. +Prefix for moc output files when source is a header. + + +Changed in 4.5.0: renamed from QT_MOCHPREFIX. + + + + + + + +Default value is '&cv-link-CXXFILESUFFIX;'. +Suffix for moc output files when source is a header. + + +Changed in 4.5.0: renamed from QT_MOCHSUFFIX. + + + + + + + +Default value is '&cv-link-QT3_BINPATH;/uic'. + + +Changed in 4.5.0: renamed from QT_UIC. + + + + + + + +Command to generate header files from .ui files. + + +Changed in 4.5.0: renamed from QT_UICCOM. + + + + + + + +The string displayed when generating header files from .ui files. +If this is not set, then &cv-link-QT3_UICCOM; (the command line) is displayed. + + +Changed in 4.5.0: renamed from QT_UICCOMSTR. + + + + + + + +Default value is ''. These flags are passed to uic +when creating a header file from a .ui file. + + +Changed in 4.5.0: renamed from QT_UICDECLFLAGS. + + + + + + + +Default value is ''. +Prefix for uic generated header files. + + +Changed in 4.5.0: renamed from QT_UICDECLPREFIX. + + + + + + + +Default value is '.h'. +Suffix for uic generated header files. + + +Changed in 4.5.0: renamed from QT_UICDECLSUFFIX. + + + + + + + +Default value is ''. +These flags are passed to uic when creating a C++ +file from a .ui file. + + +Changed in 4.5.0: renamed from QT_UICIMPFLAGS. + + + + + + + +Default value is 'uic_'. +Prefix for uic generated implementation files. + + +Changed in 4.5.0: renamed from QT_UICIMPLPREFIX. + + + + + + + +Default value is '&cv-link-CXXFILESUFFIX;'. Suffix for uic generated implementation +files. + + +Changed in 4.5.0: renamed from QT_UICIMPLSUFFIX. + + + + + + + +Default value is '.ui'. +Suffix of designer input files. + + +Changed in 4.5.0: renamed from QT_UISUFFIX. + + + + + diff --git a/sconscontrib/SCons/Tool/qt3/test/.exclude_tests b/sconscontrib/SCons/Tool/qt3/test/.exclude_tests new file mode 100644 index 0000000..cbe873f --- /dev/null +++ b/sconscontrib/SCons/Tool/qt3/test/.exclude_tests @@ -0,0 +1 @@ +TestSCons_QT.py diff --git a/sconscontrib/SCons/Tool/qt3/test/CPPPATH-appended.py b/sconscontrib/SCons/Tool/qt3/test/CPPPATH-appended.py new file mode 100644 index 0000000..ce8e6fa --- /dev/null +++ b/sconscontrib/SCons/Tool/qt3/test/CPPPATH-appended.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python +# +# MIT License +# +# Copyright The SCons Foundation +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +""" +Test that an appended relative CPPPATH works with generated files. + +This is basically the same as CPPPATH.py, but the include path +is env.Append-ed and everything goes into sub directory "sub". +""" + +import os.path + +import TestSCons_QT + +test = TestSCons_QT.TestSConsQt() + +test.subdir('sub', ['sub', 'local_include']) + +test.Qt_dummy_installation() + +aaa_exe = os.path.join('sub', 'aaa' + TestSCons_QT._exe) + +test.Qt_create_SConstruct('SConstruct') + +test.write('SConscript', r""" +SConscript('sub/SConscript') +""") + +test.write(['sub', 'SConscript'], r""" +Import("env") +env.Append(CPPPATH=['./local_include']) +env.Program(target = 'aaa', source = 'aaa.cpp') +""") + +test.write(['sub', 'aaa.cpp'], r""" +#include "aaa.h" +int main(void) { aaa(); return 0; } +""") + +test.write(['sub', 'aaa.h'], r""" +#include "my_qobject.h" +#include "local_include.h" +void aaa(void) Q_OBJECT; +""") + +test.write(['sub', 'local_include', 'local_include.h'], r""" +/* empty; just needs to be found */ +""") + +test.run(arguments='--warn=no-tool-qt-deprecated ' + aaa_exe) + +test.pass_test() diff --git a/sconscontrib/SCons/Tool/qt3/test/CPPPATH.py b/sconscontrib/SCons/Tool/qt3/test/CPPPATH.py new file mode 100644 index 0000000..5836dec --- /dev/null +++ b/sconscontrib/SCons/Tool/qt3/test/CPPPATH.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python +# +# MIT License +# +# Copyright The SCons Foundation +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +""" +Test that an overwritten CPPPATH works with generated files. +""" + +import TestSCons_QT + +test = TestSCons_QT.TestSConsQt() + +test.subdir('local_include') + +test.Qt_dummy_installation() + +aaa_exe = 'aaa' + TestSCons_QT._exe + +test.Qt_create_SConstruct('SConstruct') + +test.write('SConscript', """\ +Import("env") +env.Program(target = 'aaa', source = 'aaa.cpp', CPPPATH=['$CPPPATH', './local_include']) +""") + +test.write('aaa.cpp', r""" +#include "aaa.h" +int main(void) { aaa(); return 0; } +""") + +test.write('aaa.h', r""" +#include "my_qobject.h" +#include "local_include.h" +void aaa(void) Q_OBJECT; +""") + +test.write(['local_include', 'local_include.h'], r""" +/* empty; just needs to be found */ +""") + +test.run(arguments='--warn=no-tool-qt-deprecated ' + aaa_exe) + +test.pass_test() diff --git a/sconscontrib/SCons/Tool/qt3/test/QTFLAGS.py b/sconscontrib/SCons/Tool/qt3/test/QTFLAGS.py new file mode 100644 index 0000000..7a01cc7 --- /dev/null +++ b/sconscontrib/SCons/Tool/qt3/test/QTFLAGS.py @@ -0,0 +1,214 @@ +#!/usr/bin/env python +# +# MIT License +# +# Copyright The SCons Foundation +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +""" +Testing the configuration mechanisms of the 'qt3' tool. +""" + +import TestSCons_QT + +_python_ = TestSCons_QT._python_ +_exe = TestSCons_QT._exe + +test = TestSCons_QT.TestSConsQt() + +test.Qt_dummy_installation() +test.subdir('work1', 'work2') + +test.run( + chdir=test.workpath('qt', 'lib'), + arguments=".", + stderr=TestSCons.noisy_ar, + match=TestSCons.match_re_dotall, +) + +QT3 = test.workpath('qt') +QT3_LIB = 'myqt' +QT3_MOC = '%s %s' % (_python_, test.workpath('qt', 'bin', 'mymoc.py')) +QT3_UIC = '%s %s' % (_python_, test.workpath('qt', 'bin', 'myuic.py')) + +def createSConstruct(test, place, overrides): + test.write(place, """\ +env = Environment( + tools=['default','qt3'], + QT3DIR = r'%s', + QT3_LIB = r'%s', + QT3_MOC = r'%s', + QT3_UIC = r'%s', + %s # last because 'overrides' may add comma +) +if ARGUMENTS.get('variant_dir', 0): + if ARGUMENTS.get('chdir', 0): + SConscriptChdir(1) + else: + SConscriptChdir(0) + VariantDir('build', '.', duplicate=1) + sconscript = Dir('build').File('SConscript') +else: + sconscript = File('SConscript') +Export("env") +SConscript(sconscript) +""" % (QT3, QT3_LIB, QT3_MOC, QT3_UIC, overrides)) + + +createSConstruct(test, ['work1', 'SConstruct'], + """QT3_UICIMPLFLAGS='-x', + QT3_UICDECLFLAGS='-y', + QT3_MOCFROMHFLAGS='-z', + QT3_MOCFROMCXXFLAGS='-i -w', + QT3_UICDECLPREFIX='uic-', + QT3_UICDECLSUFFIX='.hpp', + QT3_UICIMPLPREFIX='', + QT3_UICIMPLSUFFIX='.cxx', + QT3_MOCHPREFIX='mmm', + QT3_MOCHSUFFIX='.cxx', + QT3_MOCCXXPREFIX='moc', + QT3_MOCCXXSUFFIX='.inl', + QT3_UISUFFIX='.myui',""") +test.write(['work1', 'SConscript'],""" +Import("env") +env.Program('mytest', ['mocFromH.cpp', + 'mocFromCpp.cpp', + 'an_ui_file.myui', + 'another_ui_file.myui', + 'main.cpp']) +""") + +test.write(['work1', 'mocFromH.hpp'], """ +#include "my_qobject.h" +void mocFromH() Q_OBJECT +""") + +test.write(['work1', 'mocFromH.cpp'], """ +#include "mocFromH.hpp" +""") + +test.write(['work1', 'mocFromCpp.cpp'], """ +#include "my_qobject.h" +void mocFromCpp() Q_OBJECT +#include "mocmocFromCpp.inl" +""") + +test.write(['work1', 'an_ui_file.myui'], """ +void an_ui_file() +""") + +test.write(['work1', 'another_ui_file.myui'], """ +void another_ui_file() +""") + +test.write(['work1', 'another_ui_file.desc.hpp'], """ +/* just a dependency checker */ +""") + +test.write(['work1', 'main.cpp'], """ +#include "mocFromH.hpp" +#include "uic-an_ui_file.hpp" +#include "uic-another_ui_file.hpp" +void mocFromCpp(); + +int main(void) { + mocFromH(); + mocFromCpp(); + an_ui_file(); + another_ui_file(); +} +""") + +test.run(chdir='work1', arguments="mytest" + _exe) + +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): + for f,c in fileToContentsStart.items(): + if not test.read(test.workpath('work1', f), mode='r').startswith(c): + return 1 + return 0 + +test.fail_test( + _flagTest( + test, + { + 'mmmmocFromH.cxx': '/* mymoc.py -z */', + 'mocmocFromCpp.inl': '/* mymoc.py -w */', + 'an_ui_file.cxx': '/* myuic.py -x */', + 'uic-an_ui_file.hpp': '/* myuic.py -y */', + 'mmman_ui_file.cxx': '/* mymoc.py -z */', + }, + ) +) + +test.write(['work2', 'SConstruct'], """ +import os.path + +DefaultEnvironment(tools=[]) +env1 = Environment( + tools=['qt3'], + QT3DIR=r'%(QT3DIR)s', + QT3_BINPATH='$QT3DIR/bin64', + QT3_LIBPATH='$QT3DIR/lib64', + QT3_CPPPATH='$QT3DIR/h64', +) + +cpppath = env1.subst('$CPPPATH') +if os.path.normpath(cpppath) != os.path.join(r'%(QT3DIR)s', 'h64'): + print(cpppath) + Exit(1) +libpath = env1.subst('$LIBPATH') +if os.path.normpath(libpath) != os.path.join(r'%(QT3DIR)s', 'lib64'): + print(libpath) + Exit(2) +qt_moc = env1.subst('$QT3_MOC') +if os.path.normpath(qt_moc) != os.path.join(r'%(QT3DIR)s', 'bin64', 'moc'): + print(qt_moc) + Exit(3) + +env2 = Environment( + tools=['default', 'qt3'], QT3DIR=None, QT3_LIB=None, QT3_CPPPATH=None, QT3_LIBPATH=None +) + +env2.Program('main.cpp') +""" % {'QT3DIR':QT3}) + +test.write(['work2', 'main.cpp'], """ +int main(void) { 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() diff --git a/sconscontrib/SCons/Tool/qt3/test/TestSCons_QT.py b/sconscontrib/SCons/Tool/qt3/test/TestSCons_QT.py new file mode 100644 index 0000000..10cdff0 --- /dev/null +++ b/sconscontrib/SCons/Tool/qt3/test/TestSCons_QT.py @@ -0,0 +1,235 @@ +# MIT License +# +# Copyright The SCons Foundation +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +""" +TestSCons subclass for Qt3 testing. + +This module provides a TestSCons subclass specifically for testing Qt3 +functionality. It includes methods for setting up dummy Qt installations +and creating appropriate SConstruct files for Qt3 tests. + +This is not a testcase - it is the extension to the existing SCons +test framework (where it used to live) that you need to run the actual +test cases. +""" + +from __future__ import annotations + +from TestSCons import TestSCons, noisy_ar +from TestCmd import _python_ + + +class TestSConsQt(TestSCons): + """TestSCons subclass for Qt3 testing. + + This class extends TestSCons with methods specific to Qt3 tool testing, + including setting up a dummy Qt installation and creating appropriate + SConstruct files for Qt3 projects. + """ + + def Qt_dummy_installation(self, dir: str = 'qt') -> None: + """Create a dummy Qt installation for testing. + + Sets up a minimal Qt directory structure with mock moc and uic tools + that can be used for testing the Qt3 builder. + + Args: + dir: Directory name for the dummy Qt installation (default: 'qt') + """ + # create a dummy qt installation + + self.subdir(dir, [dir, 'bin'], [dir, 'include'], [dir, 'lib']) + + self.write( + [dir, 'bin', 'mymoc.py'], + """\ +import getopt +import sys +import re + +# -w and -z are fake options used in test/QT/QTFLAGS.py +cmd_opts, args = getopt.getopt(sys.argv[1:], 'io:wz', []) +impl = 0 +opt_string = '' +for opt, arg in cmd_opts: + if opt == '-o': + outfile = arg + elif opt == '-i': + impl = 1 + else: + opt_string = opt_string + ' ' + opt + +with open(outfile, 'w') as ofp: + ofp.write("/* mymoc.py%s */\\n" % opt_string) + for a in args: + with open(a, 'r') as ifp: + contents = ifp.read() + a = a.replace('\\\\', '\\\\\\\\') + subst = r'{ my_qt_symbol( "' + a + '\\\\n" ); }' + if impl: + contents = re.sub(r'#include.*', '', contents) + ofp.write(contents.replace('Q_OBJECT', subst)) +sys.exit(0) +""", + ) + + self.write( + [dir, 'bin', 'myuic.py'], + """\ +import os.path +import re +import sys + +output_arg = 0 +impl_arg = 0 +impl = None +source = None +opt_string = '' +for arg in sys.argv[1:]: + if output_arg: + outfile = arg + output_arg = 0 + elif impl_arg: + impl = arg + impl_arg = 0 + elif arg == "-o": + output_arg = 1 + elif arg == "-impl": + impl_arg = 1 + elif arg[0:1] == "-": + opt_string = opt_string + ' ' + arg + else: + if source: + sys.exit(1) + source = sourceFile = arg + +with open(outfile, 'w') as ofp, open(source, 'r') as ifp: + ofp.write("/* myuic.py%s */\\n" % opt_string) + if impl: + ofp.write('#include "' + impl + '"\\n') + includes = re.findall('(.*?)', ifp.read()) + for incFile in includes: + # this is valid for ui.h files, at least + if os.path.exists(incFile): + ofp.write('#include "' + incFile + '"\\n') + else: + ofp.write('#include "my_qobject.h"\\n' + ifp.read() + " Q_OBJECT \\n") +sys.exit(0) +""", + ) + + self.write( + [dir, 'include', 'my_qobject.h'], + """\ +#define Q_OBJECT ; +void my_qt_symbol(const char *arg); +""", + ) + + self.write( + [dir, 'lib', 'my_qobject.cpp'], + """\ +#include "../include/my_qobject.h" +#include +void my_qt_symbol(const char *arg) { + fputs(arg, stdout); +} +""", + ) + + self.write( + [dir, 'lib', 'SConstruct'], + r""" +import sys +DefaultEnvironment(tools=[]) # test speedup +env = Environment() +if sys.platform == 'win32': + env.StaticLibrary('myqt', 'my_qobject.cpp') +else: + env.SharedLibrary('myqt', 'my_qobject.cpp') +""", + ) + + self.run( + chdir=self.workpath(dir, 'lib'), + arguments='.', + stderr=noisy_ar, + match=self.match_re_dotall, + ) + + self.QT = self.workpath(dir) + self.QT_LIB = 'myqt' + self.QT_MOC = f"{_python_} {self.workpath(dir, 'bin', 'mymoc.py')}" + self.QT_UIC = f"{_python_} {self.workpath(dir, 'bin', 'myuic.py')}" + self.QT_LIB_DIR = self.workpath(dir, 'lib') + + def Qt_create_SConstruct(self, place, qt_tool: str = 'qt3') -> None: + """Create a SConstruct file for Qt3 testing. + + Generates a SConstruct file configured for Qt3 building, with + optional variant directory support. + + Args: + place: File path or list of path components for the SConstruct file + qt_tool: Qt tool name to use (default: 'qt3') + """ + if isinstance(place, list): + place = self.workpath(*place) + + var_prefix = qt_tool.upper() + self.write( + place, + f"""\ +if ARGUMENTS.get('noqtdir', 0): + {var_prefix}DIR = None +else: + {var_prefix}DIR = r'{self.QT}' +DefaultEnvironment(tools=[]) # test speedup +env = Environment( + {var_prefix}DIR={var_prefix}DIR, + {var_prefix}_LIB=r'{self.QT_LIB}', + {var_prefix}_MOC=r'{self.QT_MOC}', + {var_prefix}_UIC=r'{self.QT_UIC}', + tools=['default', '{qt_tool}'], +) +dup = 1 +if ARGUMENTS.get('variant_dir', 0): + if ARGUMENTS.get('chdir', 0): + SConscriptChdir(1) + else: + SConscriptChdir(0) + dup = int(ARGUMENTS.get('dup', 1)) + if dup == 0: + builddir = 'build_dup0' + env['QT_DEBUG'] = 1 + else: + builddir = 'build' + VariantDir(builddir, '.', duplicate=dup) + print(builddir, dup) + sconscript = Dir(builddir).File('SConscript') +else: + sconscript = File('SConscript') +Export("env dup") +SConscript(sconscript) +""", + ) diff --git a/sconscontrib/SCons/Tool/qt3/test/Tool.py b/sconscontrib/SCons/Tool/qt3/test/Tool.py new file mode 100644 index 0000000..184ff5e --- /dev/null +++ b/sconscontrib/SCons/Tool/qt3/test/Tool.py @@ -0,0 +1,150 @@ +#!/usr/bin/env python +# +# MIT License +# +# Copyright The SCons Foundation +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +""" +Verify that applying env.Tool('qt3') after running Configure checks +works properly. This was broken in 0.96.95. + +The configuration here is a moderately stripped-down version of the +real-world configuration for lprof (lprof.sourceforge.net). It's probably +not completely minimal, but we're leaving it as-is since it represents a +good real-world sanity check on the interaction of some key subsystems. +""" + +import os + +import TestSCons_QT + +test = TestSCons_QT.TestSConsQt() + +if not os.environ.get('QTDIR', None): + x ="External environment variable $QTDIR not set; skipping test(s).\n" + test.skip_test(x) + +test.write('SConstruct', """ +import os + +def DoWithVariables(variables, prefix, what): + saved_variables = { } + for name in variables.keys(): + saved_variables[ name ] = env[ name ][:] + env[ name ].append(variables[ name ]) + + result = what() + + for name in saved_variables.keys(): + env[ name ] = saved_variables[ name ] + env[ prefix+name ] = variables[ name ] + + return result + +def CheckForQtAt(context, qtdir): + context.Message('Checking for Qt at %s... ' % qtdir) + libp = os.path.join(qtdir, 'lib') + cppp = os.path.join(qtdir, 'include') + result = AttemptLinkWithVariables(context, + { "LIBS": "qt-mt", "LIBPATH": libp , "CPPPATH": cppp }, + ''' +#include +int main(int argc, char **argv) { + QApplication qapp(argc, argv); + return 0; +} +''',".cpp","QT_") + context.Result(result) + return result + +def CheckForQt(context): + # list is currently POSIX centric - what happens with Windows? + potential_qt_dirs = [ + "/usr/share/qt3", # Debian unstable + "/usr/share/qt", + "/usr", + "/usr/local", + "/usr/lib/qt3", # Suse + "/usr/lib/qt", + "/usr/qt/3", # Gentoo + "/usr/pkg/qt3" # pkgsrc (NetBSD) + ] + + if 'QTDIR' in os.environ: + potential_qt_dirs.insert(0, os.environ['QTDIR']) + + if env[ 'qt_directory' ] != "/": + uic_path = os.path.join(env['qt_directory'], 'bin', 'uic') + if os.path.isfile(uic_path): + potential_qt_dirs.insert(0, env[ 'qt_directory' ]) + else: + print("QT not found. Invalid qt_directory value - failed to find uic.") + return 0 + + for i in potential_qt_dirs: + context.env.Replace(QT3DIR = i) + if CheckForQtAt(context, i): + # additional checks to validate QT installation + if not os.path.isfile(os.path.join(i, 'bin', 'uic')): + print("QT - failed to find uic.") + return 0 + if not os.path.isfile(os.path.join(i, 'bin', 'moc')): + print("QT - failed to find moc.") + return 0 + if not os.path.exists(os.path.join(i, 'lib')): + print("QT - failed to find QT lib path.") + return 0 + if not os.path.exists(os.path.join(i, 'include')): + print("QT - failed to find QT include path.") + return 0 + return 1 + else: + if i==env['qt_directory']: + print("QT directory not valid. Failed QT test build.") + return 0 + return 0 + +def AttemptLinkWithVariables(context, variables, code, extension, prefix): + return DoWithVariables(variables, prefix, + lambda: context.TryLink(code, extension)) + +env = Environment(CPPPATH=['.'], LIBPATH=['.'], LIBS=[]) + +opts = Variables('lprof.conf') +opts.Add(PathVariable("qt_directory", "Path to Qt directory", "/")) +opts.Update(env) + +env['QT3_LIB'] = 'qt-mt' +config = env.Configure(custom_tests = { + 'CheckForQt' : CheckForQt, +}) + +if not config.CheckForQt(): + print("Failed to find valid QT environment.") + Exit(1) + +env.Tool('qt3', ['$TOOL_PATH']) +""") + +test.run(arguments='.') + +test.pass_test() diff --git a/sconscontrib/SCons/Tool/qt3/test/copied-env.py b/sconscontrib/SCons/Tool/qt3/test/copied-env.py new file mode 100644 index 0000000..a7ddd3e --- /dev/null +++ b/sconscontrib/SCons/Tool/qt3/test/copied-env.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python +# +# MIT License +# +# Copyright The SCons Foundation +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +""" +Test Qt with a copied construction environment. +""" + +import TestSCons_QT + +test = TestSCons_QT.TestSConsQt() + +test.Qt_dummy_installation() + +test.Qt_create_SConstruct('SConstruct', qt_tool='qt3') + +test.write('SConscript', """\ +Import("env") +env.Append(CPPDEFINES = ['FOOBAZ']) + +copy = env.Clone() +copy.Append(CPPDEFINES = ['MYLIB_IMPL']) + +copy.SharedLibrary( + target = 'MyLib', + source = ['MyFile.cpp','MyForm.ui'] +) +""") + +test.write('MyFile.h', r""" +void aaa(void); +""") + +test.write('MyFile.cpp', r""" +#include "MyFile.h" +void useit() { + aaa(); +} +""") + +test.write('MyForm.ui', r""" +void aaa(void) +""") + +test.run() + +moc_MyForm = [x for x in test.stdout().split('\n') if 'moc_MyForm' in x] + +MYLIB_IMPL = [x for x in moc_MyForm if 'MYLIB_IMPL' in x] + +if not MYLIB_IMPL: + print("Did not find MYLIB_IMPL on moc_MyForm compilation line:") + print(test.stdout()) + test.fail_test() + +test.pass_test() diff --git a/sconscontrib/SCons/Tool/qt3/test/empty-env.py b/sconscontrib/SCons/Tool/qt3/test/empty-env.py new file mode 100644 index 0000000..cb4c954 --- /dev/null +++ b/sconscontrib/SCons/Tool/qt3/test/empty-env.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python +# +# MIT License +# +# Copyright The SCons Foundation +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +""" +Test Qt creation from a copied empty environment. +""" + +import TestSCons_QT + +test = TestSCons_QT.TestSConsQt() + +test.Qt_dummy_installation('qt') + +test.write('SConstruct', """\ +orig = Environment() +env = orig.Clone(QT3DIR = r'%s', + QT3_LIB = r'%s', + QT3_MOC = r'%s', + QT3_UIC = r'%s', + tools=['qt3']) +env.Program('main', 'main.cpp', CPPDEFINES=['FOO'], LIBS=[]) +""" % (test.QT, test.QT_LIB, test.QT_MOC, test.QT_UIC)) + +test.write('main.cpp', r""" +#include "foo6.h" +int main(void) { foo6(); return 0; } +""") + +test.write(['qt', 'include', 'foo6.h'], """\ +#include +void +foo6(void) +{ +#ifdef FOO + printf("qt/include/foo6.h\\n"); +#endif +} +""") + +# we can receive warnings about a non detected qt (empty QTDIR) +# these are not critical, but may be annoying. +test.run(stderr=None) + +test.run( + program=test.workpath('main' + TestSCons_QT._exe), + stderr=None, + stdout='qt/include/foo6.h\n', +) + +test.pass_test() diff --git a/sconscontrib/SCons/Tool/qt3/test/generated-ui.py b/sconscontrib/SCons/Tool/qt3/test/generated-ui.py new file mode 100644 index 0000000..2b44821 --- /dev/null +++ b/sconscontrib/SCons/Tool/qt3/test/generated-ui.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python +# +# MIT License +# +# Copyright The SCons Foundation +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +""" +Test that the UI scanning logic correctly picks up scansG +""" + +import os + +import TestSCons_QT + +test = TestSCons_QT.TestSConsQt() + +if not os.environ.get('QTDIR', None): + x ="External environment variable $QTDIR not set; skipping test(s).\n" + test.skip_test(x) + +test.subdir(['layer'], + ['layer', 'aclock'], + ['layer', 'aclock', 'qt_bug']) + +test.write(['SConstruct'], """\ +import os +aa=os.getcwd() + +env=Environment(tools=['default','expheaders','qt3'],toolpath=[aa]) +if 'HOME' in os.environ: + env['ENV']['HOME'] = os.environ['HOME'] +env["EXP_HEADER_ABS"]=os.path.join(os.getcwd(),'include') +if not os.access(env["EXP_HEADER_ABS"],os.F_OK): + os.mkdir (env["EXP_HEADER_ABS"]) +Export('env') +env.SConscript('layer/aclock/qt_bug/SConscript') +""") + +test.write(['expheaders.py'], """\ +import SCons.Defaults +def ExpHeaderScanner(node, env, path): + return [] +def generate(env): + HeaderAction=SCons.Action.Action([SCons.Defaults.Copy('$TARGET','$SOURCE'),SCons.Defaults.Chmod('$TARGET',0o755)]) + HeaderBuilder= SCons.Builder.Builder(action=HeaderAction) + env['BUILDERS']['ExportHeaders'] = HeaderBuilder +def exists(env): + return 0 +""") + +test.write(['layer', 'aclock', 'qt_bug', 'SConscript'], """\ +import os + +Import ("env") +#src=os.path.join(env.Dir('.').srcnode().abspath, 'testfile.h') +env.ExportHeaders(os.path.join(env["EXP_HEADER_ABS"],'main.h'), 'main.h') +env.ExportHeaders(os.path.join(env["EXP_HEADER_ABS"],'migraform.h'), 'migraform.h') +env.Append(CPPPATH=env["EXP_HEADER_ABS"]) +env.StaticLibrary('all',['main.ui','migraform.ui']) +""") + +test.write(['layer', 'aclock', 'qt_bug', 'main.ui'], """\ + +Main + + + Main + + + + 0 + 0 + 600 + 385 + + + + + migraform.h + + +""") + +test.write(['layer', 'aclock', 'qt_bug', 'migraform.ui'], """\ + +MigrateForm + + + MigrateForm + + + + 0 + 0 + %s + 385 + + + + +""") + +test.run( + stderr=TestSCons.noisy_ar, + match=TestSCons.match_re_dotall, +) + +test.up_to_date(arguments=".") + +test.pass_test() diff --git a/sconscontrib/SCons/Tool/qt3/test/installed.py b/sconscontrib/SCons/Tool/qt3/test/installed.py new file mode 100644 index 0000000..9af7cdf --- /dev/null +++ b/sconscontrib/SCons/Tool/qt3/test/installed.py @@ -0,0 +1,214 @@ +#!/usr/bin/env python +# +# MIT License +# +# Copyright The SCons Foundation +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +""" +Look if qt3 is installed, and try out all builders. +""" + +import os +import sys + +import TestSCons_QT + +test = TestSCons_QT.TestSConsQt() + +if not os.environ.get('QTDIR', None): + x ="External environment variable $QTDIR not set; skipping test(s).\n" + test.skip_test(x) + +test.Qt_dummy_installation() + +QTDIR=os.environ['QTDIR'] + + +test.write('SConstruct', """\ +import os +dummy_env = Environment() +ENV = dummy_env['ENV'] +try: + PATH=ARGUMENTS['PATH'] + if 'PATH' in ENV: + ENV_PATH = PATH + os.pathsep + ENV['PATH'] + else: + Exit(0) # this is certainly a weird system :-) +except KeyError: + ENV_PATH=ENV.get('PATH', '') + +env = Environment(tools=['default','qt3'], + ENV={'PATH':ENV_PATH, + 'PATHEXT':os.environ.get('PATHEXT'), + 'HOME':os.getcwd(), + 'SystemRoot':ENV.get('SystemRoot')}, + # moc / uic want to write stuff in ~/.qt + CXXFILESUFFIX=".cpp") + +conf = env.Configure() +if not conf.CheckLib(env.subst("$QT3_LIB"), autoadd=0): + conf.env['QT3_LIB'] = 'qt-mt' + if not conf.CheckLib(env.subst("$QT3_LIB"), autoadd=0): + Exit(0) +env = conf.Finish() +VariantDir('bld', '.') +env.Program('bld/test_realqt', ['bld/mocFromCpp.cpp', + 'bld/mocFromH.cpp', + 'bld/anUiFile.ui', + 'bld/main.cpp']) +""") + +test.write('mocFromCpp.h', """\ +void mocFromCpp(); +""") + +test.write('mocFromCpp.cpp', """\ +#include +#include "mocFromCpp.h" +class MyClass1 : public QObject { + Q_OBJECT + public: + MyClass1() : QObject() {}; + public slots: + void myslot() {}; +}; +void mocFromCpp() { + MyClass1 myclass; +} +#include "mocFromCpp.moc" +""") + +test.write('mocFromH.h', """\ +#include +class MyClass2 : public QObject { + Q_OBJECT; + public: + MyClass2(); + public slots: + void myslot(); +}; +void mocFromH(); +""") + +test.write('mocFromH.cpp', """\ +#include "mocFromH.h" + +MyClass2::MyClass2() : QObject() {} +void MyClass2::myslot() {} +void mocFromH() { + MyClass2 myclass; +} +""") + +test.write('anUiFile.ui', """\ + +MyWidget + + QWidget + + MyWidget + + + MyWidget + + + + anUiFile.ui.h + + + testSlot() + + + +""") + +test.write('anUiFile.ui.h', r""" +#include +#if QT_VERSION >= 0x030100 +void MyWidget::testSlot() +{ + printf("Hello World\n"); +} +#endif +""") + +test.write('main.cpp', r""" +#include +#include "mocFromCpp.h" +#include "mocFromH.h" +#include "anUiFile.h" +#include + +int main(int argc, char **argv) { + QApplication app(argc, argv); + mocFromCpp(); + mocFromH(); + MyWidget mywidget; +#if QT_VERSION >= 0x030100 + mywidget.testSlot(); +#else + printf("Hello World\n"); +#endif + return 0; +} +""") + +test.run(arguments="--warn=no-tool-qt-deprecated bld/test_realqt" + TestSCons_QT._exe) + +test.run( + program=test.workpath("bld", "test_realqt"), + arguments="--warn=no-tool-qt-deprecated", + stdout=None, + status=None, + stderr=None, +) + +if test.stdout() != "Hello World\n" or test.stderr() != '' or test.status: + sys.stdout.write(test.stdout()) + sys.stderr.write(test.stderr()) + # The test might be run on a system that doesn't have an X server + # running, or may be run by an ID that can't connect to the server. + # If so, then print whatever it showed us (which is in and of itself + # an indication that it built correctly) but don't fail the test. + expect = 'cannot connect to X server' + test.fail_test(test.stdout()) + test.fail_test(expect not in test.stderr()) + if test.status != 1 and (test.status >> 8) != 1: + sys.stdout.write('test_realqt returned status %s\n' % test.status) + test.fail_test() + +QT3DIR = os.environ['QTDIR'] +PATH = os.environ['PATH'] +os.environ['QTDIR'] = '' +os.environ['PATH'] = '.' + +test.run( + stderr=None, + arguments="-c bld/test_realqt" + TestSCons_QT._exe, +) + +expect1 = "scons: warning: Could not detect qt3, using empty QT3DIR" +expect2 = "scons: warning: Could not detect qt3, using moc executable as a hint" + +test.fail_test(expect1 not in test.stderr() and expect2 not in test.stderr()) + +test.pass_test() diff --git a/sconscontrib/SCons/Tool/qt3/test/manual.py b/sconscontrib/SCons/Tool/qt3/test/manual.py new file mode 100644 index 0000000..cf031ac --- /dev/null +++ b/sconscontrib/SCons/Tool/qt3/test/manual.py @@ -0,0 +1,142 @@ +#!/usr/bin/env python +# +# MIT License +# +# Copyright The SCons Foundation +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +""" +Test the manual QT3 builder calls. +""" + +import TestSCons_QT + +test = TestSCons_QT.TestSConsQt() + +test.subdir('include', 'ui') + +test.Qt_dummy_installation() + +aaa_exe = 'aaa' + TestSCons_QT._exe + +test.Qt_create_SConstruct('SConstruct') + +test.write('SConscript', r""" +Import("env") +sources = ['aaa.cpp', 'bbb.cpp', 'ddd.cpp', 'eee.cpp', 'main.cpp'] + +# normal invocation +sources.append(env.Moc('include/aaa.h')) +moc = env.Moc('bbb.cpp') +env.Ignore( moc, moc ) +sources.extend(env.Uic('ui/ccc.ui')[1:]) + +# manual target specification +sources.append(env.Moc('moc-ddd.cpp', 'include/ddd.h', + QT3_MOCHPREFIX='')) # Watch out ! +moc = env.Moc('moc_eee.cpp', 'eee.cpp') +env.Ignore( moc, moc ) +sources.extend(env.Uic(['include/uic_fff.hpp', 'fff.cpp', 'fff.moc.cpp'], + 'ui/fff.ui')[1:]) + +print(list(map(str,sources))) +env.Program(target='aaa', + source=sources, + CPPPATH=['$CPPPATH', './include'], + QT3_AUTOSCAN=0) +""") + +test.write('aaa.cpp', r""" +#include "aaa.h" +""") + +test.write(['include', 'aaa.h'], r""" +#include "my_qobject.h" +void aaa(void) Q_OBJECT; +""") + +test.write('bbb.h', r""" +void bbb(void); +""") + +test.write('bbb.cpp', r""" +#include "my_qobject.h" +void bbb(void) Q_OBJECT +#include "bbb.moc" +""") + +test.write(['ui', 'ccc.ui'], r""" +void ccc(void) +""") + +test.write('ddd.cpp', r""" +#include "ddd.h" +""") + +test.write(['include', 'ddd.h'], r""" +#include "my_qobject.h" +void ddd(void) Q_OBJECT; +""") + +test.write('eee.h', r""" +void eee(void); +""") + +test.write('eee.cpp', r""" +#include "my_qobject.h" +void eee(void) Q_OBJECT +#include "moc_eee.cpp" +""") + +test.write(['ui', 'fff.ui'], r""" +void fff(void) +""") + +test.write('main.cpp', r""" +#include "aaa.h" +#include "bbb.h" +#include "ui/ccc.h" +#include "ddd.h" +#include "eee.h" +#include "uic_fff.hpp" + +int main(void) { + aaa(); bbb(); ccc(); ddd(); eee(); fff(); return 0; +} +""") + +test.run(arguments=aaa_exe) + +# normal invocation +test.must_exist(test.workpath('include', 'moc_aaa.cc')) +test.must_exist(test.workpath('bbb.moc')) +test.must_exist(test.workpath('ui', 'ccc.h')) +test.must_exist(test.workpath('ui', 'uic_ccc.cc')) +test.must_exist(test.workpath('ui', 'moc_ccc.cc')) + +# manual target spec. +test.must_exist(test.workpath('moc-ddd.cpp')) +test.must_exist(test.workpath('moc_eee.cpp')) +test.must_exist(test.workpath('include', 'uic_fff.hpp')) +test.must_exist(test.workpath('fff.cpp')) +test.must_exist(test.workpath('fff.moc.cpp')) + +test.pass_test() diff --git a/sconscontrib/SCons/Tool/qt3/test/moc-from-cpp.py b/sconscontrib/SCons/Tool/qt3/test/moc-from-cpp.py new file mode 100644 index 0000000..953c82f --- /dev/null +++ b/sconscontrib/SCons/Tool/qt3/test/moc-from-cpp.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python +# +# MIT License +# +# Copyright The SCons Foundation +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +""" +Create a moc file from a cpp file. +""" + +import TestSCons_QT + +test = TestSCons_QT.TestSConsQt() + +test.Qt_dummy_installation() + +############################################################################## + +lib_aaa = TestSCons_QT.lib_ + 'aaa' + TestSCons_QT._lib +moc = 'aaa.moc' + +test.Qt_create_SConstruct('SConstruct') + +test.write('SConscript', """ +Import("env dup") +if dup == 0: env.Append(CPPPATH=['.']) +env.StaticLibrary(target = '%s', source = ['aaa.cpp','useit.cpp']) +""" % lib_aaa) + +test.write('aaa.h', r""" +void aaa(void); +""") + +test.write('aaa.cpp', r""" +#include "my_qobject.h" +void aaa(void) Q_OBJECT +#include "%s" +""" % moc) + +test.write('useit.cpp', r""" +#include "aaa.h" +void useit() { + aaa(); +} +""") + +test.run( + arguments="--warn=no-tool-qt-deprecated " + lib_aaa, + stderr=TestSCons.noisy_ar, + match=TestSCons.match_re_dotall, +) + +test.up_to_date(options='-n --warn=no-tool-qt-deprecated', arguments=lib_aaa) + +test.write('aaa.cpp', r""" +#include "my_qobject.h" +/* a change */ +void aaa(void) Q_OBJECT +#include "%s" +""" % moc) + +test.not_up_to_date(options='-n --warn=no-tool-qt-deprecated', arguments=moc) + +test.run(options="--warn=no-tool-qt-deprecated -c", arguments=lib_aaa) + +test.run( + arguments="--warn=no-tool-qt-deprecated variant_dir=1 " + + test.workpath('build', lib_aaa), + stderr=TestSCons.noisy_ar, + match=TestSCons.match_re_dotall, +) + +test.run( + arguments="--warn=no-tool-qt-deprecated variant_dir=1 chdir=1 " + + test.workpath('build', lib_aaa) +) + +test.must_exist(test.workpath('build', moc)) + +test.run( + arguments="--warn=no-tool-qt-deprecated variant_dir=1 dup=0 " + + test.workpath('build_dup0', lib_aaa), + stderr=TestSCons.noisy_ar, + match=TestSCons.match_re_dotall, +) + +test.must_exist(test.workpath('build_dup0', moc)) + +test.pass_test() diff --git a/sconscontrib/SCons/Tool/qt3/test/moc-from-header.py b/sconscontrib/SCons/Tool/qt3/test/moc-from-header.py new file mode 100644 index 0000000..88b967f --- /dev/null +++ b/sconscontrib/SCons/Tool/qt3/test/moc-from-header.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python +# +# MIT License +# +# Copyright The SCons Foundation +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +""" +Create a moc file from a header file. +""" + +import os + +import TestSCons_QT + +test = TestSCons_QT.TestSConsQt() + +test.write('SConstruct', """ +env = Environment() +""") + +test.Qt_dummy_installation() + +# We'll run some test programs later that need to find our dummy +# Qt library. +os.environ['LD_LIBRARY_PATH'] = test.QT_LIB_DIR + +############################################################################## + +aaa_exe = 'aaa' + TestSCons_QT._exe +build_aaa_exe = test.workpath('build', aaa_exe) +moc = 'moc_aaa.cc' + +test.Qt_create_SConstruct('SConstruct') + +test.write('SConscript', """\ +Import("env") +env.Program(target = 'aaa', source = 'aaa.cpp') +if env['PLATFORM'] == 'darwin': + env.Install('.', 'qt/lib/libmyqt.dylib') +""") + +test.write('aaa.cpp', r""" +#include "aaa.h" +int main(void) { aaa(); return 0; } +""") + +test.write('aaa.h', r""" +#include "my_qobject.h" +void aaa(void) Q_OBJECT; +""") + +test.run(arguments="--warn=no-tool-qt-deprecated") +test.up_to_date(options='--warn=no-tool-qt-deprecated -n', arguments=aaa_exe) + +test.write('aaa.h', r""" +/* a change */ +#include "my_qobject.h" +void aaa(void) Q_OBJECT; +""") + +test.not_up_to_date(options='--warn=no-tool-qt-deprecated -n', arguments=moc) + +test.run( + arguments="--warn=no-tool-qt-deprecated", + program=test.workpath(aaa_exe), + stdout='aaa.h\n', +) + +test.run(arguments="--warn=no-tool-qt-deprecated variant_dir=1 " + build_aaa_exe) + +test.run( + arguments="--warn=no-tool-qt-deprecated variant_dir=1 chdir=1 " + build_aaa_exe +) + +test.must_exist(test.workpath('build', moc)) + +test.run( + arguments="--warn=no-tool-qt-deprecated variant_dir=1 chdir=1 dup=0 " + + test.workpath('build_dup0', aaa_exe) +) + +test.must_exist(['build_dup0', moc]) + +test.pass_test() diff --git a/sconscontrib/SCons/Tool/qt3/test/qt_warnings.py b/sconscontrib/SCons/Tool/qt3/test/qt_warnings.py new file mode 100644 index 0000000..237a498 --- /dev/null +++ b/sconscontrib/SCons/Tool/qt3/test/qt_warnings.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python +# +# MIT License +# +# Copyright The SCons Foundation +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +""" +Test the Qt tool warnings. +""" + +import os +import re + +import TestSCons_QT + +test = TestSCons_QT.TestSConsQt() + +SConstruct_path = test.workpath('SConstruct') + +test.Qt_dummy_installation() + +test.Qt_create_SConstruct(SConstruct_path) + +test.write('aaa.cpp', r""" +#include "my_qobject.h" +void aaa(void) Q_OBJECT +""") + +test.write('SConscript', r""" +Import("env") +import os +env.StaticLibrary('aaa.cpp') +""") + +test.run(stderr=None) + +match12 = r""" +scons: warning: Generated moc file 'aaa.moc' is not included by 'aaa.cpp' +""" + TestSCons.file_expr + +if not re.search(match12, test.stderr()): + print("Did not find expected regular expression in stderr:") + print(test.stderr()) + test.fail_test() + +os.environ['QTDIR'] = test.QT + +test.run(arguments='-n noqtdir=1') + +# We'd like to eliminate $QTDIR from the environment as follows: +# del os.environ['QTDIR'] +# But unfortunately, in at least some versions of Python, the Environment +# class doesn't implement a __delitem__() method to make the library +# call to actually remove the deleted variable from the *external* +# environment, so it only gets removed from the Python dictionary. +# Consequently, we need to just wipe out its value as follows> +os.environ['QTDIR'] = '' +test.run(stderr=None, arguments='-n noqtdir=1') + +moc = test.where_is('moc') +if moc: + import os.path + qtdir = os.path.dirname(os.path.dirname(moc)) + qtdir = qtdir.replace('\\', '\\\\' ) + + expect = r""" +scons: warning: Could not detect qt3, using moc executable as a hint \(QT3DIR=%s\) +File "%s", line \d+, in (\?|) +""" % (qtdir, re.escape(SConstruct_path)) +else: + + expect = r""" +scons: warning: Could not detect qt3, using empty QT3DIR +File "%s", line \d+, in (\?|) +""" % re.escape(SConstruct_path) + +test.fail_test(not test.match_re(test.stderr(), expect)) + +test.pass_test() diff --git a/sconscontrib/SCons/Tool/qt3/test/reentrant.py b/sconscontrib/SCons/Tool/qt3/test/reentrant.py new file mode 100644 index 0000000..948b767 --- /dev/null +++ b/sconscontrib/SCons/Tool/qt3/test/reentrant.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python +# +# MIT License +# +# Copyright The SCons Foundation +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +""" +Test creation from a copied environment that already has QT variables. +This makes sure the tool initialization is re-entrant. +""" + +import TestSCons_QT + +test = TestSCons_QT.TestSConsQt() + +test.Qt_dummy_installation('qt') + +test.write(['qt', 'include', 'foo5.h'], """\ +#include +void +foo5(void) +{ +#ifdef FOO + printf("qt/include/foo5.h\\n"); +#endif +} +""") + +test.Qt_create_SConstruct('SConstruct') + +test.write('SConscript', """\ +Import("env") +env = env.Clone(tools=['qt3']) +env.Program('main', 'main.cpp', CPPDEFINES=['FOO'], LIBS=[]) +""") + +test.write('main.cpp', r""" +#include "foo5.h" +int main(void) { foo5(); return 0; } +""") + +test.run(arguments="--warn=no-tool-qt-deprecated") + +test.run( + arguments='--warn=no-tool-qt-deprecated', + program=test.workpath('main' + TestSCons_QT._exe), + stdout='qt/include/foo5.h\n', +) +test.pass_test() diff --git a/sconscontrib/SCons/Tool/qt3/test/source-from-ui.py b/sconscontrib/SCons/Tool/qt3/test/source-from-ui.py new file mode 100644 index 0000000..d0b6904 --- /dev/null +++ b/sconscontrib/SCons/Tool/qt3/test/source-from-ui.py @@ -0,0 +1,155 @@ +#!/usr/bin/env python +# +# MIT License +# +# Copyright The SCons Foundation +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +""" +Create .cpp, .h, moc_....cpp from a .ui file. +""" + +import os.path + +import TestSCons_QT + +test = TestSCons_QT.TestSConsQt() + +test.Qt_dummy_installation() + +############################################################################## + +aaa_dll = TestSCons_QT.dll_ + 'aaa' + TestSCons_QT._dll +moc = 'moc_aaa.cc' +cpp = 'uic_aaa.cc' +obj = TestSCons_QT.shobj_ + os.path.splitext(cpp)[0] + TestSCons_QT._shobj +h = 'aaa.h' + +test.Qt_create_SConstruct('SConstruct') + +test.write('SConscript', """\ +Import("env dup") +if dup == 0: env.Append(CPPPATH=['#', '.']) +env.SharedLibrary(target = 'aaa', source = ['aaa.ui', 'useit.cpp']) +""") + +test.write('aaa.ui', r""" +#if defined (_WIN32) || defined(__CYGWIN__) +#define DLLEXPORT __declspec(dllexport) +#else +#define DLLEXPORT +#endif +DLLEXPORT void aaa(void) +""") + +test.write('useit.cpp', r""" +#include "aaa.h" +void useit() { + aaa(); +} +""") + +test.run(arguments=aaa_dll) + +test.up_to_date(options='-n', arguments=aaa_dll) + +test.write('aaa.ui', r""" +/* a change */ +#if defined (_WIN32) || defined(__CYGWIN__) +#define DLLEXPORT __declspec(dllexport) +#else +#define DLLEXPORT +#endif +DLLEXPORT void aaa(void) +""") + +test.not_up_to_date(options='-n', arguments=moc) +test.not_up_to_date(options='-n', arguments=cpp) +test.not_up_to_date(options='-n', arguments=h) + +test.run(arguments=" " + aaa_dll) + +test.write('aaa.ui', r""" +void aaa(void) +//aaa.ui.h +""") + +# test that non-existant ui.h files are ignored (as uic does) +test.run(arguments=" " + aaa_dll) + +test.write('aaa.ui.h', r""" +/* test dependency to .ui.h */ +""") + +test.run(arguments=" " + aaa_dll) + +test.write('aaa.ui.h', r""" +/* changed */ +""") + +test.not_up_to_date(options='-n', arguments=obj) +test.not_up_to_date(options='-n', arguments=cpp) +test.not_up_to_date(options='-n', arguments=h) +test.not_up_to_date(options='-n', arguments=moc) + +# clean up +test.run(arguments=" -c " + aaa_dll) + +test.run( + arguments="variant_dir=1 " + + test.workpath('build', aaa_dll) +) + +test.must_exist(test.workpath('build', moc)) +test.must_exist(test.workpath('build', cpp)) +test.must_exist(test.workpath('build', h)) +test.must_not_exist(test.workpath(moc)) +test.must_not_exist(test.workpath(cpp)) +test.must_not_exist(test.workpath(h)) + +cppContents = test.read(test.workpath('build', cpp), mode='r') +test.fail_test('#include "aaa.ui.h"' not in cppContents) + +test.run( + arguments="variant_dir=1 chdir=1 " + + test.workpath('build', aaa_dll) +) + +test.must_exist(test.workpath('build', moc)) +test.must_exist(test.workpath('build', cpp)) +test.must_exist(test.workpath('build', h)) +test.must_not_exist(test.workpath(moc)) +test.must_not_exist(test.workpath(cpp)) +test.must_not_exist(test.workpath(h)) + +test.run( + arguments=" variant_dir=1 chdir=1 dup=0 " + + test.workpath('build_dup0', aaa_dll) +) + +test.must_exist(test.workpath('build_dup0', moc)) +test.must_exist(test.workpath('build_dup0', cpp)) +test.must_exist(test.workpath('build_dup0', h)) +test.must_not_exist(test.workpath(moc)) +test.must_not_exist(test.workpath(cpp)) +test.must_not_exist(test.workpath(h)) + +test.pass_test() diff --git a/sconscontrib/SCons/Tool/qt3/test/up-to-date.py b/sconscontrib/SCons/Tool/qt3/test/up-to-date.py new file mode 100644 index 0000000..188c393 --- /dev/null +++ b/sconscontrib/SCons/Tool/qt3/test/up-to-date.py @@ -0,0 +1,138 @@ +#!/usr/bin/env python +# +# MIT License +# +# Copyright The SCons Foundation +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +""" +Validate that a stripped-down real-world Qt configuation (thanks +to Leanid Nazdrynau) with a generated .h file is correctly +up-to-date after a build. + +(This catches a bug that was introduced during a signature refactoring +ca. September 2005.) +""" + +import os + +import TestSCons_QT + +_obj = TestSCons_QT._obj + +test = TestSCons_QT.TestSConsQt() + +if not os.environ.get('QTDIR', None): + x ="External environment variable $QTDIR not set; skipping test(s).\n" + test.skip_test(x) + +test.subdir('layer', + ['layer', 'aclock'], + ['layer', 'aclock', 'qt_bug']) + +test.write('SConstruct', """\ +import os +aa=os.getcwd() + +env=Environment(tools=['default','expheaders','qt3'],toolpath=[aa]) +env["EXP_HEADER_ABS"]=os.path.join(os.getcwd(),'include') +if not os.access(env["EXP_HEADER_ABS"],os.F_OK): + os.mkdir (env["EXP_HEADER_ABS"]) +Export('env') +env.SConscript('layer/aclock/qt_bug/SConscript') +""") + +test.write('expheaders.py', """\ +import SCons.Defaults +def ExpHeaderScanner(node, env, path): + return [] +def generate(env): + HeaderAction=SCons.Action.Action([SCons.Defaults.Copy('$TARGET','$SOURCE'),SCons.Defaults.Chmod('$TARGET',0o755)]) + HeaderBuilder= SCons.Builder.Builder(action=HeaderAction) + env['BUILDERS']['ExportHeaders'] = HeaderBuilder +def exists(env): + return 0 +""") + +test.write(['layer', 'aclock', 'qt_bug', 'SConscript'], """\ +import os + +Import ("env") +env.ExportHeaders(os.path.join(env["EXP_HEADER_ABS"],'main.h'), 'main.h') +env.ExportHeaders(os.path.join(env["EXP_HEADER_ABS"],'migraform.h'), 'migraform.h') +env.Append(CPPPATH=env["EXP_HEADER_ABS"]) +env.StaticLibrary('all',['main.ui','migraform.ui','my.cc']) +""") + +test.write(['layer', 'aclock', 'qt_bug', 'main.ui'], """\ + +Main + + + Main + + + + 0 + 0 + 600 + 385 + + + + + migraform.h + + +""") + +test.write(['layer', 'aclock', 'qt_bug', 'migraform.ui'], """\ + +MigrateForm + + + MigrateForm + + + + 0 + 0 + 600 + 385 + + + + +""") + +test.write(['layer', 'aclock', 'qt_bug', 'my.cc'], """\ +#include +""") + +my_obj = 'layer/aclock/qt_bug/my' + _obj + +test.run(arguments='--warn=no-tool-qt-deprecated ' + my_obj, stderr=None) + +expect = my_obj.replace('/', os.sep) +test.up_to_date(options='--debug=explain', arguments=expect, stderr=None) + +test.pass_test()