diff options
author | Jussi Pakkanen <jpakkane@gmail.com> | 2015-04-29 17:38:29 +0300 |
---|---|---|
committer | Jussi Pakkanen <jpakkane@gmail.com> | 2015-04-29 17:38:29 +0300 |
commit | 45d7b589ebfe4f87bad175d3c2e663423b6b3377 (patch) | |
tree | 94b2a0f722a04796b199fb62a2e2aab83dc11c13 | |
parent | 8de41caac8364126c51452acae437ef4e9b30dcb (diff) | |
download | meson-45d7b589ebfe4f87bad175d3c2e663423b6b3377.zip meson-45d7b589ebfe4f87bad175d3c2e663423b6b3377.tar.gz meson-45d7b589ebfe4f87bad175d3c2e663423b6b3377.tar.bz2 |
Added module for Qt4 support.
-rw-r--r-- | dependencies.py | 39 | ||||
-rw-r--r-- | manual tests/6 qt4/main.cpp | 20 | ||||
-rw-r--r-- | manual tests/6 qt4/mainWindow.cpp | 8 | ||||
-rw-r--r-- | manual tests/6 qt4/mainWindow.h | 20 | ||||
-rw-r--r-- | manual tests/6 qt4/mainWindow.ui | 34 | ||||
-rw-r--r-- | manual tests/6 qt4/manualinclude.cpp | 20 | ||||
-rw-r--r-- | manual tests/6 qt4/manualinclude.h | 16 | ||||
-rw-r--r-- | manual tests/6 qt4/meson.build | 41 | ||||
-rw-r--r-- | manual tests/6 qt4/q4core.cpp | 10 | ||||
-rw-r--r-- | manual tests/6 qt4/stuff.qrc | 7 | ||||
-rw-r--r-- | manual tests/6 qt4/thing.png | bin | 0 -> 40303 bytes | |||
-rw-r--r-- | manual tests/6 qt4/thing2.png | bin | 0 -> 40303 bytes | |||
-rw-r--r-- | modules/qt4.py | 155 |
13 files changed, 370 insertions, 0 deletions
diff --git a/dependencies.py b/dependencies.py index 1aa19ec..b890149 100644 --- a/dependencies.py +++ b/dependencies.py @@ -588,6 +588,44 @@ class Qt5Dependency(Dependency): # Fix this to be more portable, especially to MSVC. return ['-fPIE'] +class Qt4Dependency(Dependency): + def __init__(self, kwargs): + Dependency.__init__(self) + self.name = 'qt4' + self.root = '/usr' + self.modules = [] + mods = kwargs.get('modules', []) + if isinstance(mods, str): + mods = [mods] + for module in mods: + self.modules.append(PkgConfigDependency('Qt' + module, kwargs)) + if len(self.modules) == 0: + raise DependencyException('No Qt5 modules specified.') + + def get_version(self): + return self.modules[0].get_version() + + def get_compile_args(self): + args = [] + for m in self.modules: + args += m.get_compile_args() + return args + + def get_sources(self): + return [] + + def get_link_args(self): + args = [] + for module in self.modules: + args += module.get_link_args() + return args + + def found(self): + for i in self.modules: + if not i.found(): + return False + return True + class GnuStepDependency(Dependency): def __init__(self, kwargs): Dependency.__init__(self) @@ -831,6 +869,7 @@ packages = {'boost': BoostDependency, 'gtest': GTestDependency, 'gmock': GMockDependency, 'qt5': Qt5Dependency, + 'qt4': Qt4Dependency, 'gnustep': GnuStepDependency, 'appleframeworks': AppleFrameworks, 'wxwidgets' : WxDependency, diff --git a/manual tests/6 qt4/main.cpp b/manual tests/6 qt4/main.cpp new file mode 100644 index 0000000..4c257a4 --- /dev/null +++ b/manual tests/6 qt4/main.cpp @@ -0,0 +1,20 @@ +#include <QApplication> +#include "mainWindow.h" + +int main(int argc, char **argv) { + QApplication app(argc, argv); + MainWindow *win = new MainWindow(); + QImage qi(":/thing.png"); + if(qi.width() != 640) { + return 1; + } + QImage qi2(":/thing2.png"); + if(qi2.width() != 640) { + return 1; + } + win->setWindowTitle("Meson Qt5 build test"); + + win->show(); + return app.exec(); + return 0; +} diff --git a/manual tests/6 qt4/mainWindow.cpp b/manual tests/6 qt4/mainWindow.cpp new file mode 100644 index 0000000..cc82c4f --- /dev/null +++ b/manual tests/6 qt4/mainWindow.cpp @@ -0,0 +1,8 @@ +#include "mainWindow.h" + +MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { + setupUi(this); +} + +MainWindow::~MainWindow() { +} diff --git a/manual tests/6 qt4/mainWindow.h b/manual tests/6 qt4/mainWindow.h new file mode 100644 index 0000000..7f6d906 --- /dev/null +++ b/manual tests/6 qt4/mainWindow.h @@ -0,0 +1,20 @@ +#ifndef MES_MAINWINDOW +#define MES_MAINWINDOW + +#include <QObject> +#include <QMainWindow> +#include "ui_mainWindow.h" + +class NotificationModel; + +class MainWindow : public QMainWindow, private Ui_MainWindow { + Q_OBJECT + +public: + explicit MainWindow(QWidget *parent=0); + ~MainWindow(); + +private: +}; + +#endif diff --git a/manual tests/6 qt4/mainWindow.ui b/manual tests/6 qt4/mainWindow.ui new file mode 100644 index 0000000..2eb226a --- /dev/null +++ b/manual tests/6 qt4/mainWindow.ui @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>MainWindow</class> + <widget class="QMainWindow" name="MainWindow"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>270</width> + <height>115</height> + </rect> + </property> + <property name="windowTitle"> + <string>MainWindow</string> + </property> + <widget class="QWidget" name="centralwidget"> + <widget class="QPushButton" name="pushButton"> + <property name="geometry"> + <rect> + <x>10</x> + <y>10</y> + <width>241</width> + <height>91</height> + </rect> + </property> + <property name="text"> + <string>I am a button</string> + </property> + </widget> + </widget> + </widget> + <resources/> + <connections/> +</ui> diff --git a/manual tests/6 qt4/manualinclude.cpp b/manual tests/6 qt4/manualinclude.cpp new file mode 100644 index 0000000..0602882 --- /dev/null +++ b/manual tests/6 qt4/manualinclude.cpp @@ -0,0 +1,20 @@ +#include"manualinclude.h" +#include<QCoreApplication> + +#include<QObject> + +ManualInclude::ManualInclude() { +} + +class MocClass : public QObject { + Q_OBJECT +}; + +int main(int argc, char **argv) { + ManualInclude mi; + MocClass mc; + return 0; +} + +#include"manualinclude.moc" + diff --git a/manual tests/6 qt4/manualinclude.h b/manual tests/6 qt4/manualinclude.h new file mode 100644 index 0000000..4a00b6c --- /dev/null +++ b/manual tests/6 qt4/manualinclude.h @@ -0,0 +1,16 @@ +#ifndef MANUALINCLUDE_H_ +#define MANUALINCLUDE_H_ + +#include<QObject> + +class ManualInclude : public QObject { + Q_OBJECT + +public: + ManualInclude(); + +signals: + int mysignal(); +}; + +#endif diff --git a/manual tests/6 qt4/meson.build b/manual tests/6 qt4/meson.build new file mode 100644 index 0000000..b9694d9 --- /dev/null +++ b/manual tests/6 qt4/meson.build @@ -0,0 +1,41 @@ +project('qt5 build test', 'cpp') + +# This is a manual test rather than an automatic one +# because during Debian package builds only Qt4 or Qt5 +# can be active. + +qt4 = import('qt4') +qt4dep = dependency('qt4', modules : 'Gui') + +prep = qt4.preprocess(moc_headers : ['mainWindow.h'], # These need to be fed through the moc tool before use. + ui_files : 'mainWindow.ui', # XML files that need to be compiled with the uic tol. + qresources : 'stuff.qrc', # Resource file for rcc compiler. +) + +q5exe = executable('qt4app', +sources : ['main.cpp', 'mainWindow.cpp', # Sources that don't need preprocessing. +prep], +dependencies : qt4dep) + +# We need a console test application because some test environments +# do not have an X server. + +qt4core = dependency('qt4', modules : 'Core') + +qt4coreapp = executable('q4core', 'q4core.cpp', +dependencies : qt4core) + +test('qt4test', qt4coreapp) + +# The build system needs to include the cpp files from +# headers but the user must manually include moc +# files from sources. +manpreprocessed = qt4.preprocess( + moc_sources : 'manualinclude.cpp', + moc_headers : 'manualinclude.h') + +q4maninclude = executable('q4maninclude', +sources : ['manualinclude.cpp', manpreprocessed], +dependencies : qt4core) + +test('q4maninclude', q4maninclude) diff --git a/manual tests/6 qt4/q4core.cpp b/manual tests/6 qt4/q4core.cpp new file mode 100644 index 0000000..706e4dc --- /dev/null +++ b/manual tests/6 qt4/q4core.cpp @@ -0,0 +1,10 @@ +#include <QCoreApplication> + +int main(int argc, char **argv) { + QCoreApplication app(argc, argv); + + // Don't actually start the main loop so this + // can be run as a unit test. + //return app.exec(); + return 0; +} diff --git a/manual tests/6 qt4/stuff.qrc b/manual tests/6 qt4/stuff.qrc new file mode 100644 index 0000000..9152500 --- /dev/null +++ b/manual tests/6 qt4/stuff.qrc @@ -0,0 +1,7 @@ +<!DOCTYPE RCC> +<RCC version="1.0"> + <qresource> + <file>thing.png</file> + <file>thing2.png</file> + </qresource> +</RCC> diff --git a/manual tests/6 qt4/thing.png b/manual tests/6 qt4/thing.png Binary files differnew file mode 100644 index 0000000..4b001bd --- /dev/null +++ b/manual tests/6 qt4/thing.png diff --git a/manual tests/6 qt4/thing2.png b/manual tests/6 qt4/thing2.png Binary files differnew file mode 100644 index 0000000..4b001bd --- /dev/null +++ b/manual tests/6 qt4/thing2.png diff --git a/modules/qt4.py b/modules/qt4.py new file mode 100644 index 0000000..ddaca39 --- /dev/null +++ b/modules/qt4.py @@ -0,0 +1,155 @@ +# Copyright 2015 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import dependencies, mlog +import os, subprocess +import build +from coredata import MesonException +import xml.etree.ElementTree as ET + +class Qt5Module(): + + def __init__(self): + mlog.log('Detecting Qt tools.') + # The binaries have different names on different + # distros. Joy. + self.moc = dependencies.ExternalProgram('moc', silent=True) + if not self.moc.found(): + self.moc = dependencies.ExternalProgram('moc-qt4', silent=True) + self.uic = dependencies.ExternalProgram('uic', silent=True) + if not self.uic.found(): + self.uic = dependencies.ExternalProgram('uic-qt4', silent=True) + self.rcc = dependencies.ExternalProgram('rcc', silent=True) + if not self.rcc.found(): + self.rcc = dependencies.ExternalProgram('rcc-qt4', silent=True) + # Moc, uic and rcc write their version strings to stderr. + # Moc and rcc return a non-zero result when doing so. + # What kind of an idiot thought that was a good idea? + if self.moc.found(): + mp = subprocess.Popen(self.moc.get_command() + ['-v'], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + (stdout, stderr) = mp.communicate() + stdout = stdout.decode().strip() + stderr = stderr.decode().strip() + if 'Qt Meta' in stderr: + moc_ver = stderr + else: + raise MesonException('Moc preprocessor is not for Qt 4. Output:\n%s\n%s' % + (stdout, stderr)) + mlog.log(' moc:', mlog.green('YES'), '(%s, %s)' % \ + (' '.join(self.moc.fullpath), moc_ver.split()[-1])) + else: + mlog.log(' moc:', mlog.red('NO')) + if self.uic.found(): + up = subprocess.Popen(self.uic.get_command() + ['-v'], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + (stdout, stderr) = up.communicate() + stdout = stdout.decode().strip() + stderr = stderr.decode().strip() + if 'version 4.' in stderr: + uic_ver = stderr + else: + raise MesonException('Uic compiler is not for Qt4. Output:\n%s\n%s' % + (stdout, stderr)) + mlog.log(' uic:', mlog.green('YES'), '(%s, %s)' % \ + (' '.join(self.uic.fullpath), uic_ver.split()[-1])) + else: + mlog.log(' uic:', mlog.red('NO')) + if self.rcc.found(): + rp = subprocess.Popen(self.rcc.get_command() + ['-v'], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + (stdout, stderr) = rp.communicate() + stdout = stdout.decode().strip() + stderr = stderr.decode().strip() + if 'version 4.' in stderr: + rcc_ver = stderr + else: + raise MesonException('Rcc compiler is not for Qt 4. Output:\n%s\n%s' % + (stdout, stderr)) + mlog.log(' rcc:', mlog.green('YES'), '(%s, %s)'\ + % (' '.join(self.rcc.fullpath), rcc_ver.split()[-1])) + else: + mlog.log(' rcc:', mlog.red('NO')) + + def parse_qrc(self, state, fname): + abspath = os.path.join(state.environment.source_dir, state.subdir, fname) + try: + tree = ET.parse(abspath) + root = tree.getroot() + result = [] + for child in root[0]: + if child.tag != 'file': + mlog.log("Warning, malformed rcc file: ", os.path.join(state.subdir, fname)) + break + else: + result.append(os.path.join(state.subdir, child.text)) + return result + except Exception: + return [] + + def preprocess(self, state, args, kwargs): + rcc_files = kwargs.pop('qresources', []) + if not isinstance(rcc_files, list): + rcc_files = [rcc_files] + ui_files = kwargs.pop('ui_files', []) + if not isinstance(ui_files, list): + ui_files = [ui_files] + moc_headers = kwargs.pop('moc_headers', []) + if not isinstance(moc_headers, list): + moc_headers = [moc_headers] + moc_sources = kwargs.pop('moc_sources', []) + if not isinstance(moc_sources, list): + moc_sources = [moc_sources] + srctmp = kwargs.pop('sources', []) + if not isinstance(srctmp, list): + srctmp = [srctmp] + sources = args[1:] + srctmp + if len(rcc_files) > 0: + rcc_kwargs = {'output' : '@BASENAME@.cpp', + 'arguments' : ['@INPUT@', '-o', '@OUTPUT@']} + rcc_gen = build.Generator([self.rcc], rcc_kwargs) + rcc_output = build.GeneratedList(rcc_gen) + qrc_deps = [] + for i in rcc_files: + qrc_deps += self.parse_qrc(state, i) + rcc_output.extra_depends = qrc_deps + [rcc_output.add_file(os.path.join(state.subdir, a)) for a in rcc_files] + sources.append(rcc_output) + if len(ui_files) > 0: + ui_kwargs = {'output' : 'ui_@BASENAME@.h', + 'arguments' : ['-o', '@OUTPUT@', '@INPUT@']} + ui_gen = build.Generator([self.uic], ui_kwargs) + ui_output = build.GeneratedList(ui_gen) + [ui_output.add_file(os.path.join(state.subdir, a)) for a in ui_files] + sources.append(ui_output) + if len(moc_headers) > 0: + moc_kwargs = {'output' : 'moc_@BASENAME@.cpp', + 'arguments' : ['@INPUT@', '-o', '@OUTPUT@']} + moc_gen = build.Generator([self.moc], moc_kwargs) + moc_output = build.GeneratedList(moc_gen) + [moc_output.add_file(os.path.join(state.subdir, a)) for a in moc_headers] + sources.append(moc_output) + if len(moc_sources) > 0: + moc_kwargs = {'output' : '@BASENAME@.moc', + 'arguments' : ['@INPUT@', '-o', '@OUTPUT@']} + moc_gen = build.Generator([self.moc], moc_kwargs) + moc_output = build.GeneratedList(moc_gen) + [moc_output.add_file(os.path.join(state.subdir, a)) for a in moc_sources] + sources.append(moc_output) + return sources + +def initialize(): + mlog.log('Warning, rcc dependencies will not work properly until this upstream issue is fixed:', + mlog.bold('https://bugreports.qt.io/browse/QTBUG-45460')) + return Qt5Module() |