[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Multiarch qualification of GCC cross-compiler packages



Hi John,

On Sun, Apr 27, 2025 at 03:31:19AM +0000, John Scott wrote:
> The situation with GCC plugins sounds similar to the 'gotcha' with CPython (although I'm not familiar enough with Python to understand the catch there). GCC plugins, I believe, are shared objects, and if a user or developer has any intention of using a GCC plugin, however it be supplied, then they absolutely *would* care about the architecture of the cross-compiler itself. If one has a foobarf.so for x86_64 you wish to use as a GCC plugin, gcc-sh-elf:i386 isn't going to cut it anymore because it won't be able to load the shared object, and there's no way for a reverse build dependency to say "Yes, I really *am* sure I need the native gcc-sh-elf this time" when gcc-sh-elf is Multi-Arch: foreign.
> My understanding is this is the very rare problem Multi-Arch: allowed is intended to solve: a typical reverse build dependency (like carl9170fw which builds SuperH firmware) that has no intention of using any esoteric GCC plugin can say 'Build-Depends: gcc-sh-elf:any', for gcc-sh-elf won't be used in any way that'd expose its own architecture; but if a reverse build dependency really needs to use a GCC plugin (maybe a video game emulator wants to use a plugin to implement special C #pragma directives for building a Sega Dreamcast demo game?), this is actually a decent reason to care about the architecture of the cross-compiler binary itself, and saying 'Build-Depends: gcc-sh-elf:native' will force it to converge on the "native" architecture.
> If I'm not mistaken, this is probably the reason GNU Make in the 'make' package is Multi-Arch: allowed. Recent versions of GNU Make support plugins a la dlopen(), but the majority of GNU Make users won't need to play with that. This probably isn't as visible because GNU Make is build-essential, so this isn't as painful as it could be.
> 
> So, do I understand right that as long as gcc-sh-elf and similar cross-compilers support GCC plugins, adding Multi-Arch: allowed is actually justified and more correct? And if that's right, why is gcc-x86-64-linux-gnu:arm64 (for example) Multi-Arch: foreign? Could this have flown under the radar?

I fear your observation and interpretation is spot-on.

The same situation was encountered for binutils. I originally marked
binutils-<triplet> M-A:foreign. If you look closely, you see that it now
is M-A:allowed instead. For implementing link time optimization, gcc
installs a linker plugin and that in turn means that gcc actually cares
about the architecture of the ld executable that will end up loading
gcc's plugin.

As far as I can tell, there presently are no gcc plugins packaged as
Debian packages. If you were to package or on-demand build one for
another build, you'd likely have to depend on gcc-VER-plugin-dev. That'd
pull in gcc-VER which would end all attempts to cross build anything.

So yeah, in principle we should be changing the M-A field in toolchain
packages. The practical effects would be disastrous to cross compilation
though. I guess for the time being, the lie is more useful practically
speaking than fixing it. Technically speaking, libc6-dev must not be
M-A:same and linux-libc-dev must not be M-A:foreign. If we were to fix
those, we'd break all attempts to cross build anything.

This is not meant to say that we should not fix this. It is saying that
we should be careful to select a cure that isn't worse than the disease
though. I appreciate practical proposals.

In very general terms, I more and more reach the conclusion that
M-A:allowed rarely works well, because :any fails to communicate the
intent. M-A:allowed does not technically give us anything that we
couldn't get otherwise. If you have

    Package: spam
    M-A: allowed

you could refactor that into

    Package: spam-arch-api
    M-A: no

    Package: spam-indep-api
    Architecture: all
    M-A: foreign
    Depends: spam-arch-api

and then rewrite spam into spam-arch-api and spam:any into
spam-indep-api. For instance with make, such a split would allow us to
use descriptive names such as "make" (for make:any) and make-plugin-abi
(for make) and a lot more people would get their dependency right
intuitively.

This observation makes me wonder whether we may want to consider a more
fundamental change to the multiarch mechanics. Suppose we were extending
dpkg to accept :any inside a Provides field such that a provided package
with a :any qualifier would be treated as if that virtual package (but
not the real package) were marked M-A:foreign. At that point we could
rephrase the make example above as a single real package.

    Package: make-plugin-api
    Architecture: any
    M-A: no
    Provides: make:any (= ${binary:Version})

The gcc plugin story would become solvable in a very similar way.

Such fundamental changes to our packaging ecosystem take multiple
releases to trickle down though so you only get to see the benefits like
five years from when you started.

Helmut


Reply to: