您的位置:首页 > 运维架构 > Linux

Linux2.6.0源码kbuild、Makefile文档翻译

2014-04-10 22:28 441 查看

目的

为了学习Linux下的Makefile,从昨天开始决定要翻译一下源码底下/Documentation/kbuild目录下的modules.txt和Makefile.txt说明文档,今天翻译完,从网上找了篇别人的译文对比了下,感觉自己翻译的还算差强人意,所以贴出来记录下自己学习的点点滴滴。
译文对比地址点击打开链接http://blog.csdn.net/luo3532869/article/details/7650524。PS--这是本人第一次写翻译,翻译效果比不了别人的作品,只还算通顺。请多多指教、指正,谢谢。本人的译文下载地址http://download.csdn.net/detail/fengyehudie/7174663

2.6.0源码modules.txt翻译

Linux 内核Makefiles

这个文档描述了Linux kernel Makefiles

===目录表
===1 概览
===2 谁做了什么工作(o(╯□╰)o)
===3 kbuild Makefiles
  ---3.1 目标定义
  ---3.2 将目标编译进内核
  ---3.3 将目标编译成可加载模块
  ---3.4 导出目标符号
  ---3.5 库文件编译
  ---3.6 跟随目录向下依赖
  ---3.7 编译标志
  ---3.8 命令行依赖关系
  ---3.9 依赖关系
  ---3.10 特殊规则
  
===4 主机程序支持
  ---4.1 简单的主机程序
  ---4.2 合成主机程序
  ---4.3 定义共享库
  ---4.4 主程序使用C++
  ---4.5 为主程序设置编译选项
  ---4.6 主程序何时被正式编译
===5 Kbuild清除其下组织

===6 和架构相关的Makefiles
  ---6.1设置变量来维系架构的编译
  ---6.2添加必要条件进行准备
  ---6.3列出向下进入的子目录
  ---6.4架构相关启动镜像特性
  ---6.5 Building non-kbuild targets
  ---6.6对构建启动内核有用的命令
  ---6.7 Custom kbuild commands
  
===7 kbuild变量
=== 8 Makefile language
=== 9 Credits
=== 10 TODO

=== 1 Overview

Makefiles由5部分组成

Makefile
顶层Makefile
.config
内核配置文件
arch/$(ARCH)/Makefile
架构Makefile文件
scripts/Makefiles.*
所有Kbuild Makefiles 的通用规则等等
Kbuild Makefiles
这类文件大约有500多个。

顶层Makefile用来读取.config配置文件(.config文件来自对内核的配置过程)

顶层的Makefile用来支持vmlinux(内核镜像)和模块驱动(modules)的编译。

该Makefile通过重复地依赖源码树子目录的编译规则来编译上述vmlinux和modules。

同时子目录列表(哪些子目录会被依赖)取决于内核配置。顶层Makefile原装

引入架构Makefile即   arch/$(ARCH)/Makefile。而关于架构的Makefile为顶层Makefile

提供具体的架构信息。

每个子目录下都会有一个Kbuild Makefile文件用来执行从上层目录传下来的命令。

Kbuild Makefile使用来自.config的信息去构建不同的文件(被编译进内核或者驱动模块)。

scripts/Makefile.* 包含了所有的定义/规则等。用来基于Kbuild makefiles构建内核。

=== 2 Who does what

四中不同的人会用到Makefiles

*Users* 是构建内核的人。这些人制使用比如"make menuconfig" "make"等命令。

他们通常不会去阅读或编辑kernel Makefiles(或任何其他的源文件).

*Normal developers* 这些人为系统外表做研发,比如驱动、文件系统、网络协议等。

这些人需要去维护他们工作的子系统的Kbuild Makefiles。为了更有效的

做这份工作,他们需要一些更为总览全局的

知识和能力,来为Kbuild增加详细的共用接口。

*Arch developers* 为整个架构工作的人,像SPARC或IA64等架构。架构开发人员需要

了解ARCH Makefiles的同时也要掌握Kbuild Makefiles。

*Kbuild developers* 从事内核构建的开发人员。这类人需要知道kernel Makefiles的各个方面。

这份文档针对普通开发者和架构开发人员。

=== 3 The kbuild Makefiles

内核中多数的Makefiles都是使用了Kbuild组织的Kbuild Makefiles规则

。这章主要介绍在Kbuild Makefiles中常用的语法。

 3.1小节就是一个快速入门,以后的几节将会提供更多带有例子的细节。

 

 --- 3.1 Goal definitions

 

 目标定义是Kbuild Makefile的核心。这些代码决定了哪些文件应该被编译、

 特殊的编译选项、以及应该进入哪些子目录进行重复地执行此操作。

 最简单的Kbuild Makefile文件如下一行:

 

 obj-y += foo.o

 

 这告诉Kbuild该目录下有个名字叫foo.o的object。foo.o来自foo.c或者foo.s文件。

 

 如果foo.o应该被编译成动态模块,那么就该使用obj-m代替obj-y。因此会用到

 如下的代码

 

 obj-$(CONFIG_FOO) += foo.o

 

 $(COFNIG_FOO) 的值取决于你键入"y"(编入内核)或者键入"m"(编译动态模块)

 或者你什么也不键入代表该文件不会被编译。

 

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

 

 Kbuild Makefile使用$(obj-y)列表为vmlinux指定具体被编译文件。而这些列表依赖于

 内核配置

 

 Kbuild 将编译所有的标定为$(obj-y)的文件,调用"$(LD) -r"命令来融合连接这些文件到

 built-in.o中。后来built-in.o经由其上层Makefile连接进入vmlinux。

被标定编入内核的文件次序是很重要的,可以在集列表中有重复项。第一个文件会被编入

内核,后继相同的文件会被忽略。

连接次序也是很重要的,因为某些具体的函数会在他们模块调用之前调用,比如module_init()。

所以请牢记连接顺序。比如更改了SCSI控制器连接顺序,你的磁盘会被重新编号

(希望是这样) change the order in which your SCSI
controllers are detected, and thus you disks are renumbered.

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

--- 3.3 Loadable module goals - obj-m

$(obj-m)指定目标文件将会被编译成内核模块。

一个模块的编译源文件可能来自一个或几个源文件。在前一种情况下,代码如下:

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

note: $(CONFIG_ISDN_PPP_BSDCOMP)等价于m

若是内核驱动依赖多个源文件,你必须像上例那样指定你想构建的驱动。

同时Kbuild需要知晓用来构建你的驱动的具体文件,所以你必须定义一个如下的变量

来告诉Kbuild

$(<module_name>-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)变量中的目标然后执行"$(LD)
-r"来生成isdn.o

Kbuild能够通过"-bjs" "-y"后缀识别目标.这就能够让Makefiles使用CONFIG_symbol变量
来决定目标是编译入内核还是复合对象的一部分。

note:当你打算将目标编入内核的时候,上属语法也能奏效。你让CONFIG_EXT2_FS = y
Kbuild将会为你单独编译出ext2.o,并且连接入built-in.o,只要你愿意。

--- 3.4 Objects which export symbols

在makefiles文件中没有具体的标记、语法来为驱动模块导出符号。

--- 3.5 Library file goals - lib-y

在具体目录中的带有obj-*的目标文件都会用来编译驱动模块或者编译入built-in.o
当然也有可能将列出的目标包含成一个库文件。
在具体目录中所有带有lib-y的目标文件都会编译入一个库文件。
带有obj-y同时附带有lib-y的目标由于他们都会被操作,将不会包含入库文件
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.
为了保持一致性,标有lib-m的目标将会被包含入库文件。
note:有些kbuild make可能会列出一些文件编译入built-in.o同时成为库文件的一部分。
因此相同目录下可能会包含有一个built-in.o和一个lib.a文件。
例子:
#arch/i386/lib/Makefile
lib-y := checksum.o delay.o
这会生成一个基于checksum.o和delay.o的库文件lib.a。kbuild真正意识到lib.a正在被构建
是在该目录下将目标加入libs-y列表集
For kbuild to actually recognize that there is a lib.a being build
the directory shall be listed in libs-y.
请参考6.3 List directories to visit when descending
一般只有lib/和arch/*/lib目录下可以使用lib-y

--- 3.6 Descending down in directories

一个makefile文件只为当前目录下的构建目标负责。子目录中的构建目标必须由自己
目录下的Makefile进行维护。只要你让build知晓子目录下的kbuild,他会自动重复地
引入子目录kbuild进行构建。

为了上述目的,此处会用到obj-y和obj-m。
ext2位于一个独立的目录,同时位于fs/目录下的Makefile告诉kbuild要继续向下执行
例子:
#fs/Makefile
obj-$(CONFIG_EXT2_FS)
+= ext2/
如果CONFIG_EXT2_FS设置成y或者m那么该变量生效,那么kbuild会向下进入该目录
kbuild仅仅使用这个信息来决定自己是不是要进入这个ext2目录,而ext2目录下的
Makefile文件决定ext2是编译成built-in.o还是module

使用CONFIG_variable来指定访问目录名是一个好的方式。这会让kbuild忽略无关文件夹

--- 3.7 Compilation flags

EXTRA_CFLAGS, EXTRA_AFLAGS, EXTRA_LDFLAGS, EXTRA_ARFLAGS

全部的EXTRA_ variables仅仅存放到被指定的kbuild makefile中,这些变量适用于kbuild 
makefile中所有可执行的命令
EXTRA_ variables都能够被执行。
$(EXTRA_CFLAGS)为C文件指定编译选项$(CC)
例子:
#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

@CFLAGS_$@,AFLAGS_$@
@CFLAGS_$@和AFLAGS_$@仅适用于当前kbuild makefile的命令。

$(CFLAGS_$@)会具体到为每个文件都应用$(CC)选项。$@代表了具体文件名称

例子:
#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

这三行分别编译了aha152x.ogdth.o seagate.o

相比之下,$(AFLAGS_$@)就是对汇编源文件的相似描述变量。
例子:
# arch/arm/kernel/Makefile
AFLAGS_head-armv.o := -DTEXTADDR=$(TEXTADDR) -traditional
AFLAGS_head-armo.o := -DTEXTADDR=$(TEXTADDR) -traditional

--- 3.9 Dependency tracking

kbuild的去向依赖于如下条件
1)所有必需的文件(*.c *.h)
2)所需文件的CONFIG_options标志
3)用来编译目标的命令

因此,如果你改变了$(CC)的某个选项,那么所有相关的文件都会重新编译

--- 3.10 Special Rules

当kbuild下部组织不能提供相应支持的时候,就需要使用特殊规则进行编译。
典型的例子就是编译过程中产生的头文件。再者,架构下的某些Makefile需要
特殊规则来制作启动镜像等等。

特殊规则的写法和普通规则的写法是一样的。
kbuild不会在有Makefile的目录下执行,因此所有的特殊规则会为必需文件和目标
文件提供一个相对路径。
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.

定义特殊规则的时候会用到下俩变量:

$(src)
$(src)指向Makefile目录位置的相对路径。通常使用它来指向源码树中的位置

$(obj)
$(obj)指向目标(target)目录位置的相对路径。通常使用它指向生成文件位置。

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

这是一个特殊规则,make会执行如下的通用规则。
目标文件依赖于两个必需文件,应用和$(obj)前缀相同的目标文件,引用$(src)
必需文件。(因为这些文件没有事先生成)
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).

=== 4 Host Program support

在编译阶段kbuild支持在主机上构建可执行文件并执行。
使用主机程序需要以下两步:

第一步:告诉kbuild主机程序存在,这由host-prog变量告知
第二步:为此添加详细的依赖关系。这可由两种方式完成。
在规则中添加或者使用$(always)变量

--- 4.1 Simple Host Program

有些情况下,我们 需要在主机上编译并运行一个程序。
下面代码告诉kbuild bin2hex会在主机上进行构建

例子:
host_progs
:= bin2hex

上例中kbuild假设bin2hex由一个和Makefile位置相同的名叫bin2hex.c
的文件编译而来

--- 4.2 Composite Host Programs

主机程序也可能是由多个必需目标组合成的。
下列语法为主机程序定义必须的多个目标,这和定义内核必须的多个
目标的语法是相同的。
$(<executeable>-objs)列出所有用来连接最终可执行程序的目标。

例子:
#scripts/lxdialog/Makefile
host-progs    := lxdialog  
lxdialog-objs := checklist.o lxdialog.o

带有.o的目标都会由对应的带有.c编译而来。上例中,checklist.o由
checklist.c编译而来。最终这两个.o文件连接成可执行文件lxdialog
note:对于主机程序编译 <executable>-y是不合法的。

--- 4.3 Defining shared libraries

带有.so扩展的目标是共享库文件,会被编译成独立的目标。
kbuild也为so提供支持,但是用法却很严格。
下例中libkconfig.so用来连接入conf可执行文件
例子:
#scripts/kconfig/Makefile
host-progs
:= conf
conf-objs
:= conf.o libkconfig.so
libkconfig-objs
:= expr.o type.o
共享库通常需要-objs后缀,上例中的libkconfig就是由expr.o和type.o
构成。
expr.o和type.o将会构建成独立的代码并且作为libkconfig.so连接入conf
C++不支持so库

--- 4.4 Using C++ for host programs

kbuild支持C++格式的主机程序代码。接受它完全是为了支持kconfig,
一般不建议使用。

例子:
#scripts/kconfig/Makefile
host-progs
:= qconf
qconf-cxxobjs
:= qconf.o

上例中可执行文件由以$(qconf-cxxobjs)标定的C++文件qconf.cc编译而来。

如果qconf由c和c++文件混合编译而来,那么附加代码如下

Example:
#scripts/kconfig/Makefile
host-progs    := qconf
qconf-cxxobjs := qconf.o
qconf-objs    := check.o

--- 4.5 Controlling compiler options for host programs

编译主机程序的时候,会设置具体的标志。
The programs will always be compiled utilising $(HOSTCC) passed
the options specified in $(HOSTCFLAGS).
o(╯□╰)o这句不会翻译,怕翻译错了。
编译主机程序的过程中可以使用$(HOSTCC)变量
来传递$(HOSTCFLAGS)变量中指定的选项。

若使用HOST_EXTRACFLAGS标志,那么本Makefile内的上述编译会奏效

例子:
#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才会去真正构建主机程序。
这有两种方式进行构建:
(1)使用特殊规则明确列出必要的目标

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

目标$(obj)/devlist.h总在$(obj)/gen-devlist之后构建.注意,带有特殊规则的
主机程序目标必须带有$(obj)前缀。
Note that references to
the host programs in special rules must be prefixed with $(obj).

(2)使用$(always)
当没有合适的特殊规则的时候,可以使用$(always)变量来进行构建主机程序

例子:
#scripts/lxdialog/Makefile
host-progs    := lxdialog
always        := $(host-progs)

这样做是要告诉kbuild进行构建lxdialog即便没有任何参考规则

=== 5 Kbuild clean infrastructure

"make clean"会删除源码树中多数的生成文件。
这些文件中包含生成的主机程序。kbuild知晓标有$(host-progs) $(always) $(extra-y)
和$(targets)的目标。在执行make clean的时候这些都会被删除。
当执行"make clean"的时候oas和ko格式的文件也会被删除。

其他文件若是想要被删除,可以在makefiles中使用$(clean-files)具体指定

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

执行make clean的时候这两个文件会被删除,同时这两个文件跟makefile位于
相同目录下

通常kbuild重复地向下依赖子目录是依靠"obj-* := dir/"来完成,但是在与架构
相关的makefiles中kbuild下部组织不会这样详细列出。

例子:
#arch/i386/boot/Makefile
subdir-
:= compressed/
上例中,当make clean时,kbuild会进入compressed/目录

为了支持清除内核镜像相关的下部组织,可以在Makefile中使用archclean执行
此操作

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

执行make clean的时候,make会进入arch/i386/boot目录执行清除。此目录下的
makefile也可以使用subdir- 来进入更深层的子目录执行清除工作。

note1:arch/$(ARCH)/Makefile不能使用"subdir-",因为该文件被顶层makefile包含
,而kbuild的下部组织在那个位置是不能被选择的。

note2:列在core-y,libs-y,drivers-y和net-y的所有目录make clean都会进入,执行clean

=== 6 Architecture Makefiles

在进入子目录之前,顶层makefile配置了编译环境做了准备工作。

顶层makefile包含了通用的部分,anrch/$(ARCH)/Makefile文件包含了和架构相关

的配置部分。

因此arch/$(ARCH)/Makefile设置了大量的变量定义了很多目标。

当kbuild执行的时候下列的步骤也会执行

1)内核配置=>生成.config

2)保存内核版本号到include/linux/version.h

3)符号链接include/asm到include/asm-$(ARCH)

ymlink include/asm to include/asm-$(ARCH)

4)针对目标更新所有必需的文件,必需文件在arch/$(ARCH)/Makefile中指定

5)进入子目录进行递归罗列 init-* core-* drivers-* net-* lib-*,并且构建所有的目标

上述变量的值会备份到arch/$(ARCH)/Makefile中

6)所有的目标文件会被连接到到一起,构成源码树根目录下的vmlinux。

第一个被连接的目标是由arch/$(ARCH)/Makefile指定的列为head-y的目标。

7)最终和架构相关的部分接管进程,来构建最终的bootimage

这包含了构建启动记录、准备初始化镜像等

   - This includes building boot records

   - Preparing initrd images and 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.

例子:
#arch/s390/Makefile
LDFLAGS
:= -m elf_s390

Note:EXTRA_LDFLAGS和LDFLAGS_$@用来做更深层的标志定义,详见第七章

LDFLAGS_MODULE
对应$(LD),进行模块连接的时候LDFLAGS_MODULE
用来为$(LD)设置标志。默认标志是"-r",    
Default is "-r", for relocatable output.

LDFLAGS_vmlinux对应$(LD)在连接vmlinux时
LDFLAGS_vmlinux用来为连接器指定附加标志来连接最终的vmlinux
LDFLAGS_vmlinux支持LDFLAGS_$@

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

LDFLAGS_BLOB
对应$(LD),在连接initramfs blob
LDFLAGS_BLOB
Options for $(LD) when linking the initramfs blob

The image used for initramfs is made during the build process.

在生成initramfs_data.o文件时,LDFLAGS_BLOB用来指定附加的标志

例子:
#arch/i386/Makefile
LDFLAGS_BLOB
:= --format binary --oformat elf32-i386

OBJCOPYFLAGS
objcopy flags

当$(call if_chabged,objcopy)用来编译a.o文件时,该标志才会被使用。
$(call if_changed,objcopy)经常用来生成原生二进制vmlinux文件。

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

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

本例中binary $(obj)/image是vmlinux的二进制版本,$(call if_changed,xxx)在后续中讲解

AFLAGS
$(AS) assembler flags

默认值请参照顶层makefile
作为架构的追加或修改内容

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

CFLAGS
$(CC) compiler flags

默认值参照顶层makefile
作为架构的追加或者修改内容

通常CFLAGS变量依赖于配置

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

许多架构相关的makefiles会动态地运行目标机C编译器来检测
支持选项。

#arch/i386/makefile
check_gcc = $(shell if $(CC) $(1) -S -o /dev/null -xc \
           /dev/null\ > /dev/null 2>&1; then echo "$(1)"; \
           else echo "$(2)"; fi)
cflags-$(CONFIG_MCYRIXIII) += $(call check_gcc,\
                                    -march=c3,-march=i486)

CFLAGS += $(cflags-y)

当选中选项的时候,上述例子是很好的方法将选项扩展成y
The above examples both utilise the trick that a config option expands
to 'y' when selected.

CFLAGS_KERNEL
$(CC) options specific for built-in
 
$(CFLAGS_KERNEL)包含额外C编译器标志用以编译内核代码
 
CFLAGS_MODULE
$(CC) options specific for modules
 
$(CFLAGS_MODULE)包含额外的C编译器标志用以编译可加载内核模块

--- 6.2 Add prerequisites to prepare:

archprepare:这是一条用来列出先决条件的规则,这些先决条件是build进
入子目录前 必须建立的。

这将从在包含汇编内容的头文件中使用

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

本例中,在进入子目录之前,include/asm-$(ARCH)/offset.h会被先编译

--- 6.3 List directories to visit when descending

架构相关makefile会和顶层makefile合作定义指定如何构建vmlinux的变量。
请留意,并没有和架构相关的章节为驱动(modules)而存在。模块构建
是和架构无关的。

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

$(head-y)为首次连接入vmlinux的目标列表
$(libs-y)为lib.a的位置列出目录$(libs-y) list directories where a lib.a archive can be located.
剩下的列表目录是built-in.o的位置The rest list directories where a built-in.o object file can be located.

$(init-y)目标会位于$(head-y)之后
剩下的位置排放次序如下:
$(core-y), $(libs-y), $(drivers-y) and $(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

arch makefile具体指定组成vmlinux的目标文件,并将它压缩、包含入启动代码
这个过程包含了各类安装命令,它的实际目的不     是标准化整个架构。

在arch/$(ARCH)/目录下的boot/目录可以很轻松的找打任何额外添加的内容。

在编译boot/下指定的target时,kbuild并不会提供任何捷径去执行。因此,arch/
$(ARCH)/makefile必须按部就班地在boot/下构建target。

推荐的方法是在arch/$(ARCH)/Makefile中包含入相对路径,进入子目录执行arch/$(ARCH)/
boot/makefile时使用绝对路径。

例子:
#arch/i386/Makefile
boot := arch/i386/boot
bzImage : vmlinux
$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
"$(Q)$(MAKE) $(build)=<dir>" is the recommended way to invoke
此处添加推荐的方法--相对路径
制作一个子目录

针对具体架构命名的target没有对应的规则进行编译,但是执行"make help"
会列出所有相关的targets,为了支持上述编译,$(archhelp)必须要定义。

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

当只执行make操作时,将会编译第一个目标。在顶层makefile中,
第一个目标是all:
每种架构都会默认编译一个启动镜像。在"make help"中默认的目标
是一个带有“*”的高亮显示的名称。在"all"后边添加新的target,
选择一个不同于vmlinux的默认goal。
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.

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

当单独执行make时,将会构建bzImage

--- 6.5 Building non-kbuild targets

extra-y
extra-y在当前目录下指定构建额外targets(只要被标记为obj-*)。

将所有的带有extra-y的targets列表主要有一下两个目的:
1)让kbuild在命令行检查targets改变
-是不是有$(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针对构建起动镜像提供了几个非常有用的宏。

if_changed
if_changed是下列命令的基础

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

当一个规则被求值的时候,会检查规则相对于上次
被调用是否有文件被更新或者命令行         被改变。
如果任何可执行文件的选项被改变,那么就会强制执行rebuild。
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.

任何使用过if_changed标志的targets必须要列入$(targets),否则会导致命令
行检测失败,这样会使target总是会被重新编译。
$(targets)并不带有$(obj)前缀。if_changed也可能与定制命令一起使用,请
参考6.7节。
note:忘记写FORCE是一个典型的错误,请谨记。

ld
连接目标。LDFLAGS_$@通常用作ld的具体指明选项。

objcopy
Copy binary。通常在arch/$(ARCH)/makefile中使用OBJCOPYLAGS标志,
该标志也可以作为附加选项使用。

gzip
压缩目标。使用尺寸最优进行压缩target

例子:
#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)

本例中可能会有两个targets,所以连接器需要不同的选项。连接器
选项指明使用LDFLAGS_$@方式,来构建每个潜在的target。
In this example there is 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)检查命令行更改
2)执行make clean 时删除target

": %: %.o"是一种让我们省事的速记方法。
note:忘记写"target :="是一个常见的错误

--- 6.7 Custom kbuild commands

当kbuild执行到KBUILD_VERBOSE=0时,只会正常显示一个命令行
速记。
custome commands kbuild必须要设置两个变量来使能这个功能
quiet_cmd_<command>
- what shall be echoed
     cmd_<command>
- 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”

=== 7 Kbuild Variables

顶层makefile导出下列变量
VERSION,PATCHLEVEL,SUBLEVEL,EXTRAVERSION

这些变量定义了当前内核版本,有些和架构相关的makefiles
会直接使用这些变量;他们会使用$(KERNELRELEASE)来代替。

$(VERSION),$(PATCHLEVEL),$(SUBLEVEL)定义了基本的内核版本
号的三部分,这三个变量就是数字格式。

$(EXTRAVERSION)为每个补丁定义了一个更小的子号。
这个通常是非数字的字符串例如"-pre4",或者是空格

KERNNELRELEASE

该变量是一个字符串类似"2.4.0-pre4",用来创建导入目录名或者展示
内核版本号字符串。

ARCH

这个变量定义了目标架构,比如"i386","arm", "sparc"。有的kbuild
makefiles测试$(ARCH)来决定哪些文件应该进行编译。

默认设置情况下,顶层makefile设置$(ARCH)是和主机系统架构相同的
,为了进行交叉编译,使用者应该修在命令行上改这个变量。

make ARCH=m68k

INSTALL_PATH

这个变量定义了架构相关的makefiles导入当前编译内核镜像或者
system.map的存放位置,使用这个变量来指定导入targets位置。

INSTALL_MOD_PATH,MODLIB

$(INSTALL_MOD_PATH)为$(MODLIB)指定前缀。这个变量没有在Makefile
中定义,但可以由用户传入。
This variable is not defined in the Makefile but
may be passed in by the user if desired.

$(MODLIB)为模块导入操作指定目录,顶层makefile定义了该变量
并设置为$(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE).
用户可以使用目录更改这个设置。

=== 8 Makefile language

内核makefiles使用GNU Make规则设计,同时也使用了很多GNU扩展设计。

GNU Make支持基本的列表处理功能。内核Makefiles使用一种新的

方式使用更少的"if"来列表构建、操作目标。

GNU Make有两个重要的操作符 ":="和"="。。":="立即计算出

等式右边的值,并且储存一个实际的字符串到等式左边。

"="就像一个规则定义;它将等式右边直接储存到等式左边而

不计算出实际的值,当每次使用等式左边的值时再去计算出实际的值。

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

=== 9 Credits

Original version made by Michael Elizabeth Chastain, <mailto:mec@shout.net>

Updates by Kai Germaschewski <kai@tp1.ruhr-uni-bochum.de>

Updates by Sam Ravnborg <sam@ravnborg.org>

=== 10 TODO

- Describe how kbuild support shipped files with _shipped.

- Generating offset header files.

- Add more variables to section 7?

源码下modules.txt译文

到目前为止这个文件是从原先版本的/Documentation/modules.txt(2.6.0内核)的原生拷贝。

如下的内容是正确的,但并不是完整的内容

将模块modules导入非标准(其他)路径

----------------------------------------------

当将modules导入其他路径时,导入路径INSTALL_MOD_PATH 应该使用目标目录路径

来代替/lib/modules。这样做将会把modules导入到"目标路径/lib/modules"下,目标路径可

以是挂载在系统上的其他机器的NFS设备,也可以是远程主机上。

编译非标准内核(其他内核,非本机内核,个人意见)的modules

-----------------------------------------------

目标模块的开发通常不是在目标系统上进行的。

为了在本地主机上避开目标内核与本地内核的差异,编译一个供其他内核使用的驱动

可行的方法是使用如下的命令来编译驱动。

make -C path/to/kernel/src SUBDIRS=$PWD modules

当然了这要求您先根据/Documentation/kbuild/makefiles.txt中的说明来编写一个Makefile文件

总结

经过自己的翻译对Makefile规则 有了一定的了解,相信以后再去查阅Makefile的时候就容易理解了。本人的译文下载地址
http://download.csdn.net/detail/fengyehudie/7174663
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Linux Makefile kbuil