1# Recipe creation tool - Qt5 support plugin 2# 3# Copyright (C) 2016 Intel Corporation 4# 5# This program is free software; you can redistribute it and/or modify 6# it under the terms of the GNU General Public License version 2 as 7# published by the Free Software Foundation. 8# 9# This program is distributed in the hope that it will be useful, 10# but WITHOUT ANY WARRANTY; without even the implied warranty of 11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12# GNU General Public License for more details. 13# 14# You should have received a copy of the GNU General Public License along 15# with this program; if not, write to the Free Software Foundation, Inc., 16# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 18import re 19import os 20 21from recipetool.create import RecipeHandler 22from recipetool.create_buildsys import CmakeExtensionHandler, AutotoolsExtensionHandler 23 24 25class Qt5AutotoolsHandler(AutotoolsExtensionHandler): 26 def process_macro(self, srctree, keyword, value, process_value, libdeps, pcdeps, deps, outlines, inherits, values): 27 if keyword == 'AX_HAVE_QT': 28 # We don't know specifically which modules it needs, but let's assume it's covered by qtbase 29 deps.append('qtbase') 30 return True 31 return False 32 33 def extend_keywords(self, keywords): 34 keywords.append('AX_HAVE_QT') 35 36 def process_prog(self, srctree, keyword, value, prog, deps, outlines, inherits, values): 37 return False 38 39 40class Qt5CmakeHandler(CmakeExtensionHandler): 41 def process_findpackage(self, srctree, fn, pkg, deps, outlines, inherits, values): 42 return False 43 cmake_qt5_pkgmap = {'qtbase': 'Qt5 Qt5Concurrent Qt5Core Qt5DBus Qt5Gui Qt5Network Qt5OpenGL Qt5OpenGLExtensions Qt5PrintSupport Qt5Sql Qt5Test Qt5Widgets Qt5Xml', 44 'qtsvg': 'Qt5Svg', 45 'qtdeclarative': 'Qt5Qml Qt5Quick Qt5QuickWidgets Qt5QuickTest', 46 'qtxmlpatterns': 'Qt5XmlPatterns', 47 'qtsystems': 'Qt5PublishSubscribe Qt5ServiceFramework Qt5SystemInfo', 48 'qtscript': 'Qt5Script Qt5ScriptTools', 49 'qttools': 'Qt5Designer Qt5Help Qt5LinguistTools Qt5UiPlugin Qt5UiTools', 50 'qtsensors': 'Qt5Sensors', 51 'qtmultimedia': 'Qt5Multimedia Qt5MultimediaWidgets', 52 'qtwebchannel': 'Qt5WebChannel', 53 'qtwebsockets': 'Qt5WebSockets', 54 'qtserialport': 'Qt5SerialPort', 55 'qtx11extras': 'Qt5X11Extras', 56 'qtlocation': 'Qt5Location Qt5Positioning', 57 'qt3d': 'Qt53DCollision Qt53DCore Qt53DInput Qt53DLogic Qt53DQuick Qt53DQuickRender Qt53DRender', 58 } 59 for recipe, pkgs in cmake_qt5_pkgmap.iteritems(): 60 if pkg in pkgs.split(): 61 deps.append(recipe) 62 return True 63 return False 64 65 def post_process(self, srctree, fn, pkg, deps, outlines, inherits, values): 66 for dep in deps: 67 if dep.startswith('qt'): 68 if 'cmake_qt5' not in inherits: 69 inherits.append('cmake_qt5') 70 break 71 72 73class Qmake5RecipeHandler(RecipeHandler): 74 # Map of QT variable items to recipes 75 qt_map = {'axcontainer': '', 76 'axserver': '', 77 'concurrent': 'qtbase', 78 'core': 'qtbase', 79 'gui': 'qtbase', 80 'dbus': 'qtbase', 81 'designer': 'qttools', 82 'help': 'qttools', 83 'multimedia': 'qtmultimedia', 84 'multimediawidgets': 'qtmultimedia', 85 'network': 'qtbase', 86 'opengl': 'qtbase', 87 'printsupport': 'qtbase', 88 'qml': 'qtdeclarative', 89 'qmltest': 'qtdeclarative', 90 'x11extras': 'qtx11extras', 91 'quick': 'qtdeclarative', 92 'script': 'qtscript', 93 'scripttools': 'qtscript', 94 'sensors': 'qtsensors', 95 'serialport': 'qtserialport', 96 'sql': 'qtbase', 97 'svg': 'qtsvg', 98 'testlib': 'qtbase', 99 'uitools': 'qttools', 100 'webkit': 'qtwebkit', 101 'webkitwidgets': 'qtwebkit', 102 'widgets': 'qtbase', 103 'winextras': '', 104 'xml': 'qtbase', 105 'xmlpatterns': 'qtxmlpatterns'} 106 107 def process(self, srctree, classes, lines_before, lines_after, handled, extravalues): 108 # There's not a conclusive way to tell a Qt2/3/4/5 .pro file apart, so we 109 # just assume that qmake5 is a reasonable default if you have this layer 110 # enabled 111 if 'buildsystem' in handled: 112 return False 113 114 unmappedqt = [] 115 files = RecipeHandler.checkfiles(srctree, ['*.pro']) 116 deps = [] 117 if files: 118 for fn in files: 119 self.parse_qt_pro(fn, deps, unmappedqt) 120 121 classes.append('qmake5') 122 if unmappedqt: 123 outlines.append('# NOTE: the following QT dependencies are unknown, ignoring: %s' % ' '.join(list(set(unmappedqt)))) 124 if deps: 125 lines_before.append('DEPENDS = "%s"' % ' '.join(list(set(deps)))) 126 handled.append('buildsystem') 127 return True 128 return False 129 130 def parse_qt_pro(self, fn, deps, unmappedqt): 131 with open(fn, 'r') as f: 132 for line in f: 133 if re.match('^QT\s*[+=]+', line): 134 if '=' in line: 135 for item in line.split('=')[1].split(): 136 dep = Qmake5RecipeHandler.qt_map.get(item, None) 137 if dep: 138 deps.append(dep) 139 elif dep is not None: 140 unmappedqt.append(item) 141 elif re.match('^SUBDIRS\s*[+=]+', line): 142 if '=' in line: 143 for item in line.split('=')[1].split(): 144 subfiles = RecipeHandler.checkfiles(os.path.join(os.path.dirname(fn), item), ['*.pro']) 145 for subfn in subfiles: 146 self.parse_qt_pro(subfn, deps, unmappedqt) 147 elif 'qml' in line.lower(): 148 deps.append('qtdeclarative') 149 150 151def register_recipe_handlers(handlers): 152 # Insert handler in front of default qmake handler 153 handlers.append((Qmake5RecipeHandler(), 21)) 154 155def register_cmake_handlers(handlers): 156 handlers.append(Qt5CmakeHandler()) 157 158def register_autotools_handlers(handlers): 159 handlers.append(Qt5AutotoolsHandler()) 160 161