@ -5,58 +5,49 @@ and how to use them.
# Using RPM build flags
The %set_build_flags macro sets the environment variables `CFLAGS` ,
`CXXFLAGS` , `FFLAGS` , `FCFLAGS` , `VALAFLAGS` , `LDFLAGS` and `LT_SYS_LIBRARY_PATH` to
the value of their corresponding rpm macros. `%set_build_flags` is automatically
called prior to the `%build` , `%check` , and `%install` phases so these flags can be
used by makefiles and other build tools.
You can opt out of this behavior by doing:
%undefine _auto_set_build_flags
If you do opt out of this behavior, you can still manually use `%set_build_flags`
by adding it to the `%build` section of your spec file or by using one of the
build system helper macros like `%configure` , `%cmake` , and `%meson` .
For packages which use autoconf to set up the build environment, use
the `%configure` macro to obtain the full complement of flags, like
this:
%configure
This will invoke `./configure` with arguments (such as
`--prefix=/usr` ) to adjust the paths to the packaging defaults. Prior
to that, some common problems in autotools scripts are automatically
patched across the source tree.
This will invoke the `./configure` with arguments (such as
`--prefix=/usr` ) to adjust the paths to the packaging defaults.
Prior to that, some common problems in autotools scripts are
automatically patched across the source tree.
As a side effect, this will set the environment variables `CFLAGS` ,
`CXXFLAGS` , `FFLAGS` , `FCFLAGS` , `LDFLAGS` and `LT_SYS_LIBRARY_PATH` ,
so they can be used by makefiles and other build tools. (However,
existing values for these variables are not overwritten.)
If your package does not use autoconf, you can still set the same
environment variables using
%set_build_flags
early in the `%build` section. (Again, existing environment variables
are not overwritten.) `%set_build_flags` does not perform autotools
script rewriting, unlike `%configure` .
Individual build flags are also available through RPM macros:
* `%{build_cc}` for the command name of the C compiler.
* `%{build_cxx}` for the command name of the C++ compiler.
* `%{build_cpp}` for the command name of the C-compatible preprocessor.
* `%{build_cflags}` for the C compiler flags (also known as the
`CFLAGS` variable).
`CFLAGS` variable). Also historically available as `%{optflags}` .
Furthermore, at the start of the `%build` section, the environment
variable `RPM_OPT_FLAGS` is set to this value.
* `%{build_cxxflags}` for the C++ compiler flags (usually assigned to
the `CXXFLAGS` shell variable).
* `%{build_fflags}` for `FFLAGS` (the Fortran compiler flags, also
* `%{build_fflags} for ` FFLAGS` (the Fortran compiler flags, also
known as the `FCFLAGS` variable).
* `%{build_valaflags}` for `VALAFLAGS` (the Vala compiler flags)
* `%{build_ldflags}` for the linker (`ld`) flags, usually known as
`LDFLAGS` . Note that the contents quote linker arguments using
* `%{build_ldflags}` for the link editor (ld) flags, usually known as
`LDFLAGS` . Note that the contents quotes linker arguments using
`-Wl` , so this variable is intended for use with the `gcc` compiler
driver. At the start of the `%build` section, the environment
driver. At the start of the `%build` section, the environment
variable `RPM_LD_FLAGS` is set to this value.
The C and C++ compiler flags are historically available as the
`%{optflags}` macro. These flags may not contain flags that work with
certain languagues or compiler front ends, so the language-specific
`%build_*` are more precise. At the start of the `%build` section,
the environment variable `RPM_OPT_FLAGS` is set to the `%{optflags}`
value; similar limitations apply.
The variable `LT_SYS_LIBRARY_PATH` is defined here to prevent the `libtool`
script (v2.4.6+) from hardcoding ` %_libdir` into the binaries' ` RPATH` .
script (v2.4.6+) from hardcoding %_libdir into the binaries' RPATH.
These RPM macros do not alter shell environment variables.
@ -114,67 +105,6 @@ or:
BuildRequires: clang compiler-rt
%endif
### Controlling Type Safety
The macro `%build_type_safety_c` can be set to change the C type
safety level. The default level is 3, see below. It can be set to 0
to get historic levels of type safety. Changing the type safety level
may depend on correct `CFLAGS` propagation during the build. The
`%build_type_safety_c` macro needs to be set before `CFLAGS` -related
macros are expanded by RPM (that is, earlier in the file works
better).
Packages can set `%build_type_safety_c` to higher values to adopt
future distribution-wide type-safety increases early. When changing
the `%build_type_safety_c` level to increase it, spec file should use
a construct like this to avoid *lowering* a future default:
```
%if %build_type_safety_c < 4
%global build_type_safety_c 4
%endif
```
At level 0, all C constructs that GCC accepts for backwards
compatibility with obsolete language standards are accepted during
package builds. This is achieved by passing `-fpermissive` to GCC.
At level 1, the following additional error categories are enabled:
* `-Werror=implicit-int` : Reject declarations and definitions that
omit a type name where one is required. Examples are:
`extern int_variable;` , `extern int_returning_function (void);` ,
and missing separate parameter type declarations in old-style
function definitions.
* `-Werror=implicit-function-declaration` : Reject calls to functions
to undeclared functions such as `function_not_defined_anywhere ()` .
Previously, such expressions where we compiled as if a declaration
`extern int function_not_defined_anywhere ();` (a prototype-less
function declaration) were in scope.
* `-Werror=return-mismatch` : Reject `return` statements with missing
or extra expressions, based on the declared return type of the
function.
* `-Wdeclaration-missing-parameter-type` : Reject function declarations
that contain unknown type names (which used to be treated as ignored
identifier names).
At level 2, the following error category is enabled in addition:
* `-Werror=int-conversion` : Reject the use of integer expressions
where a pointer type expected, and pointer expressions where an
integer type is expected. Without this option, GCC may produce an
executable, but often, there are failures at run time because not
the full 64 bits of pointers are preserved.
The additional level 3 error category is:
* `-Werror=incompatible-pointer-types` : An expression of one pointer
type is used where different pointer type is expected. (This does
not cover signed/unsigned mismatches in the pointer target type.)
Clang errors out on more obsolete and invalid C constructs than C, so
the type safety is higher by default than with the GCC toolchain.
### Disable autotools compatibility patching
By default, the invocation of the `%configure` macro replaces
@ -190,16 +120,6 @@ are set as well during libtool-. This can be switched off using:
Further patching happens in LTO mode, see below.
### Other autotools compatibility settings
During `%configure` , `--runstatedir` is automatically passed to the
`configure` script if support for this option is detected. This
detection can fail if the package has multiple `configure` scripts
that invoke each other, and only some of them support `--runstatedir` .
To disable passing `--runstatedir` , use:
%undefine _configure_use_runstatedir
### Disabling Link-Time Optimization
By default, builds use link-time optimization. In this build mode,
@ -209,7 +129,7 @@ account which symbols are exported.
To disable this optimization, include this in the spec file:
%global _lto_cflags %{nil}
%define _lto_cflags %{nil}
If LTO is enabled, `%configure` applies some common required fixes to
`configure` scripts. To disable that, define the RPM macro
@ -238,30 +158,6 @@ This turns off certain hardening features, as described in detail
below. The main difference is that executables will be
position-dependent (no full ASLR) and use lazy binding.
### Source Fortification
By default, the build flags include `-Wp,-D_FORTIFY_SOURCE=3` : Source
fortification activates various hardening features in glibc:
* String functions such as `memcpy` attempt to detect buffer lengths
and terminate the process if a buffer overflow is detected.
* `printf` format strings may only contain the `%n` format specifier
if the format string resides in read-only memory.
* `open` and `openat` flags are checked for consistency with the
presence of a *mode* argument.
* Plus other minor hardening changes.
These changes can, on rare occasions, break valid programs. The source
fortification level can be overridden by adding this in the RPM spec file:
%define _fortify_level 2
to reduce source fortification level to 2 or:
%undefine _fortify_level
to disable fortification altogether.
### Annotated builds/watermarking
By default, the build flags cause a special output section to be
@ -296,23 +192,6 @@ For example, this can be required if shared objects are used for their
side effects in ELF constructors, or for making them available to
dynamically loaded plugins.
### Switching to legacy relative relocations
By default, ELF objects use the architecture-independent `DT_RELR`
mechanism for relative relocations. To switch to the older,
architecture-specific relocation scheme, add this to the RPM spec file:
%undefine _ld_pack_relocs
This adds `-Wl,-z,pack-relative-relocs` to the linker flags (`LDFLAGS`).
### Specifying the build-id algorithm
If you want to specify a different build-id algorithm for your builds, you
can use the `%_build_id_flags` macro:
%_build_id_flags -Wl,--build-id=sha1
### Strict symbol checks in the link editor (ld)
Optionally, the link editor will refuse to link shared objects which
@ -327,7 +206,7 @@ executed before the shared object containing them is fully relocated.
To switch on these checks, define this macro in the RPM spec file:
%global _strict_symbol_defs_build 1
%define _strict_symbol_defs_build 1
If this RPM spec option is active, link failures will occur if the
linker command line does not list all shared objects which are needed.
@ -353,43 +232,10 @@ Builds may fail with `multiple definition of ...` errors.
As a short term workaround for such failure,
it is possible to add `-fcommon` to the flags by defining `%_legacy_common_support` .
%global _legacy_common_support 1
%define _legacy_common_support 1
Properly fixing the failure is always preferred!
### Package note on ELF objects
A note that describes the package name, version, and architecture is
inserted via a linker script (`%_package_note_file`). The script is
generated when `%set_build_flags` is called. The linker option that
injects the linker script is added to `%{build_ldflags}` via the
`%{_package_note_flags}` macro.
To opt out of the use of this feature completely, the best way is to
undefine the first macro. Include this in the spec file:
%undefine _package_note_file
The other macros can be undefined too to replace parts of the functionality.
If `%_generate_package_note_file` is undefined, the linker script will not
be generated, but the link flags may still refer to it. This may be useful
if the default generation method is insufficient and a different mechanism
will be used to generate `%_package_note_file` . If `%_package_note_flags`
is undefined, the linker argument that injects the script will not be added
to `%build_ldfags` , but the linker script would still be generated.
### Frame pointers
Frame pointers will be included by default via the `%_include_frame_pointers`
macro. To opt out, the best way is to undefine the macro. Include this in the
spec file:
%undefine _include_frame_pointers
Note that opting out might still result in frame pointers being included on
architectures where they are part of the ABI (e.g. aarch64) depending on
compiler defaults.
### Post-build ELF object processing
By default, DWARF debugging information is separated from installed
@ -455,8 +301,6 @@ These steps can be skipped by undefining the corresponding macros:
are loadable immediately after installation, even if they are not yet
listed in the `/etc/ld.so.cache` file (because `ldconfig` has not been
invoked yet).
* `__brp_remove_la_files` : This step removes libtool-generated `.la`
files from the installed files.
# Individual compiler flags
@ -465,11 +309,10 @@ Compiler flags end up in the environment variables `CFLAGS`,
The general (architecture-independent) build flags are:
* `-O2` : Turn on various GCC optimizations. See the
[GCC manual ](https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#index-O2 ).
* `-O2` : Turn on various GCC optimizations. See the [GCC manual ](https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#index-O2 ).
Optimization improves performance, the accuracy of warnings, and the
reach of toolchain-based hardening, but it makes debugging harder.
* `-g` : Generate debugging information (DWARF). In Fedora, this data
* `-g` : Generate debugging information (DWARF). In Fedora, this data
is separated into `-debuginfo` RPM packages whose installation is
optional, so debuging information does not increase the size of
installed binaries by default.
@ -478,19 +321,22 @@ The general (architecture-independent) build flags are:
compilation performance. (This does not affect code generation.)
* `-Wall` : Turn on various GCC warnings.
See the [GCC manual ](https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wall ).
* `-Wno-complain-wrong-lang` : Do not warn about front end mismatches
(e.g, using `-Werror=format-security` with Fortran). Only included
in `%optflags` , and not the front-end-specific `%build_*` macros.
* `-Werror=format-security` : Turn on format string warnings and treat
them as errors.
See the [GCC manual ](https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wformat-security ).
This can occasionally result in compilation errors. In that case,
This can occasionally result in compilation errors. In this case,
the best option is to rewrite the source code so that only constant
format strings (string literals) are used.
* Other `-Werror=` options. See **Controlling C Type Safety** .
* `-U_FORTIFY_SOURCE, -Wp,-U_FORTIFY_SOURCE -Wp,-D_FORTIFY_SOURCE=3` :
See the Source Fortification section above and the `%_fortify_level`
override.
* `-Wp,-D_FORTIFY_SOURCE=2` : Source fortification activates various
hardening features in glibc:
* String functions such as `memcpy` attempt to detect buffer lengths
and terminate the process if a buffer overflow is detected.
* `printf` format strings may only contain the `%n` format specifier
if the format string resides in read-only memory.
* `open` and `openat` flags are checked for consistency with the
presence of a *mode* argument.
* Plus other minor hardening changes.
(These changes can occasionally break valid programs.)
* `-fexceptions` : Provide exception unwinding support for C programs.
See the [`-fexceptions` option in the GCC
manual](https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#index-fexceptions)
@ -507,8 +353,7 @@ The general (architecture-independent) build flags are:
asynchronous cancellation and proper unwinding from signal
handlers. It also makes performance and debugging tools more
useful because unwind information is available without having to
install (and load) debugging information. (Not enabled on armhfp
due to architectural differences in stack management.)
install (and load) debugging information.
* `-Wp,-D_GLIBCXX_ASSERTIONS` : Enable lightweight assertions in the
C++ standard library, such as bounds checking for the subscription
operator on vectors. (This flag is added to both `CFLAGS` and
@ -525,8 +370,7 @@ The general (architecture-independent) build flags are:
vulnerabilities can result where the stack overlaps with the heap,
or thread stacks spill into other regions of memory.) This flag is
fully ABI-compatible and has adds very little run-time overhead.
This flag is currently not available on armhfp (both `gcc` and `clang`
toolchains) and on aarch64 with the `clang` toolchain.
This flag is currently not available on aarch64 with the `clang` toolchain.
* `-flto=auto` : Enable link-time optimization (LTO), using `make` job server
integration for parallel processing. (`gcc` toolchain only)
* `-ffat-lto-objects` : Generate EFL object files which contain both
@ -543,93 +387,67 @@ to disable them), the flag
`-specs=/usr/lib/rpm/redhat/redhat-hardened-cc1` is added to the
command line. It adds the following flag to the command line:
* `-fPIE` : Compile for a position-independent executable (PIE),
enabling full address space layout randomization (ASLR). This is
similar to `-fPIC` , but avoids run-time indirections on certain
architectures, resulting in improved performance and slightly
smaller executables. However, compared to position-dependent code
(the default generated by GCC), there is still a measurable
performance impact.
* `-fPIE` : Compile for a position-independent executable (PIE),
enabling full address space layout randomization (ASLR). This is
similar to `-fPIC` , but avoids run-time indirections on certain
architectures, resulting in improved performance and slightly
smaller executables. However, compared to position-dependent code
(the default generated by GCC), there is still a measurable
performance impact.
If the command line also contains `-r` (producing a relocatable
object file), `-fpic` or `-fPIC` , this flag is automatically
dropped. (`-fPIE` can only be used for code which is linked into
the main program.) Code which goes into static libraries should be
compiled with `-fPIE` , except when this code is expected to be
linked into DSOs, when `-fPIC` must be used.
If the command line also contains `-r` (producing a relocatable
object file), `-fpic` or `-fPIC` , this flag is automatically
dropped. (`-fPIE` can only be used for code which is linked into
the main program.) Code which goes into static libraries should be
compiled with `-fPIE` , except when this code is expected to be
linked into DSOs, when `-fPIC` must be used.
To be effective, `-fPIE` must be used with the `-pie` linker flag
when producing an executable, see below.
To be effective, `-fPIE` must be used with the `-pie` linker flag
when producing an executable, see below.
To support [binary watermarks for ELF
objects](https://fedoraproject.org/wiki/Toolchain/Watermark) using
annobin, the `-specs=/usr/lib/rpm/redhat/redhat-annobin-cc1` flag is
added by default (with the `gcc` toolchain). This can be switched off
by undefining the `%_annotated_build` RPM macro (see above). Binary
watermarks are currently disabled on armhpf, and with the `clang`
toolchain.
If frame pointers are enabled by default (via `%_include_frame_pointers` ),
the `-fno-omit-frame-pointer` will be added on all architectures except i686
and s390x. Additional flags will be added on specific architectures:
* `-mno-omit-leaf-frame-pointer` on x86_64 and aarch64
watermarks are currently disabled with the `clang` toolchain.
### Architecture-specific compiler flags
These compiler flags are enabled for all builds (hardened/annotated or
not), but their selection depends on the architecture:
* `-fcf-protection` : Instrument binaries to guard against
ROP/JOP exploitation techniques. Used on x86_64.
* `-mbranch-protection=standard` : Instrument binaries to guard against
ROP/JOP exploitation techniques. Used on aarch64.
* `-m64` and `-m32` : Some GCC builds support both 32-bit and 64-bit in
the same compilation. For such architectures, the RPM build process
explicitly selects the architecture variant by passing this compiler
flag.
* `-fcf-protection` : Instrument binaries to guard against
ROP/JOP attacks. Used on i686 and x86_64.
* `-m64` and `-m32` : Some GCC builds support both 32-bit and 64-bit in
the same compilation. For such architectures, the RPM build process
explicitly selects the architecture variant by passing this compiler
flag.
In addition, `redhat-rpm-config` re-selects the built-in default
tuning in the `gcc` package. These settings are:
* **armhfp** : `-march=armv7-a -mfpu=vfpv3-d16 -mfloat-abi=hard`
selects an Arm subarchitecture based on the ARMv7-A architecture
with 16 64-bit floating point registers. `-mtune=cortex-8a` selects
tuning for the Cortex-A8 implementation (while preserving
compatibility with other ARMv7-A implementations).
`-mabi=aapcs-linux` switches to the AAPCS ABI for GNU/Linux.
* **i686** : `-march=i686` is used to select a minmum support CPU level
of i686 (corresponding to the Pentium Pro). SSE2 support is enabled
with `-msse2` (so only CPUs with SSE2 support can run the compiled
code; SSE2 was introduced first with the Pentium 4).
`-mtune=generic` activates tuning for a current blend of CPUs (under
the assumption that most users of i686 packages obtain them through
an x86_64 installation on current hardware). `-mfpmath=sse`
instructs GCC to use the SSE2 unit for floating point math to avoid
excess precision issues. `-mstackrealign` avoids relying on the
stack alignment guaranteed by the current version of the i386 ABI.
* **ppc64le** : `-mcpu=power8 -mtune=power8` selects a minimum
supported CPU level of POWER8 (the first CPU with ppc64le support)
and tunes for POWER8.
* **s390x** : `-march=zEC12 -mtune=z13` specifies a minimum supported
CPU level of zEC12, while optimizing for a subsequent CPU generation
(z13).
* **x86_64** : `-mtune=generic` selects tuning which is expected to
beneficial for a broad range of current CPUs. Distribution-specific
defaults for `-march=x86-64-v2` or `-march=x86-64-v3` may be
applied. The default can be overriden (for any distribution)
by specifying `--target x86_64_v2` , `--target x86_64_v3` ,
`--target x86_64_v4` in the `rpmbuild` invocation.
With the GCC toolchain, TLS descriptors are enabled using
`-mtls-dialect=gnu2` .
* **aarch64** does not have any architecture-specific tuning.
### Vala-specific compiler flags
* `-g` : causes valac to emit `#line` directives in the generated C
source code. This improves backtrace generation by causing gdb to
point to Vala source file and line number instead of the generated C
source when possible.
* **i686** : `-march=i686` is used to select a minmum support CPU level
of i686 (corresponding to the Pentium Pro). SSE2 support is
enabled with `-msse2` (so only CPUs with SSE2 support can run the
compiled code; SSE2 was introduced first with the Pentium 4).
`-mtune=generic` activates tuning for a current blend of CPUs
(under the assumption that most users of i686 packages obtain them
through an x86_64 installation on current hardware).
`-mfpmath=sse` instructs GCC to use the SSE2 unit for floating
point math to avoid excess precision issues. `-mstackrealign`
avoids relying on the stack alignment guaranteed by the current
version of the i386 ABI.
* **ppc64le** : `-mcpu=power9 -mtune=power9` selects a minimum supported
CPU level of POWER9.
* **s390x** : `-march=z14 -mtune=z15` specifies a minimum supported CPU
level of z14, while optimizing for a subsequent CPU generation
(z15).
* **x86_64** : `-march=x86-64-v2 -mtune=generic` builds for the
[x86-64-v2 micro-architecture level ](https://gitlab.com/x86-psABIs/x86-64-ABI/-/blob/master/x86-64-ABI/low-level-sys-info.tex )
and selects tuning which is expected to beneficial for a broad range
of current CPUs.
* **aarch64** does not have any architecture-specific tuning.
# Individual linker flags
@ -649,16 +467,14 @@ to the compiler driver `gcc`, and not directly to the link editor
for shared objects that actually provide symbols required by the link.
Shared objects which are not needed to fulfill symbol dependencies
are essentially ignored due to this flag.
* `-z pack-relative-relocs` : Use the portable `DT_RELR` scheme for
relative relocations, resulting in reduced startup time compared to
legacy architecture-specific relocations. (`-z pack-relative-relocs`
is currently disabled on aarch64 and s390x due to toolchain limitations.)
* `-z defs` : Refuse to link shared objects (DSOs) with undefined symbols
(optional, see above).
For hardened builds, some more linker options are added to the
compiler driver command line. These can be disabled by undefining the
`%_hardened_build` macro - see above.
For hardened builds, the
`-specs=/usr/lib/rpm/redhat/redhat-hardened-ld` flag is added to the
compiler driver command line. (This can be disabled by undefining the
`%_hardened_build` macro; see above) This activates the following
linker flags:
* `-pie` : Produce a PIE binary. This is only activated for the main
executable, and only if it is dynamically linked. This requires
@ -667,10 +483,6 @@ compiler driver command line. These can be disabled by undefining the
By itself, `-pie` has only a slight performance impact because it
disables some link editor optimization, however the `-fPIE` compiler
flag has some overhead.
Note: this option is added via adding a spec file to the compiler
driver command line (`-specs=/usr/lib/rpm/redhat/redhat-hardened-ld`)
rather than using the `-Wl` mechanism mentioned above. As a result
this option is only enabled if the compiler driver is gcc.
* `-z now` : Disable lazy binding and turn on the `BIND_NOW` dynamic
linker feature. Lazy binding involves an array of function pointers
which is writable at run time (which could be overwritten as part of
@ -678,34 +490,6 @@ compiler driver command line. These can be disabled by undefining the
preferable to turn of lazy binding, although it increases startup
time.
In addition hardened builds default to converting a couple of linker
warning messages into errors, because they represent potential
missed hardening opportunities, and warnings in the linker's output are
often ignored. This behaviour can be turned off by undefining the
`%_hardened_build` macro as mentioned above, or by undefining the
`%_hardened_linker_errors` macro. The linker options enabled by this
feature are:
* `--error-rwx-segments` : Generates an error if an output binary would
contain a loadable memory segment with read, write and execute
permissions. It will also generate an error if a thread local
storage (TLS) segment is created with execute permission. The
error can be disabled on an individual basis by adding the
`--no-warn-rwx-segments` option to the linker command line.
* `--error-execstack` : Generates an error if an output binary would
contain a stack that is held in memory with execute permission.
If a binary is being intentionally created with an executable stack
then the linker command line option `-z execstack` can be used to
indicate this.
Note: these options are added via a spec file on the compiler driver
command line (`-specs=/usr/lib/rpm/redhat/redhat-hardened-ld-errors`)
rather than using the `-Wl` mechanism mentioned above. As a result
these options are only enabled if the compiler driver is gcc. In
addition the spec file only adds the options if the `-fuse-ld=...`
option has not been enabled. This prevents the options from being
used when the gold or lld linkers are enabled.
# Support for extension builders
Some packages include extension builders that allow users to build
@ -722,11 +506,16 @@ with such toolchains.
The macros `%{extension_cflags}` , `%{extension_cxxflags}` ,
`%{extension_fflags}` , `%{extension_ldflags}` contain a subset of
flags that have been adjusted for compatibility with alternative
toolchains.
toolchains, while still preserving some of the compile-time security
hardening that the standard Fedora build flags provide.
The current set of differences are:
* No GCC plugins (such as annobin) are activated.
* No GCC spec files (`-specs=` arguments) are used.
Currently the -fexceptions and -fcf-protection flags are preserved
for binary compatibility with the languages the extensions are
built against.
Additional flags may be removed in the future if they prove to be
incompatible with alternative toolchains.
Extension builders should detect whether they are performing a regular
RPM build (e.g., by looking for an `RPM_OPT_FLAGS` variable). In this