Let's Preserve Debuginfo in Static Libraries
Summary
RPMs supplying static libraries should build with useful & preserved debuginfo. Let's stop stripping them by default, and rely on new debugedit to process static library debuginfo in a way that's useful for full debugging.
See also: an earlier attempt at this idea.
Owner
- Name: Frank Ch. Eigler
- Adjutants: Mark Wielaard Florian Weimer
- Email: fche@redhat.com
Current status
- Targeted release: Fedora Linux 43
- Last updated: 2025-08-25
- Announced
- Discussion thread
- FESCo issue: #3439
- Tracker bug: #2383272
- Release notes tracker: #240
Detailed Description
The current rpmbuild environment includes a post-build process that includes:
%__os_install_post \
...
%{!?__debug_package:\
%{?__brp_strip} \
%{?__brp_strip_comment_note} \
} \
%{?__brp_strip_lto} \
%{?__brp_strip_static_archive} \
...
The last part, __brp_strip_static_archive, removes all debuginfo from any static archive (.a) files that may be packaged into foo-static subrpms. These are not stripped into a separate -debuginfo file (there's no tech for that); they are simply removed. This makes those functions permanently undebuggable.
This was undesirable for several packages, so they experimented with disabling the stripping step by redefining the __brp_strip_static_archive macro to nothing. This would allow the original object file / archive debuginfo to proceed into RPMs. However, these files were not subject to source-file rewriting normally performed by find-debuginfo.sh / debugedit, which let random build-time directory names propagate into those debuginfo files. (Normally, debugedit rewrites them to standard /usr/src/debug/PACKGE/... paths and arranges to ship them into debugsource RPMs.) This made their source files unpackaged and/or inaccessible. But now debugedit master (coming to release 5.2 shortly) can process .a files, rewriting source path names and collecting source files.
Fedora is finally in a position to preserve all static library debuginfo, and also arrange for distribution of their source code. This Change proposes that this be done by default:
- adopt the forthcoming version of
debugedit5.2 - change the
%__os_install_postrpm macro to avoid the__brp_strip_static_archivestep - offer an opt-in option for packages to retain stripping
We performed test mass-rebuilds of a number of packages, including all fedora 42 packages that include "static" subrpms. There were no build-breaking concerns.
We measured file size differences before/after to quantify the size impact. Some interesting corner cases:
xzis a typical case: small C libraryfftwis a worst-case scenario: template meta-programming C++ causes huge debuginfo.gccis good case: includes small C static-library, linked into many fedora binaries. For this test, we removed the manual strip of libgcc and other static libraries done in gcc.spec.llvmis also C++ and relatively debuginfo intensive
| package or file | old size | new size | delta | notes |
|---|---|---|---|---|
| xz-static-5.8.1-2.fc42.x86_64.rpm | 119173 | 506301 | 4.2x bigger | |
| liblzma.a | 392948 | 2172276 | 5.6x bigger | |
| fftw-static-3.3.10-13.fc42.x86_64.rpm | 2904595 | 34036502 | 11x bigger | |
| libfftw3f.a | 6976592 | 104539928 | 15x bigger | |
| gcc-15.1.1-2.fc42.x86_64.rpm | 41440269 | 45581745 | +9% | includes libgcc.a |
| libgcc.a | 3349468 | 8271084 | 2.5x bigger | 64-bit |
| gcc debugsource rpm | 8243 | 10582 | +2339 | number of files (mostly offload libraries) |
| llvm 20.1.7 lib64/libMLIRArithDialect.a | 6441876 | 45053964 | 7x bigger | |
| llvm-static-20.1.7-1.fc42.x86_64.rpm | 50674246 | 450169182 | 7.9x bigger | |
| llvm debugsource rpm | 17409 | 18449 | +1040 | number of files |
Note that figures like "10x bigger" should be taken in context. These static libraries / RPMs form a tiny fraction of the entire Fedora distro. Binary packages are unaffected, and their debuginfo would be only trivially affected (e.g., by including snippets of libgcc.a). Preserving debuginfo in the small number of static libraries should not dramatically grow the overall distro. However, we don't have a complete mass-build-based measurement on the overall impact.
Feedback
In previous discussions over the last years, some concerns have come up:
Larger .a files and static RPMs
Static archive files become 2-12 times bigger after they carry debuginfo content, and cannot be compressed by DWZ. (Hypothetically, they could be processed with
objcopy --compress-debug-sections to win back some of this space.) However, subrpms carrying those larger .a files are are compressed at the rpm level, so the storage / transport penalty of these subrpms can be reasonable. Downstream packages that use static libraries can be fully compressed by DWZ in the usual way. A small number of very common libraries (e.g., libgcc.a) with newly preserved debuginfo would enlarge many other Fedora -debuginfo packages, but only by a trivial relative amount.
We believe the RPM size increases for the ~300ish static-library-bearing packages are bearable to Fedora infrastructure. For those who develop against static libraries, we expect the larger disk footprint of those libraries is acceptable, in exchange for the value of getting full debuggability of the finished binaries.
Alternative idea of moving debuginfo-carrying static .a files into a -debuginfo subrpm
The gcc.spec has an option _enable_debug_packages, which if set, moves original unstripped libFOO.a files under /usr/lib/debug/..., thus getting them packaged into a gcc-debuginfo subrpm. This macro is not enabled in Fedora builds, but the logic is consistent with ideas expressed rhbz1395280.
We believe these measures are unnecessary. Users of static libraries should not need to use cumbersome custom -L/usr/lib/debug/... paths nor BuildRequire debuginfo RPMs just to make their programs debuggable. Keeping debuginfo data in the original .a files & subrpms is simple and effective.
Non-RPM developers getting some debuginfo even without gcc -g
Since basic runtime libraries like crt, libgcc would now carry debuginfo, that data would be linked into binaries produced with "gcc foo.c", even if "-g" was not specified. This is a relatively small amount: x86_64 libgcc.a without -g is about 3MB, with -g is about 8MB, and that's for all the individual runtime .o files. A developer concerned about this could opt to strip his/her binaries after linking. (Note that the toolchain has never guaranteed that there would be zero debuginfo in a binary compiled/linked without -g.)
We believe this is not a serious impediment, when developers can work around the distro change with classic tooling.
What about source code
In the status quo, a static library that is somehow packaged unstripped ends up with broken DWARF source references, and thus no files in the -debugsource. This change actually solves the "what about the source" problem, because new debugedit (find-debuginfo.sh) rewrites the source file names in the preserved DWARF, and arranges for those source files to be included in the FOO-debugsource subrpm. In the new scheme, debuginfod can automatically fetch the static library sources!
Benefit to Fedora
Binaries that link Fedora static libraries would become fully debuggable. Crashed programs that include static libraries would become fully backtraceable.
Scope
- Proposal owners:
- ☑ Update debugedit rpm to bring in static-archive support, rebased, rpm built
- ☑ Update redhat-rpm-config to disable
__brp_strip_static_archiveby default in/usr/lib/rpm/redhat/macros, merged, rpm built - ☐ Identify packages that perform manual static-library stripping now (e.g.,
gcc), file bugs to request discontinuation.
- Other developers:
foo-staticpackagers who embrace the change: do nothingfoo-staticpackagers who prefer to keep rpmbuild-stripped.astatus quo: activate__brp_strip_static_archiveby%undefine _preserve_static_debuginfofoo-staticpackagers who want to keep manually stripping their own.a: do nothingfoo-staticpackagers who no longer want to manually strip their own.a: strip that part from the .spec files- Non-package developers linking against
foo-staticwho embrace the change: do nothing - Non-package developers linking against
foo-staticwho want stripped binaries: strip binaries after linking
- Release engineering: #12799 to note somewhat larger RPMs, which would be generated during a mass-rebuild.
- Policies and guidelines: No formal change is necessary, as the packaging guidelines do not specify whether static libraries do or do not carry debuginfo. Packaging committee engaged for advice.
- Trademark approval: N/A (not needed for this Change)
- Alignment with the Fedora Strategy: N/A
Upgrade/compatibility impact
The only upgrade/compat impact appears to be larger disk footprint if updating from previous -static subrpms.
Early Testing (Optional)
Do you require 'QA Blueprint' support? N.
How To Test
- Build RPMs or non-RPM binaries that link against -static libraries.
- Observe they function just like before.
- Run readelf -w on the static .a files. It should print lots of .debug_info stuff (not just .eh_frame information)
- Run under debugger. Observe that the portions that came from -static libraries now have full debuginfo and source code.
- Check that an RPM with static subrpm contents builds without or with debuginfo, if
%undefine _preserve_static_debuginfois or isn't included in the .spec file.
User Experience
Ordinary Fedora user experience is unaffected, since this is a developer rather than user change. Users of packages that incorporate static library elements would, if the program crashed, be able to get complete traceback information to assist with problem reporting.
Developers of static-library related packages would need to accept somewhat larger disk footprint for the debuginfo-carrying files, and would benefit from the thorough debuggability.
Dependencies
This change is not blocked on others, nor on new upstream work. The precise mechanism by which the __brp_strip_static_archive macro would be disabled by default is proposed in this PR. We'd provide a way of forcing stripping back on for packages who prefer the status quo.
The changes should land before the mass-rebuild for full effectiveness.
Contingency Plan
- Contingency mechanism: If debugedit changes were to somehow break builds for this or unrelated reasons, we can roll that back immediately. If the rpm-side macro changes cannot be committed in time, then status quo (stripping .a files) will happen. Packages will be able to force static-library stripping for themselves.
- Contingency deadline: Beta freeze. Even if the rpmbuild-default reconfiguration were to miss the mass-rebuild, subsequently rebuilt packages could gradually take advantage.
- Blocks release? No.
Documentation
End-user documentation should not be necessary.
Developer documentation is being added to /usr/share/doc/redhat-rpm-config/buildflags.md
https://src.fedoraproject.org/rpms/redhat-rpm-config/pull-request/338#request_diff
Release Notes
The release notes should mention that developers who do not want debugging information in statically linked applications should link with the -s flag or run the strip -g command after linking. If building RPMs with redhat-rpm-config, add %undefine _preserve_static_debuginfo to your .spec. If building RPMs with very-large-cardinality .a files with no sensible debuginfo (e.g., mingw32 .dll.a import stubs), add %define _find_debuginfo_opts --no-ar-files to reduce processing time.
