Commit Graph

97 Commits

Author SHA1 Message Date
Chun-wei Fan ada6236f76 i18n module: Invoke itstool with the full command line
Certain envs may not support invoking itstool by itself directly as a script
as shebang lines are not supported, such as under cmd.exe shells on Windows,
that are normally used for Visual Studio (and the like, such as clang-cl)
builds.

This will call the corresponding interpreter to invoke itstool when needed, so
that itstool can be properly run, even if shebang lines are not supported by
the env.

This will fix building appstream on Windows using clang-cl, for instance.
2023-10-26 01:12:14 -04:00
Charles Brunet 7cbe37ebd9 Add more descriptive description to CustomTarget
Allow modules using CustomTarget to modify the command description used by ninja backend. This result in more precise logs when building a project.
2023-08-18 00:36:49 -04:00
Eli Schwartz 1f71911ae4
i18n module: check for a good enough msgfmt before permitting merge_file
The concept of merge_file intrinsically requires some GNU-specific
functionality, so let's emit a useful error message during
configuration, when we don't have that.

The relevant GNU gettext versions date back to around 2015 so *probably*
anyone has that too, but we may as well verify that while we are here.
2023-05-22 21:20:18 -04:00
Eli Schwartz af49e8010b
i18n module: be broadly supportive of portable gettext tools
There are a number of implementations for msgfmt, supporting various
options. The simplest, and most common, use case is to compile .po files
into .mo files, and this should be able to work on gettext
implementations other than the GNU one.

The problem is that we were passing some pretty portable arguments in an
unportable manner. The `-o` option-argument and its associated argument
came after the input file operand, which violates the POSIX Utility
Syntax Guidelines, and happens to not be supported by Solaris gettext.
The GNU gettext doesn't care; GNU invented GNU argument permutation.

Switch the order around so that our use respects the POSIX style.
2023-05-22 21:20:18 -04:00
Corentin Noël e0792f4819 modules/i18n: fix typo in gettext decorator 2023-03-16 14:20:26 -04:00
Dylan Baker 4c3d9ab22d modules/i18n: fix type annotations
Again, state.find_program is wrong
2023-01-10 09:53:22 -08:00
Eli Schwartz 100456de07
fix broken fs.copyfile function that crashed if you tried to use it
At least, if you tried to use it when passing an install_dir. Because
T.Sequence is horrible and we should never use it, and the annotations
are a lie that produces bugs.

So, fix the annotations on CustomTarget to never allow this to happen
again, and also fix the function too. Move some definitions elsewhere
inline to satisfy the linter.

Fixes #11157
2022-12-11 18:28:39 -05:00
David Ward 68add86f7b i18n: Fix source root in Gettext targets for subprojects
Gettext should search for input files relative to the (sub)project
source root, not the global source root.

This change exposes a root_subdir member in ModuleState.
2022-09-12 00:27:21 -04:00
Dylan Baker 6843f56f6b modules: use module level information about new and deprecation
Instead of using FeatureNew/FeatureDeprecated in the module.

The goal here is to be able to handle information about modules in a
single place, instead of having to handle it separately. Each module
simply defines some metadata, and then the interpreter handles the rest.
2022-08-17 16:25:36 -04:00
Eli Schwartz 1eaf49c880 flake8: remove no longer used imports 2022-06-10 09:15:48 -04:00
Dylan Baker 618b187f70 interpreter: use a shared KwargInfo for install_dir
CustomTarget allows multiple install dirs, while basically everything
else allows only one. So this provides a shared instance for that.
2022-06-01 22:49:10 -04:00
Eli Schwartz c88a1dc55c
fix bug in i18n merge_file/itstool_join revealed by previous commit
Logically, i18n.merge_file cannot ever take a MULTI_OUTPUT_KW, but it
does take a CT_OUTPUT_KW-like interface.

Actually trying to pass multiple merge_file outputs causes the
msgfmthelper script to be entirely malformed in the arguments it
accepts, and treat the broken one like a --flag, then exit with argparse
errors.

Even if we somehow assumed that somehow it was designed to actually
allow this, msgfmt doesn't support conceptually passing multiple outputs
so that would be a msgfmt error instead of an error inside the guts of
`meson --internal msgfmthelper`.

Same logic applies again for the itstool command and the itstool
internal helper.

Catch this error at configuration time by using the single-output kwarg
form.

Likewise, it's totally nonsense to accept multiple install_dir or
install_tags, and ever since commit 11f9638035
the CustomTarget itself won't even check this.
2022-05-31 17:49:29 -04:00
Eli Schwartz 52d01dbf38
rename a badly named KwargInfo
CT_OUTPUT_KW is the same OUTPUT_KW we use in lots of places. The most
distinctive thing about it is not that it's part of custom_target
(basically any other function that uses such a kwarg follows the same
rules due to using CustomTarget under the hood), but the fact that it
takes multiple outputs.
2022-05-31 17:49:29 -04:00
Eli Schwartz 915a468ed3
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.
2022-05-29 18:23:03 -04:00
Eli Schwartz de2c091ba6
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
2022-05-29 18:23:03 -04:00
Eli Schwartz 34da721ec2
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.
2022-05-29 18:23:03 -04:00
Eli Schwartz fdcc566590
i18n: don't let our maintainer targets run via wrapped env
They are RunTargets because they are one-shot commands without outputs.
But we implement them purely via our internal wrapper for gettext, so
there is no reason to wrap them *again* in our internal wrapper for
meson_exe and set a bunch of environment variables we know we absolutely
do not need, use, or want.

This avoids the ugly "wrapped due to env" status, and allows users to
directly see the command being run without going into despair at obscure
pickled nonsense.

It also offers a tiny defense against upgrading Meson without
reconfiguring. People should not do that, and we error out about this in
a bunch of places, but `--internal gettext` has a perfectly stable
interface just like most build tools that aren't part of Meson
internals, since it uses command line arguments instead of pickling.
2022-03-31 22:52:31 -04:00
Xavier Claessens e33ec88ac7 Pass environment down to base Target class 2022-03-29 16:10:28 -04:00
Eli Schwartz 8b573d7dc6
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
2022-03-06 11:09:56 -05:00
Eli Schwartz 1f3640c7db
i18n module: report initial call site when disabling translation support 2022-03-06 11:09:56 -05:00
Eli Schwartz 08928821ec
i18n module: detect gettext tools at configure time
Use this instead of shutil.which to detect whether they will be
available, and pass the ExternalProgram object to CustomTarget
invocations, or else make use of the new functionality to specify the
correct program path in wrapper scripts.

Drop duplicate reporting for itstool missing. Since we use find_program
in required mode, its absence is already fatal, and already has a really
good error description.
2022-03-06 11:09:47 -05:00
Eli Schwartz e67fd1f551
i18n module: fix bug that made msgfmthelper die on combinations of args
Due to misuse of argparse in commit 82492f5d76
it was impossible to use both --datadirs and extra args passed directly
to msgfmt at the same time.

I'm not sure anyone actually knows how argparse works, so misusing it is
easy. What is definitely known is that argparse is NOT a POSIX compliant
parser and doesn't behave the way you'd expect a standards based parser
to handle options. Instead it caters to the easy use case, and hopes and
prays you don't need to do anything too complicated "with the wrong kind
of complicated".

Apparently, this particular type of complicated is when you have mixed
option_arguments and operands while simultaneously passing some operands
as nargs after a --.

It totally breaks, and interprets --datadirs, which is supposed to be an
option_argument, as an operand, eats it up as a msgfmt wrapped argument,
and breaks.

But if you don't pass additional arguments with -- then it interprets
--datadirs after operands as an option_argument. This is what we were
doing.

Instead pass option_arguments before all operands (including the ones
specified via `-- ...`). Add test case to pass meaningless datadirs (we
don't actually care if $GETTEXTDATADIRS is set to something that doesn't
contain gettext data).
2022-03-06 10:48:34 -05:00
Dylan Baker 11f9638035 build: replace kwargs in CustomTarget initializer
Because we don't want to pass the Interpreter kwargs into the build
layer. This turned out to be a mega commit, as there's really on elegant
way to make this change in an incremental way. On the nice side, mypy
made this change super easy, as nearly all of the calls to
`CustomTarget` are fully type checked!

It also turns out that we're not handling install_tags in custom_target
correctly, since we're not converting the boolean values into Optional
values!
2022-01-28 15:53:20 -05:00
Eli Schwartz 3990dc6d64 flake8: fix indentation style 2022-01-27 10:48:01 -08:00
Eli Schwartz 603244b059
fix broken version annotations for the new itstool_join feature
It was not added in 0.61.0 as that was already released.
2022-01-22 22:11:32 -05:00
Matthias Klumpp 02fb0c3f8b i18n: Add support for joining XML localization via itstool 2022-01-21 22:26:17 +01:00
Matthias Klumpp efd7c7f228 i18n: Fix typo for typed_pos_args 2021-12-18 04:43:19 +01:00
Eli Schwartz 172fa4d3b2
i18n module: correctly annotate the availability of data_dirs
It was originally forgotten in merge_file() and later added for parity
with gettext(). This means that the FeatureNew for each function is
different.
2021-12-02 12:29:58 -05:00
Xavier Claessens 018d928cf5 i18n: Fix backtrace when missing input kwarg
When input kwarg is missing in i18n.merge_file() it was crashing with a
backtrace because of kwargs['input'][0]. That code was useless anyway
because CustomTarget now uses first output as default name which is what
we need here.
2021-11-16 23:35:46 -05:00
Eli Schwartz d06cc042eb
f-strings 2021-10-04 16:29:32 -04:00
Dan Streetman 3c2cca5699 modules/i18n: fix gettext use of --datadirs param
The previous commit bd2fcb268b
accidentally used the wrong var so the param name was missing,
leading to an error of "unrecognized arguments" for the
datadirs parameter value.
2021-10-03 16:23:46 -04:00
Dylan Baker bd2fcb268b modules/i18n: Fix remaining mypy spotted issues 2021-09-30 16:09:14 -07:00
Dylan Baker 6399544e4c modules/i18n: use typed_kwargs for gettext
There were two allowed kwargs that were unused, I've dropped them for
now, though I need to check if they were documented. If they are then we
need to deprecate them to remove them, otherwise we'll just leave them
removed.
2021-09-30 16:09:14 -07:00
Dylan Baker 6b1a80024c modules/i18n: Use typed_kwargs for merge_file 2021-09-30 16:09:14 -07:00
Dylan Baker 61f2866a9f modules/i18n: use typed_pos_args 2021-09-30 16:09:14 -07:00
Dylan Baker b923163109 modules/i18n: add easy type annotations 2021-09-30 16:09:14 -07:00
Dylan Baker 57d0d4e95a modules/i18n: sort and clean up imports 2021-09-30 16:09:14 -07:00
Eli Schwartz 1dbb6d6b8c
make the display name of a gettext translation build, look prettier
And more accurate too, TBH. Currently it says it is building "lang.mo",
even though it is actually building "domain.mo" inside
lang/LC_MESSAGES/.

Since meson loudly complains if I try to name the display name
"lang/domain.mo", name it with a dash instead of a slash. The actual
name isn't a priority here IMO, and this is nicely readable.
2021-09-01 21:18:44 -04:00
Eli Schwartz 22c38a0006
i18n module: restore the <packagename>-gmo target
Removed in commit 487d45c1e5 but perhaps
it should not have -- people may have been depending on ensuring those
are built somehow. Even though the internal implementation changed and
it is now built by the all target, let's keep the old target around too.

Now it just aliases the actual build rules, though.
2021-08-31 23:37:33 -04:00
Eli Schwartz 2fc7592e13
i18n module: provide targets as return value for gettext()
Users may wish to make use of these files for their own purposes.

For example, the -pot and -update-po pseudo targets could be reused in
an alias_target(), and at least one person wanted to reuse the built .mo
files as custom_target input.

Fixes #6227
2021-08-31 23:37:33 -04:00
Xavier Claessens 8c5aa031b5 Add install tags
Fixes: #7007.
2021-08-17 15:19:18 -04:00
Xavier Claessens 223991c09e Fix i18n target name when using @BASENAME@ and configure_file() input
Fixes: #9022
2021-08-09 19:43:45 -04:00
Eli Schwartz 487d45c1e5
i18n: use real build/install targets for gmo files
Don't just create a .PHONY target which runs a script that magically
generates files ninja doesn't know about. It results in untracked files,
and `meson install` has to run additional commands instead of copying
over files, and then cannot track them to uninstall them later.

I'm not even really sure why it was originally done via a proxy script,
most likely bad legacy design. This is after all one of the oldest
modules...

One side effect of this is that meson doesn't know how to rename
build.CustomTarget files on install (only data files are supported?),
and every file needs to be installed as "domainname.mo" so it must be
named that in-tree too. To prevent clashes, every locale gets its own
locale-specific subdirectory.

Once we are doing that anyway, we can output them to the actual
structure required by the gettext family of functions, and
bindtextdomain() can therefore point to this location if desired. This
might be useful for running localized programs from the build tree.
2021-08-09 18:25:17 -04:00
Daniel Mensinger 34c28dc92c holders: remove unholder 2021-06-18 23:48:33 +02:00
Xavier Claessens 2e02ef6592 modules: Add methods dict everywhere
This fix calling random internal methods from meson.build as long as
they were not prefixed by underscore.
2021-05-28 15:17:10 -04:00
Xavier Claessens a734bcfc83 modules: Stop using ModuleReturnValue where it's not needed
It is only needed in functions that need to add targets to the
interpreter.
2021-05-28 15:17:10 -04:00
Eli Schwartz 6a0fabc647
mass rewrite of string formatting to use f-strings everywhere
performed by running "pyupgrade --py36-plus" and committing the results
2021-03-04 17:16:11 -05:00
Xavier Claessens 522392e755 run_target: Add env kwarg
Re-implement it in backend using the same code path as for
custom_target(). This for example handle setting PATH on Windows when
command is an executable.
2021-02-05 17:53:09 -05:00
Xavier Claessens 0626465ea8 Fix executable as script on Windows
On Windows this would fail because of missing DLL:
```
mylib = library(...)
exe = executable(..., link_with: mylib)
meson.add_install_script(exe)
```

The reason is on Windows we cannot rely on rpath to find libraries from
build directory, they are searched in $PATH. We already have all that
mechanism in place for custom_target() using ExecutableSerialisation
class, so reuse it for install/dist/postconf scripts too.

This has bonus side effect to also use exe_wrapper for those scripts.

Fixes: #8187
2021-01-30 09:51:06 +00:00
Dylan Baker e81acbd606 Use a single coredata dictionary for options
This patches takes the options work to it's logical conclusion: A single
flat dictionary of OptionKey: UserOptions. This allows us to simplify a
large number of cases, as we don't need to check if an option is in this
dict or that one (or any of 5 or 6, actually).
2021-01-04 12:20:58 -08:00