qt.py
上传用户:market2
上传日期:2018-11-18
资源大小:18786k
文件大小:13k
源码类别:

外挂编程

开发平台:

Windows_Unix

  1. """SCons.Tool.qt
  2. Tool-specific initialization for Qt.
  3. There normally shouldn't be any need to import this module directly.
  4. It will usually be imported through the generic SCons.Tool.Tool()
  5. selection method.
  6. """
  7. #
  8. # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
  9. #
  10. # Permission is hereby granted, free of charge, to any person obtaining
  11. # a copy of this software and associated documentation files (the
  12. # "Software"), to deal in the Software without restriction, including
  13. # without limitation the rights to use, copy, modify, merge, publish,
  14. # distribute, sublicense, and/or sell copies of the Software, and to
  15. # permit persons to whom the Software is furnished to do so, subject to
  16. # the following conditions:
  17. #
  18. # The above copyright notice and this permission notice shall be included
  19. # in all copies or substantial portions of the Software.
  20. #
  21. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
  22. # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  23. # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  24. # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  25. # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  26. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  27. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  28. #
  29. __revision__ = "src/engine/SCons/Tool/qt.py 3057 2008/06/09 22:21:00 knight"
  30. import os.path
  31. import re
  32. import SCons.Action
  33. import SCons.Builder
  34. import SCons.Defaults
  35. import SCons.Scanner
  36. import SCons.Tool
  37. import SCons.Util
  38. class ToolQtWarning(SCons.Warnings.Warning):
  39.     pass
  40. class GeneratedMocFileNotIncluded(ToolQtWarning):
  41.     pass
  42. class QtdirNotFound(ToolQtWarning):
  43.     pass
  44. SCons.Warnings.enableWarningClass(ToolQtWarning)
  45. header_extensions = [".h", ".hxx", ".hpp", ".hh"]
  46. if SCons.Util.case_sensitive_suffixes('.h', '.H'):
  47.     header_extensions.append('.H')
  48. cplusplus = __import__('c++', globals(), locals(), [])
  49. cxx_suffixes = cplusplus.CXXSuffixes
  50. def checkMocIncluded(target, source, env):
  51.     moc = target[0]
  52.     cpp = source[0]
  53.     # looks like cpp.includes is cleared before the build stage :-(
  54.     # not really sure about the path transformations (moc.cwd? cpp.cwd?) :-/
  55.     path = SCons.Defaults.CScan.path(env, moc.cwd)
  56.     includes = SCons.Defaults.CScan(cpp, env, path)
  57.     if not moc in includes:
  58.         SCons.Warnings.warn(
  59.             GeneratedMocFileNotIncluded,
  60.             "Generated moc file '%s' is not included by '%s'" %
  61.             (str(moc), str(cpp)))
  62. def find_file(filename, paths, node_factory):
  63.     for dir in paths:
  64.         node = node_factory(filename, dir)
  65.         if node.rexists():
  66.             return node
  67.     return None
  68. class _Automoc:
  69.     """
  70.     Callable class, which works as an emitter for Programs, SharedLibraries and
  71.     StaticLibraries.
  72.     """
  73.     def __init__(self, objBuilderName):
  74.         self.objBuilderName = objBuilderName
  75.         
  76.     def __call__(self, target, source, env):
  77.         """
  78.         Smart autoscan function. Gets the list of objects for the Program
  79.         or Lib. Adds objects and builders for the special qt files.
  80.         """
  81.         try:
  82.             if int(env.subst('$QT_AUTOSCAN')) == 0:
  83.                 return target, source
  84.         except ValueError:
  85.             pass
  86.         try:
  87.             debug = int(env.subst('$QT_DEBUG'))
  88.         except ValueError:
  89.             debug = 0
  90.         
  91.         # some shortcuts used in the scanner
  92.         splitext = SCons.Util.splitext
  93.         objBuilder = getattr(env, self.objBuilderName)
  94.   
  95.         # some regular expressions:
  96.         # Q_OBJECT detection
  97.         q_object_search = re.compile(r'[^A-Za-z0-9]Q_OBJECT[^A-Za-z0-9]') 
  98.         # cxx and c comment 'eater'
  99.         #comment = re.compile(r'(//.*)|(/*(([^*])|(*[^/]))**/)')
  100.         # CW: something must be wrong with the regexp. See also bug #998222
  101.         #     CURRENTLY THERE IS NO TEST CASE FOR THAT
  102.         
  103.         # The following is kind of hacky to get builders working properly (FIXME)
  104.         objBuilderEnv = objBuilder.env
  105.         objBuilder.env = env
  106.         mocBuilderEnv = env.Moc.env
  107.         env.Moc.env = env
  108.         
  109.         # make a deep copy for the result; MocH objects will be appended
  110.         out_sources = source[:]
  111.         for obj in source:
  112.             if not obj.has_builder():
  113.                 # binary obj file provided
  114.                 if debug:
  115.                     print "scons: qt: '%s' seems to be a binary. Discarded." % str(obj)
  116.                 continue
  117.             cpp = obj.sources[0]
  118.             if not splitext(str(cpp))[1] in cxx_suffixes:
  119.                 if debug:
  120.                     print "scons: qt: '%s' is no cxx file. Discarded." % str(cpp) 
  121.                 # c or fortran source
  122.                 continue
  123.             #cpp_contents = comment.sub('', cpp.get_contents())
  124.             cpp_contents = cpp.get_contents()
  125.             h=None
  126.             for h_ext in header_extensions:
  127.                 # try to find the header file in the corresponding source
  128.                 # directory
  129.                 hname = splitext(cpp.name)[0] + h_ext
  130.                 h = find_file(hname, (cpp.get_dir(),), env.File)
  131.                 if h:
  132.                     if debug:
  133.                         print "scons: qt: Scanning '%s' (header of '%s')" % (str(h), str(cpp))
  134.                     #h_contents = comment.sub('', h.get_contents())
  135.                     h_contents = h.get_contents()
  136.                     break
  137.             if not h and debug:
  138.                 print "scons: qt: no header for '%s'." % (str(cpp))
  139.             if h and q_object_search.search(h_contents):
  140.                 # h file with the Q_OBJECT macro found -> add moc_cpp
  141.                 moc_cpp = env.Moc(h)
  142.                 moc_o = objBuilder(moc_cpp)
  143.                 out_sources.append(moc_o)
  144.                 #moc_cpp.target_scanner = SCons.Defaults.CScan
  145.                 if debug:
  146.                     print "scons: qt: found Q_OBJECT macro in '%s', moc'ing to '%s'" % (str(h), str(moc_cpp))
  147.             if cpp and q_object_search.search(cpp_contents):
  148.                 # cpp file with Q_OBJECT macro found -> add moc
  149.                 # (to be included in cpp)
  150.                 moc = env.Moc(cpp)
  151.                 env.Ignore(moc, moc)
  152.                 if debug:
  153.                     print "scons: qt: found Q_OBJECT macro in '%s', moc'ing to '%s'" % (str(cpp), str(moc))
  154.                 #moc.source_scanner = SCons.Defaults.CScan
  155.         # restore the original env attributes (FIXME)
  156.         objBuilder.env = objBuilderEnv
  157.         env.Moc.env = mocBuilderEnv
  158.         return (target, out_sources)
  159. AutomocShared = _Automoc('SharedObject')
  160. AutomocStatic = _Automoc('StaticObject')
  161. def _detect(env):
  162.     """Not really safe, but fast method to detect the QT library"""
  163.     QTDIR = None
  164.     if not QTDIR:
  165.         QTDIR = env.get('QTDIR',None)
  166.     if not QTDIR:
  167.         QTDIR = os.environ.get('QTDIR',None)
  168.     if not QTDIR:
  169.         moc = env.WhereIs('moc')
  170.         if moc:
  171.             QTDIR = os.path.dirname(os.path.dirname(moc))
  172.             SCons.Warnings.warn(
  173.                 QtdirNotFound,
  174.                 "Could not detect qt, using moc executable as a hint (QTDIR=%s)" % QTDIR)
  175.         else:
  176.             QTDIR = None
  177.             SCons.Warnings.warn(
  178.                 QtdirNotFound,
  179.                 "Could not detect qt, using empty QTDIR")
  180.     return QTDIR
  181. def uicEmitter(target, source, env):
  182.     adjustixes = SCons.Util.adjustixes
  183.     bs = SCons.Util.splitext(str(source[0].name))[0]
  184.     bs = os.path.join(str(target[0].get_dir()),bs)
  185.     # first target (header) is automatically added by builder
  186.     if len(target) < 2:
  187.         # second target is implementation
  188.         target.append(adjustixes(bs,
  189.                                  env.subst('$QT_UICIMPLPREFIX'),
  190.                                  env.subst('$QT_UICIMPLSUFFIX')))
  191.     if len(target) < 3:
  192.         # third target is moc file
  193.         target.append(adjustixes(bs,
  194.                                  env.subst('$QT_MOCHPREFIX'),
  195.                                  env.subst('$QT_MOCHSUFFIX')))
  196.     return target, source
  197. def uicScannerFunc(node, env, path):
  198.     lookout = []
  199.     lookout.extend(env['CPPPATH'])
  200.     lookout.append(str(node.rfile().dir))
  201.     includes = re.findall("<include.*?>(.*?)</include>", node.get_contents())
  202.     result = []
  203.     for incFile in includes:
  204.         dep = env.FindFile(incFile,lookout)
  205.         if dep:
  206.             result.append(dep)
  207.     return result
  208. uicScanner = SCons.Scanner.Base(uicScannerFunc,
  209.                                 name = "UicScanner", 
  210.                                 node_class = SCons.Node.FS.File,
  211.                                 node_factory = SCons.Node.FS.File,
  212.                                 recursive = 0)
  213. def generate(env):
  214.     """Add Builders and construction variables for qt to an Environment."""
  215.     CLVar = SCons.Util.CLVar
  216.     Action = SCons.Action.Action
  217.     Builder = SCons.Builder.Builder
  218.     env.SetDefault(QTDIR  = _detect(env),
  219.                    QT_BINPATH = os.path.join('$QTDIR', 'bin'),
  220.                    QT_CPPPATH = os.path.join('$QTDIR', 'include'),
  221.                    QT_LIBPATH = os.path.join('$QTDIR', 'lib'),
  222.                    QT_MOC = os.path.join('$QT_BINPATH','moc'),
  223.                    QT_UIC = os.path.join('$QT_BINPATH','uic'),
  224.                    QT_LIB = 'qt', # may be set to qt-mt
  225.                    QT_AUTOSCAN = 1, # scan for moc'able sources
  226.                    # Some QT specific flags. I don't expect someone wants to
  227.                    # manipulate those ...
  228.                    QT_UICIMPLFLAGS = CLVar(''),
  229.                    QT_UICDECLFLAGS = CLVar(''),
  230.                    QT_MOCFROMHFLAGS = CLVar(''),
  231.                    QT_MOCFROMCXXFLAGS = CLVar('-i'),
  232.                    # suffixes/prefixes for the headers / sources to generate
  233.                    QT_UICDECLPREFIX = '',
  234.                    QT_UICDECLSUFFIX = '.h',
  235.                    QT_UICIMPLPREFIX = 'uic_',
  236.                    QT_UICIMPLSUFFIX = '$CXXFILESUFFIX',
  237.                    QT_MOCHPREFIX = 'moc_',
  238.                    QT_MOCHSUFFIX = '$CXXFILESUFFIX',
  239.                    QT_MOCCXXPREFIX = '',
  240.                    QT_MOCCXXSUFFIX = '.moc',
  241.                    QT_UISUFFIX = '.ui',
  242.                    # Commands for the qt support ...
  243.                    # command to generate header, implementation and moc-file
  244.                    # from a .ui file
  245.                    QT_UICCOM = [
  246.                     CLVar('$QT_UIC $QT_UICDECLFLAGS -o ${TARGETS[0]} $SOURCE'),
  247.                     CLVar('$QT_UIC $QT_UICIMPLFLAGS -impl ${TARGETS[0].file} '
  248.                           '-o ${TARGETS[1]} $SOURCE'),
  249.                     CLVar('$QT_MOC $QT_MOCFROMHFLAGS -o ${TARGETS[2]} ${TARGETS[0]}')],
  250.                    # command to generate meta object information for a class
  251.                    # declarated in a header
  252.                    QT_MOCFROMHCOM = (
  253.                           '$QT_MOC $QT_MOCFROMHFLAGS -o ${TARGETS[0]} $SOURCE'),
  254.                    # command to generate meta object information for a class
  255.                    # declarated in a cpp file
  256.                    QT_MOCFROMCXXCOM = [
  257.                     CLVar('$QT_MOC $QT_MOCFROMCXXFLAGS -o ${TARGETS[0]} $SOURCE'),
  258.                     Action(checkMocIncluded,None)])
  259.     # ... and the corresponding builders
  260.     uicBld = Builder(action=SCons.Action.Action('$QT_UICCOM', '$QT_UICCOMSTR'),
  261.                      emitter=uicEmitter,
  262.                      src_suffix='$QT_UISUFFIX',
  263.                      suffix='$QT_UICDECLSUFFIX',
  264.                      prefix='$QT_UICDECLPREFIX',
  265.                      source_scanner=uicScanner)
  266.     mocBld = Builder(action={}, prefix={}, suffix={})
  267.     for h in header_extensions:
  268.         act = SCons.Action.Action('$QT_MOCFROMHCOM', '$QT_MOCFROMHCOMSTR')
  269.         mocBld.add_action(h, act)
  270.         mocBld.prefix[h] = '$QT_MOCHPREFIX'
  271.         mocBld.suffix[h] = '$QT_MOCHSUFFIX'
  272.     for cxx in cxx_suffixes:
  273.         act = SCons.Action.Action('$QT_MOCFROMCXXCOM', '$QT_MOCFROMCXXCOMSTR')
  274.         mocBld.add_action(cxx, act)
  275.         mocBld.prefix[cxx] = '$QT_MOCCXXPREFIX'
  276.         mocBld.suffix[cxx] = '$QT_MOCCXXSUFFIX'
  277.     # register the builders 
  278.     env['BUILDERS']['Uic'] = uicBld
  279.     env['BUILDERS']['Moc'] = mocBld
  280.     static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
  281.     static_obj.add_src_builder('Uic')
  282.     shared_obj.add_src_builder('Uic')
  283.     # We use the emitters of Program / StaticLibrary / SharedLibrary
  284.     # to scan for moc'able files
  285.     # We can't refer to the builders directly, we have to fetch them
  286.     # as Environment attributes because that sets them up to be called
  287.     # correctly later by our emitter.
  288.     env.AppendUnique(PROGEMITTER =[AutomocStatic],
  289.                      SHLIBEMITTER=[AutomocShared],
  290.                      LIBEMITTER  =[AutomocStatic],
  291.                      # Of course, we need to link against the qt libraries
  292.                      CPPPATH=["$QT_CPPPATH"],
  293.                      LIBPATH=["$QT_LIBPATH"],
  294.                      LIBS=['$QT_LIB'])
  295. def exists(env):
  296.     return _detect(env)