Analysis of Linux 2.6 Kernel Makefile

1 Overview

Makefile consists of five parts:

  • Makefile: The root directory Makefile, which reads the .config file and is responsible for creating vmlinux (kernel image) and modules (module files).
  • .config: Kernel configuration file (generally generated by make menuconfig).
  • arch/$(ARCH)/Makefile: Makefile of the target processor.
  • scripts/Makefile.*: All kbuild Makefile rules, they include definitions/rules, etc.
  • kbuild Makefiles: Each subdirectory has kbuild Makefiles, which are responsible for generating built-in or modular targets. (Note: kbuild Makefile refers to the Makefile that uses the kbuild structure, and most Makefiles in the kernel are kbuild Makefiles.)

2. kbuild file

2.1. obj-y 和 obj-m

The simplest kbuild Makefile can only contain:

obj-$(CONFIG_FOO) += foo.o

Which $(CONFIG_FOO)can be equal to y or m, and its value is given by the .config file. If it $(CONFIG_FOO)is neither y nor m, then the file will not be compiled and linked

When $(CONFIG_FOO)equal to y, the above statement is equivalent to obj-y += foo.o, it tells kbuild that there is an object file called foo.o in the current directory, which will be compiled from foo.c or foo.S .

When it $(CONFIG_FOO)is equal to m, it means that foo.o needs to be compiled into a module.

2.1.1. obj-y生成built-in.o

Kbuild compiles all $(obj-y)files, and calls "$(LD) -r"to merge all these files into built-in.ofiles. This built-in.o will be used by the Makefile in the upper-level directory and finally linked to vmlinux.

2.1.2. The target is compiled from multiple source files

If a target is compiled from multiple source files, you can $(<module_name>-objs)tell kbuild these source files through or $(<module_name>-y). Kbuild can recognize the suffixes -objs and -y, for example:

#drivers/isdn/i4l/Makefile
obj-$(CONFIG_ISDN) += isdn.o
isdn-objs := isdn_net_lib.o isdn_v110.o isdn_common.o

Kbuild will compile all $(isdn-objs)the objects in it, and call "$(LD) -r"them to link them into the isdn.o file.

The following is an example of using the suffix -y. The advantage of the suffix -y is that you can use CONFIG_XXXsymbols to decide whether to add some source files (.o is compiled from the corresponding .c or .S):

#fs/ext2/Makefile
obj-$(CONFIG_EXT2_FS)        += ext2.o
ext2-y                       := balloc.o bitmap.o
ext2-$(CONFIG_EXT2_FS_XATTR) += xattr.o

2.1.3. Call the subdirectory Makefile

Makefile is only responsible for compiling objects in the current directory. Objects in subdirectories are in charge of Makefiles in subdirectories. How to make make call the Makefile in the subdirectory? The answer is to include the subdirectories in obj-y or obj-m. E.g:

#fs/Makefile
obj-$(CONFIG_EXT2_FS) += ext2/

When CONFIG_EXT2_FS is y or m, the kbuild system will call the make command in the ext2 directory (that is, call the Makefile in the ext2 directory)

2.2. lib-y和lib-m

In a directory, obj-ythe listed files will be compiled into built-in.ofiles, and lib-y或lib-mthe listed files will be generated in the current directory lib.a.

注意:一般lib-y或lib-m只用在lib/和arch/*/lib这两个目录中。

2.3. Compiler option variables

2.3.1. ccflags-y 、 asflags-y 、 ldflags-y

These three variables are only valid in the current Makefile. Supplement: It $(KBUILD_CFLAGS)is a variable defined in the root directory Makefile, which applies to the entire number of cores.

2.3.2. subdir-ccflags-y、subdir-asflags-y

These two variables act on the current Makefile and all its subdirectories.

2.3.3. CFLAGS_$@、AFLAGS_$@

These two variables are only valid in the current Makefile. $@ can be used to specify the file name, so that different files can use different compilation options. E.g:

# drivers/scsi/Makefile
CFLAGS_aha152x.o =   -DAHA152X_STAT -DAUTOCONF
CFLAGS_gdth.o    = # -DDEBUG_GDTH=2 -D__SERIAL__ -D__COM2__ /
                     -DGDTH_STATISTICS
CFLAGS_seagate.o =   -DARBITRATE -DPARITY -DSEAGATE_USE_ASM

2.4. $(src)、$(obj)、$(kecho)

$(src)Point to the relative path of the current Makefie directory. $(obj)Point to the relative directory used to save the target file. Examples are as follows:

#drivers/scsi/Makefile
$(obj)/53c8xx_d.h: $(src)/53c7,8xx.scr $(src)/script_asm.pl
       $(CPP) -DCHIP=810 - < $< | ... $(src)/script_asm.pl

Here, it $(src)is equal to drivers/scsi/, and $(obj)it is also equal to drivers/scsi/.

When using the “make -s”command, only warning and error messages are output. $(kecho)The following content can be output to the standard output stream (usually the display), provided that "make -s" is not used. Examples are as follows:

#arch/blackfin/boot/Makefile
$(obj)/vmImage: $(obj)/vmlinux.gz
       $(call if_changed,uimage)
       @$(kecho) 'Kernel: $@ is ready'

2.5. $(CC) related functions

2.5.1. as-option、ld-option、cc-option

When compiling and linking files, xx-opiton can be used to check $(CC)whether the currently used compile options are supported. If the former is not supported, the latter can be used. E.g:

#arch/sh/Makefile
cflags-y += $(call as-option,-Wa$(comma)-isa=$(isa-y),)

If the current one is $(CC)not supported -Wa$(comma)-isa=$(isa-y), you can use the second compilation option (empty here).

2.5.2. cc-option-in

cc-option-yn is used to check $(CC)whether the given compiler option is supported. If supported, return y, otherwise return n. E.g:

#arch/ppc/Makefile
biarch := $(call cc-option-yn, -m32)
aflags-$(biarch) += -a32
cflags-$(biarch) += -m32

2.5.3. cc-option-align

After 3.0, gcc changed the types of alignment options such as specified functions and loops. When gcc <3.00, cc-option-align = -malign; when gcc >= 3.00, cc-option-align = -falign. Use $(cc-option-align) to select the correct prefix. E.g:

KBUILD_CFLAGS += $(cc-option-align)-functions=4

2.5.4. cc-version、cc-ifversion 、cc-fullversion

cc-version returns the $(CC)version. If it $(CC)is gcc 3.41, then cc-version returns 0341. E.g:

#arch/i386/Makefile
cflags-y += $(shell /
if [ $(call cc-version) -ge 0300 ] ; then /
        echo "-mregparm=3"; fi ;)

cc-ifversion returns the last parameter if the version meets the conditions. Examples are as follows:

#fs/reiserfs/Makefile
ccflags-y := $(call cc-ifversion, -lt, 0402, -O1)

If the $(CC) version is lower than 4.2, then ccflags-y will be equal to -O1.

cc-fullversion gives more detailed version information, for example:

#arch/powerpc/Makefile
$(Q)if test "$(call cc-fullversion)" = "040200" ; then /
       echo -n '*** GCC-4.2.0 cannot compile the 64-bit powerpc ' ; /
       false ; /
fi

2.5.5. cc-cross-prefix

cc-cross-prefixUsed to check whether the given prefix $(CC)exists, if it exists, return the first matching prefix, otherwise return empty. If multiple prefixes need to be matched, use a single space to separate each prefix. E.g:

#arch/m68k/Makefile
ifneq ($(SUBARCH),$(ARCH))
      ifeq ($(CROSS_COMPILE),)
           CROSS_COMPILE := $(call cc-cross-prefix, m68k-linux-gnu-)
      endif
endif

(注:本文所述内容来自kernel-2.6.30/Documentation/kbuild/makefiles.txt,适用于Linux 2.6内核)

3. Linux kernel compilation system

Starting from Linux kernel 2.6, the Kbuild system is used to compile the Linux kernel, which is very different from the previous compiling system, especially for the compilation of Linux kernel modules. Under the new system, the Linux build system will scan the Linux Makefile twice: first, the build system will read the Makefile at the top of the Linux kernel, and then read the Kbuild Makefile a second time based on what it reads to compile the Linux kernel.

3.1. Linux kernel Makefile classification

  • Kernel Makefile
    Kernel Makefile is located in the top directory of the Linux kernel source code, also called Top Makefile. It is mainly used to specify and compile Linux Kernel object files (vmlinux) and modules (module). When compiling the kernel or module, this file will be read first, and the compiling environment variables will be configured according to the read content. For kernel or driver developers, this file hardly needs any modification.

  • Kbuild Makefile
    Kbuild system uses Kbuild Makefile to compile the kernel or modules. When the Kernel Makefile is parsed, Kbuild will read the relevant Kbuild Makefile to compile the kernel or modules. Kbuild Makefile has a specific syntax to specify which ones are compiled into the kernel, which ones are compiled into modules, and what the corresponding source files are. Kernel and driver developers need to write this Kbuild Makefile.

  • ARCH Makefile
    ARCH Makefile is located in ARCH/$(ARCH)/Makefile, which is the Makefile of the system corresponding to the platform. Kernel Top Makefile will include this file to specify platform-related information. Only platform developers will care about this file.

3.2. Kbuild Makefile

The file name of Kbuild Makefile is not necessarily Makefile, although the name Makefile is recommended. The name of most Kbuild files is Makefile. In order to distinguish it from other Makefile files, you can also specify the name of the Kbuild Makefile as Kbuild. And if the "Makefile" and "Kbuild" files exist at the same time, the Kbuild system will use the "Kbuild" file.


  • One of the main functions of the target definition Kbuild Makefile is to specify what to compile. This function is obj-? and xxx-objs specified by the following two objects:

    • obj-?
      obj-? specify what to compile and how to compile? The "?" may be "y" or "m", "y" specifies that the object is compiled into the kernel, and "m" specifies that the object is compiled into a module. The syntax is as follows;
      obj-? = $(target).o
      target is the name of the compiled object. If not specified xxx-objs, the source files needed to compile this object are $(target).c或$(target).s. If it is specified $(target)-objs, the source file needed to compile this object is $(target)-objsspecified by the 不能有$(target).c 或$(target).sfile.

    • xxx-objs
      xxx-objs specifies the files needed by the compiled object. Generally, it is only needed when there are multiple source files.

    As long as these two lines are included, the Kbuild Makefile should work.

  • Nested compilation
    Sometimes an object may be embedded in the directory of another object, so how to compile the objects in the subdirectories? In fact, it is very simple, as long as the specified obj_?object is the name of the subdirectory:
    obj-? = $(sub_target)/
    where "?" can be "y" or "m", which $(sub_target)is the name of the subdirectory.

  • Compiler options
    Although in most cases there is no need to specify compiler options, sometimes we still need to specify some compiler options.

    • ccflags-y, asflags-y and ldflags-y
      These compilation options are used to specify the compilation options of cc, as and ld

3.3. Compile external modules

Sometimes we need to compile kernel modules outside the kernel source tree. The basic commands for compilation are:

make -C $(KERNEL_DIR) M=`pwd` modules

We can integrate this command into the Makefile so that we can just enter the "make" command. Recall the Makefile in the previous chapter. It integrates the Normal Makefile and Kbuild Makefile into one file. In order to distinguish between Kbuild Makefile and Normal Makefile, we rewrite Makefile to the following form and add Kbuild Makefile-"Kbuild".

##Makefile
ifneq ($(KERNELRELEASE),)
include "Kbuild"
else
KERNEL_DIR = /lib/modules/`uname -r`/build
MODULEDIR := $(shell pwd)
.PHONY: modules
default: modules
modules:
        make -C $(KERNEL_DIR)  M=$(MODULEDIR) modules
clean distclean:
        rm -f *.o *.mod.c .*.*.cmd *.ko
        rm -rf .tmp_versions
endif

##Kbuild Makefile

## Kbuild
MODULE_NAME = helloworld
$(MODULE_NAME)-objs := hello.o
obj-m   := $(MODULE_NAME).o

Generally, there is no need to include the following code in the Makefile, which is written in order to be compatible with the old version of the Kbuild system. The KERNELRELEASE variable is defined in the Kernel Makefile, so the content of Kbuild will be parsed only when the Makefile is read by Kbuild for the second time.

ifneq ($(KERNELRELEASE),)
include "Kbuild"
else
...
endif

External header files
Sometimes it is necessary to connect the system header files outside the kernel source code, but the default system header files of the Kbuild system are inside the kernel source code. How to use external header files? This can be done with the help of the special rules of the Kbuild system:

  • EXTRA_CFLAGS
    EXTRA_CFLAGS can add an external system header file to the Kbuild system.
    EXTRA_CFLAGS += $(ext_include_path)
    Generally, the external header file may be located in the directory of the external module source file. How to specify it? This can be done with $(src)or$(obj)
  • $(src)/$(obj)
    $(src)is a relative path, which is the path where the Makefile/Kbuild file is located. The same $(obj)is the path where the compilation target is saved, and the default is the path where the source code is located.

Guess you like

Origin blog.csdn.net/houxiaoni01/article/details/103561563