aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJussi Pakkanen <jpakkane@gmail.com>2016-11-12 12:19:28 -0500
committerGitHub <noreply@github.com>2016-11-12 12:19:28 -0500
commit28b70ba4e583cba7c9043a42ab8696547fc0dcbc (patch)
tree974bb0722caf07d9ca04930fc0f15887c4b6b162
parent1d9c40c9c311e2f015104dcfa568a9eaf82a1e76 (diff)
parentcedfa575f6144b9eb3ed9f777074c7b95ad52231 (diff)
downloadmeson-28b70ba4e583cba7c9043a42ab8696547fc0dcbc.zip
meson-28b70ba4e583cba7c9043a42ab8696547fc0dcbc.tar.gz
meson-28b70ba4e583cba7c9043a42ab8696547fc0dcbc.tar.bz2
Merge pull request #1010 from centricular/qt5-broken-moc-detection
Overhaul Qt4/5 detection with pkg-config/qmake and improve moc/uic/rcc detection
-rw-r--r--manual tests/6 qt4/main.cpp20
-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--mesonbuild/dependencies.py200
-rw-r--r--mesonbuild/modules/qt4.py55
-rw-r--r--mesonbuild/modules/qt5.py43
-rwxr-xr-xrun_unittests.py30
-rw-r--r--test cases/frameworks/4 qt/main.cpp (renamed from test cases/frameworks/4 qt5/main.cpp)0
-rw-r--r--test cases/frameworks/4 qt/mainWindow.cpp (renamed from manual tests/6 qt4/mainWindow.cpp)0
-rw-r--r--test cases/frameworks/4 qt/mainWindow.h (renamed from manual tests/6 qt4/mainWindow.h)0
-rw-r--r--test cases/frameworks/4 qt/mainWindow.ui (renamed from manual tests/6 qt4/mainWindow.ui)0
-rw-r--r--test cases/frameworks/4 qt/manualinclude.cpp (renamed from manual tests/6 qt4/manualinclude.cpp)0
-rw-r--r--test cases/frameworks/4 qt/manualinclude.h (renamed from manual tests/6 qt4/manualinclude.h)0
-rw-r--r--test cases/frameworks/4 qt/meson.build45
-rw-r--r--test cases/frameworks/4 qt/q5core.cpp (renamed from test cases/frameworks/4 qt5/q5core.cpp)0
-rw-r--r--test cases/frameworks/4 qt/stuff.qrc (renamed from test cases/frameworks/4 qt5/stuff.qrc)0
-rw-r--r--test cases/frameworks/4 qt/stuff2.qrc (renamed from test cases/frameworks/4 qt5/stuff2.qrc)0
-rw-r--r--test cases/frameworks/4 qt/thing.png (renamed from manual tests/6 qt4/thing.png)bin40303 -> 40303 bytes
-rw-r--r--test cases/frameworks/4 qt/thing2.png (renamed from manual tests/6 qt4/thing2.png)bin40303 -> 40303 bytes
-rw-r--r--test cases/frameworks/4 qt5/mainWindow.cpp8
-rw-r--r--test cases/frameworks/4 qt5/mainWindow.h20
-rw-r--r--test cases/frameworks/4 qt5/mainWindow.ui34
-rw-r--r--test cases/frameworks/4 qt5/manualinclude.cpp20
-rw-r--r--test cases/frameworks/4 qt5/manualinclude.h16
-rw-r--r--test cases/frameworks/4 qt5/meson.build41
-rw-r--r--test cases/frameworks/4 qt5/thing.pngbin40303 -> 0 bytes
-rw-r--r--test cases/frameworks/4 qt5/thing2.pngbin40303 -> 0 bytes
28 files changed, 252 insertions, 338 deletions
diff --git a/manual tests/6 qt4/main.cpp b/manual tests/6 qt4/main.cpp
deleted file mode 100644
index 30fcd4b..0000000
--- a/manual tests/6 qt4/main.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-#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 Qt4 build test");
-
- win->show();
- return app.exec();
- return 0;
-}
diff --git a/manual tests/6 qt4/meson.build b/manual tests/6 qt4/meson.build
deleted file mode 100644
index 94f78ab..0000000
--- a/manual tests/6 qt4/meson.build
+++ /dev/null
@@ -1,41 +0,0 @@
-project('qt4 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
deleted file mode 100644
index 706e4dc..0000000
--- a/manual tests/6 qt4/q4core.cpp
+++ /dev/null
@@ -1,10 +0,0 @@
-#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
deleted file mode 100644
index 9152500..0000000
--- a/manual tests/6 qt4/stuff.qrc
+++ /dev/null
@@ -1,7 +0,0 @@
-<!DOCTYPE RCC>
-<RCC version="1.0">
- <qresource>
- <file>thing.png</file>
- <file>thing2.png</file>
- </qresource>
-</RCC>
diff --git a/mesonbuild/dependencies.py b/mesonbuild/dependencies.py
index 74738ae..8a1ff16 100644
--- a/mesonbuild/dependencies.py
+++ b/mesonbuild/dependencies.py
@@ -22,6 +22,7 @@
import re
import os, stat, glob, subprocess, shutil
import sysconfig
+from collections import OrderedDict
from . mesonlib import MesonException
from . import mlog
from . import mesonlib
@@ -806,11 +807,20 @@ class GMockDependency(Dependency):
def found(self):
return self.is_found
-class Qt5Dependency(Dependency):
- def __init__(self, environment, kwargs):
- Dependency.__init__(self, 'qt5')
- self.name = 'qt5'
+class QtBaseDependency(Dependency):
+ def __init__(self, name, env, kwargs):
+ Dependency.__init__(self, name)
+ self.name = name
+ self.qtname = name.capitalize()
+ self.qtver = name[-1]
self.root = '/usr'
+ self.bindir = None
+ self.silent = kwargs.get('silent', False)
+ # We store the value of required here instead of passing it on to
+ # PkgConfigDependency etc because we want to try the qmake-based
+ # fallback as well.
+ self.required = kwargs.pop('required', True)
+ kwargs['required'] = False
mods = kwargs.get('modules', [])
self.cargs = []
self.largs = []
@@ -818,69 +828,130 @@ class Qt5Dependency(Dependency):
if isinstance(mods, str):
mods = [mods]
if len(mods) == 0:
- raise DependencyException('No Qt5 modules specified.')
- type_text = 'native'
- if environment.is_cross_build() and kwargs.get('native', False):
- type_text = 'cross'
- self.pkgconfig_detect(mods, environment, kwargs)
- elif not environment.is_cross_build() and shutil.which('pkg-config') is not None:
- self.pkgconfig_detect(mods, environment, kwargs)
- elif shutil.which('qmake') is not None:
- self.qmake_detect(mods, kwargs)
- else:
- self.version = 'none'
+ raise DependencyException('No ' + self.qtname + ' modules specified.')
+ type_text = 'cross' if env.is_cross_build() else 'native'
+ found_msg = '{} {} `{{}}` dependency found:'.format(self.qtname, type_text)
+ from_text = 'pkg-config'
+ # Prefer pkg-config, then fallback to `qmake -query`
+ self._pkgconfig_detect(mods, env, kwargs)
if not self.is_found:
- mlog.log('Qt5 %s dependency found: ' % type_text, mlog.red('NO'))
+ from_text = self._qmake_detect(mods, env, kwargs)
+ if not self.is_found:
+ from_text = '(checked pkg-config, qmake-{}, and qmake)' \
+ ''.format(self.name)
+ self.version = 'none'
+ if self.required:
+ err_msg = '{} {} dependency not found {}' \
+ ''.format(self.qtname, type_text, from_text)
+ raise DependencyException(err_msg)
+ if not self.silent:
+ mlog.log(found_msg.format(from_text), mlog.red('NO'))
+ return
+ if not self.silent:
+ mlog.log(found_msg.format(from_text), mlog.green('YES'))
+
+ def compilers_detect(self):
+ "Detect Qt (4 or 5) moc, uic, rcc in the specified bindir or in PATH"
+ if self.bindir:
+ moc = ExternalProgram(os.path.join(self.bindir, 'moc'), silent=True)
+ uic = ExternalProgram(os.path.join(self.bindir, 'uic'), silent=True)
+ rcc = ExternalProgram(os.path.join(self.bindir, 'rcc'), silent=True)
else:
- mlog.log('Qt5 %s dependency found: ' % type_text, mlog.green('YES'))
-
- def pkgconfig_detect(self, mods, environment, kwargs):
- modules = []
+ # We don't accept unsuffixed 'moc', 'uic', and 'rcc' because they
+ # are sometimes older, or newer versions.
+ moc = ExternalProgram('moc-' + self.name, silent=True)
+ uic = ExternalProgram('uic-' + self.name, silent=True)
+ rcc = ExternalProgram('rcc-' + self.name, silent=True)
+ return moc, uic, rcc
+
+ def _pkgconfig_detect(self, mods, env, kwargs):
+ if self.qtver == "4":
+ qtpkgname = 'Qt'
+ else:
+ qtpkgname = self.qtname
+ modules = OrderedDict()
for module in mods:
- modules.append(PkgConfigDependency('Qt5' + module, environment, kwargs))
- for m in modules:
+ modules[module] = PkgConfigDependency(qtpkgname + module, env, kwargs)
+ self.is_found = True
+ for m in modules.values():
+ if not m.found():
+ self.is_found = False
self.cargs += m.get_compile_args()
self.largs += m.get_link_args()
- self.is_found = True
- self.version = modules[0].modversion
-
- def qmake_detect(self, mods, kwargs):
- pc = subprocess.Popen(['qmake', '-v'], stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- (stdo, _) = pc.communicate()
- if pc.returncode != 0:
- return
- stdo = stdo.decode()
- if not 'version 5' in stdo:
- mlog.log('QMake is not for Qt5.')
+ self.version = m.modversion
+ # Try to detect moc, uic, rcc
+ if 'Core' in modules:
+ core = modules['Core']
+ else:
+ corekwargs = {'required': 'false', 'silent': 'true'}
+ core = PkgConfigDependency(qtpkgname + 'Core', env, corekwargs)
+ # Used by self.compilers_detect()
+ self.bindir = core.get_pkgconfig_variable('host_bins')
+ if not self.bindir:
+ # If exec_prefix is not defined, the pkg-config file is broken
+ prefix = core.get_pkgconfig_variable('exec_prefix')
+ if prefix:
+ self.bindir = os.path.join(prefix, 'bin')
+
+ def _find_qmake(self, qmake, env):
+ # Even when cross-compiling, if we don't get a cross-info qmake, we
+ # fallback to using the qmake in PATH because that's what we used to do
+ if env.is_cross_build():
+ qmake = env.cross_info.config['binaries'].get('qmake', qmake)
+ return ExternalProgram(qmake, silent=True)
+
+ def _qmake_detect(self, mods, env, kwargs):
+ for qmake in ('qmake-' + self.name, 'qmake'):
+ self.qmake = self._find_qmake(qmake, env)
+ if not self.qmake.found():
+ continue
+ # Check that the qmake is for qt5
+ pc = subprocess.Popen(self.qmake.fullpath + ['-v'],
+ stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
+ universal_newlines=True)
+ stdo = pc.communicate()[0]
+ if pc.returncode != 0:
+ continue
+ if not 'Qt version ' + self.qtver in stdo:
+ mlog.log('QMake is not for ' + self.qtname)
+ continue
+ # Found qmake for Qt5!
+ break
+ else:
+ # Didn't find qmake :(
return
- self.version = re.search('5(\.\d+)+', stdo).group(0)
- (stdo, _) = subprocess.Popen(['qmake', '-query'], stdout=subprocess.PIPE).communicate()
+ self.version = re.search(self.qtver + '(\.\d+)+', stdo).group(0)
+ # Query library path, header path, and binary path
+ stdo = subprocess.Popen(self.qmake.fullpath + ['-query'],
+ stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
+ universal_newlines=True).communicate()[0]
qvars = {}
- for line in stdo.decode().split('\n'):
+ for line in stdo.split('\n'):
line = line.strip()
if line == '':
continue
(k, v) = tuple(line.split(':', 1))
qvars[k] = v
if mesonlib.is_osx():
- return self.framework_detect(qvars, mods, kwargs)
+ return self._framework_detect(qvars, mods, kwargs)
incdir = qvars['QT_INSTALL_HEADERS']
self.cargs.append('-I' + incdir)
libdir = qvars['QT_INSTALL_LIBS']
- bindir = qvars['QT_INSTALL_BINS']
+ # Used by self.compilers_detect()
+ self.bindir = qvars['QT_INSTALL_BINS']
#self.largs.append('-L' + libdir)
for module in mods:
mincdir = os.path.join(incdir, 'Qt' + module)
self.cargs.append('-I' + mincdir)
- libfile = os.path.join(libdir, 'Qt5' + module + '.lib')
+ libfile = os.path.join(libdir, self.qtname + module + '.lib')
if not os.path.isfile(libfile):
# MinGW links directly to .dll, not to .lib.
- libfile = os.path.join(bindir, 'Qt5' + module + '.dll')
+ libfile = os.path.join(self.bindir, self.qtname + module + '.dll')
self.largs.append(libfile)
self.is_found = True
+ return qmake
- def framework_detect(self, qvars, modules, kwargs):
+ def _framework_detect(self, qvars, modules, kwargs):
libdir = qvars['QT_INSTALL_LIBS']
for m in modules:
fname = 'Qt' + m
@@ -890,7 +961,8 @@ class Qt5Dependency(Dependency):
self.is_found = True
self.cargs += fwdep.get_compile_args()
self.largs += fwdep.get_link_args()
-
+ # Used by self.compilers_detect()
+ self.bindir = qvars['QT_INSTALL_BINS']
def get_version(self):
return self.version
@@ -917,43 +989,13 @@ class Qt5Dependency(Dependency):
# Fix this to be more portable, especially to MSVC.
return ['-fPIC']
-class Qt4Dependency(Dependency):
- def __init__(self, environment, kwargs):
- Dependency.__init__(self, 'qt4')
- 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, environment, kwargs))
- if len(self.modules) == 0:
- raise DependencyException('No Qt4 modules specified.')
+class Qt5Dependency(QtBaseDependency):
+ def __init__(self, env, kwargs):
+ QtBaseDependency.__init__(self, 'qt5', env, kwargs)
- 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 Qt4Dependency(QtBaseDependency):
+ def __init__(self, env, kwargs):
+ QtBaseDependency.__init__(self, 'qt4', env, kwargs)
class GnuStepDependency(Dependency):
def __init__(self, environment, kwargs):
diff --git a/mesonbuild/modules/qt4.py b/mesonbuild/modules/qt4.py
index b1d951b..5108baa 100644
--- a/mesonbuild/modules/qt4.py
+++ b/mesonbuild/modules/qt4.py
@@ -12,26 +12,27 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-from .. import dependencies, mlog
import os, subprocess
+from .. import mlog
from .. import build
from ..mesonlib import MesonException
+from ..dependencies import Qt4Dependency
import xml.etree.ElementTree as ET
class Qt4Module():
- def __init__(self):
- mlog.log('Detecting Qt tools.')
- # The binaries have different names on different
- # distros. Joy.
- self.moc = dependencies.ExternalProgram('moc-qt4', silent=True)
- if not self.moc.found():
- self.moc = dependencies.ExternalProgram('moc', silent=True)
- self.uic = dependencies.ExternalProgram('uic-qt4', silent=True)
- if not self.uic.found():
- self.uic = dependencies.ExternalProgram('uic', silent=True)
- self.rcc = dependencies.ExternalProgram('rcc-qt4', silent=True)
- if not self.rcc.found():
- self.rcc = dependencies.ExternalProgram('rcc', silent=True)
+ tools_detected = False
+
+ def _detect_tools(self, env):
+ if self.tools_detected:
+ return
+ mlog.log('Detecting Qt4 tools')
+ # FIXME: We currently require Qt4 to exist while importing the module.
+ # We should make it gracefully degrade and not create any targets if
+ # the import is marked as 'optional' (not implemented yet)
+ kwargs = {'required': 'true', 'modules': 'Core', 'silent': 'true'}
+ qt4 = Qt4Dependency(env, kwargs)
+ # Get all tools and then make sure that they are the right version
+ self.moc, self.uic, self.rcc = qt4.compilers_detect()
# 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?
@@ -80,6 +81,7 @@ class Qt4Module():
% (' '.join(self.rcc.fullpath), rcc_ver.split()[-1]))
else:
mlog.log(' rcc:', mlog.red('NO'))
+ self.tools_detected = True
def parse_qrc(self, state, fname):
abspath = os.path.join(state.environment.source_dir, state.subdir, fname)
@@ -115,18 +117,29 @@ class Qt4Module():
if not isinstance(srctmp, list):
srctmp = [srctmp]
sources = args[1:] + srctmp
+ self._detect_tools(state.environment)
+ err_msg = "{0} sources specified and couldn't find {1}, " \
+ "please check your qt4 installation"
+ if len(moc_headers) + len(moc_sources) > 0 and not self.moc.found():
+ raise MesonException(err_msg.format('MOC', 'moc-qt4'))
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)
+ if not self.rcc.found():
+ raise MesonException(err_msg.format('RCC', 'rcc-qt4'))
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)
+ basename = os.path.split(rcc_files[0])[1]
+ name = 'qt4-' + basename.replace('.', '_')
+ rcc_kwargs = {'input' : rcc_files,
+ 'output' : name + '.cpp',
+ 'command' : [self.rcc, '-o', '@OUTPUT@', '@INPUT@'],
+ 'depend_files' : qrc_deps,
+ }
+ res_target = build.CustomTarget(name, state.subdir, rcc_kwargs)
+ sources.append(res_target)
if len(ui_files) > 0:
+ if not self.uic.found():
+ raise MesonException(err_msg.format('UIC', 'uic-qt4'))
ui_kwargs = {'output' : 'ui_@BASENAME@.h',
'arguments' : ['-o', '@OUTPUT@', '@INPUT@']}
ui_gen = build.Generator([self.uic], ui_kwargs)
diff --git a/mesonbuild/modules/qt5.py b/mesonbuild/modules/qt5.py
index 9fffcff..52ad155 100644
--- a/mesonbuild/modules/qt5.py
+++ b/mesonbuild/modules/qt5.py
@@ -12,27 +12,27 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-from .. import dependencies, mlog
import os, subprocess
+from .. import mlog
from .. import build
from ..mesonlib import MesonException
+from ..dependencies import Qt5Dependency
import xml.etree.ElementTree as ET
class Qt5Module():
+ tools_detected = False
- def __init__(self):
- mlog.log('Detecting Qt tools.')
- # The binaries have different names on different
- # distros. Joy.
- self.moc = dependencies.ExternalProgram('moc-qt5', silent=True)
- if not self.moc.found():
- self.moc = dependencies.ExternalProgram('moc', silent=True)
- self.uic = dependencies.ExternalProgram('uic-qt5', silent=True)
- if not self.uic.found():
- self.uic = dependencies.ExternalProgram('uic', silent=True)
- self.rcc = dependencies.ExternalProgram('rcc-qt5', silent=True)
- if not self.rcc.found():
- self.rcc = dependencies.ExternalProgram('rcc', silent=True)
+ def _detect_tools(self, env):
+ if self.tools_detected:
+ return
+ mlog.log('Detecting Qt5 tools')
+ # FIXME: We currently require Qt5 to exist while importing the module.
+ # We should make it gracefully degrade and not create any targets if
+ # the import is marked as 'optional' (not implemented yet)
+ kwargs = {'required': 'true', 'modules': 'Core', 'silent': 'true'}
+ qt5 = Qt5Dependency(env, kwargs)
+ # Get all tools and then make sure that they are the right version
+ self.moc, self.uic, self.rcc = qt5.compilers_detect()
# 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?
@@ -87,6 +87,7 @@ class Qt5Module():
% (' '.join(self.rcc.fullpath), rcc_ver.split()[-1]))
else:
mlog.log(' rcc:', mlog.red('NO'))
+ self.tools_detected = True
def parse_qrc(self, state, fname):
abspath = os.path.join(state.environment.source_dir, state.subdir, fname)
@@ -122,7 +123,14 @@ class Qt5Module():
if not isinstance(srctmp, list):
srctmp = [srctmp]
sources = args[1:] + srctmp
+ self._detect_tools(state.environment)
+ err_msg = "{0} sources specified and couldn't find {1}, " \
+ "please check your qt5 installation"
+ if len(moc_headers) + len(moc_sources) > 0 and not self.moc.found():
+ raise MesonException(err_msg.format('MOC', 'moc-qt5'))
if len(rcc_files) > 0:
+ if not self.rcc.found():
+ raise MesonException(err_msg.format('RCC', 'rcc-qt5'))
qrc_deps = []
for i in rcc_files:
qrc_deps += self.parse_qrc(state, i)
@@ -132,11 +140,12 @@ class Qt5Module():
'command' : [self.rcc, '-o', '@OUTPUT@', '@INPUT@'],
'depend_files' : qrc_deps,
}
- res_target = build.CustomTarget(basename.replace('.', '_'),
- state.subdir,
- rcc_kwargs)
+ name = 'qt5-' + basename.replace('.', '_')
+ res_target = build.CustomTarget(name, state.subdir, rcc_kwargs)
sources.append(res_target)
if len(ui_files) > 0:
+ if not self.uic.found():
+ raise MesonException(err_msg.format('UIC', 'uic-qt5'))
ui_kwargs = {'output' : 'ui_@BASENAME@.h',
'arguments' : ['-o', '@OUTPUT@', '@INPUT@']}
ui_gen = build.Generator([self.uic], ui_kwargs)
diff --git a/run_unittests.py b/run_unittests.py
index 8df0001..44e190e 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -19,7 +19,7 @@ import re, json
import tempfile
import mesonbuild.environment
from mesonbuild.environment import detect_ninja
-from mesonbuild.dependencies import PkgConfigDependency
+from mesonbuild.dependencies import PkgConfigDependency, Qt5Dependency
def get_soname(fname):
# HACK, fix to not use shell.
@@ -59,6 +59,7 @@ class LinuxlikeTests(unittest.TestCase):
self.ninja_command = [detect_ninja(), '-C', self.builddir]
self.common_test_dir = os.path.join(src_root, 'test cases/common')
self.vala_test_dir = os.path.join(src_root, 'test cases/vala')
+ self.framework_test_dir = os.path.join(src_root, 'test cases/frameworks')
self.output = b''
self.orig_env = os.environ.copy()
@@ -67,22 +68,29 @@ class LinuxlikeTests(unittest.TestCase):
os.environ = self.orig_env
super().tearDown()
+ def _run(self, command):
+ self.output += subprocess.check_output(command, env=os.environ.copy())
+
def init(self, srcdir):
- self.output += subprocess.check_output(self.meson_command + [srcdir, self.builddir])
+ self._run(self.meson_command + [srcdir, self.builddir])
def build(self):
- self.output += subprocess.check_output(self.ninja_command)
+ self._run(self.ninja_command)
def run_target(self, target):
self.output += subprocess.check_output(self.ninja_command + [target])
def setconf(self, arg):
- self.output += subprocess.check_output(self.mconf_command + [arg, self.builddir])
+ self._run(self.mconf_command + [arg, self.builddir])
def get_compdb(self):
with open(os.path.join(self.builddir, 'compile_commands.json')) as ifile:
return json.load(ifile)
+ def get_meson_log(self):
+ with open(os.path.join(self.builddir, 'meson-logs', 'meson-log.txt')) as f:
+ return f.readlines()
+
def introspect(self, arg):
out = subprocess.check_output(self.mintro_command + [arg, self.builddir])
return json.loads(out.decode('utf-8'))
@@ -181,5 +189,19 @@ class LinuxlikeTests(unittest.TestCase):
self.init(testdir)
self.run_target('check_exists')
+ def test_qt5dependency_qmake_detection(self):
+ # Can't be sure that `qmake` is Qt5, so just try qmake-qt5.
+ if not shutil.which('qmake-qt5'):
+ raise unittest.SkipTest('qt5 not found')
+ # Disable pkg-config codepath and force searching with qmake/qmake-qt5
+ os.environ['PKG_CONFIG_LIBDIR'] = self.builddir
+ os.environ['PKG_CONFIG_PATH'] = self.builddir
+ testdir = os.path.join(self.framework_test_dir, '4 qt')
+ self.init(testdir)
+ # Confirm that the dependency was found with qmake
+ msg = 'Qt5 native `qmake-qt5` dependency found: YES\n'
+ mesonlog = self.get_meson_log()
+ self.assertTrue(msg in mesonlog)
+
if __name__ == '__main__':
unittest.main()
diff --git a/test cases/frameworks/4 qt5/main.cpp b/test cases/frameworks/4 qt/main.cpp
index 4c257a4..4c257a4 100644
--- a/test cases/frameworks/4 qt5/main.cpp
+++ b/test cases/frameworks/4 qt/main.cpp
diff --git a/manual tests/6 qt4/mainWindow.cpp b/test cases/frameworks/4 qt/mainWindow.cpp
index cc82c4f..cc82c4f 100644
--- a/manual tests/6 qt4/mainWindow.cpp
+++ b/test cases/frameworks/4 qt/mainWindow.cpp
diff --git a/manual tests/6 qt4/mainWindow.h b/test cases/frameworks/4 qt/mainWindow.h
index 7f6d906..7f6d906 100644
--- a/manual tests/6 qt4/mainWindow.h
+++ b/test cases/frameworks/4 qt/mainWindow.h
diff --git a/manual tests/6 qt4/mainWindow.ui b/test cases/frameworks/4 qt/mainWindow.ui
index 2eb226a..2eb226a 100644
--- a/manual tests/6 qt4/mainWindow.ui
+++ b/test cases/frameworks/4 qt/mainWindow.ui
diff --git a/manual tests/6 qt4/manualinclude.cpp b/test cases/frameworks/4 qt/manualinclude.cpp
index 0602882..0602882 100644
--- a/manual tests/6 qt4/manualinclude.cpp
+++ b/test cases/frameworks/4 qt/manualinclude.cpp
diff --git a/manual tests/6 qt4/manualinclude.h b/test cases/frameworks/4 qt/manualinclude.h
index 4a00b6c..4a00b6c 100644
--- a/manual tests/6 qt4/manualinclude.h
+++ b/test cases/frameworks/4 qt/manualinclude.h
diff --git a/test cases/frameworks/4 qt/meson.build b/test cases/frameworks/4 qt/meson.build
new file mode 100644
index 0000000..1096c78
--- /dev/null
+++ b/test cases/frameworks/4 qt/meson.build
@@ -0,0 +1,45 @@
+project('qt4 and 5 build test', 'cpp')
+
+foreach qt : ['qt4', 'qt5']
+ qtdep = dependency(qt, modules : ['Core', 'Gui', 'Widgets'], required : qt == 'qt5')
+ if qtdep.found()
+ qtmodule = import(qt)
+
+ # The following has two resource files because having two in one target
+ # requires you to do it properly or you get linker symbol clashes.
+
+ prep = qtmodule.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', 'stuff2.qrc'], # Resource file for rcc compiler.
+ )
+
+ qexe = executable(qt + 'app',
+ sources : ['main.cpp', 'mainWindow.cpp', # Sources that don't need preprocessing.
+ prep],
+ dependencies : qtdep)
+
+ # We need a console test application because some test environments
+ # do not have an X server.
+
+ qtcore = dependency(qt, modules : 'Core')
+
+ qtcoreapp = executable(qt + 'core', 'q5core.cpp',
+ dependencies : qtcore)
+
+ test(qt + 'test', qtcoreapp)
+
+ # The build system needs to include the cpp files from
+ # headers but the user must manually include moc
+ # files from sources.
+ manpreprocessed = qtmodule.preprocess(
+ moc_sources : 'manualinclude.cpp',
+ moc_headers : 'manualinclude.h')
+
+ qtmaninclude = executable(qt + 'maninclude',
+ sources : ['manualinclude.cpp', manpreprocessed],
+ dependencies : qtcore)
+
+ test(qt + 'maninclude', qtmaninclude)
+ endif
+endforeach
diff --git a/test cases/frameworks/4 qt5/q5core.cpp b/test cases/frameworks/4 qt/q5core.cpp
index 706e4dc..706e4dc 100644
--- a/test cases/frameworks/4 qt5/q5core.cpp
+++ b/test cases/frameworks/4 qt/q5core.cpp
diff --git a/test cases/frameworks/4 qt5/stuff.qrc b/test cases/frameworks/4 qt/stuff.qrc
index fdfb58e..fdfb58e 100644
--- a/test cases/frameworks/4 qt5/stuff.qrc
+++ b/test cases/frameworks/4 qt/stuff.qrc
diff --git a/test cases/frameworks/4 qt5/stuff2.qrc b/test cases/frameworks/4 qt/stuff2.qrc
index 910e2fb..910e2fb 100644
--- a/test cases/frameworks/4 qt5/stuff2.qrc
+++ b/test cases/frameworks/4 qt/stuff2.qrc
diff --git a/manual tests/6 qt4/thing.png b/test cases/frameworks/4 qt/thing.png
index 4b001bd..4b001bd 100644
--- a/manual tests/6 qt4/thing.png
+++ b/test cases/frameworks/4 qt/thing.png
Binary files differ
diff --git a/manual tests/6 qt4/thing2.png b/test cases/frameworks/4 qt/thing2.png
index 4b001bd..4b001bd 100644
--- a/manual tests/6 qt4/thing2.png
+++ b/test cases/frameworks/4 qt/thing2.png
Binary files differ
diff --git a/test cases/frameworks/4 qt5/mainWindow.cpp b/test cases/frameworks/4 qt5/mainWindow.cpp
deleted file mode 100644
index cc82c4f..0000000
--- a/test cases/frameworks/4 qt5/mainWindow.cpp
+++ /dev/null
@@ -1,8 +0,0 @@
-#include "mainWindow.h"
-
-MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
- setupUi(this);
-}
-
-MainWindow::~MainWindow() {
-}
diff --git a/test cases/frameworks/4 qt5/mainWindow.h b/test cases/frameworks/4 qt5/mainWindow.h
deleted file mode 100644
index 7f6d906..0000000
--- a/test cases/frameworks/4 qt5/mainWindow.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#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/test cases/frameworks/4 qt5/mainWindow.ui b/test cases/frameworks/4 qt5/mainWindow.ui
deleted file mode 100644
index 2eb226a..0000000
--- a/test cases/frameworks/4 qt5/mainWindow.ui
+++ /dev/null
@@ -1,34 +0,0 @@
-<?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/test cases/frameworks/4 qt5/manualinclude.cpp b/test cases/frameworks/4 qt5/manualinclude.cpp
deleted file mode 100644
index 0602882..0000000
--- a/test cases/frameworks/4 qt5/manualinclude.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-#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/test cases/frameworks/4 qt5/manualinclude.h b/test cases/frameworks/4 qt5/manualinclude.h
deleted file mode 100644
index 4a00b6c..0000000
--- a/test cases/frameworks/4 qt5/manualinclude.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef MANUALINCLUDE_H_
-#define MANUALINCLUDE_H_
-
-#include<QObject>
-
-class ManualInclude : public QObject {
- Q_OBJECT
-
-public:
- ManualInclude();
-
-signals:
- int mysignal();
-};
-
-#endif
diff --git a/test cases/frameworks/4 qt5/meson.build b/test cases/frameworks/4 qt5/meson.build
deleted file mode 100644
index 5672071..0000000
--- a/test cases/frameworks/4 qt5/meson.build
+++ /dev/null
@@ -1,41 +0,0 @@
-project('qt5 build test', 'cpp')
-
-qt5 = import('qt5')
-qt5dep = dependency('qt5', modules : ['Core', 'Gui', 'Widgets'])
-
-# The following has two resource files because having two in one target
-# requires you to do it properly or you get linker symbol clashes.
-
-prep = qt5.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', 'stuff2.qrc'], # Resource file for rcc compiler.
-)
-
-q5exe = executable('qt5app',
- sources : ['main.cpp', 'mainWindow.cpp', # Sources that don't need preprocessing.
- prep],
- dependencies : qt5dep)
-
-# We need a console test application because some test environments
-# do not have an X server.
-
-qt5core = dependency('qt5', modules : 'Core')
-
-qt5coreapp = executable('q5core', 'q5core.cpp',
- dependencies : qt5core)
-
-test('qt5test', qt5coreapp)
-
-# The build system needs to include the cpp files from
-# headers but the user must manually include moc
-# files from sources.
-manpreprocessed = qt5.preprocess(
- moc_sources : 'manualinclude.cpp',
- moc_headers : 'manualinclude.h')
-
-q5maninclude = executable('q5maninclude',
- sources : ['manualinclude.cpp', manpreprocessed],
- dependencies : qt5core)
-
-test('q5maninclude', q5maninclude)
diff --git a/test cases/frameworks/4 qt5/thing.png b/test cases/frameworks/4 qt5/thing.png
deleted file mode 100644
index 4b001bd..0000000
--- a/test cases/frameworks/4 qt5/thing.png
+++ /dev/null
Binary files differ
diff --git a/test cases/frameworks/4 qt5/thing2.png b/test cases/frameworks/4 qt5/thing2.png
deleted file mode 100644
index 4b001bd..0000000
--- a/test cases/frameworks/4 qt5/thing2.png
+++ /dev/null
Binary files differ