======================

Linux Kernel Makefiles

这个文档介绍了Linux kernel Makefiles

.. 目录

    === 1 Overview
    === 2 Who does what
    === 3 The kbuild files
       --- 3.1 目标定义(Goal definitions)
       --- 3.2 要编译进内核的目标(Built-in object goals) - `obj-y`
       --- 3.3 可加载模块目标(Loadable module goals) - `obj-m`
       --- 3.4 要导出符号的目标(Objects which export symbols)
       --- 3.5 库文件目标(Library file goals) - `lib-y`
       --- 3.6 Descending down in directories
       --- 3.7 编译参数(Compilation flags)
       --- 3.8 <deleted>
       --- 3.9 依赖追踪(Dependency tracking)
       --- 3.10 特定的规则(Special Rules)
       --- 3.11 $(CC) 支持的函数(support functions)
       --- 3.12 $(LD) 支持的函数
       --- 3.13 脚本调用

    === 4 Host Program support
       --- 4.1 Simple Host Program
       --- 4.2 Composite Host Programs
       --- 4.3 Using C++ for host programs
       --- 4.4 Controlling compiler options for host programs
       --- 4.5 When host programs are actually built

    === 5 Userspace Program support
       --- 5.1 Simple Userspace Program
       --- 5.2 Composite Userspace Programs
       --- 5.3 Controlling compiler options for userspace programs
       --- 5.4 When userspace programs are actually built

    === 6 Kbuild clean infrastructure

    === 7 Architecture Makefiles
       --- 7.1 Set variables to tweak the build to the architecture
       --- 7.2 Add prerequisites to archheaders
       --- 7.3 Add prerequisites to archprepare
       --- 7.4 List directories to visit when descending
       --- 7.5 Architecture-specific boot images
       --- 7.6 Building non-kbuild targets
       --- 7.7 Commands useful for building a boot image
       --- 7.8 Custom kbuild commands
       --- 7.9 Preprocessing linker scripts
       --- 7.10 Generic header files
       --- 7.11 Post-link pass
    === 8 Kbuild syntax for exported headers
       --- 8.1 no-export-headers
       --- 8.2 generic-y
       --- 8.3 generated-y
       --- 8.4 mandatory-y

    === 9 Kbuild Variables
    === 10 Makefile language
    === 11 Credits
    === 12 TODO

1 Overview

内核的Makefiles由五部分组成::

    Makefile                顶层Makefile,即内核目录树根目录下的Makefile文件。
    .config                 内核的配置文件。
    arch/$(ARCH)/Makefile   体系结构相关的Makefle文件。
    scripts/Makefile.*      kbuild Makefiles通用的规则文件。
    kbuild Makefiles        大约500多个kbuild Makefile文件。

顶层Makefile读取内核配置阶段生成的.config文件。

顶层Makefile负责构建两个主要的东西:vmlinux(常驻内核镜像)和modules(所有的内核模块)。它通过递归进入内核源码树的子目录来构建这些目标。

被访问的子目录列表取决于内核配置,顶层Makefile文件包含了一个名字叫做arch/$(ARCH)/Makefile的体系结构相关的Makefile文件,这个体系结构相关的Makefile文件为顶层Makefile文件提供体系结构相关的信息。

每个子目录都有一个kbuild Makefile,该文件执行上层Makefile传递下来的命令。kbuild Makefile使用.config文件中的信息来生成一个kbuild使用的文件列表,该文件列表被kbuild用于构建要编译进内核的目标(built-in)或内核模块。

scripts / Makefile.* 包含所有的变量定义/编译规则等,这些变量和规则被kbuild用于构建内核。

2 Who does what

People have four different relationships with the kernel Makefiles. 有四种人会关心内核Makefiles文件。

Users 需要自己构建内核的人,这些人需要执行"make menuconfig" 和 “make"命令,通常不会阅读或者修改内核的Makefiles文件(或者不需要修改内核的任何源文件)。

Normal developers 指从事诸如设备驱动、文件系统或者网络协议栈等开发维护的人。这些人需要维护自己所关注的子系统使用的kbuild Makefile文件。为了更好地完成维护或者开发工作,他们需要对内核Makefile,以及有关kbuild公用接口有较为全面的了解。

Arch developers 指从事特定体系结构比如ia64等相关开发的人员。体系结构相关的开发人员需要对arch/$(ARCH)/Makefilekbuild Makefiles有一定的了解。

Kbuild developers 指开发或者维护内核构建系统本身的人,他们需要对内核中所有的Makefile文件都有比较深入的认识。

这个文档适用于normal developersarch developers,也即从事设备驱动、文件系统等相关内核子系统维护或者开发,以及从事体系结构相关开发工作的工程师们。

3 The kbuild files

内核中的大部分Makefile文件都是kbuild Makefiles。本章介绍kbuild makefiles的语法。

The preferred name for the kbuild files are ‘Makefile’ but ‘Kbuild’ can be used and if both a ‘Makefile’ and a ‘Kbuild’ file exists, then the ‘Kbuild’ file will be used. kbuild文件的首选名称是“Makefile”,但“Kbuild”可以使用,如果同时存在“ Makefile”和“ Kbuild”文件,则将使用“Kbuild”文件。

3.1 节“目标定义” (“Goal definitions” )是一个快速的大概介绍;后边的章节将给出更多细节以及实际的例子。 3.1 Goal definitions

    Goal definitions are the main part (heart) of the kbuild Makefile.
    These lines define the files to be built, any special compilation
    options, and any subdirectories to be entered recursively.

    The most simple kbuild makefile contains one line:

目标定义是kbuild Makefile的主要部分(核心)。这些行定义了要构建的文件、特殊的编译选项以及要递归编译的所有子目录。

最简单的kbuild makefile包含一行:

    Example::

            obj-y += foo.o

    This tells kbuild that there is one object in that directory, named foo.o. foo.o will be built from foo.c or foo.S.
    这告诉`kbuild`当前目录有一个名字叫做`foo.o`的目标,`foo.o`可能是从`foo.c`或者`foo.S`编译而来的。

    If foo.o shall be built as a module, the variable obj-m is used.
    Therefore the following pattern is often used:

如果要将foo.o编译为内核模块,则将使用obj-m来定义,因此经常使用下边的形式:

    Example::

            obj-$(CONFIG_FOO) += foo.o

    `$(CONFIG_FOO)` evaluates to either y (for built-in) or m (for module).
    `$(CONFIG_FOO)`的值可以是`y`(编译进内核)或者`m`(编译成模块).
    If CONFIG_FOO is neither y nor m, then the file will not be compiled nor linked.
    如果`CONFIG_FOO`既不是`y`也不是`m`,则该文件将不会被编译或链接。

3.2 Built-in object goals - obj-y

    The kbuild Makefile specifies object files for vmlinux
    in the $(obj-y) lists.  These lists depend on the kernel
    configuration.
    `kbuild Makefile`在`$(obj-y)`中指定构建`vmlinux`所需要的目标文件列表。文件列表取决于内核的配置。

    Kbuild compiles all the $(obj-y) files.  It then calls
    "$(AR) rcSTP" to merge these files into one built-in.a file.
    This is a thin archive without a symbol table. It will be later
    linked into vmlinux by scripts/link-vmlinux.sh
    `Kbuild`编译所有`$(obj-y)`文件。 然后,它调用“ $(AR)rcSTP”将这些文件合并为一个`built-in.a`文件。这是一个没有符号表的精简归档文件,稍后将通过`scripts / link-vmlinux.sh`将其链接到`vmlinux`中。


    The order of files in $(obj-y) is significant.  Duplicates in
    the lists are allowed: the first instance will be linked into
    built-in.a and succeeding instances will be ignored.

$(obj-y)列表中文件的顺序是重要的,列表中的文件是可以重复的,同一个文件第一次出现在列表中时将被连接进built-in.a,其他重复的文件名将被忽略。 Link order is significant, because certain functions

    (module_init() / __initcall) will be called during boot in the
    order they appear. So keep in mind that changing the link
    order may e.g. change the order in which your SCSI
    controllers are detected, and thus your disks are renumbered.

链接顺序很重要,因为某些功能(module_init()/ __initcall)将在引导过程中按它们出现的顺序被调用。 因此请记住,更改链接顺序可能例如 更改检测SCSI控制器的顺序,从而对磁盘重新编号。

    Example::

            #drivers/isdn/i4l/Makefile
            # Makefile for the kernel ISDN subsystem and device drivers.
            # Each configuration option enables a list of files.
            obj-$(CONFIG_ISDN_I4L)         += isdn.o
            obj-$(CONFIG_ISDN_PPP_BSDCOMP) += isdn_bsdcomp.o

3.3 Loadable module goals - obj-m 可加载模块目标 - obj-m

    $(obj-m) specifies object files which are built as loadable
    kernel modules.
    `$(obj-m)`定义可以编译为可加载模块的目标文件。

    A module may be built from one source file or several source
    files. In the case of one source file, the kbuild makefile
    simply adds the file to $(obj-m).
    一个模块可以由一个源文件或者多个源文件构建。对于一个源文件的情况,`kbuild makefile`只是将文件添加到`$(obj-m)`。

    Example::

            #drivers/isdn/i4l/Makefile
            obj-$(CONFIG_ISDN_PPP_BSDCOMP) += isdn_bsdcomp.o

    Note: In this example $(CONFIG_ISDN_PPP_BSDCOMP) evaluates to 'm'
    注意:在此示例中,`$(CONFIG_ISDN_PPP_BSDCOMP)`定义为“ m”

    If a kernel module is built from several source files, you specify that you want to build a module in the same way as above; however,kbuild needs to know which object files you want to build your module from, so you have to tell it by setting a $(<module_name>-y) variable.
    如果一个内核模块式由多个源文件构建,要以与上述相同的方式构建一个模块; 但是,`kbuild`需要知道要从哪个目标文件构建模块,因此必须通过设置`$(<module_name> -y)`变量来告诉它。
    
    Example::

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

    In this example, the module name will be isdn.o. Kbuild will
    compile the objects listed in $(isdn-y) and then run
    "$(LD) -r" on the list of these files to generate isdn.o.
	在此例中,模块名字为`isdn.o`。`Kbuild`将编译`$(isdn-y)`列出的文件,之后运行 "$(LD) -r"以生成`isdn.o`。     

    Due to kbuild recognizing $(<module_name>-y) for composite objects, you can use the value of a `CONFIG_` symbol to optionally include an object file as part of a composite object.
    由于`kbuild`以变量`$(<module_name>-y)`识别复合对象,因此可以使用`CONFIG_`符号的值来选择性的将对象包含为复合对象的一部分。

    Example::

            #fs/ext2/Makefile
            obj-$(CONFIG_EXT2_FS) += ext2.o
            ext2-y := balloc.o dir.o file.o ialloc.o inode.o ioctl.o \
                      namei.o super.o symlink.o                                     ext2-$(CONFIG_EXT2_FS_XATTR) += xattr.o xattr_user.o \
                                            xattr_trusted.o

    In this example, xattr.o, xattr_user.o and xattr_trusted.o are only part of the composite object ext2.o if $(CONFIG_EXT2_FS_XATTR) evaluates to 'y'.
    在此例中,如果`$(CONFIG_EXT2_FS_XATTR) `定义为'y',`xattr.o`, `xattr_user.o` 和 `xattr_trusted.o`只是复合对象`ext2.o`的一部分。

    Note: Of course, when you are building objects into the kernel, the syntax above will also work. So, if you have CONFIG_EXT2_FS=y, kbuild will build an ext2.o file for you out of the individual parts and then link this into built-in.a, as you would expect.
    注意:当然,当您将对象构建到内核中时,以上语法也将起作用。因此如果定义了 `CONFIG_EXT2_FS=y`,`kbuild`将根据各个部分为您构建一个ext2.o文件,然后将其链接到Built-in.a中。

3.4 Objects which export symbols 导出符号的目标

    No special notation is required in the makefiles for
    modules exporting symbols.
    对于导出符号的模块,makefile中不需要特殊的符号。

3.5 Library file goals - lib-y 库文件目标 - lib-y

    Objects listed with obj-* are used for modules, or
    combined in a built-in.a for that specific directory.
    There is also the possibility to list objects that will
    be included in a library, lib.a.
    用`obj- *`列出的对象用于模块,或组合到该特定目录的`built-in.a`中。也有可能列出将包含在库lib.a中的对象。
    
    All objects listed with lib-y are combined in a single
    library for that directory.
    `lib-y`列出的所有对象都合并到该目录的单个库中。
    Objects that are listed in obj-y and additionally listed in
    lib-y will not be included in the library, since they will
    be accessible anyway.
    obj-y中列出的对象以及lib-y外列出的对象将不包含在库中,因为无论如何它们都可以访问。 
    For consistency, objects listed in lib-m will be included in lib.a.
    为了保持一致性,lib-m中列出的对象将包含在lib.a中。

    Note that the same kbuild makefile may list files to be built-in
    and to be part of a library. Therefore the same directory
    may contain both a built-in.a and a lib.a file.

请注意,相同的kbuild makefile可能会列出要built-in的文件并成为库的一部分。 因此,同一目录可能同时包含一个built-in.a和一个lib.a文件。

    Example::

            #arch/x86/lib/Makefile
            lib-y    := delay.o

    This will create a library lib.a based on delay.o. For kbuild to
    actually recognize that there is a lib.a being built, the directory
    shall be listed in libs-y.
    这将基于delay.o创建一个库lib.a。 为了使kbuild实际上识别出正在构建一个lib.a,该目录应在libs-y中列出。

    See also "6.4 List directories to visit when descending".
    参见"6.4 List directories to visit when descending"

    Use of lib-y is normally restricted to `lib/` and `arch/*/lib`.
    lib-y的使用通常仅限于`lib /`和`arch / * / lib`。

3.6 Descending down in directories

    A Makefile is only responsible for building objects in its own
    directory. Files in subdirectories should be taken care of by
    Makefiles in these subdirs. The build system will automatically
    invoke make recursively in subdirectories, provided you let it know of
    them.

Makefile仅负责在其自己的目录中构建对象。 子目录中的文件应由这些子目录中的Makefile处理。 构建系统将自动在子目录中递归调用make,前提是让makefile知道需要编译的文件。

    To do so, obj-y and obj-m are used.
    为此,使用obj-y和obj-m。
    ext2 lives in a separate directory, and the Makefile present in fs/
    tells kbuild to descend down using the following assignment.
    ext2位于一个单独的目录中,并且fs/中的Makefile使用以下赋值告诉kbuild递归构建。

    Example::

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

    If CONFIG_EXT2_FS is set to either 'y' (built-in) or 'm' (modular)the corresponding obj- variable will be set, and kbuild will descend down in the ext2 directory.
    如果将CONFIG_EXT2_FS设置为“ y”(built-in 编译进内核)或“ m”(编译模块),则将设置相应的obj-变量,并且kbuild将在ext2目录中构建。
    Kbuild uses this information not only to decide that it needs to visit the directory, but also to decide whether or not to link objects from the directory into vmlinux.
    Kbuild使用此信息不仅决定需要访问目录,还决定是否将目录中的对象链接到vmlinux。

    When Kbuild descends into the directory with 'y', all built-in objects from that directory are combined into the built-in.a, which will be eventually linked into vmlinux.
	当Kbuild递归到带有“ y”的目录时,该目录中的所有build-in对象都将合并到built-in.a中,最终将其链接到vmlinux中。
	
    When Kbuild descends into the directory with 'm', in contrast, nothing from that directory will be linked into vmlinux. If the Makefile in that directory specifies obj-y, those objects will be left orphan.
    It is very likely a bug of the Makefile or of dependencies in Kconfig.
    相反,当Kbuild以'm'进入目录时,该目录中的任何内容都不会链接到vmlinux。 如果该目录中的Makefile指定obj-y,则这些对象将保持孤立状态。
     很可能是Makefile或Kconfig中的依赖项的错误。

    It is good practice to use a `CONFIG_` variable when assigning directory names. This allows kbuild to totally skip the directory if the corresponding `CONFIG_` option is neither 'y' nor 'm'.
    分配目录名称时,最好使用`CONFIG_`变量。 如果相应的CONFIG_选项既不是'y'也不是'm',这将使kbuild完全跳过目录。

3.7 Compilation flags 编译选项

ccflags-y, asflags-y and ldflags-y
    These three flags apply only to the kbuild makefile in which they are assigned. They are used for all the normal cc, as and ld invocations happening during a recursive build.
    
    Note: Flags with the same behaviour were previously named:
    EXTRA_CFLAGS, EXTRA_AFLAGS and EXTRA_LDFLAGS.
    They are still supported but their usage is deprecated.

    ccflags-y specifies options for compiling with $(CC).

    Example::

            # drivers/acpi/acpica/Makefile
            ccflags-y                       := -Os -D_LINUX -DBUILDING_ACPICA
            ccflags-$(CONFIG_ACPI_DEBUG)    += -DACPI_DEBUG_OUTPUT

    This variable is necessary because the top Makefile owns the
    variable $(KBUILD_CFLAGS) and uses it for compilation flags for the
    entire tree.

    asflags-y specifies assembler options.

    Example::

            #arch/sparc/kernel/Makefile
            asflags-y := -ansi

    ldflags-y specifies options for linking with $(LD).

    Example::

            #arch/cris/boot/compressed/Makefile
            ldflags-y += -T $(srctree)/$(src)/decompress_$(arch-y).lds

subdir-ccflags-y, subdir-asflags-y
    The two flags listed above are similar to ccflags-y and asflags-y.
    The difference is that the subdir- variants have effect for the kbuild
    file where they are present and all subdirectories.
    Options specified using subdir-* are added to the commandline before
    the options specified using the non-subdir variants.