Packaging Friendliness: Compiler Flags to Avoid
It is tempting to enable some (generally useful) compiler flags
such as -Werror
and -march=native
in you build by default
(such as to discover more problems and generate more efficient
code), however in practice these flags may lead to packaging problems
instead.
TL;DR
Don’t add -Werror
and -march=native
to default build flags of
your project.
-Werror
This flag makes compiler reject code with warnings, forcing author to
fix all of them and thus write cleaner code, so it does make sense
to enable it for local builds and for continuous integration. However,
even if a code is warning-free for you right now, you cannot expect
it to remain so with future compiler versions or on different
compilers/arches/OSes, so with -Werror
your code is prone to break
in different environments as well as over time, which is best to avoid.
Such fragile code increases burden on maintainers (who are forced
to fix warnings in addition to critical problems when doing bulk
updates), and leads to unexpected build failures for end users (such
as after compiler update). In either case, it will likely be shut
up by patching out the -Werror
flag instead of fixing the warning,
so using -Werror
as a way to force consumers to submit warning
fixes upstream is not a good idea.
Enabling individual warnings (e.g. -Werror=uninitialized
) may be
an option, but it requires you to maintain a list of (still incomplete)
must-have warnings, keep it up to date and compatible with different
compilers.
So instead, consider looking for new warnings in package build logs (available on Repology for some distros, for instance) and try to use as many different environments for you CI as possible.
Example from FreeBSD Ports Collection of patching -Werror
out:
--- mpy-cross/Makefile.orig 2021-09-01 14:07:13 UTC
+++ mpy-cross/Makefile
@@ -17,7 +17,7 @@ INC += -I$(BUILD)
INC += -I$(TOP)
# compiler settings
-CWARN = -Wall -Werror
+CWARN = -Wall
CWARN += -Wextra -Wno-unused-parameter -Wpointer-arith
CFLAGS = $(INC) $(CWARN) -std=gnu99 $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA)
CFLAGS += -fdata-sections -ffunction-sections -fno-asynchronous-unwind-tables
-march=native
This flag enables optimizations for the CPU the code is built on.
Generally, enabling it allows compiler to generate more effective
code, however the problem with packages is that they are built on
completely different hardware than they are installed and used on.
Not only the code built for different CPU may have performance
regressions on users hardware, but it may not even run (usually
crashing with SIGILL
), because of using unsupported CPU features.
The additional danger of this flag is that it usually comes unnoticed by package maintainers and the problems caused by it are hard to reproduce. The code runs fine on maintainers hardware; it runs fine on package building cluster as well; even packages built on cluster run fine on maintainers hardware. However some user with slightly older hardware will experience (an unobvious to investigate) crash.
Example from FreeBSD Ports Collection of patching -march=native
out:
post-patch:
@${REINPLACE_CMD} -e 's/ -march=native//' \
${WRKSRC}/cmake/FindAVX.cmake \
${WRKSRC}/cmake/FindFMA.cmake \
${WRKSRC}/cmake/FindSSE.cmake