Typical makefiles often use the built-in variables CFLAGS
, CXXFLAGS
, CPPFLAGS
and so on1 to set the flags passed to the C, C++ or other compilers/tools. In principle, this sometimes even lets you avoid writing a compilation recipe entirely since the various built-in rules use these flags.
In general, a makefile might add things to the FLAGS
variables that are required for the code to compile, such as include directories, arguments indicating which language standard to use and so on. The variables might also include "optional" or "default" arguments, such as optimization level, warning level and other settings that might validly be altered or removed.
Since CFLAGS
and fields are "well known" variables, they are also apparently a configuration point for end users. For example, if a project compiles without debug information by default, it is expected that CFLAGS=-g
on the make
command line causes -g
to be added to the $(CC) compiler command line and hence cause debug info to be produced. Similarly for other options the end user might want to control, such as the optimization level, the -march
setting on gcc, and so on.
However, these two uses seem incompatible to me. If the user overrides $(CFLAGS)
they will obliterate any internal "required" flags as described above, and the project either may not compile or may compile incorrectly.
Is there a best practice for handling this? The same problem doesn't really arise for "single value" variables like $(CC)
since they generally have exactly one value: in this example, the C compiler to use. If the user overrides it, you use their value. Things like $(CFLAGS)
are in principle a list of values, some of which are internal and shouldn't be overridden, an others which a user may want to override.
Intuitively, a solution seems to be to leave $(CFLAGS)
and friends empty and unused in your makefile, preferring say CFLAGS_INTERNAL
for in-makefile arguments, and then put both on the command line. I'm curious, however, if there is a best practice around this or if I'm missing something obvious.
1 For the rest of this question I will often simply refer to $(CFLAGS)
with the understanding that this is simply a convenient representative of the whole family of well known compiler flag variables such as $(CPPFLAGS)
, $(CXXFLAGS)
and so on.