From 5de5e7673f48bd1d11f68c3c1cb69041f27d8d22 Mon Sep 17 00:00:00 2001 From: Alexis Jeandet Date: Wed, 22 Nov 2017 22:52:38 +0100 Subject: [PATCH 1/4] [Qt module] Few minor fixes - removed a typo in tools detection loop - added include dir also when parsing cpp sources with moc, not only headers Signed-off-by: Alexis Jeandet --- mesonbuild/modules/qt.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mesonbuild/modules/qt.py b/mesonbuild/modules/qt.py index 285169ba0..df6a63175 100644 --- a/mesonbuild/modules/qt.py +++ b/mesonbuild/modules/qt.py @@ -62,7 +62,7 @@ class QtBaseModule: raise MesonException('{name} preprocessor is not for Qt {version}. Output:\n{stdo}\n{stderr}'.format( name=compiler_name, version=self.qt_version, stdo=stdout, stderr=stderr)) mlog.log(' {}:'.format(compiler_name.lower()), mlog.green('YES'), '({path}, {version})'.format( - path=self.moc.get_path(), version=compiler_ver.split()[-1])) + path=compiler.get_path(), version=compiler_ver.split()[-1])) else: mlog.log(' {}:'.format(compiler_name.lower()), mlog.red('NO')) self.tools_detected = True @@ -137,7 +137,7 @@ class QtBaseModule: moc_output = moc_gen.process_files('Qt{} moc header'.format(self.qt_version), moc_headers, state) sources.append(moc_output) if len(moc_sources) > 0: - arguments = moc_extra_arguments + ['@INPUT@', '-o', '@OUTPUT@'] + arguments = moc_extra_arguments + inc + ['@INPUT@', '-o', '@OUTPUT@'] moc_kwargs = {'output': '@BASENAME@.moc', 'arguments': arguments} moc_gen = build.Generator([self.moc], moc_kwargs) From 1fd743e6adbb04fc0d75ac21908a108c3483dc80 Mon Sep 17 00:00:00 2001 From: Alexis Jeandet Date: Wed, 22 Nov 2017 23:28:32 +0100 Subject: [PATCH 2/4] [Qt module] Added lrelease detection Just detect lrelease as done with other Qt tools. Uses -version instead of -v to probe version since lrelease don't support it. Signed-off-by: Alexis Jeandet --- mesonbuild/dependencies/ui.py | 4 +++- mesonbuild/modules/qt.py | 6 +++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/mesonbuild/dependencies/ui.py b/mesonbuild/dependencies/ui.py index 3412dc655..837149cf7 100644 --- a/mesonbuild/dependencies/ui.py +++ b/mesonbuild/dependencies/ui.py @@ -207,13 +207,15 @@ class QtBaseDependency(ExternalDependency): 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) + lrelease = ExternalProgram(os.path.join(self.bindir, 'lrelease'), silent=True) else: # 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 + lrelease = ExternalProgram('lrelease-' + self.name, silent=True) + return moc, uic, rcc, lrelease def _pkgconfig_detect(self, mods, kwargs): # We set the value of required to False so that we can try the diff --git a/mesonbuild/modules/qt.py b/mesonbuild/modules/qt.py index df6a63175..c07a3615e 100644 --- a/mesonbuild/modules/qt.py +++ b/mesonbuild/modules/qt.py @@ -43,13 +43,13 @@ class QtBaseModule: kwargs = {'required': 'true', 'modules': 'Core', 'silent': 'true', 'method': method} qt = _QT_DEPS_LUT[self.qt_version](env, kwargs) # Get all tools and then make sure that they are the right version - self.moc, self.uic, self.rcc = qt.compilers_detect() + self.moc, self.uic, self.rcc, self.lrelease = qt.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? - for compiler, compiler_name in ((self.moc, "Moc"), (self.uic, "Uic"), (self.rcc, "Rcc")): + for compiler, compiler_name in ((self.moc, "Moc"), (self.uic, "Uic"), (self.rcc, "Rcc"), (self.lrelease, "lrelease")): if compiler.found(): - stdout, stderr = Popen_safe(compiler.get_command() + ['-v'])[1:3] + stdout, stderr = Popen_safe(compiler.get_command() + ['-version'])[1:3] stdout = stdout.strip() stderr = stderr.strip() if 'Qt {}'.format(self.qt_version) in stderr: From 5c5eac357199092a1766bc43ce46bd7483451e74 Mon Sep 17 00:00:00 2001 From: Alexis Jeandet Date: Thu, 23 Nov 2017 01:42:49 +0100 Subject: [PATCH 3/4] [Qt module] Added translation files compilation method - Added a new compile_translations method since preprocess was already quite full and translations compilation is quite different from ui, qrc, cpp files preprocessing. - Updated translation. - Updated test case. Signed-off-by: Alexis Jeandet --- docs/markdown/Qt5-module.md | 14 +++++++++++--- mesonbuild/modules/qt.py | 18 ++++++++++++++++++ test cases/frameworks/4 qt/meson.build | 2 ++ test cases/frameworks/4 qt/q5core.cpp | 18 ++++++++++++++++++ test cases/frameworks/4 qt/qt4core_fr.ts | 12 ++++++++++++ test cases/frameworks/4 qt/qt5core_fr.ts | 12 ++++++++++++ 6 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 test cases/frameworks/4 qt/qt4core_fr.ts create mode 100644 test cases/frameworks/4 qt/qt5core_fr.ts diff --git a/docs/markdown/Qt5-module.md b/docs/markdown/Qt5-module.md index aea2ae139..c7a2578a5 100644 --- a/docs/markdown/Qt5-module.md +++ b/docs/markdown/Qt5-module.md @@ -1,7 +1,7 @@ # Qt5 module The Qt5 module provides tools to automatically deal with the various -tools and steps required for Qt. The module has one method. +tools and steps required for Qt. The module has two methods. ## preprocess @@ -12,6 +12,14 @@ This method takes the following keyword arguments: It returns an opaque object that should be passed to a main build target. +## compile_translations + +This method generates the necessary targets to build translation files with lrelease, it takes the following keyword arguments: + - `ts_files`, the list of input translation files produced by Qt's lupdate tool. + - `install` when true, this target is installed during the install step. + - `install_dir` directory to install to + - `build_by_default` when set to true, to have this target be built by default, that is, when invoking plain ninja; the default value is false. + A simple example would look like this: ```meson @@ -21,6 +29,7 @@ inc = include_directories('includes') moc_files = qt5.preprocess(moc_headers : 'myclass.h', moc_extra_arguments: ['-DMAKES_MY_MOC_HEADER_COMPILE'], include_directories: inc) +translations = qt5.compile_translations(ts_files : 'myTranslation_fr.ts', build_by_default : true) executable('myprog', 'main.cpp', 'myclass.cpp', moc_files, include_directories: inc, dependencies : qt5_dep) @@ -28,5 +37,4 @@ executable('myprog', 'main.cpp', 'myclass.cpp', moc_files, The 'modules' argument is used to include Qt modules in the project. -See the Qt documentation for the [list of -modules](http://doc.qt.io/qt-5/qtmodules.html). +See the Qt documentation for the [list of modules](http://doc.qt.io/qt-5/qtmodules.html). diff --git a/mesonbuild/modules/qt.py b/mesonbuild/modules/qt.py index c07a3615e..463bf0100 100644 --- a/mesonbuild/modules/qt.py +++ b/mesonbuild/modules/qt.py @@ -144,3 +144,21 @@ class QtBaseModule: moc_output = moc_gen.process_files('Qt{} moc source'.format(self.qt_version), moc_sources, state) sources.append(moc_output) return ModuleReturnValue(sources, sources) + + @permittedKwargs({'ts_files', 'install', 'install_dir', 'build_by_default', 'method'}) + def compile_translations(self, state, args, kwargs): + ts_files, install_dir = extract_as_list(kwargs, 'ts_files', 'install_dir', pop=True) + self._detect_tools(state.environment, kwargs.get('method', 'auto')) + translations = [] + for ts in ts_files: + cmd = [self.lrelease, '@INPUT@', '-qm', '@OUTPUT@'] + lrelease_kwargs = {'output': '@BASENAME@.qm', + 'input': ts, + 'install': kwargs.get('install', False), + 'build_by_default': kwargs.get('build_by_default', False), + 'command': cmd} + if install_dir is not None: + lrelease_kwargs['install_dir'] = install_dir + lrelease_target = build.CustomTarget('qt{}-compile-{}'.format(self.qt_version, ts), state.subdir, state.subproject, lrelease_kwargs) + translations.append(lrelease_target) + return ModuleReturnValue(translations, translations) diff --git a/test cases/frameworks/4 qt/meson.build b/test cases/frameworks/4 qt/meson.build index 374707aac..7c33268a8 100644 --- a/test cases/frameworks/4 qt/meson.build +++ b/test cases/frameworks/4 qt/meson.build @@ -59,6 +59,8 @@ foreach qt : ['qt4', 'qt5'] # We need a console test application because some test environments # do not have an X server. + translations = qtmodule.compile_translations(ts_files : qt+'core_fr.ts', build_by_default : true) + qtcore = dependency(qt, modules : 'Core', method : get_option('method')) qtcoreapp = executable(qt + 'core', 'q5core.cpp', diff --git a/test cases/frameworks/4 qt/q5core.cpp b/test cases/frameworks/4 qt/q5core.cpp index 706e4dc87..25b80b8e3 100644 --- a/test cases/frameworks/4 qt/q5core.cpp +++ b/test cases/frameworks/4 qt/q5core.cpp @@ -1,8 +1,26 @@ #include +#include +#include +#include +#include +#include +#include int main(int argc, char **argv) { QCoreApplication app(argc, argv); + QTranslator qtTranslator; + qtTranslator.load("qt_" + QLocale::system().name(), + QLibraryInfo::location(QLibraryInfo::TranslationsPath)); + app.installTranslator(&qtTranslator); + + QTranslator myappTranslator; + if(!myappTranslator.load("qt5core_fr") ) + return 1; + + app.installTranslator(&myappTranslator); + + qDebug() << QObject::tr("Translate me!"); // Don't actually start the main loop so this // can be run as a unit test. //return app.exec(); diff --git a/test cases/frameworks/4 qt/qt4core_fr.ts b/test cases/frameworks/4 qt/qt4core_fr.ts new file mode 100644 index 000000000..0638bd5e9 --- /dev/null +++ b/test cases/frameworks/4 qt/qt4core_fr.ts @@ -0,0 +1,12 @@ + + + + + QObject + + + Translate me! + Traduisez moi! + + + diff --git a/test cases/frameworks/4 qt/qt5core_fr.ts b/test cases/frameworks/4 qt/qt5core_fr.ts new file mode 100644 index 000000000..4e3116bcf --- /dev/null +++ b/test cases/frameworks/4 qt/qt5core_fr.ts @@ -0,0 +1,12 @@ + + + + + QObject + + + Translate me! + Traduisez moi! + + + From 5462e65c44e94489ddfc1ffab82ab3f5ee6d7ea7 Mon Sep 17 00:00:00 2001 From: Alexis Jeandet Date: Thu, 23 Nov 2017 21:20:45 +0100 Subject: [PATCH 4/4] [Qt module] Updated Dokerfile, added since 0.44 mention in doc Signed-off-by: Alexis Jeandet --- ciimage/Dockerfile | 1 + docs/markdown/Qt5-module.md | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/ciimage/Dockerfile b/ciimage/Dockerfile index a2e3433df..05e679e5c 100644 --- a/ciimage/Dockerfile +++ b/ciimage/Dockerfile @@ -12,4 +12,5 @@ RUN apt-get -y update && apt-get -y upgrade \ && apt-get -y install fpga-icestorm arachne-pnr yosys \ && apt-get -y install gtk-sharp2 gtk-sharp2-gapi libglib2.0-cil-dev \ && apt-get -y install libwmf-dev \ +&& apt-get -y install qt4-linguist-tools qttools5-dev-tools \ && python3 -m pip install hotdoc codecov diff --git a/docs/markdown/Qt5-module.md b/docs/markdown/Qt5-module.md index c7a2578a5..b5393a85c 100644 --- a/docs/markdown/Qt5-module.md +++ b/docs/markdown/Qt5-module.md @@ -12,13 +12,13 @@ This method takes the following keyword arguments: It returns an opaque object that should be passed to a main build target. -## compile_translations +## compile_translations (since v0.44.0) This method generates the necessary targets to build translation files with lrelease, it takes the following keyword arguments: - `ts_files`, the list of input translation files produced by Qt's lupdate tool. - - `install` when true, this target is installed during the install step. - - `install_dir` directory to install to - - `build_by_default` when set to true, to have this target be built by default, that is, when invoking plain ninja; the default value is false. + - `install` when true, this target is installed during the install step (optional). + - `install_dir` directory to install to (optional). + - `build_by_default` when set to true, to have this target be built by default, that is, when invoking plain ninja; the default value is false (optional). A simple example would look like this: