fix(rpm): debuginfo support on some distributions (#1006)
This enables RPM debuginfo package generation across different Linux
distributions (tested on Rocky and Ubuntu in CI) by implementing RPM
version-based detection if possible, and falling back to the existing OS
release-based detection otherwise.
RPM 4.18.0 introduced changes to make `%{buildsubdir}` independent of
the `%setup` macro:
- commit: `Make %{buildsubdir} more independent of %setup`
(rpm-software-management/rpm@6caca84c904423)
- since: `rpm-4.18.0-alpha1`
- release: https://rpm.org/wiki/Releases/4.18.0
While this change enabled setting `buildsubdir` as a regular macro
rather than a `spec` object property, it had the side effect of altering
the relative path handling in install scripts.
This requires different file path formats in the `%install` section:
- RPM < 4.18, corresponding to the project's "centos" type:
```
cp 'bazel-out/k8-fastbuild/bin/tests/rpm/test_debuginfo' '%{buildroot}/test_debuginfo'
```
- RPM >= 4.18, corresponding to the project's "fedora" type:
```
cp '../bazel-out/k8-fastbuild/bin/tests/rpm/test_debuginfo' '%{buildroot}/test_debuginfo'
```
Using the wrong "type" causes build failures:
- "fedora" with RPM < 4.18:
```
cp: cannot stat '../bazel-out/k8-fastbuild/bin/tests/rpm/test_debuginfo': No such file or directory
```
- "centos" with RPM >= 4.18:
```
rm: refusing to remove '.' or '..' directory: skipping '.'
```
The present change therefore implements version detection to
automatically select the appropriate "type".
**Additional fixes for cross-distribution compatibility**
RedHat distros have redhat-rpm-config with `%_enable_debug_packages`
that auto-invokes `%debug_package` (rpm-software-management/rpm#2204).
Debian/Ubuntu ship vanilla upstream RPM without this configuration:
```
output 'tests/rpm/test_debuginfo_rpm-debuginfo-1-0..rpm' was not created
```
That's why the change adds `%debug_package` only when applicable:
- `%{!?_enable_debug_packages:%debug_package}`.
Also, since RPM [4.14](https://rpm.org/wiki/Releases/4.14.0), unique
debug package filenames are enabled by default, leading to variadic
filenames being generated:
```
Executing tests from //tests/rpm:test_golden_debuginfo_rpm_contents
-----------------------------------------------------------------------------
29c29
< /usr/lib/debug/test_debuginfo-1-0.x86_64.debug
---
> /usr/lib/debug/test_debuginfo.debug
FAIL: files "tests/rpm/test_debuginfo_rpm_contents.txt" and "tests/rpm/test_debuginfo_rpm_contents.txt.golden" differ
```
That's why the change makes debug package filenames consistent across
distributions by means of:
- `%undefine _unique_debug_names` (safe no-op on older RPM versions).
Note: I also verified the change locally with:
- RPM 4.17.1 on Fedora 35 ("centos" type)
- RPM 4.18.2 on Ubuntu 24.04.3 ("fedora" type)
- RPM 4.19.1.1 on Fedora 40 ("fedora" type)diff --git a/.bazelci/tests.yml b/.bazelci/tests.yml
index 62c5482..5dbf053 100644
--- a/.bazelci/tests.yml
+++ b/.bazelci/tests.yml
@@ -37,8 +37,6 @@
- "//pkg/..."
- "//tests/..."
- "//toolchains/..."
- # This has started to fail, even on CentOS.
- - "-//tests/rpm:test_golden_debuginfo_rpm_contents"
win_tests: &win_tests
test_flags:
@@ -66,7 +64,10 @@
ubuntu2204: &ubuntu
platform: ubuntu2204
<<: *common
- <<: *default_tests
+ <<: *default_tests_with_rpm
+ shell_commands:
+ - sudo apt-get update
+ - sudo apt-get install -y rpm elfutils # for rpmbuild & eu-strip
centos7: ¢os
platform: centos7_java11_devtoolset10
diff --git a/examples/rpm/debuginfo/README.md b/examples/rpm/debuginfo/README.md
index d42b117..08f8957 100644
--- a/examples/rpm/debuginfo/README.md
+++ b/examples/rpm/debuginfo/README.md
@@ -6,7 +6,7 @@
us register the system rpmbuild as a toolchain in a bzlmod environment.
It configures the system toolchain to be aware of which debuginfo configuration
-to use (defaults to "none", the example uses "centos7").
+to use (defaults to "none", the example uses "centos" for RPM < 4.18).
## To use
diff --git a/pkg/rpm_pfg.bzl b/pkg/rpm_pfg.bzl
index ec48512..941c4ed 100644
--- a/pkg/rpm_pfg.bzl
+++ b/pkg/rpm_pfg.bzl
@@ -604,6 +604,13 @@
if ctx.attr.architecture:
preamble_pieces.append("BuildArch: " + ctx.attr.architecture)
+ if ctx.attr.debuginfo:
+ # RedHat distros have redhat-rpm-config with %_enable_debug_packages macro; others need explicit declaration
+ preamble_pieces.append("%{{!?_enable_debug_packages:%debug_package}}") # set %debug_package unless macro exists
+
+ # https://rpm.org/wiki/Releases/4.14.0: "Add support for unique debug file names"
+ preamble_pieces.append("%undefine _unique_debug_names") # no-op if not defined
+
preamble_file = ctx.actions.declare_file(
"{}.spec.preamble".format(rpm_name),
)
diff --git a/toolchains/rpm/rpmbuild.bzl b/toolchains/rpm/rpmbuild.bzl
index 1b68c45..ebc1016 100644
--- a/toolchains/rpm/rpmbuild.bzl
+++ b/toolchains/rpm/rpmbuild.bzl
@@ -60,7 +60,7 @@
doc = """
The underlying debuginfo configuration for the system rpmbuild.
- One of `centos`, `fedora`, and `none`
+ One of `centos` (RPM < 4.18), `fedora` (RPM >= 4.18), and `none`
""",
default = "none",
),
diff --git a/toolchains/rpm/rpmbuild_configure.bzl b/toolchains/rpm/rpmbuild_configure.bzl
index 2f3c7e5..3ab6a26 100644
--- a/toolchains/rpm/rpmbuild_configure.bzl
+++ b/toolchains/rpm/rpmbuild_configure.bzl
@@ -81,15 +81,6 @@
if rctx.attr.debuginfo_type not in DEBUGINFO_VALID_VALUES:
fail("debuginfo_type must be one of", DEBUGINFO_VALID_VALUES)
- debuginfo_type = rctx.attr.debuginfo_type
- if debuginfo_type == DEBUGINFO_TYPE_AUTODETECT:
- if rctx.path(RELEASE_PATH).exists:
- rctx.watch(RELEASE_PATH)
- os_name, _ = _parse_release_info(rctx.read(RELEASE_PATH))
- debuginfo_type = DEBUGINFO_TYPE_BY_OS_RELEASE.get(os_name, debuginfo_type)
- else:
- debuginfo_type = DEBUGINFO_TYPE_NONE
-
rpmbuild_path = rctx.which("rpmbuild")
if rctx.attr.verbose:
if rpmbuild_path:
@@ -99,6 +90,7 @@
version = "unknown"
if rpmbuild_path:
+ rctx.watch(rpmbuild_path)
res = rctx.execute([rpmbuild_path, "--version"])
if res.return_code == 0:
# expect stdout like: RPM version 4.16.1.2
@@ -106,6 +98,24 @@
if parts[0] == "RPM" and parts[1] == "version":
version = parts[2]
+ debuginfo_type = rctx.attr.debuginfo_type
+ if debuginfo_type == DEBUGINFO_TYPE_AUTODETECT:
+ version_parts = version.split(".")
+ if len(version_parts) > 1 and version_parts[0].isdigit() and version_parts[1].isdigit():
+ major = int(version_parts[0])
+ minor = int(version_parts[1])
+ if major < 4 or (major == 4 and minor < 18):
+ debuginfo_type = DEBUGINFO_TYPE_CENTOS
+ else:
+ # https://rpm.org/wiki/Releases/4.18.0: "Make %{buildsubdir} settable outside %setup"
+ debuginfo_type = DEBUGINFO_TYPE_FEDORA
+ elif rctx.path(RELEASE_PATH).exists:
+ rctx.watch(RELEASE_PATH)
+ os_name, _ = _parse_release_info(rctx.read(RELEASE_PATH))
+ debuginfo_type = DEBUGINFO_TYPE_BY_OS_RELEASE.get(os_name, debuginfo_type)
+ else:
+ debuginfo_type = DEBUGINFO_TYPE_NONE
+
_write_build(
rctx = rctx,
path = rpmbuild_path,
@@ -126,7 +136,11 @@
doc = """
The underlying debuginfo configuration for the system rpmbuild.
- One of `centos`, `fedora`, `none`, and `default` (which looks up `/etc/os-release`)
+ One of:
+ - `centos` (RPM < 4.18),
+ - `fedora` (RPM >= 4.18),
+ - `none`,
+ - `default` (detects from `rpmbuild` version if available, otherwise looks up `/etc/os-release`)
""",
default = DEBUGINFO_TYPE_AUTODETECT,
),