Setting per-file flags with automake - linux

Is there a way set flags on a per-file basis with automake?
In particular, if I have a c++ project and want to compile with -WAll all the files except one for which I want to disable a particular warning, what could I do?
I tried something like:
CXXFLAGS = -WAll ...
bin_PROGRAMS = test
test_SOURCES = main.cpp utility.cpp
utility_o_CXXFLAGS = $(CXXFLAGS) -Wno-unused-value
but it didn't work.
EDITED: removed reference to automake manual, which was actually misleading (thanks to Douglas Leeder).

You can't do this with automake... but can do with make =) Add following line to your Makefile.am:
utility.$(OBJEXT) : CXXFLAGS += -Wno-unused-value
See GNU Make documentation : Target-specific Variable Values for details.

Automake only supports per-target flags, while you want per-object flags. One way around is to create a small library that contains your object:
CXXFLAGS = -Wall ...
bin_PROGRAMS = test
test_SOURCES = main.cpp
test_LDADD = libutility.a
noinst_LIBRARIES = libutility.a
libutility_a_SOURCES = utility.cpp
libutility_a_CXXFLAGS = $(CXXFLAGS) -Wno-unused-value

You've got confused - that section is referring to options to automake itself.
It's a way of setting the automake command-line options:
-W CATEGORY
--warnings=category
Output warnings falling in category. category can be one of:
gnu
warnings related to the GNU Coding Standards (see Top).
obsolete
obsolete features or constructions
override
user redefinitions of Automake rules or variables
portability
portability issues (e.g., use of make features that are known to be not portable)
syntax
weird syntax, unused variables, typos
unsupported
unsupported or incomplete features
all
all the warnings
none
turn off all the warnings
error
treat warnings as errors
A category can be turned off by prefixing its name with ‘no-’.
For instance, -Wno-syntax will hide the
warnings about unused variables.
The categories output by default are ‘syntax’ and ‘unsupported’.
Additionally, ‘gnu’ and ‘portability’
are enabled in --gnu and --gnits
strictness.
The environment variable WARNINGS can contain a comma separated list of
categories to enable. It will be taken
into account before the command-line
switches, this way -Wnone will also
ignore any warning category enabled by
WARNINGS. This variable is also used
by other tools like autoconf; unknown
categories are ignored for this
reason.
The per-file listed in section 17 refers to per-Makefile not source file.
I'm not aware of any per-source file flag setting, but you can set the option for each result binary with:
binaryname_CXXFLAGS

Related

How to pass arbitrary compiler CFLAGS with Scons from the command line without custom code?

Is there a way to write something like:
scons CFLAGS='-fsanitize=address -fsanitize=thread'
which would just work with a minimal script:
env = Environment()
env.Program(target='main.out', source=['main.c'])
without changing that script?
I know how to do it by modifying the script with AddOption + env.Append(CCFLAGS but I'm wondering it it is possible without changing the code to explicitly support it.
I ended up going with:
env = Environment()
env.Append(CCFLAGS='-Werror')
env.Append(CCFLAGS=ARGUMENTS.get('CCFLAGS', ''))
env.Program(target='main.out', source=['main.c'])
which can be used as:
scons CCFLAGS='-Wall -pedantic'
and will compile as:
gcc -o main.o -c -Werror -Wall -pedantic main.c
You likely want to keep the env.Append(CCFLAGS=ARGUMENTS.get('CCFLAGS', '')) line as the very last change made to CCFLAGS, since this will allow overriding the defaults on the command line: GCC tends to just use the last value seen as the actual one.
TODO: how to make it work with Variables? This would be nicer since we can get more error checking and the help message generation:
variables = Variables(None, ARGUMENTS)
variables.Add('CCFLAGS', 'my help', '')
env = Environment(variables)
env.Append(CCFLAGS='$CCFLAGS')
env.Append(CCFLAGS=['-Werror'])
env.Program(
source=['main.c'],
target='main.out',
)
Help(variables.GenerateHelpText(env))
but this fails due to bad quoting:
gcc -o main.o -c "-Wall -pedantic" -Werror main.c
This is not possible by design (without explicitly changing the build scripts). From the answer to #1 of the most-frequently-asked questions in our FAQ:
SCons does not automatically propagate the external environment used
to execute 'scons' to the commands used to build target files. This is
so that builds will be guaranteed repeatable regardless of the
environment variables set at the time scons is invoked. This also
means that if the compiler or other commands that you want to use to
build your target files are not in standard system locations, SCons
will not find them unless you explicitly set the PATH to include those
locations.

Understanding the role of automatic variables in make/makefile

I've recently started learning about make/makefiles and some of its associated concepts. I have thus far created some basic versions, with targets, dependencies, actions, etc. However, I have been unable to make sense of what automatic variables are in this context, their utility, or how to use them.
I've done a lot of research on this topic. However, I haven't been able to locate any satisfying material. It seems that the most reputable source of information is this GNU page. However, I still do not understand exactly what automatic variables are, what their utility is, or how I can practically use them in my makefiles.
I am interested to find out what they are, what their utility is, and how I can practically use them.
Automatic variables are simply variables for which the value is generated by Make, rather than having to be set explicitly.
If you take a look at existing Makefiles (pick your favorite open source project!), you'll find lots of practical examples to help you out. A common one looks something like this:
%.o: %.c
gcc -c -o $# $<
This is a pattern rule that says "to build a file named <something>.o, which depends on <something.c>, use the command gcc -c -o $# $<. $# is an automatic variable that evaluates to the target of the rule, and $< is an automatic variable which evaluates to the first prerequisite of the rule. These automatic variables are critical to this sort of pattern rule; they allow you to run make foo.o or make bar.o and have the appropriate values substituted into the command line. E.g., if you type make foo.o, Make will try to run:
gcc -c -o foo.o foo.c
Or consider this example from the git Makefile:
strip: $(PROGRAMS) git$X
$(STRIP) $(STRIP_OPTS) $^
This is used to strip symbol information from object files. It needs to operate on all of the prerequisites, so it uses $^, which evaluates to...a space-separated list of all the prerequisites.

Using AM_INIT_AUTOMAKE parameters and configure script command line parameters

Is it possible to use both command line parameters to the configure script, ala:
../configure CXXFLAGS=-O0 -g -foo -bar -bat
while simultaneously keeping any options that are passed to AM_INIT_AUTOMAKE in the configure.ac file? e.g.:
AM_INIT_AUTOMAKE([-Wall -Werror])
My desired result is that ALL of the above flags are passed along, e.g.:
-O0 -g -foo -bar -bat -Wall -Werror
It appears that specifying CXXFLAGS on the command line either ingores or overwrites what is passed into AM_INIT_AUTOMAKE. If anyone knows of a way to do the union of the two sets, that would be extremely helpful. Thx!
The -W warning categories options have nothing to do with C[XX]FLAGS. These are command line arguments used when invoking automake.
Conversely, the AM_INIT_AUTOMAKE options like -Wall don't affect the compiler flags. It's just the decision to use these switch names that is resulting in the confusion. They have a similar meaning, e.g., -Werror will treat automake warnings as errors, but are totally unrelated.
In short, you have to pass -Wall, etc., in C[XX]FLAGS to influence the compiler. And add -Wall to AM_INIT_AUTOMAKE to enable all warning categories when automake is invoked.

Kernel module compilation and KBUILD_NOPEDANTIC

I've noticed that recent kernels (starting from 2.16.24?) don't like if CFLAGS is changed in external module Kbuild file. If CFLAGS is changed you'll be issued the following error by Linux kernel Kbuild system:
scripts/Makefile.build:46: *** CFLAGS was changed in "/some/path". Fix it to use EXTRA_CFLAGS. Stop.
From here:
External modules have in a few cases modifed gcc option
by modifying CFLAGS. This has never been documented and
was a bad practice.
Additional email from LKML.
Why is it bad idea? What is rational?
First of all, it might be worth mentioning that EXTRA_CFLAGS has been deprecated a while ago and is replaced by ccflags-y. You can read about the intention of ccflags-y in Documentation/kbuild/makefiles.txt, section 3.7.
Basically, this variable allows you to append settings to the set of C compilation flags, within the scope of the file where it is assigned only. You are not supposed to change the global flags, because that might have a global impact beyond your own makefile, which is considered bad practice. The check that you mention verifies that indeed, the global flags did not get changed by included makefiles.
It is interesting to check out how ccflags-y, formerly known as EXTRA_CFLAGS, ends up being used in the build process. Tracing some relevant points (but not all, because that is left as an exercise to the reader ;-) ) shows the following:
EXTRA_CFLAGS can still be used, according to scripts/Makefile.lib
1 # Backward compatibility
2 asflags-y += $(EXTRA_AFLAGS)
3 ccflags-y += $(EXTRA_CFLAGS)
The same file shows how ccflags-y ends up in the C compilation flags (and also shows you that you have another variable at your disposal, called CFLAGS_<filename>.o):
104 orig_c_flags = $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(KBUILD_SUBDIR_CCFLAGS) \
105 $(ccflags-y) $(CFLAGS_$(basetarget).o)
106 _c_flags = $(filter-out $(CFLAGS_REMOVE_$(basetarget).o), $(orig_c_flags))
...
133 __c_flags = $(_c_flags)
...
147 c_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \
148 $(__c_flags) $(modkern_cflags) \
149 -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags)
Then in scripts/Makefile.build, the compilation rule is defined:
234 cmd_cc_o_c = $(CC) $(c_flags) -c -o $# $<
Note that these are all recursively expanded variables, using = and not :=, which means that your own value of ccflags-y gets inserted into the C flags when you define it in your own makefile.
Finally about KBUILD_NOPEDANTIC, which you mention in the title but not in the actual question. This test for changed value of CFLAGS can be disabled by giving KBUILD_NOPEDANTIC any value -- see scripts/Makefile.build
47 ifeq ($(KBUILD_NOPEDANTIC),)
48 ifneq ("$(save-cflags)","$(CFLAGS)")
49 $(error CFLAGS was changed in "$(kbuild-file)". Fix it to use ccflags-y)
50 endif
51 endif
The files referenced in this answer were all retrieved today.
Now... not being an expert in this area and looking further into the makefiles after writing this whole story down, there is a thing that I do not understand either. It seems to me that CFLAGS is not used in the build system (not implicitly, nor explicitly), but KBUILD_CFLAGS is. So I wonder whether this check for changes in CFLAGS should actually be a check for changes in KBUILD_CFLAGS instead.
Linux makefiles build CFLAGS in a way which is appropriate for the kernel.
Overriding CFLAGS mean you add some flags and may remove some flags. Some of the removed flags may be important for correct compilation.

autoconf & automake versus -O2 versus -O3

My configure.ac contains
AC_PROG_CXX
and my Makefile.am contains
AM_CXXFLAGS= -Werror -O3
and the resulting 'configure' script keeps on adding -O2 to the mix in addition to O3.
I have this suspicion that I'm supposed to do something in configure.ac to declare my preference for O3, but I can't find it in the doc. How do I tell it that I want to control the optimization level?
No, you are not supposed to add anything to configure.ac to indicate a preference for -O3. That sort of thing belongs in a user's CONFIG_SITE, not in configure.ac
However, if you insist on breaking the convention, you can do something like:
: ${CXXFLAGS=-Werror -O3}
Note that this line must appear before AC_PROG_CXX (or any macro that AC_REQUIRES it, such as LT_INIT, as that will cause AC_PROG_CXX to be emitted into the configure script before this line.)
The prior answer is correct in that it should be the installer's choice what flags are used. If you're still wondering where the -g -O2 comes from (likely), it is described at http://www.gnu.org/s/hello/manual/autoconf/C_002b_002b-Compiler.html.
That page does suggest "If your package does not like this default, then it is acceptable to insert the line ‘: ${CXXFLAGS=""}’ after AC_INIT and before AC_PROG_CXX to select an empty default instead."

Resources