Published: December 29th, 2024
Updated: July 3rd, 2025
As I’ve used Gentoo, I’ve become curious about what kinds of interesting build flags other systems use to compile their binaries on a global level, as well as what configure-time flags they set on GNU Compiler Collection (GCC) and Clang. This article collects these flags for some distributions to make them easier for me to track down and compare in the future.
Because this is a rabbit hole, there are some things I won’t be doing in the interest of time. They’re listed in the Caveats section.
Some relevant documentation can be found in these places:
According to this poster, the build flags can be found in the x86_64.conf file in the devtools package.
CFLAGS:
-march=x86-64
-mtune=generic
-O2
-pipe
-fno-plt
-fexceptions
-Wp,-D_FORTIFY_SOURCE=3
-Wformat
-Werror=format-security
-fstack-clash-protection
-fcf-protection
-fno-omit-frame-pointer
-mno-omit-leaf-frame-pointer
CXXFLAGS:
$CFLAGS
-Wp,-D_GLIBCXX_ASSERTIONS
LDFLAGS:
-Wl,-O1
-Wl,--sort-common
-Wl,--as-needed
-Wl,-z,relro
-Wl,-z,now
-Wl,-z,pack-relative-relocs
LTOFLAGS:
-flto=auto
Here are the configure-time GCC flags for Arch.
Here are the configure-time Clang flags for Arch.
Here are the configure-time Low Level Virtual Machine (LLVM) flags for Arch.
Alpine compiles packages using abuild. The default.conf file contains the compiler flags used for the distribution.
CFLAGS:
-Os
-fstack-clash-protection
-Wformat
-Werror=format-security
CXXFLAGS:
-Os
-fstack-clash-protection
-Wformat
-Werror=format-security
-D_GLIBCXX_ASSERTIONS=1
-D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS=1
-D_LIBCPP_ENABLE_HARDENED_MODE=1
LDFLAGS:
-Wl,--as-needed,-O1,--sort-common
Clang configuration for Alpine.
LLVM configuration for Alpine.
This discussion has some interesting details.
The performance section in the documentation lays everything out nicely.
For x86_64, here is what that looks like:
-O2
-g
-feliminate-unused-debug-types
-pipe
-Wall
-Wp,-D_FORTIFY_SOURCE=2
-fexceptions
-fstack-protector
--param=ssp-buffer-size=64
-Wformat
-Wformat-security
-Wl,-z,now,-z,relro,-z,max-page-size=0x4000,-z,separate-code
-Wno-error
-ftree-vectorize
-ftree-slp-vectorize
-Wl,--enable-new-dtags
-Wl,--build-id=sha1
-ftrivial-auto-var-init=zero
-mrelax-cmpxchg-loop
-m64
-march=westmere
-mtune=skylake-avx512
-fasynchronous-unwind-tables
-Wp,-D_REENTRANT
The configuration contains some interesting flags. Two flags in
particular I find noteworthy: -ftrivial-auto-var-init=zero
and
-mrelax-cmpxchg-loop
.
-ftrivial-auto-var-init
is a security-related flag. I’ve heard that
both ChromiumOS and Android use that flag in some form. Gentoo may add
it to their hardened builds, at least this open bug suggests
so.
-mrelax-cmpxchg-loop
relaxes spin loops in certain conditions,
benefiting thread synchronization. Here is the GCC bug where it’s
discussed. Intel
discusses it
here.
The question of compiler configure-time flags for Clear Linux gets complicated, because they have separate GCC builds for Advanced Vector Extensions 2 (AVX2) and Advanced Vector Extensions 512 (AVX512) Here are the configure-time flags for the main GCC build.
Similar situation for Clang. Here are the Clear Linux configuration-time flags for Clang/LLVM.
I’m breaking a rule I made for myself a little bit (no per-package CFLAGS/CXXFLAGS reviewing) to discuss some interesting tweaks Clear Linux does. autospec is at the heart of this. A couple of interesting things about autospec and the packages in clearlinux-pkgs:
-fzero-call-used-regs=used
on
security-sensitive
packages.
I found this due to Seirdy’s note on the
subject.funroll-loops
option is
set
(no doubt a reference/inside
joke),
-O3
gets added if use_clang
was also set. Otherwise,
-fno-semantic-interposition
and -falign-functions=32
get added.There’s a lot to learn from this distribution.
dpkg-buildflags
is a Perl script, provided by the dpkg-dev
package. A lot of the heavy
lifting gets done by the libraries sourced by the script, which live in
/usr/share/perl5/Dpkg
. Those libraries come from the libdpkg-perl
package (a dependency of dpkg-dev
).
Debian 12 (Bookworm).
$ dpkg-buildflags --query
Vendor: Debian
Environment:
Area: future
Features:
lfs=no
Builtins:
Area: hardening
Features:
bindnow=no
format=yes
fortify=yes
pie=yes
relro=yes
stackprotector=yes
stackprotectorstrong=yes
Builtins:
pie=yes
Area: optimize
Features:
lto=no
Builtins:
Area: qa
Features:
bug=no
canary=no
Builtins:
Area: reproducible
Features:
fixdebugpath=yes
fixfilepath=yes
timeless=yes
Builtins:
Area: sanitize
Features:
address=no
leak=no
thread=no
undefined=no
Builtins:
Flag: ASFLAGS
Value:
Origin: vendor
Flag: CFLAGS
Value: -g -O2 -ffile-prefix-map=/home/user=. -fstack-protector-strong -Wformat -Werror=format-security
Origin: vendor
Flag: CPPFLAGS
Value: -Wdate-time -D_FORTIFY_SOURCE=2
Origin: vendor
Flag: CXXFLAGS
Value: -g -O2 -ffile-prefix-map=/home/user=. -fstack-protector-strong -Wformat -Werror=format-security
Origin: vendor
Flag: DFLAGS
Value: -frelease
Origin: vendor
Flag: FCFLAGS
Value: -g -O2 -ffile-prefix-map=/home/user=. -fstack-protector-strong
Origin: vendor
Flag: FFLAGS
Value: -g -O2 -ffile-prefix-map=/home/user=. -fstack-protector-strong
Origin: vendor
Flag: GCJFLAGS
Value: -g -O2 -ffile-prefix-map=/home/user=. -fstack-protector-strong
Origin: vendor
Flag: LDFLAGS
Value: -Wl,-z,relro
Origin: vendor
Flag: OBJCFLAGS
Value: -g -O2 -ffile-prefix-map=/home/user=. -fstack-protector-strong -Wformat -Werror=format-security
Origin: vendor
Flag: OBJCXXFLAGS
Value: -g -O2 -ffile-prefix-map=/home/user=. -fstack-protector-strong -Wformat -Werror=format-security
Origin: vendor
Debian’s GCC configure-time flags can be found in this file, stored in the CONFARGS variable.
Debian’s Clang/LLVM configure-time flags.
Obtained via Red Hat Package Manager (RPM) macros.
These commands were run in a Fedora 40 virtual machine.
$ rpm --eval "%{optflags}" | tr ' ' '\n' | grep -v '^$'
-O2
-flto=auto
-ffat-lto-objects
-fexceptions
-g
-grecord-gcc-switches
-pipe
-Wall
-Wno-complain-wrong-lang
-Werror=format-security
-Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3
-Wp,-D_GLIBCXX_ASSERTIONS
-specs=/usr/lib/rpm/redhat/redhat-hardened-cc1
-fstack-protector-strong
-specs=/usr/lib/rpm/redhat/redhat-annobin-cc1
-m64
-march=x86-64
-mtune=generic
-fasynchronous-unwind-tables
-fstack-clash-protection
-fcf-protection
-fno-omit-frame-pointer
-mno-omit-leaf-frame-pointer
$ rpm --eval "%{build_ldflags}" | tr ' ' '\n' | grep -v '^$'
-Wl,-z,relro
-Wl,--as-needed
-Wl,-z,pack-relative-relocs
-Wl,-z,now
-specs=/usr/lib/rpm/redhat/redhat-hardened-ld
-specs=/usr/lib/rpm/redhat/redhat-annobin-cc1
-Wl,--build-id=sha1
Fedora’s GCC configure-time flags.
Fedora’s Clang configure-time flags.
/etc/portage/make.conf
. But additional flags get set implicitly as
well. The settings depend on things like what USE flags get set, as an
example.
The build flags mainly live in toolchain.eclass. Gentoo’s configure-time flags for GCC live in toolchain.eclass as well.
The referenced patches can be found here.
The hardened toolchain changes table in Project:Toolchain is worth mentioning as well.
While on the subject of Gentoo, ChromiumOS is interesting to think about. ChromiumOS is the open source base for ChromeOS on Chromebooks. It uses Portage, Gentoo’s package management system. I haven’t looked into it enough to offer insightful commentary on it—I’d have to sift through a lot of code to talk about it halfway intelligently.
I’m presuming something here: that NixOS doesn’t add CFLAGS/CXXFLAGS beyond what nixpkgs does. I don’t see why it would, after all, but I felt it was important to note that all the same.
Hardening flags get mentioned here.
Here are the ones used by default at the time of writing (I verified
this by copying the .nix file from this
guide
and setting NIX_DEBUG = 2;
in the pkgs.stdenv.mkDerivation
section,
then built the package):
-fPIC
-Wformat
-Wformat-security
-Werror=format-security
-fstack-protector-strong
--param ssp-buffer-size=4
-O2
-D_FORTIFY_SOURCE=2
-fno-strict-overflow
-Wl,-z,relro
-Wl,-z,now
If -fzero-call-used-regs=used-gpr
gets used, it wasn’t printed during
the test build.
Local changes to their integrated (and old) version of GCC get described in gcc-local. The same applies to clang-local, although it’s a current version.
OpenBSD’s GCC port and OpenBSD’s LLVM port.
Here is the source code for OpenBSD’s version of LLVM/Clang. Same for GCC.
Line 3581 here should list the options. OpenSUSE:Factory is what they use to build Tumbleweed packages.
-O2
-Wall
-U_FORTIFY_SOURCE
-D_FORTIFY_SOURCE=3
-fstack-protector-strong
-funwind-tables
-fasynchronous-unwind-tables
-fstack-clash-protection
-Werror=return-type
%%{?_lto_cflags}
There is a dummy package for GCC here, and ditto for clang/llvm. At the time of writing, the relevant versions are 14 and 19, respectively.
So, OpenSUSE’s GCC configure-time flags can be found here. Starts on line 2510.
OpenSUSE’s Clang configure-time flags can be found here. Starts on line 1092.
These flags come from this GitHub issue. From what I can tell, the flags get set by ypkg. Specifically, ypkgcontext.py.
To get the latest flags, I guess one would have to figure out how to get ypkg (or some other piece of the Solus build system) to output them somehow. I haven’t done so, but it certainly seems possible.
CFLAGS:
-mtune=generic
-march=x86-64
-g2
-O2
-pipe
-fno-plt
-fPIC
-Wformat
-Wformat-security
-D_FORTIFY_SOURCE=2
-fstack-protector-strong
--param=ssp-buffer-size=32
-fasynchronous-unwind-tables
-ftree-vectorize
-feliminate-unused-debug-types
-Wall
-Wno-error
-Wp,-D_REENTRANT
CXXFLAGS:
-mtune=generic
-march=x86-64
-g2
-O2
-pipe
-fno-plt
-fPIC
-D_FORTIFY_SOURCE=2
-fstack-protector-strong
--param=ssp-buffer-size=32
-fasynchronous-unwind-tables
-ftree-vectorize
-feliminate-unused-debug-types
-Wall
-Wno-error
-Wp,-D_REENTRANT
LDFLAGS:
-Wl,--copy-dt-needed-entries
-Wl,-O1
-Wl,-z,relro
-Wl,-z,now
-Wl,-z,max-page-size=0x1000
-Wl,-Bsymbolic-functions
-Wl,--sort-common
Solus’ GCC configure-time flags can be found here.
Solus’ Clang/LLVM configure-time flags can be found here.
Retrieved the same way as Debian. Ubuntu 24.10 (oracular).
$ dpkg-buildflags --query
Vendor: Ubuntu
Environment:
Area: abi
Features:
lfs=no
time64=yes
Builtins:
lfs=yes
time64=yes
Area: future
Features:
lfs=no
Builtins:
Area: hardening
Features:
bindnow=no
branch=yes
format=yes
fortify=yes
pie=yes
relro=yes
stackclash=yes
stackprotector=yes
stackprotectorstrong=yes
Builtins:
pie=yes
Area: optimize
Features:
lto=yes
Builtins:
Area: qa
Features:
bug=no
bug-implicit-func=yes
canary=no
elfpackagemetadata=no
framepointer=yes
Builtins:
Area: reproducible
Features:
fixdebugpath=yes
fixfilepath=yes
timeless=yes
Builtins:
Area: sanitize
Features:
address=no
leak=no
thread=no
undefined=no
Builtins:
Flag: ASFLAGS
Value:
Origin: vendor
Flag: ASFLAGS_FOR_BUILD
Value:
Origin: vendor
Flag: CFLAGS
Value: -g -O2 -Werror=implicit-function-declaration -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -ffile-prefix-map=/home/ubuntu=. -flto=auto -ffat-lto-objects -fstack-protector-strong -fstack-clash-protection -Wformat -Werror=format-security -fcf-protection
Origin: vendor
Flag: CFLAGS_FOR_BUILD
Value: -g -O2 -Werror=implicit-function-declaration -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -ffile-prefix-map=/home/ubuntu=. -flto=auto -ffat-lto-objects -fstack-protector-strong -fstack-clash-protection -Wformat -Werror=format-security -fcf-protection
Origin: vendor
Flag: CPPFLAGS
Value: -Wdate-time -D_FORTIFY_SOURCE=3
Origin: vendor
Flag: CPPFLAGS_FOR_BUILD
Value: -Wdate-time -D_FORTIFY_SOURCE=3
Origin: vendor
Flag: CXXFLAGS
Value: -g -O2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -ffile-prefix-map=/home/ubuntu=. -flto=auto -ffat-lto-objects -fstack-protector-strong -fstack-clash-protection -Wformat -Werror=format-security -fcf-protection
Origin: vendor
Flag: CXXFLAGS_FOR_BUILD
Value: -g -O2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -ffile-prefix-map=/home/ubuntu=. -flto=auto -ffat-lto-objects -fstack-protector-strong -fstack-clash-protection -Wformat -Werror=format-security -fcf-protection
Origin: vendor
Flag: DFLAGS
Value: -frelease
Origin: vendor
Flag: DFLAGS_FOR_BUILD
Value: -frelease
Origin: vendor
Flag: FCFLAGS
Value: -g -O2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -ffile-prefix-map=/home/ubuntu=. -flto=auto -ffat-lto-objects -fstack-protector-strong -fstack-clash-protection -fcf-protection
Origin: vendor
Flag: FCFLAGS_FOR_BUILD
Value: -g -O2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -ffile-prefix-map=/home/ubuntu=. -flto=auto -ffat-lto-objects -fstack-protector-strong -fstack-clash-protection -fcf-protection
Origin: vendor
Flag: FFLAGS
Value: -g -O2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -ffile-prefix-map=/home/ubuntu=. -flto=auto -ffat-lto-objects -fstack-protector-strong -fstack-clash-protection -fcf-protection
Origin: vendor
Flag: FFLAGS_FOR_BUILD
Value: -g -O2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -ffile-prefix-map=/home/ubuntu=. -flto=auto -ffat-lto-objects -fstack-protector-strong -fstack-clash-protection -fcf-protection
Origin: vendor
Flag: LDFLAGS
Value: -Wl,-Bsymbolic-functions -flto=auto -ffat-lto-objects -Wl,-z,relro
Origin: vendor
Flag: LDFLAGS_FOR_BUILD
Value: -flto=auto -ffat-lto-objects -Wl,-z,relro
Origin: vendor
Flag: OBJCFLAGS
Value: -g -O2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -ffile-prefix-map=/home/ubuntu=. -flto=auto -ffat-lto-objects -fstack-protector-strong -fstack-clash-protection -Wformat -Werror=format-security -fcf-protection
Origin: vendor
Flag: OBJCFLAGS_FOR_BUILD
Value: -g -O2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -ffile-prefix-map=/home/ubuntu=. -flto=auto -ffat-lto-objects -fstack-protector-strong -fstack-clash-protection -Wformat -Werror=format-security -fcf-protection
Origin: vendor
Flag: OBJCXXFLAGS
Value: -g -O2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -ffile-prefix-map=/home/ubuntu=. -flto=auto -ffat-lto-objects -fstack-protector-strong -fstack-clash-protection -Wformat -Werror=format-security -fcf-protection
Origin: vendor
Flag: OBJCXXFLAGS_FOR_BUILD
Value: -g -O2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -ffile-prefix-map=/home/ubuntu=. -flto=auto -ffat-lto-objects -fstack-protector-strong -fstack-clash-protection -Wformat -Werror=format-security -fcf-protection
Origin: vendor
Flag: RUSTFLAGS
Value: -Cforce-frame-pointers=yes
Origin: vendor
Flag: RUSTFLAGS_FOR_BUILD
Value:
Origin: vendor
Ubuntu Oracular GCC version appears to be 14. Here is the relevant Ubuntu GCC file that I figured that out from. Ditto for Clang/LLVM, which appears to be 19.
Ubuntu’s GCC configure-time flags begin here.
Ubuntu’s LLVM configure-time flags can be found here.
I found these by reasoning out what these files in the void-packages repo set:
CFLAGS:
-mtune=generic
-O2
-pipe
-fstack-clash-protection
-D_FORTIFY_SOURCE=2
CXXFLAGS:
-mtune=generic
-O2
-pipe
-fstack-clash-protection
-D_FORTIFY_SOURCE=2
LDFLAGS:
-Wl,--as-needed
-Wl,-z,relro
-Wl,-z,now
Void’s GCC configure-time flags can be found here.
Void’s Clang configure-time flags can be found here. The main version of clang used by the distro can be found in the llvm package template.
Here are things I haven’t done, and why I haven’t done them.
My approach favored coverage, not extreme precision. I gathered
compilation flags that I could find in a configuration file (the
equivalent of /etc/portage/make.conf
for other distributions), through
some light source code reading, or by executing some utility. I had to
limit myself in some ways because otherwise it was unlikely that I’d
release this article anytime soon.
Please don’t take what I’ve written here as gospel. Something being absent doesn’t necessarily prove anything, as the distribution may have enabled it in a place that I didn’t look. However, something being present and reflected in the linked source code does prove that a distribution uses it in that context, or at least used it at the time of writing.