Fix compatibility with current GNU Make (and Ubuntu 26.04) - #4929
Conversation
|
This still doesn't fix 26.04, because the compiler there doesn't like something in libelf: |
|
This will need vgteam/structures#15 and vgteam/libbdsg#242 |
|
I don't think we'll be able to get the Docker build logs from CI without fixing or working around greg7mdp/sparsepp#98. When I run the Docker build locally on my Mac I get a complaint at the final link step that there's something wring with This happens even if I stick a |
|
If we want the Docker to ship a static binary, which we pull out and use for our static ARM release and for putting in a new, smaller Docker container, then we can't upgrade past 22.04 until https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1104888 is fixed and shipped in an Ubuntu release, since in 24.04 and on Ubuntu no longer packages a Or else we need to pull in Cairo as a submodule or otherwise provide a source build of Cairo for the Docker container. |
|
OK I have no idea why the docs build job can't find vgteam/libbdsg@5429995 which is merged in over there. And it looks like the updated libelf is not happy back on 22.04? I will have to come back to this. |
This still doesn't work for a static build on the same system, because when Cairo calls into pixman to try and draw a png, it crashes because its thread-local storage is not there. Something is wrong with thread-local storage when loading the synamic libc on top of the existing static libc, somehow. The code to dynamically load Cairo works fine when libc itself is dynamically linked. But there's no way to build for a dynamically-linked libc from a system with a newer libc than the one you want to run on; glibc can't do this. Also when you dlopen and the wrong libc.so is there it does exciting signals instead of giving you a null result like dlopen is meant to do when it doesn't work, so you can't actually poll for the right libc at runtime.
This partly reverts 8732a33 and recursively clones all the submodules at the start of the docs build, which *should* play more nicely with whatever Gitlab is doing to the Git config.
|
I have finally fixed the docs job, but my approach makes the docs job almost twice as long as the fix in #4870. So we probably want to use that one when they conflict. |
|
There's still a problem where the Meson in the CI base image is too old to build Cairo/pixman. I think I need to also switch the CI prebake image over to a newer Ubuntu. |
The submodule restore was against the pin #4929 was carrying, 0.195, but the build rule and link line were the ones written for 0.186. 0.195 splits code out into two libraries that were not there before, so the static link fails on symbols that used to resolve: lib/libeu.a eu_search_tree_init, eu_tfind, ... libdwfl_stacktrace/libdwfl_stacktrace.a dwflst_tracker_cache_elf libdw, libelf and libdwfl all call the eu_* tsearch wrappers, added upstream in 2024 for thread safety; libdwfl calls dwflst_tracker_cache_elf from open_elf. Both libraries were already being built by the rule -- libeu because libcpu and backends need it -- but neither was installed into lib/ or passed to the linker. -leu goes last since libeu calls back into none of them. This is most likely why #4929 gave up on the submodule in the first place: b87ebaa bumped elfutils 0.186 -> 0.195 a few commits earlier in the same PR, which would have broken the link exactly like this, and switching to the system libdw makes it go away without having to work out why. Verified on Ubuntu 26.04 (Make 4.4.1, gcc 15.2, glibc 2.43), building elfutils from clean: without -leu the link reproduces the reported eu_search_tree_init failures, with it and -ldwfl_stacktrace it links, and the resulting static binary has no libdebuginfod.so string and runs on a glibc 2.39 host.
#4929 swapped the deps/elfutils submodule for the system libdw, dropping the --disable-libdebuginfod --disable-debuginfod it was configured with, and the comment saying why: We need to disable libdebuginfod or the static binary will try and load it at runtime and pull in incompatible libs it depends on on whatever system it's running on. Distro libdw has debuginfod enabled, and elfutils dlopens libdebuginfod.so.1 from a constructor before main. In a -static binary that maps the host's libc.so.6 in beside the one we linked and dies in __ctype_init, so every invocation segfaults. v1.76.0 does this on a glibc 2.39 host; v1.75.1, the last release before the change, does not. Restoring the rule also needs the two libraries 0.195 split out and the 0.186 layout it was written for did not have: libeu (eu_tsearch and friends) and libdwfl_stacktrace (dwflst_tracker_cache_elf). Both were already built by the rule, neither was installed or linked. That is probably why #4929 gave up on the submodule, since b87ebaa bumped 0.186 -> 0.195 a few commits earlier and would have broken the link exactly this way. Verified by a full static build from clean on Ubuntu 26.04 (GNU Make 4.4.1, gcc 15.2, glibc 2.43) and on 22.04: no libdebuginfod string in the binary, and it runs on a glibc 2.39 host where both v1.76.0 and an unpatched local build segfault.
#4929 swapped the deps/elfutils submodule for the system libdw, dropping the --disable-libdebuginfod --disable-debuginfod it was configured with, and the comment saying why: We need to disable libdebuginfod or the static binary will try and load it at runtime and pull in incompatible libs it depends on on whatever system it's running on. Distro libdw has debuginfod enabled, and elfutils dlopens libdebuginfod.so.1 from a constructor before main. In a -static binary that maps the host's libc.so.6 in beside the one we linked and dies in __ctype_init, so every invocation segfaults. v1.76.0 does this on a glibc 2.39 host; v1.75.1, the last release before the change, does not. Restoring the rule needs the two libraries 0.195 split out and the 0.186 layout it was written for did not have: libeu (eu_tsearch and friends) and libdwfl_stacktrace (dwflst_tracker_cache_elf). Both were already built by the rule, neither was installed or linked. The submodule points at github.com/vgteam/elfutils, not sourceware, which answers the CI runners' shared IPs with HTTP 429 on the recursive submodule fetch and fails the job before it compiles anything. Same commit, mirrored. Verified by a full static build from clean on Ubuntu 26.04 (GNU Make 4.4.1, gcc 15.2, glibc 2.43) and on 22.04: no libdebuginfod string in the binary, and it runs on a glibc 2.39 host where both v1.76.0 and an unpatched local build segfault.
Changelog Entry
To be copied to the draft changelog by merger:
make get-deps.Description
GNU Make removed the hack we were using to run a rule at Makefile startup (claiming that it would generate an include-able Makefile fragment, marking it
.PHONYso it would always run, and telling Make not to complain if the file to be included didn't exist). It's not mentioned in the project'sNEWSfile, but it happened between 4.3 and 4.4.1.This converts half of that target to
$(shell )calls (the half that needs a bunch of Make-level variables), and the other half to a shell script (the half where we need to enforce success).