Re: Meson build leaks host 'sh' path to target build when cross-compiled
- From
Eli Schwartz <eschwartz@gentoo.org>
- Date
- Feb 18, 2025, 14:41 UTC
- Message-ID
- <24df8aa2-760f-4da3-88b0-ab97796373fd@gentoo.org>
- In-Reply-To
- <Z7RzPkiBfbYPhKp_@pks.im>
On 2/18/25 6:47 AM, Patrick Steinhardt wrote:
Show 74 quoted lines
> On Mon, Feb 10, 2025 at 12:26:03PM +0100, Peter Seiderer wrote:
>> On Mon, 10 Feb 2025 08:41:18 +0100, Patrick Steinhardt <ps@pks.im> wrote:
>>> On Sun, Feb 09, 2025 at 01:30:27PM +0100, Peter Seiderer wrote:
>>> [snip]
>>>> The meson build tries to execute the non-existent '/usr/bin/sh' (instead of
>>>> '/bin/sh' as the autoconf build), 'which sh' on the host returns
>>>> '/usr/bin/sh'...
>>>>
>>>> From meson.build
>>>>
>>>> [...]
>>>> 186 shell = find_program('sh', dirs: program_path)
>>>> [...]
>>>> 685 '-DSHELL_PATH="' + fs.as_posix(shell.full_path()) + '"',
>>>>
>>>> Do not use the result of 'find_program('sh',...)' for '-DSHELL_PATH='
>>>> (at least not for cross-compile), use fix '/bin/sh' instead or make it
>>>> configurable via a meson option?
>>>
>>> Hm, very true. We're mixing up concerns here by treating the build
>>> environment and the target environment the same.
>>>
>>> I guess the proper fix is to wire up the "native:" parameter when we
>>> call `find_program()`, which allows us to tell Meson whether it should
>>> find an executable for the build or the target host. And then, for those
>>> binaries where we actually need to know about both the build and target
>>> host's locations, we'd end up calling `find_program()` twice.
>>>
>>> For executables that are supposed to be used on the target host Meson
>>> would then know to first consult the cross file, which could look like
>>> this:
>>>
>>> [binaries]
>>> sh = '/target/path/to/sh'
>>> perl = '/target/path/to/perl'
>>>
>>> Meson would then pick up that file via `meson setup --cross-file
>>> <CROSSFILE_PATH> <BUILDDIR>`.
>>
>> Sorry, I believe this will not work..., the description of the native
>> parameter in find_program ([2]) on the first sight sounds like doing the
>> right thing, but as far as I read the 'Cross compilation' page ([3], [4]) the
>> tools under the '[binaries]' section are the tools used while cross-compiling
>> (running on the build machine) and not the paths/tools on the target
>> (or as meson nomenclature host/target)...
>
> Quoting the documentation of `find_program()`'s `native` parameter [1]:
>
> Defines how this executable should be searched. By default it is set to
> false, which causes Meson to first look for the executable in the cross
> file (when cross building) and if it is not defined there, then from the
> system. If set to true, the cross file is ignored and the program is
> only searched from the system.
>
> So I think this should work as expected when passing the file via
> `--cross-file`, shouldn't it? If we are cross-compiling we'd find the
> target binaries via the cross file when `native: false`, which is
> exactly what we want.
>
> But I see what you're saying. The _intent_ is to specify the environment
> of the cross-compiling environment, and not to describe the target
> environment.
>
> I can think of two alternatives:
>
> - We can introduce build options for this. If unset, we continue to
> use the result of `find_program()`. Otherwise, we use the value
> specified by the user.
>
> - We can introduce properties into the cross file that allow the user
> to specify those parameters. We can then retrieve them by calling
> `meson.get_external_property()`, but only when cross-compiling.
>
> Let me also Cc Eli, he might have an opinion on how to do this.For the specific case of detecting sh, the portable "API filename" is exactly /bin/sh and nothing else. It should always exist on pretty much any unix system ever... except for the ones where it exists but is a pre-POSIX shell and the actual POSIX one isn't always on PATH at all. Hi there, Solaris /usr/xpg4/bin/sh ! :)
Overriding it via the cross file would be fine -- if your goal is to only ever find_program(..., native: false) in order to detect a path and embed it, then it doesn't matter whether cross files are for running cross tools on the build machine or for looking up cross tools to detect a path and embed it, since the two goals would never *come into conflict*. And that's what actually matters -- if you are concerned that cross files will be wrong as they specify the cross-compile environment not the install environment, then you shouldn't be using find_program() either, you should be exclusively using build options.
But again -- that's the general case, and for the specific case you should be defaulting to /bin/sh
This does have a highly practical application to it. Gentoo supports split-usr systems, and binary package support needs to consistently use paths that are present on both merged- and split-usr systems. There is no /usr/bin/sh on a split-usr system, but on a merged-usr system they are the same directory, so it will exist "anyway".
Note that this is NOT a cross compile environment. I'm compiling for the current x86-64 environment, but also tarring it up for installation on other x86-64 environments that happen to use a different filesystem partition scheme.
Cc Sam as we will need to fix this in our Gentoo packaging one way or another:
$ ebuild git-2.48.1.ebuild clean install [...] $ ag usr/bin /var/tmp/portage/dev-vcs/git-2.48.1/image
It is finding and embedding various hits for /usr/bin/sh because I happened to build on a merged-usr profile.
-- Eli Schwartz