Blame SOURCES/buildflags.md

a008c1
This document contains documentation of the individual compiler flags
a008c1
and how to use them.
a008c1
a008c1
[TOC]
a008c1
a008c1
# Using RPM build flags
a008c1
a008c1
For packages which use autoconf to set up the build environment, use
a008c1
the `%configure` macro to obtain the full complement of flags, like
a008c1
this:
a008c1
a008c1
    %configure
a008c1
a008c1
This will invoke the `./configure` with arguments (such as
a008c1
`--prefix=/usr`) to adjust the paths to the packaging defaults.
0c6e2c
Prior to that, some common problems in autotools scripts are
0c6e2c
automatically patched across the source tree.
a008c1
a008c1
As a side effect, this will set the environment variables `CFLAGS`,
a008c1
`CXXFLAGS`, `FFLAGS`, `FCFLAGS`, and `LDFLAGS`, so they can be used by
a008c1
makefiles and other build tools.  (However, existing values for this
a008c1
variables are not overwritten.)
a008c1
a008c1
If your package does not use autoconf, you can still set the same
a008c1
environment variables using
a008c1
a008c1
    %set_build_flags
a008c1
a008c1
early in the `%build` section.  (Again, existing environment variables
0c6e2c
are not overwritten.)  `%set_build_flags` does not perform autotools
0c6e2c
script rewriting, unlike `%configure`.
a008c1
a008c1
Individual build flags are also available through RPM macros:
a008c1
a008c1
* `%{build_cflags}` for the C compiler flags (also known as the
a008c1
  `CFLAGS` variable).  Also historically available as `%{optflags}`.
a008c1
  Furthermore, at the start of the `%build` section, the environment
a008c1
  variable `RPM_OPT_FLAGS` is set to this value.
a008c1
* `%{build_cxxflags}` for the C++ compiler flags (usually assigned to
a008c1
  the `CXXFLAGS` shell variable).
a008c1
* `%{build_fflags} for `FFLAGS` (the Fortran compiler flags, also
a008c1
  known as the `FCFLAGS` variable).
a008c1
* `%{build_ldflags}` for the link editor (ld) flags, usually known as
a008c1
  `LDFLAGS`.  Note that the contents quotes linker arguments using
a008c1
  `-Wl`, so this variable is intended for use with the `gcc` compiler
a008c1
  driver.  At the start of the `%build` section, the environment
a008c1
  variable `RPM_LD_FLAGS` is set to this value.
a008c1
a008c1
These RPM macros do not alter shell environment variables.
a008c1
a008c1
For some other build tools separate mechanisms exist:
a008c1
a008c1
* CMake builds use the the `%cmake` macro from the `cmake-rpm-macros`
a008c1
  package.
a008c1
a008c1
Care must be taking not to compile the current selection of compiler
a008c1
flags into any RPM package besides `redhat-rpm-config`, so that flag
a008c1
changes are picked up automatically once `redhat-rpm-config` is
a008c1
updated.
a008c1
a008c1
# Flag selection for the build type
a008c1
a008c1
The default flags are suitable for building applications.
a008c1
a008c1
For building shared objects, you must compile with `-fPIC` in
a008c1
(`CFLAGS` or `CXXFLAGS`) and link with `-shared` (in `LDFLAGS`).
a008c1
a008c1
For other considerations involving shared objects, see:
a008c1
a008c1
* [Fedora Packaging Guidelines: Shared Libraries](https://fedoraproject.org/wiki/Packaging:Guidelines#Shared_Libraries)
a008c1
0c6e2c
# Customizing compiler and other build flags
a008c1
a008c1
It is possible to set RPM macros to change some aspects of the
a008c1
compiler flags.  Changing these flags should be used as a last
0c6e2c
recourse if other workarounds are not available.
0c6e2c
0c6e2c
### Disable autotools compatibility patching
0c6e2c
0c6e2c
By default, the invocation of the `%configure` macro replaces
0c6e2c
`config.guess` files in the source tree with the system version.  To
0c6e2c
disable that, define this macro:
0c6e2c
0c6e2c
    %global _configure_gnuconfig_hack 0
0c6e2c
0c6e2c
`%configure` also patches `ltmain.sh` scripts, so that linker flags
0c6e2c
are set as well during libtool-.  This can be switched off using:
0c6e2c
0c6e2c
    %global _configure_libtool_hardening_hack 0
a008c1
a008c1
### Lazy binding
a008c1
a008c1
If your package depends on the semantics of lazy binding (e.g., it has
a008c1
plugins which load additional plugins to complete their dependencies,
a008c1
before which some referenced functions are undefined), you should put
a008c1
`-Wl,-z,lazy` at the end of the `LDFLAGS` setting when linking objects
a008c1
which have such requirements.  Under these circumstances, it is
a008c1
unnecessary to disable hardened builds (and thus lose full ASLR for
a008c1
executables), or link everything without `-Wl,z,now` (non-lazy
a008c1
binding).
a008c1
a008c1
### Hardened builds
a008c1
a008c1
By default, the build flags enable fully hardened builds.  To change
a008c1
this, include this in the RPM spec file:
a008c1
a008c1
    %undefine _hardened_build
a008c1
a008c1
This turns off certain hardening features, as described in detail
a008c1
below.  The main difference is that executables will be
a008c1
position-dependent (no full ASLR) and use lazy binding.
a008c1
a008c1
### Annotated builds/watermarking
a008c1
a008c1
By default, the build flags cause a special output section to be
a008c1
included in ELF files which describes certain aspects of the build.
a008c1
To change this for all compiler invocations, include this in the RPM
a008c1
spec file:
a008c1
a008c1
    %undefine _annotated_build
a008c1
a008c1
Be warned that this turns off watermarking, making it impossible to do
a008c1
full hardening coverage analysis for any binaries produced.
a008c1
a008c1
It is possible to disable annotations for individual compiler
a008c1
invocations, using the `-fplugin-arg-annobin-disable` flag.  However,
a008c1
the annobin plugin must still be loaded for this flag to be
a008c1
recognized, so it has to come after the hardening flags on the command
a008c1
line (it has to be added at the end of `CFLAGS`, or specified after
a008c1
the `CFLAGS` variable contents).
a008c1
a008c1
### Strict symbol checks in the link editor (ld)
a008c1
a008c1
Optionally, the link editor will refuse to link shared objects which
a008c1
contain undefined symbols.  Such symbols lack symbol versioning
a008c1
information and can be bound to the wrong (compatibility) symbol
a008c1
version at run time, and not the actual (default) symbol version which
a008c1
would have been used if the symbol definition had been available at
a008c1
static link time.  Furthermore, at run time, the dynamic linker will
a008c1
not have complete dependency information (in the form of DT_NEEDED
a008c1
entries), which can lead to errors (crashes) if IFUNC resolvers are
a008c1
executed before the shared object containing them is fully relocated.
a008c1
a008c1
To switch on these checks, define this macro in the RPM spec file:
a008c1
a008c1
    %define _strict_symbol_defs_build 1
a008c1
a008c1
If this RPM spec option is active, link failures will occur if the
a008c1
linker command line does not list all shared objects which are needed.
a008c1
In this case, you need to add the missing DSOs (with linker arguments
a008c1
such as `-lm`).  As a result, the link editor will also generated the
a008c1
necessary DT_NEEDED entries.
a008c1
a008c1
In some cases (such as when a DSO is loaded as a plugin and is
a008c1
expected to bind to symbols in the main executable), undefined symbols
a008c1
are expected.  In this case, you can add
a008c1
a008c1
    %undefine _strict_symbol_defs_build
a008c1
a008c1
to the RPM spec file to disable these strict checks.  Alternatively,
a008c1
you can pass `-z undefs` to ld (written as `-Wl,-z,undefs` on the gcc
a008c1
command line).  The latter needs binutils 2.29.1-12.fc28 or later.
a008c1
0c6e2c
### Post-build ELF object processing
0c6e2c
0c6e2c
By default, DWARF debugging information is separated from installed
0c6e2c
ELF objects and put into `-debuginfo` subpackages.  To disable most
0c6e2c
debuginfo processing (and thus the generation of these subpackages),
0c6e2c
define `_enable_debug_packages` as `0`.
0c6e2c
0c6e2c
Processing of debugging information is controlled using the
0c6e2c
`find-debuginfo` tool from the `debugedit` package.  Several aspects
0c6e2c
of its operation can be controlled at the RPM level.
0c6e2c
0c6e2c
* Creation of `-debuginfo` subpackages is enabled by default.
0c6e2c
  To disable, undefine `_debuginfo_subpackages`.
0c6e2c
* Likewise, `-debugsource` subpackages are automatically created.
0c6e2c
  To disable, undefine `_debugsource_subpackages`.
0c6e2c
  See [Separate Subpackage and Source Debuginfo](https://fedoraproject.org/wiki/Changes/SubpackageAndSourceDebuginfo)
0c6e2c
  for background information.
0c6e2c
* `_build_id_links`, `_unique_build_ids`, `_unique_debug_names`,
0c6e2c
  `_unique_debug_srcs` control how debugging information and
0c6e2c
  corresponding source files are represented on disk.
0c6e2c
  See `/usr/lib/rpm/macros` for details.  The defaults
0c6e2c
  enable parallel installation of `-debuginfo` packages for
0c6e2c
  different package versions, as described in
0c6e2c
  [Parallel Installable Debuginfo](https://fedoraproject.org/wiki/Changes/ParallelInstallableDebuginfo).
0c6e2c
* By default, a compressed symbol table is preserved in the
0c6e2c
  `.gnu_debugdata` section.  To disable that, undefine
0c6e2c
  `_include_minidebuginfo`.
0c6e2c
* To speed up debuggers, a `.gdb_index` section is created.  It can be
0c6e2c
  disabled by undefining `_include_gdb_index`.
0c6e2c
* Missing build IDs result in a build failure.  To ignore such
0c6e2c
  problems, undefine `_missing_build_ids_terminate_build`.
0c6e2c
* During processing, build IDs are recomputed to match the binary
0c6e2c
  content.  To skip this step, define `_no_recompute_build_ids` as `1`.
0c6e2c
* By default, the options in `_find_debuginfo_dwz_opts` turn on `dwz`
0c6e2c
  (DWARF compression) processing.  Undefine this macro to disable this
0c6e2c
  step.
0c6e2c
* Additional options can be passed by defining the
0c6e2c
  `_find_debuginfo_opts` macro.
0c6e2c
0c6e2c
After separation of debugging information, additional transformations
0c6e2c
are applied, most of them also related to debugging information.
0c6e2c
These steps can be skipped by undefining the corresponding macros:
0c6e2c
0c6e2c
* `__brp_strip`: Removal of leftover debugging information.  The tool
0c6e2c
  specified by the `__strip` macro is invoked with the `-g` option on
0c6e2c
  ELF object (`.o`) files.
0c6e2c
* `__brp_strip_static_archive`: This is similar to `__brp_strip`, but
0c6e2c
  processes static `.a` archives instead.
0c6e2c
* `__brp_strip_comment_note`: This step removes unallocated `.note`
0c6e2c
  sections, and `.comment` sections from ELF files.
0c6e2c
* `__brp_ldconfig`: For each shared object on the library search path
0c6e2c
  whose soname does not match its file name, a symbolic link from the
0c6e2c
  soname to the file name is created.  This way, these shared objects
0c6e2c
  are loadable immediately after installation, even if they are not yet
0c6e2c
  listed in the `/etc/ld.so.cache` file (because `ldconfig` has not been
0c6e2c
  invoked yet).
0c6e2c
a008c1
# Individual compiler flags
a008c1
a008c1
Compiler flags end up in the environment variables `CFLAGS`,
a008c1
`CXXFLAGS`, `FFLAGS`, and `FCFLAGS`.
a008c1
a008c1
The general (architecture-independent) build flags are:
a008c1
a008c1
* `-O2`: Turn on various GCC optimizations.  See the [GCC manual](https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#index-O2).
a008c1
  Optimization improves performance, the accuracy of warnings, and the
a008c1
  reach of toolchain-based hardening, but it makes debugging harder.
a008c1
* `-g`: Generate debugging information (DWARF).  In Fedora, this data
a008c1
  is separated into `-debuginfo` RPM packages whose installation is
a008c1
  optional, so debuging information does not increase the size of
a008c1
  installed binaries by default.
a008c1
* `-pipe`: Run compiler and assembler in parallel and do not use a
a008c1
  temporary file for the assembler input.  This can improve
a008c1
  compilation performance.  (This does not affect code generation.)
a008c1
* `-Wall`: Turn on various GCC warnings.
a008c1
  See the [GCC manual](https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wall).
a008c1
* `-Werror=format-security`: Turn on format string warnings and treat
a008c1
  them as errors.
a008c1
  See the [GCC manual](https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wformat-security).
a008c1
  This can occasionally result in compilation errors.  In this case,
a008c1
  the best option is to rewrite the source code so that only constant
a008c1
  format strings (string literals) are used.
a008c1
* `-Wp,-D_FORTIFY_SOURCE=2`: Source fortification activates various
a008c1
  hardening features in glibc:
a008c1
    * String functions such as `memcpy` attempt to detect buffer lengths
a008c1
      and terminate the process if a buffer overflow is detected.
a008c1
    * `printf` format strings may only contain the `%n` format specifier
a008c1
      if the format string resides in read-only memory.
a008c1
    * `open` and `openat` flags are checked for consistency with the
a008c1
      presence of a *mode* argument.
a008c1
    * Plus other minor hardening changes.
a008c1
  (These changes can occasionally break valid programs.)
a008c1
* `-fexceptions`: Provide exception unwinding support for C programs.
a008c1
  See the [`-fexceptions` option in the GCC
a008c1
  manual](https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#index-fexceptions)
a008c1
  and the [`cleanup` variable
a008c1
  attribute](https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-cleanup-variable-attribute).
a008c1
  This also hardens cancellation handling in C programs because
a008c1
  it is not required to use an on-stack jump buffer to install
a008c1
  a cancellation handler with `pthread_cleanup_push`.  It also makes
a008c1
  it possible to unwind the stack (using C++ `throw` or Rust panics)
a008c1
  from C callback functions if a C library supports non-local exits
a008c1
  from them (e.g., via `longjmp`).
a008c1
* `-Wp,-D_GLIBCXX_ASSERTIONS`: Enable lightweight assertions in the
a008c1
  C++ standard library, such as bounds checking for the subscription
a008c1
  operator on vectors.  (This flag is added to both `CFLAGS` and
a008c1
  `CXXFLAGS`; C compilations will simply ignore it.)
a008c1
* `-fstack-protector-strong`: Instrument functions to detect
a008c1
  stack-based buffer overflows before jumping to the return address on
a008c1
  the stack.  The *strong* variant only performs the instrumentation
a008c1
  for functions whose stack frame contains addressable local
a008c1
  variables.  (If the address of a variable is never taken, it is not
a008c1
  possible that a buffer overflow is caused by incorrect pointer
a008c1
  arithmetic involving a pointer to that variable.)
0c6e2c
* `-fstack-clash-protection`: Turn on instrumentation to avoid
0c6e2c
  skipping the guard page in large stack frames.  (Without this flag,
0c6e2c
  vulnerabilities can result where the stack overlaps with the heap,
0c6e2c
  or thread stacks spill into other regions of memory.)  This flag is
0c6e2c
  fully ABI-compatible and has adds very little run-time overhead.
a008c1
* `-grecord-gcc-switches`: Include select GCC command line switches in
a008c1
  the DWARF debugging information.  This is useful for detecting the
a008c1
  presence of certain build flags and general hardening coverage.
a008c1
a008c1
For hardened builds (which are enabled by default, see above for how
a008c1
to disable them), the flag
a008c1
`-specs=/usr/lib/rpm/redhat/redhat-hardened-cc1` is added to the
a008c1
command line.  It adds the following flag to the command line:
a008c1
a008c1
*   `-fPIE`: Compile for a position-independent executable (PIE),
a008c1
    enabling full address space layout randomization (ASLR).  This is
a008c1
    similar to `-fPIC`, but avoids run-time indirections on certain
a008c1
    architectures, resulting in improved performance and slightly
a008c1
    smaller executables.  However, compared to position-dependent code
a008c1
    (the default generated by GCC), there is still a measurable
a008c1
    performance impact.
a008c1
a008c1
    If the command line also contains `-r` (producing a relocatable
a008c1
    object file), `-fpic` or `-fPIC`, this flag is automatically
a008c1
    dropped.  (`-fPIE` can only be used for code which is linked into
a008c1
    the main program.) Code which goes into static libraries should be
a008c1
    compiled with `-fPIE`, except when this code is expected to be
a008c1
    linked into DSOs, when `-fPIC` must be used.
a008c1
a008c1
    To be effective, `-fPIE` must be used with the `-pie` linker flag
a008c1
    when producing an executable, see below.
a008c1
a008c1
To support [binary watermarks for ELF
a008c1
objects](https://fedoraproject.org/wiki/Toolchain/Watermark) using
a008c1
annobin, the `-specs=/usr/lib/rpm/redhat/redhat-annobin-cc1` flag is
a008c1
added by default.  This can be switched off by undefining the
a008c1
`%_annotated_build` RPM macro (see above).
a008c1
a008c1
### Architecture-specific compiler flags
a008c1
a008c1
These compiler flags are enabled for all builds (hardened/annotated or
a008c1
not), but their selection depends on the architecture:
a008c1
a008c1
*   `-fcf-protection`: Instrument binaries to guard against
a008c1
    ROP/JOP attacks.  Used on i686 and x86_64.
a008c1
*   `-m64` and `-m32`: Some GCC builds support both 32-bit and 64-bit in
a008c1
    the same compilation.  For such architectures, the RPM build process
a008c1
    explicitly selects the architecture variant by passing this compiler
a008c1
    flag.
a008c1
*   `-fasynchronous-unwind-tables`: Generate full unwind information
a008c1
    covering all program points.  This is required for support of
a008c1
    asynchronous cancellation and proper unwinding from signal
a008c1
    handlers.  It also makes performance and debugging tools more
a008c1
    useful because unwind information is available without having to
a008c1
    install (and load) debugging ienformation.
a008c1
    Asynchronous unwind tables are enabled for aarch64, i686, s390x,
0c6e2c
    and x86_64.  They are not needed on ppc64le due
a008c1
    to architectural differences in stack management.  On these
a008c1
    architectures, `-fexceptions` (see above) still enables regular
a008c1
    unwind tables (or they are enabled by default even without this
a008c1
    option).
a008c1
*   `-funwind-tables`: A subset of the unwind information restricted
0c6e2c
    to actual call sites.  Used on ppc64le.  Also implied by
a008c1
    `-fexceptions`.
a008c1
a008c1
In addition, `redhat-rpm-config` re-selects the built-in default
a008c1
tuning in the `gcc` package.  These settings are:
a008c1
a008c1
*   **i686**: `-march=x86-64` is used to select a minimum supported
a008c1
    CPU level matching the baseline for the x86_64 architecture.
a008c1
    `-mtune=generic` activates tuning for a current blend of CPUs.
a008c1
    `-mfpmath=sse` uses the SSE2 unit for floating point math,
a008c1
    instead of the legacy i387 FPU, avoiding issues related to excess
a008c1
    precision.  `-mstackrealign` ensures that the generated code
a008c1
    does not assume 16-byte stack alignment (as required by the current
a008c1
    i386 ABI), but stays compatible with application code compiled
a008c1
    before the introduction of 16-byte stack alignment along with SSE2
a008c1
    support.
a008c1
*   **ppc64le**: `-mcpu=power8 -mtune=power8` selects a minimum supported
a008c1
    CPU level of POWER8 (the first CPU with ppc64le support) and tunes
a008c1
    for POWER8.
a008c1
*   **s390x**: `-march=z13 -mtune=z14` specifies a minimum supported CPU
a008c1
    level of z13, while optimizing for a subsequent CPU generation
a008c1
    (z14).
a008c1
*   **x86_64**: `-mtune=generic` selects tuning which is expected to
a008c1
     beneficial for a broad range of current CPUs.
0c6e2c
*   **aarch64** does not have any architecture-specific tuning.
a008c1
a008c1
# Individual linker flags
a008c1
a008c1
Linker flags end up in the environment variable `LDFLAGS`.
a008c1
a008c1
The linker flags listed below are injected.  Note that they are
a008c1
prefixed with `-Wl` because it is expected that these flags are passed
a008c1
to the compiler driver `gcc`, and not directly to the link editor
a008c1
`ld`.
a008c1
a008c1
* `-z relro`: Activate the *read-only after relocation* feature.
a008c1
  Constant data and relocations are placed on separate pages, and the
a008c1
  dynamic linker is instructed to revoke write permissions after
a008c1
  dynamic linking.  Full protection of relocation data requires the
a008c1
  `-z now` flag (see below).
a008c1
* `-z defs`: Refuse to link shared objects (DSOs) with undefined symbols
a008c1
  (optional, see above).
a008c1
a008c1
For hardened builds, the
a008c1
`-specs=/usr/lib/rpm/redhat/redhat-hardened-ld` flag is added to the
a008c1
compiler driver command line.  (This can be disabled by undefining the
a008c1
`%_hardened_build` macro; see above) This activates the following
a008c1
linker flags:
a008c1
a008c1
* `-pie`: Produce a PIE binary.  This is only activated for the main
a008c1
  executable, and only if it is dynamically linked.  This requires
a008c1
  that all objects which are linked in the main executable have been
a008c1
  compiled with `-fPIE` or `-fPIC` (or `-fpie` or `-fpic`; see above).
a008c1
  By itself, `-pie` has only a slight performance impact because it
a008c1
  disables some link editor optimization, however the `-fPIE` compiler
a008c1
  flag has some overhead.
a008c1
* `-z now`: Disable lazy binding and turn on the `BIND_NOW` dynamic
a008c1
  linker feature.  Lazy binding involves an array of function pointers
a008c1
  which is writable at run time (which could be overwritten as part of
a008c1
  security exploits, redirecting execution).  Therefore, it is
a008c1
  preferable to turn of lazy binding, although it increases startup
a008c1
  time.
a008c1
a008c1
# Support for extension builders
a008c1
a008c1
Some packages include extension builders that allow users to build
a008c1
extension modules (which are usually written in C and C++) under the
a008c1
control of a special-purpose build system.  This is a common
a008c1
functionality provided by scripting languages such as Python and Perl.
a008c1
Traditionally, such extension builders captured the Fedora build flags
a008c1
when these extension were built.  However, these compiler flags are
a008c1
adjusted for a specific Fedora release and toolchain version and
a008c1
therefore do not work with a custom toolchain (e.g., different C/C++
a008c1
compilers), and users might want to build their own extension modules
a008c1
with such toolchains.
a008c1
a008c1
The macros `%{extension_cflags}`, `%{extension_cxxflags}`,
a008c1
`%{extension_fflags}`, `%{extension_ldflags}` contain a subset of
a008c1
flags that have been adjusted for compatibility with alternative
a008c1
toolchains, while still preserving some of the compile-time security
a008c1
hardening that the standard Fedora build flags provide.
a008c1
a008c1
The current set of differences are:
a008c1
a008c1
* No GCC plugins (such as annobin) are activated.
a008c1
* No GCC spec files (`-specs=` arguments) are used.
a008c1
a008c1
Additional flags may be removed in the future if they prove to be
a008c1
incompatible with alternative toolchains.
a008c1
a008c1
Extension builders should detect whether they are performing a regular
a008c1
RPM build (e.g., by looking for an `RPM_OPT_FLAGS` variable).  In this
a008c1
case, they should use the *current* set of Fedora build flags (that
a008c1
is, the output from `rpm --eval '%{build_cflags}'` and related
a008c1
commands).  Otherwise, when not performing an RPM build, they can
a008c1
either use hard-coded extension builder flags (thus avoiding a
a008c1
run-time dependency on `redhat-rpm-config`), or use the current
a008c1
extension builder flags (with a run-time dependency on
a008c1
`redhat-rpm-config`).
a008c1
a008c1
As a result, extension modules built for Fedora will use the official
a008c1
Fedora build flags, while users will still be able to build their own
a008c1
extension modules with custom toolchains.