Kernel module compilation and KBUILD_NOPEDANTIC

14,406

Solution 1

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.

Solution 2

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.

Share:
14,406

Related videos on Youtube

dimba
Author by

dimba

Updated on September 15, 2022

Comments

  • dimba
    dimba over 1 year

    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?

  • dimba
    dimba almost 12 years
    If I understand CFLAGS are flags the whole kernel is compiled with and therefore should not be changed. This means that kernel KBuild system will compile my external module with CFLAGS+EXTRA_CFLAGS. Correct?