Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multi-arch ELF dependency generation (v6 packages) #3578

Draft
wants to merge 9 commits into
base: master
Choose a base branch
from

Conversation

pmatilai
Copy link
Member

Traditional rpm dependencies have only supported biarch style installations between 64bit and "something else", traditionally of course 32bit. This has been denoted with (64bit) markers at the end of ELF dependency tokens for some 64bit architectures and for others not, and lets a dependency token of a completely different architecture satisfy that of another. This is inconsistent and limiting at best.

Add a new multiarch mode for elfdeps where each ELF dependency token carries an ABI identifier consisting of the base architecture, it's bitness and endiananess, optionally followed by arch-specific flags. v4 packages continue to use the traditional biarch dependencies, for v6 packages we use the new multiarch style. It's possible to generate
both for transition-period compatibility though.

The last patch is the where the real interest is, the earlier ones are just preliminaries to make this all nicer by converting it to use C++ facilities. There are no docs and the exact format is subject to change, but posting a draft PR to allow experimenting and hopefully inviting a wider community discussion on this.

Fixes: #2197

Do away with the silly typedef while at it.
Rename addDep() to addSoDep() to hint at the intended use, and add
a bare version of addDep() that has no extra logic. It's a thin layer
of isolation but isolation nevertheless. No functional changes.
Allegedly no functional changes.
Don't bother checking for non-empty soname in the callers, addSoDep()
will check for this anyhow.
The marker and ver don't *need* to be STL strings, but life is simpler
if they all follow the same conventions. Just pass empty strings in
place of NULL now and adjust the logic accordingly.
Traditional rpm dependencies have only supported biarch style
installations between 64bit and "something else", traditionally of
course 32bit. This has been denoted with (64bit) markers at the end of
ELF dependency tokens for some 64bit architectures and for others not,
and lets a dependency token of a completely different architecture
satisfy that of another. This is inconsistent and limiting at best.

Add a new multiarch mode for elfdeps where each ELF dependency token
carries an ABI identifier consisting of the base architecture, it's
bitness and endiananess, optionally followed by arch-specific flags.
v4 packages continue to use the traditional biarch dependencies, for
v6 packages we use the new multiarch style. It's possible to generate
both for transition-period compatibility though.

Inspired by and loosely based on an earlier patch by Neal Gompa.

Fixes: rpm-software-management#2197
@Conan-Kudo
Copy link
Member

Could you describe a couple of examples of output so I can visualize this better?

@pmatilai
Copy link
Member Author

There are many sample outputs in the test-cases, but here's a few more :

[pmatilai🎩︎lumikko _build]$ ./tools/elfdeps -R --multiarch /tmp/libxml2.so.2.9.9|head -2
libz.so.1(ZLIB_1.2.3.3)(aarch-64l)
libz.so.1(ZLIB_1.2.2.3)(aarch-64l)
[pmatilai🎩︎lumikko _build]$ ./tools/elfdeps -R --multiarch /tmp/a2jmidi_bridge |head -2
libgcc_s.so.1(GCC_3.5)(arm-32l-h)
ld-linux-armhf.so.3(GLIBC_2.4)(arm-32l-h)
[pmatilai🎩︎lumikko _build]$ ./tools/elfdeps -R --multiarch /tmp/libAllegroOGG.so.0 |head -2
libc.so.6(GLIBC_2.3)(ppc-64b)
libogg.so.0()(ppc-64b)
[pmatilai🎩︎lumikko _build]$ ./tools/elfdeps -R --multiarch /bin/rpm |head -2
libpopt.so.0(LIBPOPT_0)(x86-64l)
libc.so.6(GLIBC_ABI_DT_RELR)(x86-64l)

@Conan-Kudo
Copy link
Member

So very similar to what I did for #1038, then.

@pmatilai
Copy link
Member Author

Yup - said as much in the commit too.

@pmatilai
Copy link
Member Author

The main "innovation" here is really the per-arch flags which allow the rest of the string to be easily generated from the ELF content directly, without needing special code logic and oddities like the x32 thing that made you weep in your version 😅

@Conan-Kudo
Copy link
Member

😆

@voxik
Copy link
Contributor

voxik commented Feb 18, 2025

Will this include some tooling to also solve the "requires" side? To help with cases such as https://src.fedoraproject.org/rpms/rubygem-ruby-vips/blob/137e3adee00c987c5c0b9f2d746ffb8b415f930b/f/rubygem-ruby-vips.spec#_24-25

Copy link
Member

@Conan-Kudo Conan-Kudo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, this is great, just some small stuff about the flags to debate.

Comment on lines +125 to +126
{ ELFDATA2LSB, "l" },
{ ELFDATA2MSB, "b" },
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I still prefer le and be here.

Comment on lines +137 to +140
if ((ehdr->e_flags & EF_ARM_ABI_FLOAT_HARD) == EF_ARM_ABI_FLOAT_HARD)
flags += "h";
if ((ehdr->e_flags & EF_ARM_ABI_FLOAT_SOFT) == EF_ARM_ABI_FLOAT_SOFT)
flags += "s";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Likewise hf and sf here.

Copy link
Member Author

@pmatilai pmatilai Feb 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The point with the flags field is that they're all single-letter items so you can have the whole alphabet's worth of them. Humans are not the primary intended audience of these dependency values, it's enough that a human can easily compare two values to see if they differ. The meaning of these flags of course needs to be documented, I'll try to add a doc blurb today to make it easier to see what's what.

static void x86flags(GElf_Ehdr *ehdr, std::string & flags)
{
if (ehdr->e_machine == EM_X86_64 && ehdr->e_ident[EI_CLASS] == ELFCLASS32)
flags += "x";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, is this means we get x86-64x? I'm not sure this makes any sense over using -x32 here and getting x86-64-x32 as the value.

Copy link
Member Author

@pmatilai pmatilai Feb 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No no. You get "x86" from as the arch, "32" as the bits, "l" for endianess and "x" as a flag, so it becomes: x86-32l-x

In comparison, good ole i?86 is just x86-32l and x86_64 is, well, x86-64l.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I see. That makes more sense.

@pmatilai
Copy link
Member Author

pmatilai commented Feb 19, 2025

Will this include some tooling to also solve the "requires" side? To help with cases such as https://src.fedoraproject.org/rpms/rubygem-ruby-vips/blob/137e3adee00c987c5c0b9f2d746ffb8b415f930b/f/rubygem-ruby-vips.spec#_24-25

noarch -> arch dependencies are technically a different problem than this is trying to solve, for which we simply don't have any good solutions atm.

Thanks for the reminder though - as is, this would actually the manual soname dependency in the example N times worse because then have to list all the variants. IMO the least worst solution (that works with any rpm version) is to drop the BuildArch: noarch in these cases.

@pmatilai
Copy link
Member Author

pmatilai commented Feb 19, 2025

Another random note of the day: %{_isa} macros (and thus the provides too) should actually use the same values as these markers.

@pmatilai
Copy link
Member Author

FWIW, I opened a new ticket for the noarch -> arch dependency matter, let's discuss that topic there: #3579

I could've sworn we had a ticket or more like five for that already, but couldn't find any. Well, now we do.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

RFE: multi-arch dependencies
3 participants