aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJussi Pakkanen <jpakkane@gmail.com>2015-04-29 17:38:29 +0300
committerJussi Pakkanen <jpakkane@gmail.com>2015-04-29 17:38:29 +0300
commit45d7b589ebfe4f87bad175d3c2e663423b6b3377 (patch)
tree94b2a0f722a04796b199fb62a2e2aab83dc11c13
parent8de41caac8364126c51452acae437ef4e9b30dcb (diff)
downloadmeson-45d7b589ebfe4f87bad175d3c2e663423b6b3377.zip
meson-45d7b589ebfe4f87bad175d3c2e663423b6b3377.tar.gz
meson-45d7b589ebfe4f87bad175d3c2e663423b6b3377.tar.bz2
Added module for Qt4 support.
-rw-r--r--dependencies.py39
-rw-r--r--manual tests/6 qt4/main.cpp20
-rw-r--r--manual tests/6 qt4/mainWindow.cpp8
-rw-r--r--manual tests/6 qt4/mainWindow.h20
-rw-r--r--manual tests/6 qt4/mainWindow.ui34
-rw-r--r--manual tests/6 qt4/manualinclude.cpp20
-rw-r--r--manual tests/6 qt4/manualinclude.h16
-rw-r--r--manual tests/6 qt4/meson.build41
-rw-r--r--manual tests/6 qt4/q4core.cpp10
-rw-r--r--manual tests/6 qt4/stuff.qrc7
-rw-r--r--manual tests/6 qt4/thing.pngbin0 -> 40303 bytes
-rw-r--r--manual tests/6 qt4/thing2.pngbin0 -> 40303 bytes
-rw-r--r--modules/qt4.py155
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
new file mode 100644
index 0000000..4b001bd
--- /dev/null
+++ b/manual tests/6 qt4/thing.png
Binary files differ
diff --git a/manual tests/6 qt4/thing2.png b/manual tests/6 qt4/thing2.png
new file mode 100644
index 0000000..4b001bd
--- /dev/null
+++ b/manual tests/6 qt4/thing2.png
Binary files differ
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()