Chinaunix首页 | 论坛 | 博客
  • 博客访问: 955528
  • 博文数量: 116
  • 博客积分: 3923
  • 博客等级: 中校
  • 技术积分: 1337
  • 用 户 组: 普通用户
  • 注册时间: 2009-04-23 01:22
文章分类

全部博文(116)

文章存档

2013年(1)

2012年(17)

2011年(69)

2009年(29)

分类: LINUX

2009-05-05 23:54:35

Linux Kernel Makefiles

This document describes the Linux kernel Makefiles.

=== Table of Contents

    === 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 Command line dependency
       --- 3.9 Dependency tracking
       --- 3.10 Special Rules

    === 4 Host Program support
       --- 4.1 Simple Host Program
       --- 4.2 Composite Host Programs
       --- 4.3 Defining shared libraries  
       --- 4.4 Using C++ for host programs
       --- 4.5 Controlling compiler options for host programs
       --- 4.6 When host programs are actually built
       --- 4.7 Using hostprogs-$(CONFIG_FOO)

    === 5 Kbuild clean infrastructure

    === 6 Architecture Makefiles
       --- 6.1 Set variables to tweak the build to the architecture
       --- 6.2 Add prerequisites to prepare:
       --- 6.3 List directories to visit when descending
       --- 6.4 Architecture specific boot images
       --- 6.5 Building non-kbuild targets
       --- 6.6 Commands useful for building a boot image
       --- 6.7 Custom kbuild commands
       --- 6.8 Preprocessing linker scripts
       --- 6.9 $(CC) support functions

    === 7 Kbuild Variables
    === 8 Makefile language
    === 9 Credits
    === 10 TODO

=== 1 Overview

The Makefiles have five parts:

    Makefile        the top Makefile.
    .config            the kernel configuration file.
    arch/$(ARCH)/Makefile    the arch Makefile.
    scripts/Makefile.*    common rules etc. for all kbuild Makefiles.
    kbuild Makefiles    there are about 500 of these.

The top Makefile reads the .config file, which comes from the kernel
configuration process.

The top Makefile is responsible for building two major products: vmlinux
(the resident kernel image) and modules (any module files).
It builds these goals by recursively descending into the subdirectories of
the kernel source tree.
The list of subdirectories which are visited depends upon the kernel
configuration. The top Makefile textually includes an arch Makefile
with the name arch/$(ARCH)/Makefile. The arch Makefile supplies
architecture-specific information to the top Makefile.

Each subdirectory has a kbuild Makefile which carries out the commands
passed down from above. The kbuild Makefile uses information from the
.config file to construct various file lists used by kbuild to build
any built-in or modular targets.

scripts/Makefile.* contains all the definitions/rules etc. that
are used to build the kernel based on the kbuild makefiles.

(译)
=== 1 概述
Makefiles 分为五部分:

    Makefile        顶层的Makefile.
    .config            内核配置文件.
    arch/$(ARCH)/Makefile    体系Makefile.
    scripts/Makefile.*    公共规则等等. 供给所有的kbuild Makefiles.
    kbuild Makefiles    大约有500这样的Makefiles.

顶层的Makefile读入.config文件,这文件来自内核配置处理。

顶层Makefile是负责建立两个主要的产物:vmlinux(常驻内核镜像)和模块 (任何模块文件)。
它建立这些目标通过递归向下的进入内核源码树的子目录来实现的。
这些子目录列表根据内核的配置来被访问。顶层Makefile原文地包含体系的Makefile
"arch/$(ARCH)/Makefile". 这个体系的Makefile 提供指定的体系信息给顶层的Makefile.

每个子目录都有一个kbuild Makefile 来执行从上层传递下来的命令。这些kbuild Makefile使用
来自.config文件的信息来构造各种文件列表,用来给kbuild建立各种build-in或模块目标。

scripts/Makefile.* 包含所有的定义/规则等等。用以基于kbuild Makefiles来建立内核。

    

=== 2 Who does what

People have four different relationships with the kernel Makefiles.

*Users* are people who build kernels.  These people type commands such as
"make menuconfig" or "make".  They usually do not read or edit
any kernel Makefiles (or any other source files).

*Normal developers* are people who work on features such as device
drivers, file systems, and network protocols.  These people need to
maintain the kbuild Makefiles for the subsystem that they are
working on.  In order to do this effectively, they need some overall
knowledge about the kernel Makefiles, plus detailed knowledge about the
public interface for kbuild.

*Arch developers* are people who work on an entire architecture, such
as sparc or ia64.  Arch developers need to know about the arch Makefile
as well as kbuild Makefiles.

*Kbuild developers* are people who work on the kernel build system itself.
These people need to know about all aspects of the kernel Makefiles.

This document is aimed towards normal developers and arch developers.

(译)
=== 2 人们与Makefile。

人们与kernel Makefiles的之间分为4种不同的关系。

*用户* 是一类建立内核的人们。 这些人只是敲命令例如"make menuconfig" 或者 "make".
他们通常不需要阅读或者编辑任何内核Makefiles(或者任何其他的源文件)。

*普通的开发者* 是一类工作在例如设备驱动,文件系统和网络协议的人们。这些人需要
维护他们工作的子系统的kbuild Makefiles。为了使到这些更高效,他们需要一些全面
的知识关于内核Makefiles, 和详细的知识关于kbuild公共接口。

*体系开发者* 是一类工作在整个体系的人们,例如 sparc或者ia64的。体系开发者既需要
理解体系Makefile,也需要理解kbuild Makefiles.

*kbuild开发者* 是一类工作在建立内核build系统的人们。这些人们需要理解内核Makefiles
的各个方面知识。

这个文档是面向普通的开发人员和体系开发者。

=== 3 The kbuild files

Most Makefiles within the kernel are kbuild Makefiles that use the
kbuild infrastructure. This chapter introduce the syntax used in the
kbuild makefiles.
The preferred name for the kbuild files is 'Kbuild' but 'Makefile' will
continue to be supported. All new developmen is expected to use the
Kbuild filename.

Section 3.1 "Goal definitions" is a quick intro, further chapters provide
more details, with real examples.

(译)
=== 3 kbuild文件

大部分处在内核中的Makefiles都是kbuild Makefiles, 用来kbuild的下部构造。这章介绍
kbuild makefiles用到的语法。
给kbuild files个更好的称呼是'Kbuild',而不是'Makefile',这会继续被使用。希望所有新
的开发者都去使用Kbuild这个名字。

3.1 节 “目标定义”是一个快速介绍,后面的章节提供更详细的信息和真实的例子。


--- 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:

    Example:
        obj-y += foo.o

    This tell kbuild that there is one object in that directory named
    foo.o. foo.o will be built from foo.c or foo.S.

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

    Example:
        obj-$(CONFIG_FOO) += foo.o

    $(CONFIG_FOO) evaluates to either y (for built-in) or m (for module).
    If CONFIG_FOO is neither y nor m, then the file will not be compiled
    nor linked.

(译)

--- 3.1 目标定义

目标定义是kbuild Makefile主要(核心)部分。这些行定义了建立这些文件,任何特殊的
编译选项,和递归地进入任何子目录。

最简单的kbuild makefile包含一行:

例子:
obj-y += foo.o

这告诉kbuild在这个目录下有一个目标叫做foo.o. 这个foo.o将被建立通过foo.c或者foo.S.

如果foo.o应该被作为模块来建立,变量obj-m被使用。因此下面模式经常被使用:

例子:
obj-$(CONFIG_FOO) += foo.o

$(CONFIG_FOO) 评估为y(built-in)或者m(模块)。如果CONFIG_FOO既不是y也不是m,那么该文件
将会不被编译也不被链接。


--- 3.2 Built-in object goals - obj-y

    The kbuild Makefile specifies object files for vmlinux
    in the lists $(obj-y).  These lists depend on the kernel
    configuration.

    Kbuild compiles all the $(obj-y) files.  It then calls
    "$(LD) -r" to merge these files into one built-in.o file.
    built-in.o is later linked into vmlinux by the parent Makefile.

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

    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 you disks are renumbered.

    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)             += isdn.o
        obj-$(CONFIG_ISDN_PPP_BSDCOMP) += isdn_bsdcomp.o

(译)
--- 3.2 Built-in object 目标 - obj-y
这个kbuild Makefile 在$(obj-y)列表里为vmlinux指定了object文件。这些列表在
内核配置的时候将被使用到。

Kbuild 编译所有的$(obj-y)文件。它然后调用"$(LD) -r" 去合并这些文件成一个built-in.o
文件。built-in.o将会被父目录的Makefile链接到vmlinux去。

在$(obj-y)列表里的文件顺序是非常重要的。在列表里重复出现是允许的:最前面的实例将被
链接到built-in.o, 而后面同名的实例将会被忽略掉。

链接的顺序也是至关重要的,因为某些函数 (module_init()/ __initcall)将会在依赖他们
出现的顺序在boot的时候被调用。所以一定要记住改变链接顺序可能发生这样事情,例如:当你
改变SCSI控制器顺序被侦测到后,因此你的硬盘被重编号。

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


--- 3.3 Loadable module goals - obj-m

    $(obj-m) specify object files which are built as loadable
    kernel modules.

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

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

    Note: In this example $(CONFIG_ISDN_PPP_BSDCOMP) evaluates to '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.

    Kbuild needs to know which the parts that you want to build your
    module from, so you have to tell it by setting an
    $(-objs) variable.

    Example:
        #drivers/isdn/i4l/Makefile
        obj-$(CONFIG_ISDN) += isdn.o
        isdn-objs := 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-objs) and then run
    "$(LD) -r" on the list of these files to generate isdn.o.

    Kbuild recognises objects used for composite objects by the suffix
    -objs, and the suffix -y. This allows the Makefiles to use
    the value of a CONFIG_ symbol to determine if an object is part
    of a composite object.

    Example:
        #fs/ext2/Makefile
            obj-$(CONFIG_EXT2_FS)        += ext2.o
         ext2-y                       := balloc.o bitmap.o
            ext2-$(CONFIG_EXT2_FS_XATTR) += xattr.o
    
    In this example xattr.o is only part of the composite object
    ext2.o, if $(CONFIG_EXT2_FS_XATTR) evaluates to 'y'.

    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.o, as you would expect.

(译)
--- 3.3 可加载模块目标 - obj-m
$(obj-m) 指定的object文件,这些文件可以作为可加载的内核模块。

一个模块可能由一个源文件或几个源文件建立。在由一个源文件建立的情况,kbuild makefile
简单的添加文件到目标$(obj-m)。
    例子:
        #drivers/isdn/i4l/Makefile
        obj-$(CONFIG_ISDN_PPP_BSDCOMP) += isdn_bsdcomp.o

注意:这个例子里的$(CONFIG_ISDN_PPP_BSDCOMP)被评估为'm'

如果内核模块由几个源文件建立的,你只需要使用上面相同方法指定它们到要建立的目标里。

Kbuild 需要知道从哪一部分你想建立你的模块,所以你必须通过$(-objs)变量来告诉它。

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

在这个例子里,模块名将是isdn.o。Kbuild将编译这些$(isdn-objs)里的objects, 然后运行"$(LD) -r"
通过这些列表文件来产生isdn.o。

Kbuild 通过后缀-objs和-y来识别objects构造objects,它允许Makefiles去使用CONFIG_符号值去决定这个
object是否属于组合object的一部分。

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

在这个例子里xattr.o是组合目标ext2.o的一部分,紧且如果$(CONFIG_EXT2_FS_XATTR)被评估为'y'。

注意:当然,当你建立这些objects到内核,上面所说的语法同样能工作。所以,如果你的
CONFIG_EXT2_FS=y,Kbuild将为你建立ext2.o为独立的部分,然后链接它到built-in.o,如你所盼望的那样。



--- 3.4 Objects which export symbols

    No special notation is required in the makefiles for
    modules exporting symbols.

(译)
--- 3.4 导出Objects符号
没有特殊的标记法,在makefiles被请求模块导出符号的。


--- 3.5 Library file goals - lib-y

    Objects listed with obj-* are used for modules or
    combined in a built-in.o for that specific directory.
    There is also the possibility to list objects that will
    be included in a library, lib.a.
    All objects listed with lib-y are combined in a single
    library for that directory.
    Objects that are listed in obj-y and additional listed in
    lib-y will not be included in the library, since they will anyway
    be accessible.
    For consistency objects listed in lib-m will be included in 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.o and a lib.a file.

    Example:
        #arch/i386/lib/Makefile
        lib-y    := checksum.o delay.o

    This will create a library lib.a based on checksum.o and delay.o.
    For kbuild to actually recognize that there is a lib.a being build
    the directory shall be listed in libs-y.
    See also "6.3 List directories to visit when descending".
 
    Usage of lib-y is normally restricted to lib/ and arch/*/lib.

(译)
--- 3.5 库文件目标 - lib-y
Objects以obj-*列表的形式被模块使用,或者被联合到指定目录的build-in.o里。同样也有可能
去列表objects,这些object被包含到一个库,lib.a。
所有objects以lib-y列表的形式被合并成一个简单的库供给这个目录。
在obj-y里面的排列的Objects和在lib-y里的附加列表将不会被包含进库里,因为它们将经常的
被访问到。
为了使到objects列表一致性,被包含到lib-m里的同时也会被包含进lib.a中。

注意同样的kbuild makefile 可能列表文件为built-in形式和库的一部分。因此同一个目录下可能
同时包含built-in.o和lib.a文件。

    例子:
        #arch/i386/lib/Makefile
        lib-y    := checksum.o delay.o

这将基于checksum.o和delay.o创建一个库lib.a。为了kbuild去真实的明白到有这样一个lib.a库来建立
这个目录,这个目录的包含信息应该在lib-y里被列出来。
同样参见 "6.3 List directories to visit when descending".

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.

    To do so obj-y and obj-m are used.
    ext2 lives in a separate directory, and the Makefile present in fs/
    tells kbuild to descend down using the following assignment.

    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.
    Kbuild only uses this information to decide that it needs to visit
    the directory, it is the Makefile in the subdirectory that
    specifies what is modules and what is built-in.

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

(译)
--- 3.6 下降到子目录
一个Makefile只是负责建立它自己目录下的objects。子目录下的文件因该有这些子目录下的
makefiles来处理。build系统将在子目录里自动的递归调用,你应该提供足够信息给它去处理。

To do so obj-y and obj-m are used.

ext2处在一个独立的目录里,在fs/里的Makefile会告诉kbuild去下降处理下面的赋值。

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

如果CONFIG_EXT2_FS被赋值为'y' (built-in) 或者 'm' (模块),那么相应的obj-变量将会被赋值,
kbuild将下降到ext2目录。
Kbuild仅仅使用这些信息去决定它需要去访问这个目录,在这个子目录里的Makefile指示那些是模块
和那些是built-in。

这是一个很好的实例去使用CONFIG_变量,这个变量被赋值目录名。这样允许kbuild去全部跳过那些
CONFIG_选项既不是'y'又不是'm'的目录。

--- 3.7 Compilation flags

    EXTRA_CFLAGS, EXTRA_AFLAGS, EXTRA_LDFLAGS, EXTRA_ARFLAGS

    All the EXTRA_ variables apply only to the kbuild makefile
    where they are assigned. The EXTRA_ variables apply to all
    commands executed in the kbuild makefile.

    $(EXTRA_CFLAGS) specifies options for compiling C files with
    $(CC).

    Example:
        # drivers/sound/emu10k1/Makefile
        EXTRA_CFLAGS += -I$(obj)
        ifdef DEBUG
            EXTRA_CFLAGS += -DEMU10K1_DEBUG
        endif


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

    $(EXTRA_AFLAGS) is a similar string for per-directory options
    when compiling assembly language source.

    Example:
        #arch/x86_64/kernel/Makefile
        EXTRA_AFLAGS := -traditional


    $(EXTRA_LDFLAGS) and $(EXTRA_ARFLAGS) are similar strings for
    per-directory options to $(LD) and $(AR).

    Example:
        #arch/m68k/fpsp040/Makefile
        EXTRA_LDFLAGS := -x

    CFLAGS_$@, AFLAGS_$@

    CFLAGS_$@ and AFLAGS_$@ only apply to commands in current
    kbuild makefile.

    $(CFLAGS_$@) specifies per-file options for $(CC).  The $@
    part has a literal value which specifies the file that it is for.

    Example:
        # 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

    These three lines specify compilation flags for aha152x.o,
    gdth.o, and seagate.o

    $(AFLAGS_$@) is a similar feature for source files in assembly
    languages.

    Example:
        # arch/arm/kernel/Makefile
        AFLAGS_head-armv.o := -DTEXTADDR=$(TEXTADDR) -traditional
        AFLAGS_head-armo.o := -DTEXTADDR=$(TEXTADDR) -traditional

(译)
--- 3.7 编译标记

EXTRA_CFLAGS, EXTRA_AFLAGS, EXTRA_LDFLAGS, EXTRA_ARFLAGS

所有的EXTRA_变量被使用,仅且仅当在这些kbuild makefile中它们被赋值。EXTRA_变量
被应用到所有在kbuild makefile里被执行到的命令。

$(EXTRA_CFLAGS) 为使用$(CC)来编译C文件提供指定选项。

    例子:
        # drivers/sound/emu10k1/Makefile
        EXTRA_CFLAGS += -I$(obj)
        ifdef DEBUG
            EXTRA_CFLAGS += -DEMU10K1_DEBUG
        endif


这些变量是很必要的,因为顶层的Makefile拥有变量$(CFLAGS)和使用它作为整个树的编译标志。

$(EXTRA_AFLAGS) 是一个类似的字符串作为每个目录的选项,当编译汇编语言源文件的时候。

    例子:
        #arch/x86_64/kernel/Makefile
        EXTRA_AFLAGS := -traditional


$(EXTRA_LDFLAGS) 和 $(EXTRA_ARFLAGS) 都是类似的字符串为每个目录下的$(LD)和$(AR)提供选项。

    例子:
        #arch/m68k/fpsp040/Makefile
        EXTRA_LDFLAGS := -x



--- 3.9 Dependency tracking

    Kbuild tracks dependencies on the following:
    1) All prerequisite files (both *.c and *.h)
    2) CONFIG_ options used in all prerequisite files
    3) Command-line used to compile target

    Thus, if you change an option to $(CC) all affected files will
    be re-compiled.

(译)
--- 3.9 依赖跟踪
Kbuild跟踪依赖性如下所示:
1)所有的依赖文件(*.c和*.h)
2)CONFIG_选项被应用到所有的依赖文件中。
3)命令行常用来编译目标。

因此,如果你改变了$(CC)选项,那么所有受影响的文件将被重编。



--- 3.10 Special Rules

    Special rules are used when the kbuild infrastructure does
    not provide the required support. A typical example is
    header files generated during the build process.
    Another example is the architecture specific Makefiles which
    needs special rules to prepare boot images etc.

    Special rules are written as normal Make rules.
    Kbuild is not executing in the directory where the Makefile is
    located, so all special rules shall provide a relative
    path to prerequisite files and target files.

    Two variables are used when defining special rules:

    $(src)
    $(src) is a relative path which points to the directory
    where the Makefile is located. Always use $(src) when
    referring to files located in the src tree.

    $(obj)
    $(obj) is a relative path which points to the directory
    where the target is saved. Always use $(obj) when
    referring to generated files.

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

    This is a special rule, following the normal syntax
    required by make.
    The target file depends on two prerequisite files. References
    to the target file are prefixed with $(obj), references
    to prerequisites are referenced with $(src) (because they are not
    generated files).

(译)
--- 3.10 特殊规则
特殊规则在kbuild的下层结构不提供所需要的支持时被使用到。一个典型的例子是头文件在
build过程期间被产生。另一个例子是是体系指定的Makefiles,而这些Makefiles需要特殊的
规则去准备boot镜像等等。

写特殊规则跟普通的Make规则一样。Kbuild不会再Makefile所在的目录下被执行,所以所有的特殊
规则应该提供相对的路径给依赖文件和目标文件。

当定义特殊规则的时候,两个变量将被使用到:

    $(src)
    $(src) 是一个指向Makefile所在目录的相对路径,当引用src树下的本地文件时应该总是使用$(src)。

    $(obj)
    $(obj) 是一个指向存储目标目录的相对路径,当引用被产生的文件时应该总是使用$(obj)。

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




=== 4 Host Program support

Kbuild supports building executables on the host for use during the
compilation stage.
Two steps are required in order to use a host executable.

The first step is to tell kbuild that a host program exists. This is
done utilising the variable hostprogs-y.

The second step is to add an explicit dependency to the executable.
This can be done in two ways. Either add the dependency in a rule,
or utilise the variable $(always).
Both possibilities are described in the following.

(译)
=== 4 主机程序支持
Kbuild支持在编译阶段建立主机可执行程序。
下面两步是在使用可执行的主机程序时是必须的。

第一步是告诉kbuild主机程序存在。这里利用变量hostprogs-y来完成。

第二步是添加一个精确的依赖到可执行程序。这些有2种方法来完成。或者在规则
添加一个依赖,或者利用变量 $(always)。
这些可能事情的被描述如下面所示:


--- 4.1 Simple Host Program

    In some cases there is a need to compile and run a program on the
    computer where the build is running.
    The following line tells kbuild that the program bin2hex shall be
    built on the build host.

    Example:
        hostprogs-y := bin2hex

    Kbuild assumes in the above example that bin2hex is made from a single
    c-source file named bin2hex.c located in the same directory as
    the Makefile.

(译)
--- 4.1 简单的主机程序
有一些情况是需要在主机上去编译和运行一个程序,当build正在运行的时候。
下面的行告诉了kbuild程序bin2hex在build的主机上应该被构建。

    例子:
        hostprogs-y := bin2hex

如上面的例子,Kbuild假定bin2hex由一个跟Makefile同在一个目录的名字为bin2hex.c的c源码文件构成。
 

--- 4.2 Composite Host Programs

    Host programs can be made up based on composite objects.
    The syntax used to define composite objects for host programs is
    similar to the syntax used for kernel objects.
    $(-objs) list all objects used to link the final
    executable.

    Example:
        #scripts/lxdialog/Makefile
        hostprogs-y   := lxdialog  
        lxdialog-objs := checklist.o lxdialog.o

    Objects with extension .o are compiled from the corresponding .c
    files. In the above example checklist.c is compiled to checklist.o
    and lxdialog.c is compiled to lxdialog.o.
    Finally the two .o files are linked to the executable, lxdialog.
    Note: The syntax -y is not permitted for host-programs.

(译)
--- 4.2 构造主机程序
主机程序能够由基于混合objects组成。这些语法常用来为主机程序定义混合objects,类似于语法
被用来定义内核objects的用法。
$(-objs) 列出的所有objects是常用来链接成最终的可执行程序。

    例子:
        #scripts/lxdialog/Makefile
        hostprogs-y   := lxdialog  
        lxdialog-objs := checklist.o lxdialog.o

带有扩展名.o的Objects由相应的.c文件来编译。在上面的例子checklist.c被编译成checklist.o和
lxdialog.c被编译成lxdialog.o。
最后这两个.o文件都被链接成可执行文件lxdialog。
注意:语法 -y 是在主机程序里不允许的。
    

--- 4.3 Defining shared libraries  
 
    Objects with extension .so are considered shared libraries, and
    will be compiled as position independent objects.
    Kbuild provides support for shared libraries, but the usage
    shall be restricted.
    In the following example the libkconfig.so shared library is used
    to link the executable conf.

    Example:
        #scripts/kconfig/Makefile
        hostprogs-y     := conf
        conf-objs       := conf.o libkconfig.so
        libkconfig-objs := expr.o type.o
 
    Shared libraries always require a corresponding -objs line, and
    in the example above the shared library libkconfig is composed by
    the two objects expr.o and type.o.
    expr.o and type.o will be built as position independent code and
    linked as a shared library libkconfig.so. C++ is not supported for
    shared libraries.

(译)
--- 4.3 定义共享库

带有扩展名为.so的Objects被认为是共享库,将被编译为独立的objects。Kbuild提供支持共享库,
不过用法应该被限制。
在下面的例子,libkconfig.so共享库被链接为可执行文件conf。

    例子:
        #scripts/kconfig/Makefile
        hostprogs-y     := conf
        conf-objs       := conf.o libkconfig.so
        libkconfig-objs := expr.o type.o

共享库总是需要一个相应的-objs行,在例子里上面的共享库libkconfig由两个objects expr.o和type.o组成。
expr.o和type.o将被建立为以位置独立的代码和被链接成共享库libkconfig.so。C++不被共享库所支持。


--- 4.4 Using C++ for host programs

    kbuild offers support for host programs written in C++. This was
    introduced solely to support kconfig, and is not recommended
    for general use.

    Example:
        #scripts/kconfig/Makefile
        hostprogs-y   := qconf
        qconf-cxxobjs := qconf.o

    In the example above the executable is composed of the C++ file
    qconf.cc - identified by $(qconf-cxxobjs).
    
    If qconf is composed by a mixture of .c and .cc files, then an
    additional line can be used to identify this.

    Example:
        #scripts/kconfig/Makefile
        hostprogs-y   := qconf
        qconf-cxxobjs := qconf.o
        qconf-objs    := check.o

(译)
--- 4.4 在主机程序里使用C++

kbuild提供在主机上使用C++编程的支持。这将被独立的介绍去支持kconfig,但不推荐一般的使用。

    例子:
        #scripts/kconfig/Makefile
        hostprogs-y   := qconf
        qconf-cxxobjs := qconf.o

上面例子里的可执行文件由C++文件qconf.cc来构成 - 通过$(qconf-cxxobjs)被鉴别。

如果qconf由混合的.c和.cc文件构成,那么附加一行能被用来鉴别这个。

    例子:
        #scripts/kconfig/Makefile
        hostprogs-y   := qconf
        qconf-cxxobjs := qconf.o
        qconf-objs    := check.o

    
--- 4.5 Controlling compiler options for host programs

    When compiling host programs, it is possible to set specific flags.
    The programs will always be compiled utilising $(HOSTCC) passed
    the options specified in $(HOSTCFLAGS).
    To set flags that will take effect for all host programs created
    in that Makefile use the variable HOST_EXTRACFLAGS.

    Example:
        #scripts/lxdialog/Makefile
        HOST_EXTRACFLAGS += -I/usr/include/ncurses
 
    To set specific flags for a single file the following construction
    is used:

    Example:
        #arch/ppc64/boot/Makefile
        HOSTCFLAGS_piggyback.o := -DKERNELBASE=$(KERNELBASE)
 
    It is also possible to specify additional options to the linker.
 
    Example:
        #scripts/kconfig/Makefile
        HOSTLOADLIBES_qconf := -L$(QTDIR)/lib

    When linking qconf it will be passed the extra option "-L$(QTDIR)/lib".

(译)
--- 4.5 为主机程序控制编译器选项

当编译主机程序时,很可能要设定指定的标志。程序将总是使用$(HOSTCC)来编译,$(HOSTCC)被传递
的选项在$(HOSTCFLAGS)里被指定。
去设置标志将影响所有的主机程序,这些程序在Makefile里使用变量HOST_EXTRACFLAGS被创建。

    例子:
        #scripts/lxdialog/Makefile
        HOST_EXTRACFLAGS += -I/usr/include/ncurses

为一个简单的文件设置指定的标志,下面的构造被使用:

    例子:
        #arch/ppc64/boot/Makefile
        HOSTCFLAGS_piggyback.o := -DKERNELBASE=$(KERNELBASE)

它同样可能给连接器指定附加的选项。

    例子:
        #scripts/kconfig/Makefile
        HOSTLOADLIBES_qconf := -L$(QTDIR)/lib

当链接qconf时,它将被传递额外的选项 "-L$(QTDIR)/lib"。


 
--- 4.6 When host programs are actually built

    Kbuild will only build host-programs when they are referenced
    as a prerequisite.
    This is possible in two ways:

    (1) List the prerequisite explicitly in a special rule.

    Example:
        #drivers/pci/Makefile
        hostprogs-y := gen-devlist
        $(obj)/devlist.h: $(src)/pci.ids $(obj)/gen-devlist
            ( cd $(obj); ./gen-devlist ) < $<

    The target $(obj)/devlist.h will not be built before
    $(obj)/gen-devlist is updated. Note that references to
    the host programs in special rules must be prefixed with $(obj).

    (2) Use $(always)
    When there is no suitable special rule, and the host program
    shall be built when a makefile is entered, the $(always)
    variable shall be used.

    Example:
        #scripts/lxdialog/Makefile
        hostprogs-y   := lxdialog
        always        := $(hostprogs-y)

    This will tell kbuild to build lxdialog even if not referenced in
    any rule.

(译)
--- 4.6 什么时候主机程序真正的被创建

Kbuild将建立主机程序,当且仅当他们作为一个依赖来被引用。
这是可能如下的两步:

(1)在一个特殊的规则里精确的列出这些依赖文件。

    例子:
        #drivers/pci/Makefile
        hostprogs-y := gen-devlist
        $(obj)/devlist.h: $(src)/pci.ids $(obj)/gen-devlist
            ( cd $(obj); ./gen-devlist ) < $<

目标$(obj)/devlist.h在$(obj)/gen-devlist更新之前将不被建立。注意在特殊的
规则里引用主机程序必须带有前缀$(obj)。

(2)使用 $(always)
当没有特殊的规则,主机程序在进入makefile时应该被建立,变量$(always)应该被使用。

    例子:
        #scripts/lxdialog/Makefile
        hostprogs-y   := lxdialog
        always        := $(hostprogs-y)

这个将告诉kbuild去建立lxdialog甚至如果没在任何的规则里被引用到。



--- 4.7 Using hostprogs-$(CONFIG_FOO)

    A typcal pattern in a Kbuild file lok like this:

    Example:
        #scripts/Makefile
        hostprogs-$(CONFIG_KALLSYMS) += kallsyms

    Kbuild knows about both 'y' for built-in and 'm' for module.
    So if a config symbol evaluate to 'm', kbuild will still build
    the binary. In other words Kbuild handle hostprogs-m exactly
    like hostprogs-y. But only hostprogs-y is recommend used
    when no CONFIG symbol are involved.

(译)
--- 4.7 使用 hostprogs-$(CONFIG_FOO)

在Kbuild里, 一个典型的模式看起来像这样:

    例子:
        #scripts/Makefile
        hostprogs-$(CONFIG_KALLSYMS) += kallsyms

Kbuild知道关于'y' 是供给 built-in 和 'm' 供给  module 使用的。
所以如果一个配置符号被评估为'm',kbuild将仍然建立这个二进制文件。换句话来说
Kbuild处理hostprogs-m非常像hostprogs-y那样。但是当没有CONFIG符号被调用的时候,
仅仅hostprogs-y被推荐使用。


=== 5 Kbuild clean infrastructure

"make clean" deletes most generated files in the src tree where the kernel
is compiled. This includes generated files such as host programs.
Kbuild knows targets listed in $(hostprogs-y), $(hostprogs-m), $(always),
$(extra-y) and $(targets). They are all deleted during "make clean".
Files matching the patterns "*.[oas]", "*.ko", plus some additional files
generated by kbuild are deleted all over the kernel src tree when
"make clean" is executed.

Additional files can be specified in kbuild makefiles by use of $(clean-files).

    Example:
        #drivers/pci/Makefile
        clean-files := devlist.h classlist.h

When executing "make clean", the two files "devlist.h classlist.h" will
be deleted. Kbuild will assume files to be in same relative directory as the
Makefile except if an absolute path is specified (path starting with '/').

(译)
=== 5 Kbuild 清除下层结构

"make clean"删除大部分在内核编译的源码树里被产生的文件。这包含被产生的文件如主机程序。
Kbuild 知道在$(hostprogs-y), $(hostprogs-m), $(always),$(extra-y) 和 $(targets)里目标列表。
它们在"make clean"期间将区别被删除。与模式"*.[oas]", "*.ko",匹配的文件,加上附加被kbuild产生
的文件在整个内核源码树立被删除,当"make clean"被执行。

附加的文件能够在kbuild makefile里通过使用$(clean-files)来指定。

    例子:
        #drivers/pci/Makefile
        clean-files := devlist.h classlist.h

当执行"make clean",这两个文件"devlist.h classlist.h"将被删除。 Kbuild将假定文件处在跟makefile同样
的相对目录,除非如果一个绝对路径被指定(路径以'/'开头)。



To delete a directory hirachy use:
    Example:
        #scripts/package/Makefile
        clean-dirs := $(objtree)/debian/

This will delete the directory debian, including all subdirectories.
Kbuild will assume the directories to be in the same relative path as the
Makefile if no absolute path is specified (path does not start with '/').

Usually kbuild descends down in subdirectories due to "obj-* := dir/",
but in the architecture makefiles where the kbuild infrastructure
is not sufficient this sometimes needs to be explicit.

    Example:
        #arch/i386/boot/Makefile
        subdir- := compressed/

The above assignment instructs kbuild to descend down in the
directory compressed/ when "make clean" is executed.

To support the clean infrastructure in the Makefiles that builds the
final bootimage there is an optional target named archclean:

    Example:
        #arch/i386/Makefile
        archclean:
            $(Q)$(MAKE) $(clean)=arch/i386/boot

When "make clean" is executed, make will descend down in arch/i386/boot,
and clean as usual. The Makefile located in arch/i386/boot/ may use
the subdir- trick to descend further down.

Note 1: arch/$(ARCH)/Makefile cannot use "subdir-", because that file is
included in the top level makefile, and the kbuild infrastructure
is not operational at that point.

Note 2: All directories listed in core-y, libs-y, drivers-y and net-y will
be visited during "make clean".

(译)
去删除一个目录层使用:

    例子:
        #scripts/package/Makefile
        clean-dirs := $(objtree)/debian/

这将删除目录debian,包括所有的子目录们。Kuild将假定这些目录跟makefile具有相同的
相对路径,如果没有绝对路径被指定(路径以'/'开头)。

通常kbuild下降到子目录因为这个"obj-* := dir/",但是在这个体系结构里的makefiles,在
某些地方kbuild下层结构不是很充分,这样有时需要被精确指出。

    例子:
        #arch/i386/boot/Makefile
        subdir- := compressed/


上面的赋值指示了kbuild去下降到目录compressed/,当"make clean"被执行。

为了支持在makefile里清除建立最终bootimage的下层结构,有个可选的目标叫做archclean。

    例子:
        #arch/i386/Makefile
        archclean:
            $(Q)$(MAKE) $(clean)=arch/i386/boot

当"make clean"被执行,make将下降到arch/i386/boot里,像普通那样清楚目标。
处在arch/i386/boot/目录下的makefile可能使用subdir-的技巧来下降到更深的目录。

注意 1:arch/$(ARCH)/Makefile不能够使用"subdir-",因为这文件被包含到顶层makefile,
这个kbuild的下层结构在这个位置不可运作。

注意 2:所有在core-y, libs-y, drivers-y 和 net-y列表里的目录将在"make clean"时被访问到。



=== 6 Architecture Makefiles

The top level Makefile sets up the environment and does the preparation,
before starting to descend down in the individual directories.
The top level makefile contains the generic part, whereas the
arch/$(ARCH)/Makefile contains what is required to set-up kbuild
to the said architecture.
To do so arch/$(ARCH)/Makefile sets a number of variables, and defines
a few targets.

When kbuild executes the following steps are followed (roughly):
1) Configuration of the kernel => produced .config
2) Store kernel version in include/linux/version.h
3) Symlink include/asm to include/asm-$(ARCH)
4) Updating all other prerequisites to the target prepare:
   - Additional prerequisites are specified in arch/$(ARCH)/Makefile
5) Recursively descend down in all directories listed in
   init-* core* drivers-* net-* libs-* and build all targets.
   - The value of the above variables are extended in arch/$(ARCH)/Makefile.
6) All object files are then linked and the resulting file vmlinux is
   located at the root of the src tree.
   The very first objects linked are listed in head-y, assigned by
   arch/$(ARCH)/Makefile.
7) Finally the architecture specific part does any required post processing
   and builds the final bootimage.
   - This includes building boot records
   - Preparing initrd images and the like


(译)
=== 6 体系 Makefiles

顶层的Makefile在开始下降进入个别目录之前设置环境和做好一切的准备工作。
顶层Makefile包含通用的部分,然而arch/$(ARCH)/Makefile包含所需求的设置kbuild
为所说的体系。
去完成这样的arch/$(ARCH)/Makefile,设置大量变量和定义一些目标。

kbuild依次地执行下面步骤(粗略地):
1)配置内核 => 产生.config文件
2)存储内核版本到include/linux/version.h。
3)建立符号链接 include/asm 链接到 include/asm-$(ARCH)
4)更新目标所有其他依赖准备:
   -- 附加的依赖在arch/$(ARCH)/Makefile里被指定。
5)递归下降到所有的目录,这些目录被列表在init-* core* drivers-* net-* libs-*,
   里面, 和建立所有的目标。
6) 所有的object文件都然后被链接和结果文件vmlinux被放置在源码树的根目录里。
   在head-y列表里的最先的objects在arch/$(ARCH)/Makefile里被赋值。
7) 最后,这个体系指定部分完成所有需要的后置处理和建立最终的bootimage。
   - 这包括建立boot记录
   - 准备initrd 镜像和the like




--- 6.1 Set variables to tweak the build to the architecture

    LDFLAGS        Generic $(LD) options

    Flags used for all invocations of the linker.
    Often specifying the emulation is sufficient.

    Example:
        #arch/s390/Makefile
        LDFLAGS         := -m elf_s390
    Note: EXTRA_LDFLAGS and LDFLAGS_$@ can be used to further customise
    the flags used. See chapter 7.
    
    LDFLAGS_MODULE    Options for $(LD) when linking modules

    LDFLAGS_MODULE is used to set specific flags for $(LD) when
    linking the .ko files used for modules.
    Default is "-r", for relocatable output.

    LDFLAGS_vmlinux    Options for $(LD) when linking vmlinux

    LDFLAGS_vmlinux is used to specify additional flags to pass to
    the linker when linking the final vmlinux.
    LDFLAGS_vmlinux uses the LDFLAGS_$@ support.

    Example:
        #arch/i386/Makefile
        LDFLAGS_vmlinux := -e stext

    OBJCOPYFLAGS    objcopy flags

    When $(call if_changed,objcopy) is used to translate a .o file,
    then the flags specified in OBJCOPYFLAGS will be used.
    $(call if_changed,objcopy) is often used to generate raw binaries on
    vmlinux.

    Example:
        #arch/s390/Makefile
        OBJCOPYFLAGS := -O binary

        #arch/s390/boot/Makefile
        $(obj)/image: vmlinux FORCE
            $(call if_changed,objcopy)

    In this example the binary $(obj)/image is a binary version of
    vmlinux. The usage of $(call if_changed,xxx) will be described later.

    AFLAGS        $(AS) assembler flags

    Default value - see top level Makefile
    Append or modify as required per architecture.

    Example:
        #arch/sparc64/Makefile
        AFLAGS += -m64 -mcpu=ultrasparc

    CFLAGS        $(CC) compiler flags

    Default value - see top level Makefile
    Append or modify as required per architecture.

    Often the CFLAGS variable depends on the configuration.

    Example:
        #arch/i386/Makefile
        cflags-$(CONFIG_M386) += -march=i386
        CFLAGS += $(cflags-y)

    Many arch Makefiles dynamically run the target C compiler to
    probe supported options:

        #arch/i386/Makefile

        ...
        cflags-$(CONFIG_MPENTIUMII)     += $(call cc-option,\
                        -march=pentium2,-march=i686)
        ...
        # Disable unit-at-a-time mode ...
        CFLAGS += $(call cc-option,-fno-unit-at-a-time)
        ...


    The first examples utilises the trick that a config option expands
    to 'y' when selected.

    CFLAGS_KERNEL    $(CC) options specific for built-in

    $(CFLAGS_KERNEL) contains extra C compiler flags used to compile
    resident kernel code.

    CFLAGS_MODULE    $(CC) options specific for modules

    $(CFLAGS_MODULE) contains extra C compiler flags used to compile code
    for loadable kernel modules.

(译)

--- 6.1 设置变量,调节build来适应体系

    LDFLAGS        通用的 $(LD) 选项

这些标志被所有链接器使用。经常指定仿真器是充要的。    

    例子:
        #arch/s390/Makefile
        LDFLAGS         := -m elf_s390
注意: EXTRA_LDFLAGS 和 LDFLAGS_$@ 能够在今后定制标志被使用。见第7章。
    
    LDFLAGS_MODULE    选项 $(LD) 当链接模块时使用

LDFLAGS_MODULE 常常为$(LD)设置指定标志,当链接.ko文件称模块时。默认是 "-r",
表示可重定位输出。

    LDFLAGS_vmlinux    选项$(LD) 当链接vmlinux时使用

LDFLAGS_vmlinux 常常指定附加标志传递给链接器,当链接最终vmlinux时。LDFLAGS_vmlinux
使用 LDFLAGS_$@ 来支持。

    例子:
        #arch/i386/Makefile
        LDFLAGS_vmlinux := -e stext

    OBJCOPYFLAGS    objcopy 标志

当$(call if_changed,objcopy)常常用来转换.o文件,那么使用在OBJCOPYFLAGS里指定标志。
$(call if_changed,objcopy) 是经常用来在vmlinux里产生原始二进制。

    例子:
        #arch/s390/Makefile
        OBJCOPYFLAGS := -O binary

        #arch/s390/boot/Makefile
        $(obj)/image: vmlinux FORCE
            $(call if_changed,objcopy)

在这个例子里,二进制目标$(obj)/image是vmlinux的二进制版本。$(call if_changed,xxx)
的用法将在后面被描述。

    AFLAGS        $(AS) 汇编标志

默认值 - 见顶层Makefile,根据不同的体系需求添加或修改。

    例子:
        #arch/sparc64/Makefile
        AFLAGS += -m64 -mcpu=ultrasparc

    CFLAGS        $(CC) 编译标志

默认值 - 见顶层Makefile,根据不同的体系需求添加或修改。经常 CFLAGS 变量取决于配置。

    例子:
        #arch/i386/Makefile
        cflags-$(CONFIG_M386) += -march=i386
        CFLAGS += $(cflags-y)

许多体系Makefiles动态地运行C编译器去探测被支持的选项:

        #arch/i386/Makefile

        ...
        cflags-$(CONFIG_MPENTIUMII)     += $(call cc-option,\
                        -march=pentium2,-march=i686)
        ...
        # Disable unit-at-a-time mode ...
        CFLAGS += $(call cc-option,-fno-unit-at-a-time)
        ...

第一个例子利用技巧,当被选择时配置选项被扩展为'y'。

    CFLAGS_KERNEL    $(CC) 为built-in指定选项


$(CFLAGS_KERNEL) 包含额外的C编译标志用来编译居处在内核里的代码。

    CFLAGS_MODULE    $(CC) 为modules指定选项

$(CFLAGS_MODULE) 包含额外的 C 编译标志来用编译可重加载的内核模块代码。


 
--- 6.2 Add prerequisites to prepare:

    The prepare: rule is used to list prerequisites that needs to be
    built before starting to descend down in the subdirectories.
    This is usual header files containing assembler constants.

        Example:
        #arch/s390/Makefile
        prepare: include/asm-$(ARCH)/offsets.h

    In this example the file include/asm-$(ARCH)/offsets.h will
    be built before descending down in the subdirectories.
    See also chapter XXX-TODO that describe how kbuild supports
    generating offset header files.

(译)

--- 6.2 添加依赖文件到 prepare目标:

目标prepare:这规则被用来在下降访问子目录前建立必要文件的列表。这里是普通的头文件包含
汇编实例。

        例子:
        #arch/s390/Makefile
        prepare: include/asm-$(ARCH)/offsets.h

在这个例子里, 文件include/asm-$(ARCH)/offsets.h 将在下降访问子目录之前被建立。
参见XXX-TODO章节,描述如何kbuild支持产生头文件编译。



--- 6.3 List directories to visit when descending

    An arch Makefile cooperates with the top Makefile to define variables
    which specify how to build the vmlinux file.  Note that there is no
    corresponding arch-specific section for modules; the module-building
    machinery is all architecture-independent.

    
    head-y, init-y, core-y, libs-y, drivers-y, net-y

    $(head-y) list objects to be linked first in vmlinux.
    $(libs-y) list directories where a lib.a archive can be located.
    The rest list directories where a built-in.o object file can be located.

    $(init-y) objects will be located after $(head-y).
    Then the rest follows in this order:
    $(core-y), $(libs-y), $(drivers-y) and $(net-y).

    The top level Makefile define values for all generic directories,
    and arch/$(ARCH)/Makefile only adds architecture specific directories.

    Example:
        #arch/sparc64/Makefile
        core-y += arch/sparc64/kernel/
        libs-y += arch/sparc64/prom/ arch/sparc64/lib/
        drivers-$(CONFIG_OPROFILE)  += arch/sparc64/oprofile/


(译)
--- 6.3 下降访问列表目录

一个体系Makefile协同顶层的Makefile去定义变量如何去建立vmlinux文件。注意没有给模块相应的
指定体系段;基于建立模块的机器都是体系独立的。
    
    head-y, init-y, core-y, libs-y, drivers-y, net-y

$(head-y) 列表 objects 是最先被链接到vmlinux的。
$(libs-y) 列表目录存储lib.a库信息。
          其余列表目录存储着built-in.o object文件。
$(init-y) objects被安排在紧跟$(head-y)之后。
      那么其余的服从下面的顺序:
      $(core-y), $(libs-y), $(drivers-y) 和 $(net-y).

顶层Makefile为所有的普通目录定义值和 arch/$(ARCH)/Makefile 紧紧添加指定体系的目录。

    例子:
        #arch/sparc64/Makefile
        core-y += arch/sparc64/kernel/
        libs-y += arch/sparc64/prom/ arch/sparc64/lib/
        drivers-$(CONFIG_OPROFILE)  += arch/sparc64/oprofile/




--- 6.4 Architecture specific boot images

    An arch Makefile specifies goals that take the vmlinux file, compress
    it, wrap it in bootstrapping code, and copy the resulting files
    somewhere. This includes various kinds of installation commands.
    The actual goals are not standardized across architectures.

    It is common to locate any additional processing in a boot/
    directory below arch/$(ARCH)/.

    Kbuild does not provide any smart way to support building a
    target specified in boot/. Therefore arch/$(ARCH)/Makefile shall
    call make manually to build a target in boot/.

    The recommended approach is to include shortcuts in
    arch/$(ARCH)/Makefile, and use the full path when calling down
    into the arch/$(ARCH)/boot/Makefile.

    Example:
        #arch/i386/Makefile
        boot := arch/i386/boot
        bzImage: vmlinux
            $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@

    "$(Q)$(MAKE) $(build)=" is the recommended way to invoke
    make in a subdirectory.

    There are no rules for naming of the architecture specific targets,
    but executing "make help" will list all relevant targets.
    To support this $(archhelp) must be defined.

    Example:
        #arch/i386/Makefile
        define archhelp
          echo  '* bzImage      - Image (arch/$(ARCH)/boot/bzImage)'
        endef

    When make is executed without arguments, the first goal encountered
    will be built. In the top level Makefile the first goal present
    is all:.
    An architecture shall always per default build a bootable image.
    In "make help" the default goal is highlighted with a '*'.
    Add a new prerequisite to all: to select a default goal different
    from vmlinux.

    Example:
        #arch/i386/Makefile
        all: bzImage

    When "make" is executed without arguments, bzImage will be built.


(译)
--- 6.4 体系特定的 boot images

一个体系的Makefile指定目标,取 vmlinux 文件,压缩它,封装它到bootstrapping代码里,在某处复制结果文件。
这包括各类的安装命令。实际的目标还没在体系中标准化。

通常在本地的arch/$(ARCH)/boot/目录做一些附加的处理。

Kbuild不提供任何智能的方法支持建立在boot/目录下被指定的目标。因此在boot/目录下,
arch/$(ARCH)/Makefile应该调用手动地调用make去建立目录。


推荐的方法是在arch/$(ARCH)/Makefile里包含快捷方式,使用全路径当向下进入arch/$(ARCH)/boot/Makefile时。

    例子:
        #arch/i386/Makefile
        boot := arch/i386/boot
        bzImage: vmlinux
            $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@

"$(Q)$(MAKE) $(build)=" 是一种推荐方法在子目录里调用make。

没有规则用来命名指定目标的体系,但是执行"make help" 将列出所有相关的目标。
为了支持这个, $(archhelp)必须被定义。

    例子:
        #arch/i386/Makefile
        define archhelp
          echo  '* bzImage      - Image (arch/$(ARCH)/boot/bzImage)'
        endef


当make不带任何参数的被执行,第一个被遇到目标将被创建。在顶层的makefile里,第一个目标呈现的是all:。

一个体系应当总是每次默认的建立一个可启动的镜像。在"make help"默认的目标用'*'来标注。增加一个新的依赖文件
给all: 去选择一个跟vmlinux不同的默认目标。

    例子:
        #arch/i386/Makefile
        all: bzImage

当"make"不带参数的执行时,bzImage将被建立。



--- 6.5 Building non-kbuild targets

    extra-y

    extra-y specify additional targets created in the current
    directory, in addition to any targets specified by obj-*.

    Listing all targets in extra-y is required for two purposes:
    1) Enable kbuild to check changes in command lines
       - When $(call if_changed,xxx) is used
    2) kbuild knows what files to delete during "make clean"

    Example:
        #arch/i386/kernel/Makefile
        extra-y := head.o init_task.o

    In this example extra-y is used to list object files that
    shall be built, but shall not be linked as part of built-in.o.


(译)
--- 6.5 建立non-kbuild目标

    extra-y

extra-y 指定附加的目标,在当前的目录被创建,又加到通过obj-*任何指定的目标。

在extra-y里列出所有目标是有需要的,因为如下两个目的:
1) 使到kbuild能在命令行里去检查改变,当$(call if_changed,xxx)被使用。
2) kbuild知道什么文件在"make clean"的时候被删除

    例子:
        #arch/i386/kernel/Makefile
        extra-y := head.o init_task.o

在这个例子里,extra-y 被用来列出应当被建立object文件,但是不应该被链接成 built-in.o 的一部分。


    
--- 6.6 Commands useful for building a boot image

    Kbuild provides a few macros that are useful when building a
    boot image.

    if_changed

    if_changed is the infrastructure used for the following commands.

    Usage:
        target: source(s) FORCE
            $(call if_changed,ld/objcopy/gzip)

    When the rule is evaluated it is checked to see if any files
    needs an update, or the commandline has changed since last
    invocation. The latter will force a rebuild if any options
    to the executable have changed.
    Any target that utilises if_changed must be listed in $(targets),
    otherwise the command line check will fail, and the target will
    always be built.
    Assignments to $(targets) are without $(obj)/ prefix.
    if_changed may be used in conjunction with custom commands as
    defined in 6.7 "Custom kbuild commands".
    Note: It is a typical mistake to forget the FORCE prerequisite.

    ld
    Link target. Often LDFLAGS_$@ is used to set specific options to ld.
    
    objcopy
    Copy binary. Uses OBJCOPYFLAGS usually specified in
    arch/$(ARCH)/Makefile.
    OBJCOPYFLAGS_$@ may be used to set additional options.

    gzip
    Compress target. Use maximum compression to compress target.

    Example:
        #arch/i386/boot/Makefile
        LDFLAGS_bootsect := -Ttext 0x0 -s --oformat binary
        LDFLAGS_setup    := -Ttext 0x0 -s --oformat binary -e begtext

        targets += setup setup.o bootsect bootsect.o
        $(obj)/setup $(obj)/bootsect: %: %.o FORCE
            $(call if_changed,ld)

    In this example there are two possible targets, requiring different
    options to the linker. the linker options are specified using the
    LDFLAGS_$@ syntax - one for each potential target.
    $(targets) are assinged all potential targets, herby kbuild knows
    the targets and will:
        1) check for commandline changes
        2) delete target during make clean

    The ": %: %.o" part of the prerequisite is a shorthand that
    free us from listing the setup.o and bootsect.o files.
    Note: It is a common mistake to forget the "target :=" assignment,
          resulting in the target file being recompiled for no
          obvious reason.


(译)
--- 6.6 建立boot image的有用的命令


Kbuild提供一些宏,当建立boot image时它们非常有用。

    if_changed

if_changed 是基础宏被用在如下的命令:

    Usage:
        target: source(s) FORCE
            $(call if_changed,ld/objcopy/gzip)

当规则被评估,它被检查是否有任何的文件需要更新,或者命令行因为最后的调用而改变了。
后面的将被强制的重建,如果给可执行文件的任何选项改变了。
任何目标使用必须在$(targets)里被列出来。否则命令行检查将失败,目标将总是被建立。
赋值到$(targets)是不需要前缀 $(obj)/ 的,if_changed可能在联合定制命令(例如6.7 "Custom kbuild commands") 被使用到。
注意:这是一个典型的错误由于忘记添加 FORCE 这个依赖。

    ld
链接目标。通常LDFLAGS_$@被用来设定指定的参数给 ld 。


    objcopy
复制二进制。使用 OBJCOPYFLAGS,通常在arch/$(ARCH)/Makefile里被指定。OBJCOPYFLAGS_$@ 可以被用来设定附加选项。

    gzip
压缩目标。使用最大压缩去压缩目标。

    例子:
        #arch/i386/boot/Makefile
        LDFLAGS_bootsect := -Ttext 0x0 -s --oformat binary
        LDFLAGS_setup    := -Ttext 0x0 -s --oformat binary -e begtext

        targets += setup setup.o bootsect bootsect.o
        $(obj)/setup $(obj)/bootsect: %: %.o FORCE
            $(call if_changed,ld)

在这个例子里,有两个可能的目标,需要不同的选项供给链接器,链接器选项通过使用LDFLAGS_$@语法来
指定 - 一个是给每个可能的目标。$(targets)被赋值给所有可能的目标,因此kbuild知道这些目标,将要:
1) 命令行改变检查
2) 在make clean期间删除目标


依赖部分": %: %.o"是一种速记帮助我们列出setup.o和bootsect.o文件。
注意:有个一公共的错误是忘记了"target :="赋值,导致很不明显的理由在目标文件里被重编。




--- 6.7 Custom kbuild commands

    When kbuild is executing with KBUILD_VERBOSE=0 then only a shorthand
    of a command is normally displayed.
    To enable this behaviour for custom commands kbuild requires
    two variables to be set:
    quiet_cmd_    - what shall be echoed
          cmd_    - the command to execute

    Example:
        #
        quiet_cmd_image = BUILD   $@
              cmd_image = $(obj)/tools/build $(BUILDFLAGS) \
                                             $(obj)/vmlinux.bin > $@

        targets += bzImage
        $(obj)/bzImage: $(obj)/vmlinux.bin $(obj)/tools/build FORCE
            $(call if_changed,image)
            @echo 'Kernel: $@ is ready'

    When updating the $(obj)/bzImage target the line:

    BUILD    arch/i386/boot/bzImage

    will be displayed with "make KBUILD_VERBOSE=0".
    
(译)

--- 6.7 定制kbuild命令

当kbuild使用KBUILD_VERBOSE=0执行时,那么仅仅命令速记正常被显示。
为了激活这行为去定制命令kbuild需要两个变量被设置:

    quiet_cmd_    - what shall be echoed
          cmd_    - the command to execute

    例子:
        #
        quiet_cmd_image = BUILD   $@
              cmd_image = $(obj)/tools/build $(BUILDFLAGS) \
                                             $(obj)/vmlinux.bin > $@

        targets += bzImage
        $(obj)/bzImage: $(obj)/vmlinux.bin $(obj)/tools/build FORCE
            $(call if_changed,image)
            @echo 'Kernel: $@ is ready'

当更新$(obj)/bzImage目标, 所示:

    BUILD    arch/i386/boot/bzImage

将显示为 "make KBUILD_VERBOSE=0"。





--- 6.8 Preprocessing linker scripts

    When the vmlinux image is build the linker script:
    arch/$(ARCH)/kernel/vmlinux.lds is used.
    The script is a preprocessed variant of the file vmlinux.lds.S
    located in the same directory.
    kbuild knows .lds file and includes a rule *lds.S -> *lds.
    
    Example:
        #arch/i386/kernel/Makefile
        always := vmlinux.lds
    
        #Makefile
        export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH)
        
    The assigment to $(always) is used to tell kbuild to build the
    target: vmlinux.lds.
    The assignment to $(CPPFLAGS_vmlinux.lds) tell kbuild to use the
    specified options when building the target vmlinux.lds.
    
    When building the *.lds target kbuild used the variakles:
    CPPFLAGS    : Set in top-level Makefile
    EXTRA_CPPFLAGS    : May be set in the kbuild makefile
    CPPFLAGS_$(@F)  : Target specific flags.
                      Note that the full filename is used in this
                      assignment.

    The kbuild infrastructure for *lds file are used in several
    architecture specific files.


(译)
--- 6.8 预处理链接器脚本

当vmlinux镜像被建立,使用链接脚本arch/$(ARCH)/kernel/vmlinux.lds。
这脚本被放置在共同的目录下,是文件vmlinux.lds.S预处理后的变种。
kbuild知道.lds文件和包含规则 *lds.S -> *lds.
    
    例子:
        #arch/i386/kernel/Makefile
        always := vmlinux.lds
    
        #Makefile
        export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH)
        
赋值到 $(always)被用来告诉kbuild去建立目标:vmlinux.lds 。
赋值到 $(CPPFLAGS_vmlinux.lds)告诉kbuild使用指定的选项,当建立vmlinux.lds目标时。
    
当建立目标 *.lds时, kbuild 使用变量:
    CPPFLAGS    : 设置最高层的makefile
    EXTRA_CPPFLAGS    : 可以在kbuild makefile里被设置
    CPPFLAGS_$(@F)  : 目标指定的标志
                      注意这里的赋值使用到全路径名。

建立*lds的kubild组织在几个指定文件的体系里被用到。




--- 6.9 $(CC) support functions

    The kernel may be build with several different versions of
    $(CC), each supporting a unique set of features and options.
    kbuild provide basic support to check for valid options for $(CC).
    $(CC) is useally the gcc compiler, but other alternatives are
    available.

    cc-option
    cc-option is used to check if $(CC) support a given option, and not
    supported to use an optional second option.

    Example:
        #arch/i386/Makefile
        cflags-y += $(call cc-option,-march=pentium-mmx,-march=i586)

    In the above example cflags-y will be assigned the option
    -march=pentium-mmx if supported by $(CC), otherwise -march-i586.
    The second argument to cc-option is optional, and if omitted
    cflags-y will be assigned no value if first option is not supported.

   cc-option-yn
       cc-option-yn is used to check if gcc supports a given option
    and return 'y' if supported, otherwise 'n'.

    Example:
        #arch/ppc/Makefile
        biarch := $(call cc-option-yn, -m32)
        aflags-$(biarch) += -a32
        cflags-$(biarch) += -m32
    
    In the above example $(biarch) is set to y if $(CC) supports the -m32
    option. When $(biarch) equals to y the expanded variables $(aflags-y)
    and $(cflags-y) will be assigned the values -a32 and -m32.

    cc-option-align
    gcc version >= 3.0 shifted type of options used to speify
    alignment of functions, loops etc. $(cc-option-align) whrn used
    as prefix to the align options will select the right prefix:
    gcc < 3.00
        cc-option-align = -malign
    gcc >= 3.00
        cc-option-align = -falign
    
    Example:
        CFLAGS += $(cc-option-align)-functions=4

    In the above example the option -falign-functions=4 is used for
    gcc >= 3.00. For gcc < 3.00 -malign-functions=4 is used.
    
    cc-version
    cc-version return a numerical version of the $(CC) compiler version.
    The format is where both are two digits. So for example
    gcc 3.41 would return 0341.
    cc-version is useful when a specific $(CC) version is faulty in one
    area, for example the -mregparm=3 were broken in some gcc version
    even though the option was accepted by gcc.

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

    In the above example -mregparm=3 is only used for gcc version greater
    than or equal to gcc 3.0.

(译)

--- 6.9 $(CC) 支持函数

内核可能由几个不同版本的$(CC)来建立,每个支持一个唯一的功能集和选项。
kbuild提供基本的支持,去检查$(CC)的有效选项。
$(CC) 通常是gcc编译器,但是其他的代替也是有效的。

    cc-option
cc-option 被用来检查 $(CC)是否支持一个给出的选项和不支持去使用一个可选的第二选项。

    例子:
        #arch/i386/Makefile
        cflags-y += $(call cc-option,-march=pentium-mmx,-march=i586)

在上面的例子里,cflags-y将被赋值给选项-march=pentium-mmx 如果被$(CC)所支持。否则是-march-i586。
第二参数给cc-option是可选的,如果被省略,cflags-y将被赋值为空,假如第一个选项不支持的话。

   cc-option-yn
cc-option-yn 被用来检查gcc 是否支持一个给出的选项,和返回'y'如果被支持,否则返回 'n'。

    例子:
        #arch/ppc/Makefile
        biarch := $(call cc-option-yn, -m32)
        aflags-$(biarch) += -a32
        cflags-$(biarch) += -m32
    
在上面的例子,$(biarch) 被赋值为 y 如果 $(CC) 支持选项 -m32。当 $(biarch) 等于 y,扩展变量$(aflags-y)
和 $(cflags-y) 将被赋值为 -a32 和 -m32。

    cc-option-align
gcc version >= 3.0 转变选项的类型被用来指定功能的赋值,循环等等。$(cc-option-align) 当被
使用作为前缀给赋值选项将选择右边的前缀:

    gcc < 3.00
        cc-option-align = -malign
    gcc >= 3.00
        cc-option-align = -falign
    
    例子:
        CFLAGS += $(cc-option-align)-functions=4

在上面的例子,选项-falign-functions=4供gcc >= 3.00使用。由于gcc < 3.00 -malign-functions=4 将被取用。
    
    cc-version
cc-version 返回$(CC)编译器的数字版本。它的格式是 ,这两个地方都由数字组成。因此例如
gcc 3.41 将返回0341。
cc-version 是非常有用当指定 $(CC) 版本在一处有毛病,例如 -mregparm=3 被分为一些gcc的版本,甚至尽管这些选项
都被gcc所接受。

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

在上面的例子里,-mregparm=3 仅仅供大于或等于gcc 3.0的版本使用。

    

=== 7 Kbuild Variables

The top Makefile exports the following variables:

    VERSION, PATCHLEVEL, SUBLEVEL, EXTRAVERSION

    These variables define the current kernel version.  A few arch
    Makefiles actually use these values directly; they should use
    $(KERNELRELEASE) instead.

    $(VERSION), $(PATCHLEVEL), and $(SUBLEVEL) define the basic
    three-part version number, such as "2", "4", and "0".  These three
    values are always numeric.

    $(EXTRAVERSION) defines an even tinier sublevel for pre-patches
    or additional patches.    It is usually some non-numeric string
    such as "-pre4", and is often blank.

    KERNELRELEASE

    $(KERNELRELEASE) is a single string such as "2.4.0-pre4", suitable
    for constructing installation directory names or showing in
    version strings.  Some arch Makefiles use it for this purpose.

    ARCH

    This variable defines the target architecture, such as "i386",
    "arm", or "sparc". Some kbuild Makefiles test $(ARCH) to
    determine which files to compile.

    By default, the top Makefile sets $(ARCH) to be the same as the
    host system architecture.  For a cross build, a user may
    override the value of $(ARCH) on the command line:

        make ARCH=m68k ...


    INSTALL_PATH

    This variable defines a place for the arch Makefiles to install
    the resident kernel image and System.map file.
    Use this for architecture specific install targets.

    INSTALL_MOD_PATH, MODLIB

    $(INSTALL_MOD_PATH) specifies a prefix to $(MODLIB) for module
    installation.  This variable is not defined in the Makefile but
    may be passed in by the user if desired.

    $(MODLIB) specifies the directory for module installation.
    The top Makefile defines $(MODLIB) to
    $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE).  The user may
    override this value on the command line if desired.

(译)

=== 7 Kbuild 变量

顶层的Makefile导出下面的变量:

    VERSION, PATCHLEVEL, SUBLEVEL, EXTRAVERSION

这些变量定义了当前的版本号。一些体系makefiles真实地直接地使用这些值;他们应该使用$(KERNELRELEASE)来代替。

$(VERSION), $(PATCHLEVEL), 和 $(SUBLEVEL) 定义了基本的三部分的版本号,例如 "2", "4", 和 "0"。这三个值总是数字。

$(EXTRAVERSION) 定义了一个非常细微的子级别给预补丁或者附加的补丁。它通常是一些非数字的串,例如 "-pre4",经常是空白。


    KERNELRELEASE

$(KERNELRELEASE) 是一个简单的字符串如 "2.4.0-pre4"。适合去构造安装目录名或

在版本串里显示。一些体系Makefiles为这个目的而使用它。

 

    ARCH

 

这个变量定义了目标体系,例如"i386","arm",或 "sparc"。一些kbuild makefiles测试$(ARCH)来

侦测哪一些文件需要被编译。

 

默认地,顶层的Makefile设置$(ARCH)跟主机系统体系相同。如果是交叉编译,那么用户在命令行里重载这个$(ARCH)值:

 

             make ARCH=m68k ...

 

 

    INSTALL_PATH

 

这个变量定义一个地方给体系Makefiles去安装内核的image和System.map文件。使用这个给体系指定安装目标。

 

    INSTALL_MOD_PATH, MODLIB

 

$(INSTALL_MOD_PATH) 为模块安装指定一个前缀到$(MODLIB)。这个变量在Makefile里没有被定义,但可以被用户传进来,如何需要的话。

 

$(MODLIB) 指定模块的安装目录。顶层的Makefile定义了$(MODLIB)到$(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)。用户可能

要在命令行里重载这个值,如果需要的话。

 

 

 

=== 8 Makefile language

 

The kernel Makefiles are designed to run with GNU Make.  The Makefiles

use only the documented features of GNU Make, but they do use many

GNU extensions.

 

GNU Make supports elementary list-processing functions.  The kernel

Makefiles use a novel style of list building and manipulation with few

"if" statements.

 

GNU Make has two assignment operators, ":=" and "=".  ":=" performs

immediate evaluation of the right-hand side and stores an actual string

into the left-hand side.  "=" is like a formula definition; it stores the

right-hand side in an unevaluated form and then evaluates this form each

time the left-hand side is used.

 

There are some cases where "=" is appropriate.  Usually, though, ":="

is the right choice.

 

 

(译)

=== 8 Makefile语言

 

内核Makefiles被设置给GNU Make运行。这个Makefiles使用仅仅使用到GNU Make里文档里

有记录的功能,但是他们使用了许多GNU扩展的功能。

 

GNU Make支持基本的列表处理函数。内核Makefiles使用了一个奇异的列表风格利用一些"if"

语句来建立和操作。

 

GNU Make 有两种赋值操作,":="和"="。":="立即执行右边的评估和存储一个实际的字符串到左边。

"="就像一个公式的定义;它以已评估的格式存储右边内容,然后每次评估这个格式,左边的会被使用到。

 

有一些情况在那里的"=" 是可以适合的,通常,尽管":="是最恰当的选择。

 

 

 

=== 9 Credits

 

Original version made by Michael Elizabeth Chastain,

Updates by Kai Germaschewski

Updates by Sam Ravnborg

 

(译)

=== 9 Credits

 

原始的版本是由Michael Elizabeth Chastain来完成的,

被Kai Germaschewski 更新。

被Sam Ravnborg 更新。

 

 

 

=== 10 TODO

 

- Describe how kbuild support shipped files with _shipped.

- Generating offset header files.

- Add more variables to section 7?

 

 

(译)

 

=== 10 TODO

- 描述kbuild如何支持使用_shipped来搬运文件。

- 产生偏移头文件。

- 在第7章立增加更多的变量。

阅读(1496) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~