Kernel module compilation and KBUILD_NOPEDANTIC - linux

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.

Related

How to add "-fstack-protector-all" to makefile?

There is a error in my code:
*** stack smashing detected ***: ./mummergpu terminated
I search it in stackoverflow, a solution is add -fno-stack-protector to environment variable, but i don't know how to add it ? can anyone help me ?
nakefile follow:
all: clean mummergpu
.SUFFIXES : .cu .cu_dbg_o .c_dbg_o .cpp_dbg_o .cu_rel_o .c_rel_o .cpp_rel_o .cubin
## Reenable this for testing all variations
#include ../experiments/test_rule.mk
CUDA_INSTALL_PATH := /usr/local/cuda-8.0
# Compilers
NVCC := $(CUDA_INSTALL_PATH)/bin/nvcc
CXX := g++ $(PROFILE)
CC := gcc
LINK := g++ $(PROFILE)
# Add source files here
STATIC_LIB := libmummergpu.a
# Cuda source files (compiled with cudacc)
CUFILES := mummergpu.cu
# C/C++ source files (compiled with gcc / c++)
CCFILES := \
mummergpu_gold.cpp suffix-tree.cpp PoolMalloc.cpp
Consider using "-fstack-protector-strong" instead of "all".
With "-fstack-protector-all" it applies protection to all functions regardless they actually need this protection and hence make greater impact on performance.
Find more details here: https://lwn.net/Articles/584225/
The "Strong" stack protector aims to add stack protection only to those functions, which actually may need this protection.
You can use additional parameters to ./configure command to include stack protection:
./configure [options] CFLAGS='-fstack-protector-strong' CXXFLAGS='-fstack-protector-strong'
However, some packages may override this later.
Here is the command to apply stack protection for CFLAGS inside Makefile:
run:
sed '/^.*CFLAGS = / s/$/ -fstack-protector-strong' /path/to/Makefile
Once the output is verified and acceptable to apply changes on Makefile run sed with -i switch as follows:
sed -i '/^.*CFLAGS = / s/$/ -fstack-protector-strong' /path/to/Makefile

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.

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."

Symbols from convenience library not getting exported in executable

I have a program, myprogram, which is linked with a static convenience library, call it libconvenience.a, which contains a function, func(). The function func() isn't called anywhere in myprogram; it needs to be able to be called from a plugin library, plugin.so.
The symbol func() is not getting exported dynamically in myprogram. If I run
nm myprogram | grep func
I get nothing. However, it isn't missing from libconvenience.a:
nm libconvenience/libconvenience.a | grep func
00000000 T func
I am using automake, but if I do the last linking step by hand on the command line instead, it doesn't work either:
gcc -Wl,--export-dynamic -o myprogram *.o libconvenience/libconvenience.a `pkg-config --libs somelibraries`
However, if I link the program like this, skipping the use of a convenience library and linking the object files that would have gone into libconvenience.a directly, func() shows up in myprogram's symbols as it should:
gcc -Wl,--export-dynamic -o myprogram *.o libconvenience/*.o `pkg-config --libs somelibraries`
If I add a dummy call to func() somewhere in myprogram, then func() also shows up in myprogram's symbols. But I thought that --export-dynamic was supposed to export all symbols regardless of whether they were used in the program or not!
I am using automake 1.11.1 and gcc 4.5.1 on Fedora 14. I am also using Libtool 2.2.10 to build plugin.so (but not the convenience library.)
I didn't forget to put -Wl,--export-dynamic in myprogram_LDFLAGS, nor did I forget to put the source that contains func() in libconvenience_a_SOURCES (some Googling suggests that these are common causes of this problem.)
Can somebody help me understand what is going on here?
I managed to solve it. It was this note from John Calcote's excellent Autotools book that pointed me in the right direction:
Linkers add to the binary product every object file specified explicitly on the command line, but they only extract from archives those object files that are actually referenced in the code being linked.
To counteract this behavior, one can use the --whole-archive flag to libtool. However, this causes all the symbols from all the system libraries to be pulled in also, causing lots of double symbol definition errors. So --whole-archive needs to be right before libconvenience.a on the linker command line, and it needs to be followed by --no-whole-archive so that the other libraries aren't treated that way. This is a bit difficult since automake and libtool don't really guarantee keeping your flags in the same order on the command line, but this line in Makefile.am did the trick:
myprogram_LDFLAGS = -Wl,--export-dynamic \
-Wl,--whole-archive,libconvenience/libconvenience.a,--no-whole-archive
If you need func to be in plugin.so, you should try and locate it there if possible. Convenience libraries are meant to be just that -- a convenience to link to an executable or lib as an intermediate step.

Setting per-file flags with automake

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

Resources