git/list[1] front-page[2] threads[3] people[4] search[5] about
 

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
Previous: Patrick SteinhardtNext: Junio C Hamano
Message 5 of 9 in “Meson build leaks host 'sh' path to target build when cross-compiled”
  1. Peter SeidererFeb 9, 2025
  2. Patrick SteinhardtFeb 10, 2025
  3. Peter SeidererFeb 10, 2025
  4. Patrick SteinhardtFeb 18, 2025
  5. Eli SchwartzFeb 18, 2025
  6. Junio C HamanoFeb 10, 2025
  7. Peter SeidererFeb 10, 2025
  8. Junio C HamanoFeb 10, 2025
  9. Peter SeidererFeb 11, 2025

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.