"Fossies" - the Fresh Open Source Software Archive

Member "scons-3.0.5/engine/SCons/Tool/qt.py" (26 Mar 2019, 14155 Bytes) of package /linux/misc/scons-3.0.5.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. For more information about "qt.py" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 3.0.4_vs_3.0.5.

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