aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/markdown/Qt5-module.md17
-rw-r--r--docs/markdown/snippets/qt_compile_translations_from_qrc.md19
-rw-r--r--mesonbuild/modules/qt.py60
3 files changed, 85 insertions, 11 deletions
diff --git a/docs/markdown/Qt5-module.md b/docs/markdown/Qt5-module.md
index 0d9a6b6..9665267 100644
--- a/docs/markdown/Qt5-module.md
+++ b/docs/markdown/Qt5-module.md
@@ -22,6 +22,12 @@ This method generates the necessary targets to build translation files with lrel
- `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 `meson compile`; the default value is false (optional).
+ - `qresource` rcc source file to extract ts_files from; cannot be used with ts_files kwarg. Available since v0.56.0.
+ - `rcc_extra_arguments`, any additional arguments to `rcc` (optional), when used with `qresource. Available since v0.56.0.
+
+Returns either: a list of custom targets for the compiled translations, or, if
+using a `qresource` file, a single custom target containing the processed
+source file, which should be passed to a main build target.
## has_tools
@@ -71,3 +77,14 @@ executable('myprog', 'main.cpp', 'myclass.cpp', moc_files,
include_directories: inc,
dependencies : qt5_dep)
```
+
+Sometimes, translations are embedded inside the binary using qresource files.
+In this case the ts files do not need to be explicitly listed. For example:
+
+```meson
+qt5 = import('qt5')
+qt5_dep = dependency('qt5', modules: ['Core', 'Gui'])
+lang_cpp = qt5.compile_translations(qresource: 'lang.qrc')
+executable('myprog', 'main.cpp', lang_cpp,
+ dependencies: qt5_dep)
+```
diff --git a/docs/markdown/snippets/qt_compile_translations_from_qrc.md b/docs/markdown/snippets/qt_compile_translations_from_qrc.md
new file mode 100644
index 0000000..bfa8619
--- /dev/null
+++ b/docs/markdown/snippets/qt_compile_translations_from_qrc.md
@@ -0,0 +1,19 @@
+## Qt5 compile_translations now supports qresource preprocessing
+
+When using qtmod.preprocess() in combination with qtmod.compile_translations()
+to embed translations using rcc, it is no longer required to do this:
+
+```meson
+ts_files = ['list', 'of', 'files']
+qtmod.compile_translations(ts_files)
+# lang.qrc also contains the duplicated list of files
+lang_cpp = qtmod.preprocess(qresources: 'lang.qrc')
+```
+
+Instead, use:
+```meson
+lang_cpp = qtmod.compile_translations(qresource: 'lang.qrc')
+```
+
+which will automatically detect and generate the needed compile_translations
+targets.
diff --git a/mesonbuild/modules/qt.py b/mesonbuild/modules/qt.py
index c810df6..c7a1c46 100644
--- a/mesonbuild/modules/qt.py
+++ b/mesonbuild/modules/qt.py
@@ -13,6 +13,7 @@
# limitations under the License.
import os
+import shutil
from .. import mlog
from .. import build
from ..mesonlib import MesonException, extract_as_list, File, unholder, version_compare
@@ -59,7 +60,7 @@ class QtBaseModule(ExtensionModule):
self.rcc = NonExistingExternalProgram(name='rcc' + suffix)
self.lrelease = NonExistingExternalProgram(name='lrelease' + suffix)
- def parse_qrc(self, state, rcc_file):
+ def qrc_nodes(self, state, rcc_file):
if type(rcc_file) is str:
abspath = os.path.join(state.environment.source_dir, state.subdir, rcc_file)
rcc_dirname = os.path.dirname(abspath)
@@ -76,7 +77,16 @@ class QtBaseModule(ExtensionModule):
mlog.warning("malformed rcc file: ", os.path.join(state.subdir, rcc_file))
break
else:
- resource_path = child.text
+ result.append(child.text)
+
+ return rcc_dirname, result
+ except Exception:
+ return []
+
+ def parse_qrc_deps(self, state, rcc_file):
+ rcc_dirname, nodes = self.qrc_nodes(state, rcc_file)
+ result = []
+ for resource_path in nodes:
# We need to guess if the pointed resource is:
# a) in build directory -> implies a generated file
# b) in source directory
@@ -100,9 +110,7 @@ class QtBaseModule(ExtensionModule):
# b)
else:
result.append(File(is_built=False, subdir=state.subdir, fname=path_from_rcc))
- return result
- except Exception:
- return []
+ return result
@noPosargs
@permittedKwargs({'method', 'required'})
@@ -142,7 +150,7 @@ class QtBaseModule(ExtensionModule):
if args:
qrc_deps = []
for i in rcc_files:
- qrc_deps += self.parse_qrc(state, i)
+ qrc_deps += self.parse_qrc_deps(state, i)
name = args[0]
rcc_kwargs = {'input': rcc_files,
'output': name + '.cpp',
@@ -152,7 +160,7 @@ class QtBaseModule(ExtensionModule):
sources.append(res_target)
else:
for rcc_file in rcc_files:
- qrc_deps = self.parse_qrc(state, rcc_file)
+ qrc_deps = self.parse_qrc_deps(state, rcc_file)
if type(rcc_file) is str:
basename = os.path.basename(rcc_file)
elif type(rcc_file) is File:
@@ -205,15 +213,42 @@ class QtBaseModule(ExtensionModule):
return ModuleReturnValue(sources, sources)
@FeatureNew('qt.compile_translations', '0.44.0')
- @permittedKwargs({'ts_files', 'install', 'install_dir', 'build_by_default', 'method'})
+ @FeatureNewKwargs('qt.compile_translations', '0.56.0', ['qresource'])
+ @FeatureNewKwargs('qt.compile_translations', '0.56.0', ['rcc_extra_arguments'])
+ @permittedKwargs({'ts_files', 'qresource', 'rcc_extra_arguments', 'install', 'install_dir', 'build_by_default', 'method'})
def compile_translations(self, state, args, kwargs):
- ts_files, install_dir = [extract_as_list(kwargs, c, pop=True) for c in ['ts_files', 'install_dir']]
+ ts_files, install_dir = [extract_as_list(kwargs, c, pop=True) for c in ['ts_files', 'install_dir']]
+ qresource = kwargs.get('qresource')
+ if qresource:
+ if ts_files:
+ raise MesonException('qt.compile_translations: Cannot specify both ts_files and qresource')
+ if os.path.dirname(qresource) != '':
+ raise MesonException('qt.compile_translations: qresource file name must not contain a subdirectory.')
+ qresource = File.from_built_file(state.subdir, qresource)
+ infile_abs = os.path.join(state.environment.source_dir, qresource.relative_name())
+ outfile_abs = os.path.join(state.environment.build_dir, qresource.relative_name())
+ os.makedirs(os.path.dirname(outfile_abs), exist_ok=True)
+ shutil.copy2(infile_abs, outfile_abs)
+ self.interpreter.add_build_def_file(infile_abs)
+
+ rcc_file, nodes = self.qrc_nodes(state, qresource)
+ for c in nodes:
+ if c.endswith('.qm'):
+ ts_files.append(c.rstrip('.qm')+'.ts')
+ else:
+ raise MesonException('qt.compile_translations: qresource can only contain ts files, found {}'.format(c))
+ results = self.preprocess(state, [], {'qresources': qresource, 'rcc_extra_arguments': kwargs.get('rcc_extra_arguments', [])})
self._detect_tools(state.environment, kwargs.get('method', 'auto'))
translations = []
for ts in ts_files:
if not self.lrelease.found():
raise MesonException('qt.compile_translations: ' +
self.lrelease.name + ' not found')
+ if qresource:
+ outdir = os.path.dirname(os.path.normpath(os.path.join(state.subdir, ts)))
+ ts = os.path.basename(ts)
+ else:
+ outdir = state.subdir
cmd = [self.lrelease, '@INPUT@', '-qm', '@OUTPUT@']
lrelease_kwargs = {'output': '@BASENAME@.qm',
'input': ts,
@@ -222,6 +257,9 @@ class QtBaseModule(ExtensionModule):
'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)
+ lrelease_target = build.CustomTarget('qt{}-compile-{}'.format(self.qt_version, ts), outdir, state.subproject, lrelease_kwargs)
translations.append(lrelease_target)
- return ModuleReturnValue(translations, translations)
+ if qresource:
+ return ModuleReturnValue(results.return_value[0], [results.new_objects, translations])
+ else:
+ return ModuleReturnValue(translations, translations)