mirror of
https://github.com/borgbackup/borg.git
synced 2026-10-12 02:11:36 +00:00
The Linux binaries from native_tests are built on ubuntu-26.04 and thus
need glibc 2.43, and the x86_64 one does not run on CPUs below x86-64-v3
("Illegal instruction"). The new oldglibc_binary job builds on
ubuntu-24.04 and ubuntu-24.04-arm (glibc 2.39, the oldest GitHub-hosted
Ubuntu image, with its baseline x86-64 toolchain and packages) and
produces borg-linux-glibc239-{x86_64,arm64}-gh.
Fixes #10342.
Ubuntu 24.04 only has OpenSSL 3.0 and Python 3.12 (and setup-python's
3.14 for it links the system OpenSSL 3.0), so the job builds OpenSSL
3.5.8 (no-tests, no-docs - the OpenSSL test suite is very slow and is
never run) and Python 3.14.7 from source, pinned by version and sha256,
links Python and borg's crypto extension against that OpenSSL, and
PyInstaller bundles those libraries. OpenSSL is built with an rpath to
its prefix, so that its libssl and the openssl program do not pick up
the system's OpenSSL 3.0 libraries, which have the same SONAMEs. Python
is a PGO build like the setup-python ones; its PGO training run (a
subset of python's test suite) runs in parallel worker processes. The
job checks that the ssl module, borg's crypto extension and the frozen
binary really use the OpenSSL and Python built there and that no
bundled ELF file needs a newer glibc than the binary's name promises.
The binary is built on every run of the job and the test suite runs
against it. On tags, the binaries get a provenance attestation and the
release job (which now depends on this job) attaches them and their
sigstore bundles to the GitHub release.
Also: scripts/glibc_check.py no longer crashes on an ELF file without
versioned glibc symbols.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
66 lines
1.7 KiB
Python
Executable File
66 lines
1.7 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
Check whether all given binaries work with the specified glibc version.
|
|
|
|
Usage: glibc_check.py 2.11 BIN [BIN ...]
|
|
|
|
Exit code 0 means "yes"; exit code 1 means "no".
|
|
"""
|
|
|
|
import re
|
|
import subprocess
|
|
import sys
|
|
|
|
verbose = True
|
|
glibc_re = re.compile(r"GLIBC_([0-9]\.[0-9]+)")
|
|
|
|
|
|
def parse_version(v):
|
|
major, minor = v.split(".")
|
|
return int(major), int(minor)
|
|
|
|
|
|
def format_version(version):
|
|
return "%d.%d" % version
|
|
|
|
|
|
def main():
|
|
given = parse_version(sys.argv[1])
|
|
filenames = sys.argv[2:]
|
|
|
|
overall_versions = set()
|
|
for filename in filenames:
|
|
try:
|
|
output = subprocess.check_output(["objdump", "-T", filename], stderr=subprocess.STDOUT)
|
|
output = output.decode()
|
|
versions = {parse_version(match.group(1)) for match in glibc_re.finditer(output)}
|
|
if not versions:
|
|
if verbose:
|
|
print(f"{filename} does not reference any versioned glibc symbol.")
|
|
continue
|
|
requires_glibc = max(versions)
|
|
overall_versions.add(requires_glibc)
|
|
if verbose:
|
|
print(f"{filename} {format_version(requires_glibc)}")
|
|
except subprocess.CalledProcessError:
|
|
if verbose:
|
|
print("%s failed." % filename)
|
|
|
|
wanted = max(overall_versions)
|
|
ok = given >= wanted
|
|
|
|
if verbose:
|
|
if ok:
|
|
print("The binaries work with the given glibc %s." % format_version(given))
|
|
else:
|
|
print(
|
|
"The binaries do not work with the given glibc %s. "
|
|
"Minimum required is %s." % (format_version(given), format_version(wanted))
|
|
)
|
|
return ok
|
|
|
|
|
|
if __name__ == "__main__":
|
|
ok = main()
|
|
sys.exit(0 if ok else 1)
|