Summary
./configure --enable-debug is meant to produce an unoptimized, debuggable build: its own
code sets -g -O0 -DDEBUG. The resulting build is in fact compiled at -O2. -g and
-DDEBUG take effect, but the -O0 is silently overridden, so a "debug" build is as hard to
step through in gdb as a release build (inlined frames, "value optimized out"). This has been
the case since b91325caa3 (2018-12-28) and also affects rpmbuild --with debug.
Observed on devel @ a482a8578a; reproduced on 14 distro toolchains (details below).
Root cause
--enable-debug puts -O0 into GF_CFLAGS, which reaches the compiler through
AM_CFLAGS / the per-target _CFLAGS. automake emits every compile as
… $(AM_CFLAGS) $(CFLAGS) …, so CFLAGS is placed last. autoconf's AC_PROG_CC
defaults CFLAGS to -g -O2 for gcc (and the RPM %configure macro exports
CFLAGS=%{optflags}, i.e. -O2 …), and configure.ac never neutralizes that. gcc honours
the last -O on the command line, so the -O2 from CFLAGS wins over the -O0
from GF_CFLAGS.
Real compile line for one TU under ./configure --enable-debug (make V=1):
gcc … -g -O0 -DDEBUG …(from GF_CFLAGS)… -g -O2 -fsigned-char …(from CFLAGS)… -c mem-pool.c
└─ intended └─ wins (last -O)
Decisive check (gcc defines __OPTIMIZE__ iff the effective level is ≥ -O1):
gcc -O0 -DDEBUG -O2 … → __OPTIMIZE__ defined (effective -O2)
gcc -O0 … → __OPTIMIZE__ undefined (effective -O0)
History: this used to work
- 2012,
d9ddb5fb95 — --enable-debug introduced; put the level in CFLAGS
(CFLAGS="-O0 $CFLAGS"), emitted last, so -O0 won.
- 2013,
d85e394847 (RHBZ 955283, "enable-debug change breaks _hardened_build") — kept
-O0 in CFLAGS via a surgical sed -e s/O2/O0/, so distro hardening flags survived.
- 2018,
b91325caa3 ("configure: fix the duplicate CFLAGS options") — moved -g -O0 -DDEBUG
from CFLAGS to GF_CFLAGS while removing genuine flag duplication elsewhere. That demoted
the -O0 below CFLAGS. Building the same ./configure --enable-debug on that commit and
on its parent shows the flip: parent → effective -O0, commit → effective -O2.
Why CI and the in-tree helpers did not catch it
The automated consumers of --enable-debug never see autoconf's -O2:
- upstream Jenkins regression CI (
build.sh in the separate gluster/glusterfs-patch-acceptance-tests
repository) configures with --enable-debug and then runs make install CFLAGS="-Wall -Werror -Wno-cpp". That make-line
override replaces configure's entire CFLAGS, so the -O2 is gone and the -O0 carried by
GF_CFLAGS is the only optimisation token. CI has therefore been building at -O0 all along.
- the in-tree helpers (
run-tests-in-vagrant.sh, extras/devel-tools/devel-vagrant,
extras/distributed-testing) pass an explicit CFLAGS="-g -O0 …" next to --enable-debug.
Only a plain ./configure --enable-debug (what a developer types) and rpmbuild --with debug
(where %configure exports CFLAGS=%optflags) hit it, and in both cases the build still
succeeds, just optimized, so nothing fails loudly.
Impact
- Developer debug builds are optimized: gdb shows inlined frames and
<optimized out> variables.
rpmbuild --with debug produces optimized "debug" RPMs.
-DDEBUG instrumentation (mem-pool accounting etc.) and -g are unaffected.
- No distro's default packaging passes
--enable-debug, so no shipped release binary is
affected either way.
Fix
Keep -g -DDEBUG in GF_CFLAGS and append -O0 to CFLAGS, so it lands last and wins,
without clobbering anything already in CFLAGS (distro hardening flags stay intact — the
mistake behind RHBZ 955283 was clobbering CFLAGS, and appending avoids it; it is also robust
to -O3/-Os/-Og/no -O, unlike the 2013 sed). A PR with the one-hunk change follows.
Verification of the fix
- Arch Linux (2026-09; gcc 16.2.1, glibc 2.44, autoconf 2.73):
--enable-debug → effective
-O0, both plain and with Fedora 42 %optflags as CFLAGS (-fstack-protector-strong,
-D_FORTIFY_SOURCE=3, -fcf-protection, -fstack-clash-protection all still on the line);
full tree builds with 0 errors in three allocator/io configurations.
- AlmaLinux 8.10 (gcc 8.5): real
rpmbuild -tb --with debug before/after — before, all 351
translation units end with -O2; after, all 351 end with -O0; both builds succeed and
produce the same 39 packages; EL8 hardening flags intact.
- 14 distro containers (AlmaLinux 8, CentOS Stream 9, Fedora 42, Leap 15.6, Tumbleweed, Arch,
Debian 12, Debian 13 amd64, Ubuntu 20.04/22.04/24.04, plus Debian 13 i386, Alpine 3.22 and
Alpine edge as compile-line-only oracles;
autoconf 2.69–2.73, gcc 7.5–16.2, glibc 2.28–2.44 and musl), each with its own autotools:
identical flip on every one, same make result / error set / object counts before and after,
and the generated build system differs only in the CFLAGS/GF_CFLAGS lines.
- CI shape (
make CFLAGS="-Wall -Werror -Wno-cpp" after --enable-debug): stays at -O0
(the line then carries no -O token, which gcc treats as -O0).
One expected side effect of any real -O0 build: where CFLAGS carries -D_FORTIFY_SOURCE,
glibc's features.h emits #warning _FORTIFY_SOURCE requires compiling with optimization (-O)
once per TU (Fedora/EL/SUSE/Arch glibc; Debian/Ubuntu glibc carries no such warning). That was
also the state of --enable-debug from 2013 to 2018.
Summary
./configure --enable-debugis meant to produce an unoptimized, debuggable build: its owncode sets
-g -O0 -DDEBUG. The resulting build is in fact compiled at -O2.-gand-DDEBUGtake effect, but the-O0is silently overridden, so a "debug" build is as hard tostep through in gdb as a release build (inlined frames, "value optimized out"). This has been
the case since
b91325caa3(2018-12-28) and also affectsrpmbuild --with debug.Observed on
devel@a482a8578a; reproduced on 14 distro toolchains (details below).Root cause
--enable-debugputs-O0intoGF_CFLAGS, which reaches the compiler throughAM_CFLAGS/ the per-target_CFLAGS. automake emits every compile as… $(AM_CFLAGS) $(CFLAGS) …, soCFLAGSis placed last. autoconf'sAC_PROG_CCdefaults
CFLAGSto-g -O2for gcc (and the RPM%configuremacro exportsCFLAGS=%{optflags}, i.e.-O2 …), and configure.ac never neutralizes that. gcc honoursthe last
-Oon the command line, so the-O2fromCFLAGSwins over the-O0from
GF_CFLAGS.Real compile line for one TU under
./configure --enable-debug(make V=1):Decisive check (gcc defines
__OPTIMIZE__iff the effective level is ≥ -O1):History: this used to work
d9ddb5fb95—--enable-debugintroduced; put the level inCFLAGS(
CFLAGS="-O0 $CFLAGS"), emitted last, so-O0won.d85e394847(RHBZ 955283, "enable-debug change breaks _hardened_build") — kept-O0inCFLAGSvia a surgicalsed -e s/O2/O0/, so distro hardening flags survived.b91325caa3("configure: fix the duplicate CFLAGS options") — moved-g -O0 -DDEBUGfrom
CFLAGStoGF_CFLAGSwhile removing genuine flag duplication elsewhere. That demotedthe
-O0belowCFLAGS. Building the same./configure --enable-debugon that commit andon its parent shows the flip: parent → effective
-O0, commit → effective-O2.Why CI and the in-tree helpers did not catch it
The automated consumers of
--enable-debugnever see autoconf's-O2:build.shin the separategluster/glusterfs-patch-acceptance-testsrepository) configures with
--enable-debugand then runsmake install CFLAGS="-Wall -Werror -Wno-cpp". That make-lineoverride replaces configure's entire
CFLAGS, so the-O2is gone and the-O0carried byGF_CFLAGSis the only optimisation token. CI has therefore been building at-O0all along.run-tests-in-vagrant.sh,extras/devel-tools/devel-vagrant,extras/distributed-testing) pass an explicitCFLAGS="-g -O0 …"next to--enable-debug.Only a plain
./configure --enable-debug(what a developer types) andrpmbuild --with debug(where
%configureexportsCFLAGS=%optflags) hit it, and in both cases the build stillsucceeds, just optimized, so nothing fails loudly.
Impact
<optimized out>variables.rpmbuild --with debugproduces optimized "debug" RPMs.-DDEBUGinstrumentation (mem-pool accounting etc.) and-gare unaffected.--enable-debug, so no shipped release binary isaffected either way.
Fix
Keep
-g -DDEBUGinGF_CFLAGSand append-O0toCFLAGS, so it lands last and wins,without clobbering anything already in
CFLAGS(distro hardening flags stay intact — themistake behind RHBZ 955283 was clobbering
CFLAGS, and appending avoids it; it is also robustto
-O3/-Os/-Og/no-O, unlike the 2013sed). A PR with the one-hunk change follows.Verification of the fix
--enable-debug→ effective-O0, both plain and with Fedora 42%optflagsasCFLAGS(-fstack-protector-strong,-D_FORTIFY_SOURCE=3,-fcf-protection,-fstack-clash-protectionall still on the line);full tree builds with 0 errors in three allocator/io configurations.
rpmbuild -tb --with debugbefore/after — before, all 351translation units end with
-O2; after, all 351 end with-O0; both builds succeed andproduce the same 39 packages; EL8 hardening flags intact.
Debian 12, Debian 13 amd64, Ubuntu 20.04/22.04/24.04, plus Debian 13 i386, Alpine 3.22 and
Alpine edge as compile-line-only oracles;
autoconf 2.69–2.73, gcc 7.5–16.2, glibc 2.28–2.44 and musl), each with its own autotools:
identical flip on every one, same make result / error set / object counts before and after,
and the generated build system differs only in the
CFLAGS/GF_CFLAGSlines.make CFLAGS="-Wall -Werror -Wno-cpp"after--enable-debug): stays at-O0(the line then carries no
-Otoken, which gcc treats as-O0).One expected side effect of any real
-O0build: whereCFLAGScarries-D_FORTIFY_SOURCE,glibc's
features.hemits#warning _FORTIFY_SOURCE requires compiling with optimization (-O)once per TU (Fedora/EL/SUSE/Arch glibc; Debian/Ubuntu glibc carries no such warning). That was
also the state of
--enable-debugfrom 2013 to 2018.