|
|
|
# Copyright 2016 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.
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
from os import path
|
|
|
|
import typing as T
|
|
|
|
|
|
|
|
from . import ExtensionModule, ModuleReturnValue
|
|
|
|
from .. import build
|
|
|
|
from .. import mesonlib
|
|
|
|
from .. import mlog
|
|
|
|
from ..interpreter.type_checking import CT_BUILD_BY_DEFAULT, CT_INPUT_KW, CT_INSTALL_DIR_KW, CT_INSTALL_TAG_KW, MULTI_OUTPUT_KW, INSTALL_KW, NoneType, in_set_validator
|
|
|
|
from ..interpreterbase import FeatureNew
|
|
|
|
from ..interpreterbase.decorators import ContainerTypeInfo, KwargInfo, noPosargs, typed_kwargs, typed_pos_args
|
|
|
|
from ..scripts.gettext import read_linguas
|
|
|
|
|
|
|
|
if T.TYPE_CHECKING:
|
|
|
|
from typing_extensions import Literal, TypedDict
|
|
|
|
|
|
|
|
from . import ModuleState
|
|
|
|
from ..build import Target
|
|
|
|
from ..interpreter import Interpreter
|
|
|
|
from ..interpreterbase import TYPE_var
|
|
|
|
from ..mparser import BaseNode
|
|
|
|
from ..programs import ExternalProgram
|
|
|
|
|
|
|
|
class MergeFile(TypedDict):
|
|
|
|
|
|
|
|
input: T.List[T.Union[
|
|
|
|
str, build.BuildTarget, build.CustomTarget, build.CustomTargetIndex,
|
|
|
|
build.ExtractedObjects, build.GeneratedList, ExternalProgram,
|
|
|
|
mesonlib.File]]
|
|
|
|
output: T.List[str]
|
|
|
|
build_by_default: bool
|
|
|
|
install: bool
|
|
|
|
install_dir: T.List[T.Union[str, bool]]
|
|
|
|
install_tag: T.List[str]
|
|
|
|
args: T.List[str]
|
|
|
|
data_dirs: T.List[str]
|
|
|
|
po_dir: str
|
|
|
|
type: Literal['xml', 'desktop']
|
|
|
|
|
|
|
|
class Gettext(TypedDict):
|
|
|
|
|
|
|
|
args: T.List[str]
|
|
|
|
data_dirs: T.List[str]
|
|
|
|
install: bool
|
|
|
|
install_dir: T.Optional[str]
|
|
|
|
languages: T.List[str]
|
|
|
|
preset: T.Optional[str]
|
|
|
|
|
|
|
|
class ItsJoinFile(TypedDict):
|
|
|
|
|
|
|
|
input: T.List[T.Union[
|
|
|
|
str, build.BuildTarget, build.CustomTarget, build.CustomTargetIndex,
|
|
|
|
build.ExtractedObjects, build.GeneratedList, ExternalProgram,
|
|
|
|
mesonlib.File]]
|
|
|
|
output: T.List[str]
|
|
|
|
build_by_default: bool
|
|
|
|
install: bool
|
|
|
|
install_dir: T.List[T.Union[str, bool]]
|
|
|
|
install_tag: T.List[str]
|
|
|
|
its_files: T.List[str]
|
|
|
|
mo_targets: T.List[T.Union[build.BuildTarget, build.CustomTarget, build.CustomTargetIndex]]
|
|
|
|
|
|
|
|
|
|
|
|
_ARGS: KwargInfo[T.List[str]] = KwargInfo(
|
|
|
|
'args',
|
|
|
|
ContainerTypeInfo(list, str),
|
|
|
|
default=[],
|
|
|
|
listify=True,
|
|
|
|
)
|
|
|
|
|
|
|
|
_DATA_DIRS: KwargInfo[T.List[str]] = KwargInfo(
|
|
|
|
'data_dirs',
|
|
|
|
ContainerTypeInfo(list, str),
|
|
|
|
default=[],
|
|
|
|
listify=True
|
|
|
|
)
|
|
|
|
|
|
|
|
PRESET_ARGS = {
|
|
|
|
'glib': [
|
|
|
|
'--from-code=UTF-8',
|
|
|
|
'--add-comments',
|
|
|
|
|
|
|
|
# https://developer.gnome.org/glib/stable/glib-I18N.html
|
|
|
|
'--keyword=_',
|
|
|
|
'--keyword=N_',
|
|
|
|
'--keyword=C_:1c,2',
|
|
|
|
'--keyword=NC_:1c,2',
|
|
|
|
'--keyword=g_dcgettext:2',
|
|
|
|
'--keyword=g_dngettext:2,3',
|
|
|
|
'--keyword=g_dpgettext2:2c,3',
|
|
|
|
|
|
|
|
'--flag=N_:1:pass-c-format',
|
|
|
|
'--flag=C_:2:pass-c-format',
|
|
|
|
'--flag=NC_:2:pass-c-format',
|
|
|
|
'--flag=g_dngettext:2:pass-c-format',
|
|
|
|
'--flag=g_strdup_printf:1:c-format',
|
|
|
|
'--flag=g_string_printf:2:c-format',
|
|
|
|
'--flag=g_string_append_printf:2:c-format',
|
|
|
|
'--flag=g_error_new:3:c-format',
|
|
|
|
'--flag=g_set_error:4:c-format',
|
|
|
|
'--flag=g_markup_printf_escaped:1:c-format',
|
|
|
|
'--flag=g_log:3:c-format',
|
|
|
|
'--flag=g_print:1:c-format',
|
|
|
|
'--flag=g_printerr:1:c-format',
|
|
|
|
'--flag=g_printf:1:c-format',
|
|
|
|
'--flag=g_fprintf:2:c-format',
|
|
|
|
'--flag=g_sprintf:2:c-format',
|
|
|
|
'--flag=g_snprintf:3:c-format',
|
|
|
|
]
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
class I18nModule(ExtensionModule):
|
|
|
|
def __init__(self, interpreter: 'Interpreter'):
|
|
|
|
super().__init__(interpreter)
|
|
|
|
self.methods.update({
|
|
|
|
'merge_file': self.merge_file,
|
|
|
|
'gettext': self.gettext,
|
|
|
|
'itstool_join': self.itstool_join,
|
|
|
|
})
|
|
|
|
self.tools: T.Dict[str, T.Optional[ExternalProgram]] = {
|
|
|
|
'itstool': None,
|
|
|
|
'msgfmt': None,
|
|
|
|
'msginit': None,
|
|
|
|
'msgmerge': None,
|
|
|
|
'xgettext': None,
|
|
|
|
}
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def _get_data_dirs(state: 'ModuleState', dirs: T.Iterable[str]) -> T.List[str]:
|
|
|
|
"""Returns source directories of relative paths"""
|
|
|
|
src_dir = path.join(state.environment.get_source_dir(), state.subdir)
|
|
|
|
return [path.join(src_dir, d) for d in dirs]
|
|
|
|
|
|
|
|
@FeatureNew('i18n.merge_file', '0.37.0')
|
|
|
|
@noPosargs
|
|
|
|
@typed_kwargs(
|
|
|
|
'i18n.merge_file',
|
|
|
|
CT_BUILD_BY_DEFAULT,
|
|
|
|
CT_INPUT_KW,
|
|
|
|
CT_INSTALL_DIR_KW,
|
|
|
|
CT_INSTALL_TAG_KW,
|
|
|
|
MULTI_OUTPUT_KW,
|
|
|
|
INSTALL_KW,
|
|
|
|
_ARGS.evolve(since='0.51.0'),
|
|
|
|
_DATA_DIRS.evolve(since='0.41.0'),
|
|
|
|
KwargInfo('po_dir', str, required=True),
|
|
|
|
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 or not self.tools['msgfmt'].found():
|
i18n.merge_file: do not disable in the absence of gettext tools
Disabling targets because the tools used to build them aren't available
is a pretty suspicious thing to do. Users who want this are probably, in
general, advised to check themselves whether it is possible to build
those targets with find_program(..., required: false)
The i18n.gettext() invocation is a bit unusual because the product of
running it is non-critical files, specifically, translation catalogs. If
users don't have the tools needed to build them, they may not be able to
use them either, because perhaps they have NLS disabled on their
platform or it's difficult to put it in the bootstrap path.
So, for this reason, it was made non-fatal and the message catalogs are
just not created, and the resulting build is still perfectly usable
*unless* you want to use it in another language, at which point it
"works" but the text is all inscrutable to the end user, and that's a
feature of the target platform.
That's an acceptable tradeoff for translation catalogs.
It is NOT an acceptable tradeoff for merge_file, which produces desktop
files or MIME database catalogs or other files which have crucial roles
to perform, without which the software in question simply doesn't work
at all. In such cases, this just fails to install crucial files, users
report bugs to the project in question, and the project adds
`find_program('xgettext')` to guarantee the hard error due to lack of
confidence in Meson.
Fixes #6165
Fixes #8436
3 years ago
|
|
|
self.tools['msgfmt'] = state.find_program('msgfmt', for_machine=mesonlib.MachineChoice.BUILD)
|
|
|
|
podir = path.join(state.build_to_src, state.subdir, kwargs['po_dir'])
|
|
|
|
|
|
|
|
ddirs = self._get_data_dirs(state, kwargs['data_dirs'])
|
|
|
|
datadirs = '--datadirs=' + ':'.join(ddirs) if ddirs else None
|
|
|
|
|
|
|
|
command: T.List[T.Union[str, build.BuildTarget, build.CustomTarget,
|
|
|
|
build.CustomTargetIndex, 'ExternalProgram', mesonlib.File]] = []
|
|
|
|
command.extend(state.environment.get_build_command())
|
|
|
|
command.extend([
|
|
|
|
'--internal', 'msgfmthelper',
|
|
|
|
'--msgfmt=' + self.tools['msgfmt'].get_path(),
|
|
|
|
])
|
|
|
|
if datadirs:
|
|
|
|
command.append(datadirs)
|
|
|
|
command.extend(['@INPUT@', '@OUTPUT@', kwargs['type'], podir])
|
|
|
|
if kwargs['args']:
|
|
|
|
command.append('--')
|
|
|
|
command.extend(kwargs['args'])
|
|
|
|
|
|
|
|
build_by_default = kwargs['build_by_default']
|
|
|
|
if build_by_default is None:
|
|
|
|
build_by_default = kwargs['install']
|
|
|
|
|
|
|
|
ct = build.CustomTarget(
|
|
|
|
'',
|
|
|
|
state.subdir,
|
|
|
|
state.subproject,
|
|
|
|
state.environment,
|
|
|
|
command,
|
|
|
|
kwargs['input'],
|
|
|
|
kwargs['output'],
|
|
|
|
build_by_default=build_by_default,
|
|
|
|
install=kwargs['install'],
|
|
|
|
install_dir=kwargs['install_dir'],
|
|
|
|
install_tag=kwargs['install_tag'],
|
|
|
|
)
|
|
|
|
|
|
|
|
return ModuleReturnValue(ct, [ct])
|
|
|
|
|
|
|
|
@typed_pos_args('i81n.gettext', str)
|
|
|
|
@typed_kwargs(
|
|
|
|
'i18n.gettext',
|
|
|
|
_ARGS,
|
|
|
|
_DATA_DIRS.evolve(since='0.36.0'),
|
|
|
|
INSTALL_KW.evolve(default=True),
|
|
|
|
KwargInfo('install_dir', (str, NoneType), since='0.50.0'),
|
|
|
|
KwargInfo('languages', ContainerTypeInfo(list, str), default=[], listify=True),
|
|
|
|
KwargInfo(
|
|
|
|
'preset',
|
|
|
|
(str, NoneType),
|
|
|
|
validator=in_set_validator(set(PRESET_ARGS)),
|
|
|
|
since='0.37.0',
|
|
|
|
),
|
|
|
|
)
|
|
|
|
def gettext(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'Gettext') -> ModuleReturnValue:
|
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.
3 years ago
|
|
|
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():
|
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.
3 years ago
|
|
|
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}'
|
|
|
|
|
|
|
|
languages = kwargs['languages']
|
|
|
|
lang_arg = '--langs=' + '@@'.join(languages) if languages else None
|
|
|
|
|
|
|
|
_datadirs = ':'.join(self._get_data_dirs(state, kwargs['data_dirs']))
|
|
|
|
datadirs = f'--datadirs={_datadirs}' if _datadirs else None
|
|
|
|
|
|
|
|
extra_args = kwargs['args']
|
|
|
|
targets: T.List['Target'] = []
|
|
|
|
gmotargets: T.List['build.CustomTarget'] = []
|
|
|
|
|
|
|
|
preset = kwargs['preset']
|
|
|
|
if preset:
|
|
|
|
preset_args = PRESET_ARGS[preset]
|
|
|
|
extra_args = list(mesonlib.OrderedSet(preset_args + extra_args))
|
|
|
|
|
|
|
|
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:
|
|
|
|
potargs.append(extra_arg)
|
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.
3 years ago
|
|
|
if self.tools['xgettext'].found():
|
|
|
|
potargs.append('--xgettext=' + self.tools['xgettext'].get_path())
|
|
|
|
pottarget = build.RunTarget(packagename + '-pot', potargs, [], state.subdir, state.subproject,
|
|
|
|
state.environment, default_env=False)
|
|
|
|
targets.append(pottarget)
|
|
|
|
|
|
|
|
install = kwargs['install']
|
|
|
|
install_dir = kwargs['install_dir'] or state.environment.coredata.get_option(mesonlib.OptionKey('localedir'))
|
|
|
|
assert isinstance(install_dir, str), 'for mypy'
|
|
|
|
if not languages:
|
|
|
|
languages = read_linguas(path.join(state.environment.source_dir, state.subdir))
|
|
|
|
for l in languages:
|
|
|
|
po_file = mesonlib.File.from_source_file(state.environment.source_dir,
|
|
|
|
state.subdir, l+'.po')
|
|
|
|
gmotarget = build.CustomTarget(
|
|
|
|
f'{packagename}-{l}.mo',
|
|
|
|
path.join(state.subdir, l, 'LC_MESSAGES'),
|
|
|
|
state.subproject,
|
|
|
|
state.environment,
|
|
|
|
[self.tools['msgfmt'], '@INPUT@', '-o', '@OUTPUT@'],
|
|
|
|
[po_file],
|
|
|
|
[f'{packagename}.mo'],
|
|
|
|
install=install,
|
|
|
|
# We have multiple files all installed as packagename+'.mo' in different install subdirs.
|
|
|
|
# What we really wanted to do, probably, is have a rename: kwarg, but that's not available
|
|
|
|
# to custom_targets. Crude hack: set the build target's subdir manually.
|
|
|
|
# Bonus: the build tree has something usable as an uninstalled bindtextdomain() target dir.
|
|
|
|
install_dir=[path.join(install_dir, l, 'LC_MESSAGES')],
|
|
|
|
install_tag=['i18n'],
|
|
|
|
)
|
|
|
|
targets.append(gmotarget)
|
|
|
|
gmotargets.append(gmotarget)
|
|
|
|
|
|
|
|
allgmotarget = build.AliasTarget(packagename + '-gmo', gmotargets, state.subdir, state.subproject,
|
|
|
|
state.environment)
|
|
|
|
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:
|
|
|
|
updatepoargs.append(datadirs)
|
|
|
|
if extra_arg:
|
|
|
|
updatepoargs.append(extra_arg)
|
|
|
|
for tool in ['msginit', 'msgmerge']:
|
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.
3 years ago
|
|
|
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,
|
|
|
|
state.environment, default_env=False)
|
|
|
|
targets.append(updatepotarget)
|
|
|
|
|
|
|
|
return ModuleReturnValue([gmotargets, pottarget, updatepotarget], targets)
|
|
|
|
|
|
|
|
@FeatureNew('i18n.itstool_join', '0.62.0')
|
|
|
|
@noPosargs
|
|
|
|
@typed_kwargs(
|
|
|
|
'i18n.itstool_join',
|
|
|
|
CT_BUILD_BY_DEFAULT,
|
|
|
|
CT_INPUT_KW,
|
|
|
|
CT_INSTALL_DIR_KW,
|
|
|
|
CT_INSTALL_TAG_KW,
|
|
|
|
MULTI_OUTPUT_KW,
|
|
|
|
INSTALL_KW,
|
|
|
|
_ARGS.evolve(),
|
|
|
|
KwargInfo('its_files', ContainerTypeInfo(list, str)),
|
|
|
|
KwargInfo('mo_targets', ContainerTypeInfo(list, build.CustomTarget), required=True),
|
|
|
|
)
|
|
|
|
def itstool_join(self, state: 'ModuleState', args: T.List['TYPE_var'], kwargs: 'ItsJoinFile') -> ModuleReturnValue:
|
|
|
|
if self.tools['itstool'] is None:
|
|
|
|
self.tools['itstool'] = state.find_program('itstool', for_machine=mesonlib.MachineChoice.BUILD)
|
|
|
|
mo_targets = kwargs['mo_targets']
|
|
|
|
its_files = kwargs.get('its_files', [])
|
|
|
|
|
|
|
|
mo_fnames = []
|
|
|
|
for target in mo_targets:
|
|
|
|
mo_fnames.append(path.join(target.get_subdir(), target.get_outputs()[0]))
|
|
|
|
|
|
|
|
command: T.List[T.Union[str, build.BuildTarget, build.CustomTarget,
|
|
|
|
build.CustomTargetIndex, 'ExternalProgram', mesonlib.File]] = []
|
|
|
|
command.extend(state.environment.get_build_command())
|
|
|
|
command.extend([
|
|
|
|
'--internal', 'itstool', 'join',
|
|
|
|
'-i', '@INPUT@',
|
|
|
|
'-o', '@OUTPUT@',
|
|
|
|
'--itstool=' + self.tools['itstool'].get_path(),
|
|
|
|
])
|
|
|
|
if its_files:
|
|
|
|
for fname in its_files:
|
|
|
|
if not path.isabs(fname):
|
|
|
|
fname = path.join(state.environment.source_dir, state.subdir, fname)
|
|
|
|
command.extend(['--its', fname])
|
|
|
|
command.extend(mo_fnames)
|
|
|
|
|
|
|
|
build_by_default = kwargs['build_by_default']
|
|
|
|
if build_by_default is None:
|
|
|
|
build_by_default = kwargs['install']
|
|
|
|
|
|
|
|
ct = build.CustomTarget(
|
|
|
|
'',
|
|
|
|
state.subdir,
|
|
|
|
state.subproject,
|
|
|
|
state.environment,
|
|
|
|
command,
|
|
|
|
kwargs['input'],
|
|
|
|
kwargs['output'],
|
|
|
|
build_by_default=build_by_default,
|
|
|
|
extra_depends=mo_targets,
|
|
|
|
install=kwargs['install'],
|
|
|
|
install_dir=kwargs['install_dir'],
|
|
|
|
install_tag=kwargs['install_tag'],
|
|
|
|
)
|
|
|
|
|
|
|
|
return ModuleReturnValue(ct, [ct])
|
|
|
|
|
|
|
|
|
|
|
|
def initialize(interp: 'Interpreter') -> I18nModule:
|
|
|
|
return I18nModule(interp)
|