Upstream-URL: https://github.com/mesonbuild/meson/pull/10365 From 7606b19f8981f75b7076a765cec1ecf7b04220fb Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Sat, 7 May 2022 23:03:01 -0400 Subject: [PATCH 1/3] gettext: explicitly pass source root / subdir as cli args Because this is a wrapper script and we could/should do this, we even have half the infra for it. --- mesonbuild/modules/i18n.py | 6 ++++++ mesonbuild/scripts/gettext.py | 15 +++++++-------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/mesonbuild/modules/i18n.py b/mesonbuild/modules/i18n.py index 2bdf9d30b97..4bbc69abfb1 100644 --- a/mesonbuild/modules/i18n.py +++ b/mesonbuild/modules/i18n.py @@ -251,6 +251,9 @@ def gettext(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'Gettext') - extra_arg = '--extra-args=' + '@@'.join(extra_args) if extra_args else None potargs = state.environment.get_build_command() + ['--internal', 'gettext', 'pot', pkg_arg] + potargs.append(f'--source-root={state.source_root}') + if state.subdir: + potargs.append(f'--subdir={state.subdir}') if datadirs: potargs.append(datadirs) if extra_arg: @@ -292,6 +295,9 @@ def gettext(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'Gettext') - targets.append(allgmotarget) updatepoargs = state.environment.get_build_command() + ['--internal', 'gettext', 'update_po', pkg_arg] + updatepoargs.append(f'--source-root={state.source_root}') + if state.subdir: + updatepoargs.append(f'--subdir={state.subdir}') if lang_arg: updatepoargs.append(lang_arg) if datadirs: diff --git a/mesonbuild/scripts/gettext.py b/mesonbuild/scripts/gettext.py index c3298926ef8..c31657a71d3 100644 --- a/mesonbuild/scripts/gettext.py +++ b/mesonbuild/scripts/gettext.py @@ -23,6 +23,7 @@ parser.add_argument('--datadirs', default='') parser.add_argument('--langs', default='') parser.add_argument('--localedir', default='') +parser.add_argument('--source-root', default='') parser.add_argument('--subdir', default='') parser.add_argument('--xgettext', default='xgettext') parser.add_argument('--msgmerge', default='msgmerge') @@ -45,7 +46,7 @@ def read_linguas(src_sub: str) -> T.List[str]: print(f'Could not find file LINGUAS in {src_sub}') return [] -def run_potgen(src_sub: str, xgettext: str, pkgname: str, datadirs: str, args: T.List[str]) -> int: +def run_potgen(src_sub: str, xgettext: str, pkgname: str, datadirs: str, args: T.List[str], source_root: str) -> int: listfile = os.path.join(src_sub, 'POTFILES.in') if not os.path.exists(listfile): listfile = os.path.join(src_sub, 'POTFILES') @@ -59,7 +60,7 @@ def run_potgen(src_sub: str, xgettext: str, pkgname: str, datadirs: str, args: T ofile = os.path.join(src_sub, pkgname + '.pot') return subprocess.call([xgettext, '--package-name=' + pkgname, '-p', src_sub, '-f', listfile, - '-D', os.environ['MESON_SOURCE_ROOT'], '-k_', '-o', ofile] + args, + '-D', source_root, '-k_', '-o', ofile] + args, env=child_env) def update_po(src_sub: str, msgmerge: str, msginit: str, pkgname: str, langs: T.List[str]) -> int: @@ -77,18 +78,16 @@ def run(args: T.List[str]) -> int: subcmd = options.command langs = options.langs.split('@@') if options.langs else None extra_args = options.extra_args.split('@@') if options.extra_args else [] - subdir = os.environ.get('MESON_SUBDIR', '') - if options.subdir: - subdir = options.subdir - src_sub = os.path.join(os.environ['MESON_SOURCE_ROOT'], subdir) + subdir = options.subdir + src_sub = os.path.join(options.source_root, subdir) if not langs: langs = read_linguas(src_sub) if subcmd == 'pot': - return run_potgen(src_sub, options.xgettext, options.pkgname, options.datadirs, extra_args) + return run_potgen(src_sub, options.xgettext, options.pkgname, options.datadirs, extra_args, options.source_root) elif subcmd == 'update_po': - if run_potgen(src_sub, options.xgettext, options.pkgname, options.datadirs, extra_args) != 0: + if run_potgen(src_sub, options.xgettext, options.pkgname, options.datadirs, extra_args, options.source_root) != 0: return 1 return update_po(src_sub, options.msgmerge, options.msginit, options.pkgname, langs) else: From 3767fd103fb61c693f7a1148dea38de0dbc156e9 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Sat, 7 May 2022 23:06:22 -0400 Subject: [PATCH 2/3] i18n: fix bug where disabling gettext() broke merge_file() In the former case, the presence of tools is optional, but triggers a warning and then no-ops the target. In the latter case, the presence of the tools is mandatory. But if it was already looked up and discovered to be missing, we did not actually check that it is found before trying to use it. In the case that it isn't found, check again, so that we explicitly error out with a relevant error message due to setting the required flag. Fixes #10320 --- mesonbuild/modules/i18n.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/modules/i18n.py b/mesonbuild/modules/i18n.py index 4bbc69abfb1..151fd08a01d 100644 --- a/mesonbuild/modules/i18n.py +++ b/mesonbuild/modules/i18n.py @@ -166,7 +166,7 @@ def _get_data_dirs(state: 'ModuleState', dirs: T.Iterable[str]) -> T.List[str]: KwargInfo('type', str, default='xml', validator=in_set_validator({'xml', 'desktop'})), ) def merge_file(self, state: 'ModuleState', args: T.List['TYPE_var'], kwargs: 'MergeFile') -> ModuleReturnValue: - if self.tools['msgfmt'] is None: + if self.tools['msgfmt'] is None or not self.tools['msgfmt'].found(): self.tools['msgfmt'] = state.find_program('msgfmt', for_machine=mesonlib.MachineChoice.BUILD) podir = path.join(state.build_to_src, state.subdir, kwargs['po_dir']) From 6176ed157942fb36a2a6dd0c209e21359a1df7b3 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Sat, 7 May 2022 23:10:13 -0400 Subject: [PATCH 3/3] i18n: be build-compatible (but not developer-compatible) with gettext-tiny For maintainer targets, we need some more tools that gettext-tiny doesn't implement. It's a shame to cause NLS to be completely disabled in such environments, so instead just issue a warning and continue. Before 0.62.0 these were never checked for, and would simply fail at runtime, probably. In theory, the user might install the tools in between configuring and building, and then the maintainer targets would begin to work. Return to that behavior -- we still create the targets, which will *probably* fail, but might not -- and for existing integrations, failing at `ninja foo-update-po` with "error, program msgmerge not found" is a bit more discoverable than ninja saying "what do you mean, there's no such target". We still have the 0.62.0 preferred behavior of trying to find the programs, succeeding in all cases other than gettext-tiny, and guaranteeing that their paths are set up in a machine-file-respecting manner. --- mesonbuild/modules/i18n.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/mesonbuild/modules/i18n.py b/mesonbuild/modules/i18n.py index 151fd08a01d..d97d166f33f 100644 --- a/mesonbuild/modules/i18n.py +++ b/mesonbuild/modules/i18n.py @@ -140,10 +140,6 @@ def __init__(self, interpreter: 'Interpreter'): 'xgettext': None, } - @staticmethod - def nogettext_warning(location: BaseNode) -> None: - mlog.warning('Gettext not found, all translation targets will be ignored.', once=True, location=location) - @staticmethod def _get_data_dirs(state: 'ModuleState', dirs: T.Iterable[str]) -> T.List[str]: """Returns source directories of relative paths""" @@ -223,13 +219,18 @@ def merge_file(self, state: 'ModuleState', args: T.List['TYPE_var'], kwargs: 'Me ), ) def gettext(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'Gettext') -> ModuleReturnValue: - for tool in ['msgfmt', 'msginit', 'msgmerge', 'xgettext']: + for tool, strict in [('msgfmt', True), ('msginit', False), ('msgmerge', False), ('xgettext', False)]: if self.tools[tool] is None: self.tools[tool] = state.find_program(tool, required=False, for_machine=mesonlib.MachineChoice.BUILD) # still not found? if not self.tools[tool].found(): - self.nogettext_warning(state.current_node) - return ModuleReturnValue(None, []) + if strict: + mlog.warning('Gettext not found, all translation (po) targets will be ignored.', + once=True, location=state.current_node) + return ModuleReturnValue(None, []) + else: + mlog.warning(f'{tool!r} not found, maintainer targets will not work', + once=True, fatal=False, location=state.current_node) packagename = args[0] pkg_arg = f'--pkgname={packagename}' diff -Nurd meson-0.62.1/mesonbuild/modules/i18n.py meson-0.62.1.new/mesonbuild/modules/i18n.py --- meson-0.62.1/mesonbuild/modules/i18n.py 2022-05-30 17:31:38.274677123 +0000 +++ meson-0.62.1.new/mesonbuild/modules/i18n.py 2022-05-30 17:34:11.654676626 +0000 @@ -258,7 +258,8 @@ potargs.append(datadirs) if extra_arg: potargs.append(extra_arg) - potargs.append('--xgettext=' + self.tools['xgettext'].get_path()) + if self.tools['xgettext'].found(): + potargs.append('--xgettext=' + self.tools['xgettext'].get_path()) pottarget = build.RunTarget(packagename + '-pot', potargs, [], state.subdir, state.subproject) targets.append(pottarget) @@ -302,7 +303,8 @@ if extra_arg: updatepoargs.append(extra_arg) for tool in ['msginit', 'msgmerge']: - updatepoargs.append(f'--{tool}=' + self.tools[tool].get_path()) + if self.tools[tool].found(): + updatepoargs.append(f'--{tool}=' + self.tools[tool].get_path()) updatepotarget = build.RunTarget(packagename + '-update-po', updatepoargs, [], state.subdir, state.subproject) targets.append(updatepotarget)