Skip to content

Fix compatibility with current GNU Make (and Ubuntu 26.04) - #4929

Merged
adamnovak merged 40 commits into
masterfrom
fix-new-make
Jun 24, 2026
Merged

adamnovak merged 40 commits into
masterfrom
fix-new-make

Conversation

@adamnovak

@adamnovak adamnovak commented Jun 11, 2026

Copy link
Copy Markdown
Member

Changelog Entry

To be copied to the draft changelog by merger:

  • vg now builds with GNU Make 4.4.1, as on Ubuntu 26.04
  • vg now uses system libelf/libdw
  • vg now ships its own Cairo and pixman libraries as submodues, to enable static builds on modern Ubuntu. These build with Meson; if needed, a new enough Meson will be installed on older Ubuntu via pipx by make get-deps.
  • Reverted Pin back binfmt to work around https://github.com/tonistiigi/binfmt/issues/298 #4926 due to crashes in the compiler in the emulated builds
  • vg Docker containers are now built on top of Ubuntu 26.04

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 .PHONY so 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's NEWS file, 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).

@adamnovak adamnovak changed the title Fix compatibility with Ubuntu 26.04 and current GNU Make Fix compatibility with current GNU Make Jun 11, 2026
@adamnovak

Copy link
Copy Markdown
Member Author

This still doesn't fix 26.04, because the compiler there doesn't like something in libelf:

riscv_disasm.c: In function 'riscv_disasm':
riscv_disasm.c:1259:46: error: initialization discards 'const' qualifier from pointer target type [-Werror=discarded-qualifiers]
 1259 |                   struct known_csrs *found = bsearch (&key, known,
      |                                              ^~~~~~~

@adamnovak

Copy link
Copy Markdown
Member Author

This will need vgteam/structures#15 and vgteam/libbdsg#242

@adamnovak

Copy link
Copy Markdown
Member Author

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 libvcfh.a:

3.971 /usr/bin/aarch64-linux-gnu-ld.bfd: /vg/lib/libvcfh.a: error adding symbols: archive has no index; run ranlib to add one
3.990 collect2: error: ld returned 1 exit status
3.990 make: *** [Makefile:551: lib/vg_is_static] Error 1

This happens even if I stick a ranlib call into the command used to build it.

@adamnovak

adamnovak commented Jun 12, 2026

Copy link
Copy Markdown
Member Author

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 libcairo.a anywhere.

Or else we need to pull in Cairo as a submodule or otherwise provide a source build of Cairo for the Docker container.

@adamnovak

Copy link
Copy Markdown
Member Author

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.
@adamnovak adamnovak changed the title Fix compatibility with current GNU Make Fix compatibility with current GNU Make (and Ubuntu 26.04) Jun 23, 2026
@adamnovak

Copy link
Copy Markdown
Member Author

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.

@adamnovak

Copy link
Copy Markdown
Member Author

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.

@adamnovak
adamnovak merged commit 06a5a86 into master Jun 24, 2026
2 checks passed
@faithokamoto
faithokamoto deleted the fix-new-make branch June 26, 2026 20:58
glennhickey added a commit that referenced this pull request Jul 27, 2026
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.
glennhickey added a commit that referenced this pull request Jul 27, 2026
#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.
@glennhickey glennhickey mentioned this pull request Jul 27, 2026
glennhickey added a commit that referenced this pull request Jul 27, 2026
#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.
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.

1 participant