https://source.android.com/source/building-kernels.html
$ export PATH=/home/hzh/oldhome/learn/android-4.2.2/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin:${PATH}
$ export ARCH=arm
$ export SUBARCH=arm
$ export CROSS_COMPILE=arm-eabi-
$ make ARCH=arm goldfish_armv7_defconfig
$ make
Kernel Makefiles are part of the kbuild system, documented in various places on the web, for example http://lwn.net/Articles/21835/. The relevant excerpt is here:
--- 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 build 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.
So m means module, y means built-in (stands for yes in the kernel config process), and $(CONFIG_FOO) pulls the right answer from the normal config process.
linux kernel 的makefile的组织结构(转)
背景知识:
背景知识一:Kconfig介绍:
在#make menuconfig 时,所显示的Menu list是由各层Kconfig组成的。
最底层Kconfig存放在 ~/arch/i386/Kconfig. 以此为头,它会一层层使用source来把需要加入的各个目录中Keconfig添加近来。
例如:source "drivers/Kconfig"
则将~/drivers/Kconfig添加进Menu list中。
背景知识二:Kconfig写法语义:
config HID
tristate "Generic HID support"
depends on INPUT
default y
解释如下:
config HID :表示此条目与CONFIG-HID对应。CONFIG-HID会在Makefile中用到。
tristate "Generic HID support" 引号内的内容是会显示到Menu list中的。tristate表示这一项是三态的。
depends on INPUT:依赖于INPUT这一项。如果没有选中INPUT,则Menu list不会显示这项。
default y :缺省被选中。
背景知识三:built-in.o
vmlinux是Linux源码编译后未压缩的内核, vmlinux是由arch/i386/kernel/head.o和arch/i386/kernel/init_task.o以及各个相关子目录下的built-in.o链接而成的。
背景知识四:Kernel Makefile
Kernel中Makefile的体系以及如何编译的,其实Sam一直是一知半解的。
其中,kernel目录中的Makefile被称为底层Makefile。
当使用类似#make menuconfig配置内核成功后,会生成 .config文件。
换句话说:make menuconfig 时,Makefile会从~/arch/i386/Kconfig读取Kconfig.然后根据用户的选择。生成.config文件。
例如:在drivers/hid/Kconfig:
config HID
tristate "Generic HID support"
如果用户选中Y,则在.config中会反映出来:
CONFIG_HID=y
则在~/drivers/Makefile中可以看到:
obj-$(CONFIG_HID) += hid/
表明:如果CONFIG_HID是Y,则把hid目录添加到要编译的目录中了。
进入到/driver/hid目录,则看到:
hid-objs := hid-core.o hid-input.o
表明这两个.o文件是一定会被编译出的。
obj-$(CONFIG_HID) += hid.o
表明:如果CONFIG_HID是Y,则hid.o会被编译出来。并built-in.
如果是 =m. 则hid.o被编译出来,但最后被做成modules(ko)
背景知识五:KBuild Make:
Linux内核的Makefile与我们平时写的Makefile有所不同,它由五部分组成:
1.Makefile : 顶层Makefile。
2. .config: kernel配置文件。
3. arch/xxx/Makefile: 具体架构的Makefile。
4. scripts/Makefile.xxx : 通用规则。
5. kbuild Makefile: 整个kernel中大约有数百个这种文件。
#make menuconfig后,生成 kernel配置文件: .config。
顶层Makefile读取.config.
顶层Makefile通过解析 .config来决定递归访问哪些目录中的Kbuild Makefile .
这个过程中,Kbuild Makefile会按.config的设置,逐个添加文件列表,以供最后的编译使用。
最简单的KBuild Makefile如下:
obj-y += foo.o
表明:Kbuild在这目录里,有一个名为foo.o的目标文件。foo.o将从foo.c或foo.S文件编译得到。并且它会被包入built-in中去。
所 有编译进内核的目标文件都存在$(obj-y)列表中。而这些列表依赖内核的配置。Kbuild编译所有的$(obj-y)文件。然后,调用"$(LD) -r"将它们合并到一个build-in.o文件中。稍后,该build-in.o会被其父Makefile联接进vmlinux中。
如果foo.o要编译成一模块,那就要用obj-m了。所采用的形式如下:
obj-m += foo.o
例一:
在 ~/driver/hid/hid-core.c中,有以下语句,即内核insmod接口hid_init.
module_init(hid_init);
也就是说,当此模块被buildin或者作为module insmod时,kernel会自动调用hid_init.
然后查看 ~/driver/hid/Makefile,发现
hid-objs := hid-core.o hid-input.o
表明只要hid这个目录被加入,就会生成hid-core.o.
只好去看上一层目录中怎样会进入hid目录:
obj-$(CONFIG_HID) += hid/
表明只要CONFIG_HID=Y,m. 则hid目录被加入。
但用户作了什么,hid目录被加入编译呢?则看~/drivers/hid/Kconfig
config HID
tristate "Generic HID support"
以此得之只要在make menuconfig中选中此项,则hid-core.o被编译出来。
例2:
Sam想要研究USB Keyboard & Mouse driver. 在 make menuconfig时,需要选中:
config USB_HID
tristate "USB Human Interface Device (full HID) support"
则查看Makefile。发现只要选中CONFIG_USB_HID.则会编译出usb_hid.o
但~/drivers/hid/usbhid目录中却没有usbhid.c。那usbhid.o如何生成的呢?
drivers/hid/usbhid目录中,有个.usbhid.o.cmd文件。
_______________________________________________________________________________________________
linux kernel makefile
描述linux kernel 的makefile的组织结构,什么是linux kernel 和 makefile 不用说了。
1. 概述
kernel的makefile分为5个部分:
Makefile 最外面的Makefile
.config kernel的配置文件
arch/$(ARCH)/Makefile 不同架构cpu的makefile
scripts/Makefile.* 规则文件
kbuild Makefiles 500多个makefile文件
来看看kbuild makefile文件的构造规则定义。kbuild文件是组织kernel选项的文件。你会看到kbuild 和makefile 在一般同时存在一个目录里的。
目标定义:
一般都会用到此定义,此行的目的是要编译成foo.o 文件,而源文件是默认的foo.c或者是foo.s 。源文件在kbuild文件的同级目录里。
obj-y += foo.o
如果要将此编译成一个模块,则需要用ojb-m 。如果想通过kernel的配置传递此参数,则需要写下面的。
obj-$(CONFIG_FOO) += foo.o
(CONFIG_FOO) 就是你在kernel选项里配置的,如果你没有选中是built-in 还是 module,则此变量是y 或者 m的其他值,则不会编译此文件。
built-in 目标文件:
当你obj-y 的时候,他们将会把所有的obj-y files 都编译进去一个大的 built-in.o 目标文件。此后,会根据最上层的Makefile 链接成一个kernel image。
#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
需要注意的是,您需要注意这些 目标文件的顺序。
因为一些函数例如(module_init() / __initcall) 是按照他们出现的顺序被调用的。
ojb-m 目标:
这个是指要编译成模块。一个模块可以由一个源文件或者多个组成。
linux/2.6.20.6/make menuconfig
当在顶层目录执行”make menuconfig”会执行顶层Makefile 第415行的规则
config %config: scripts_basic outputmakefile FORCE
$(Q)mkdir -p include/linux include/config
$(Q)$(MAKE) $(build)=scripts/kconfig $@
这里”menuconfig”与模式”%config”匹配。所以其执行的规则如下:
menuconfig: scripts_basic outputmakefile FORCE
$(Q)mkdir -p include/linux include/config
$(Q)$(MAKE) $(build)=scripts/kconfig menuconfig
这个规则有三个依赖:scripts_basic、outputmakefile、FORCE。下面看一下这三个依赖:
1、 FORCE
首先分析一下这个依赖,它的规则定式义在1485行:
PHONY += FORCE
FORCE:
这个规则没有命令也没有依赖,它的目标也不是一个存在的文件名。在执行此规则时,目标FORCE总会被认为是最新的。这样当它作为其它规则的依赖时,因为依赖总被认为被更新过的,所以那个规则的中定义的命令总会被执行。
2、 scripts_basic
这个依赖的规则在347行定义:
scripts_basic:
$(Q)$(MAKE) $(build)=scripts/basic
build这个变量定义在scripts/kbuild.include的114行:
build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj
所以上面的规则可写成如下形式:
scripts_basic:
$(Q)$(MAKE) -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj=scripts/basic
这个规则的命令最终会进入scripts目录,执行Makefile.build文件,并传递参数obj=scripts/basic.
在Makefile.build的第5行有:
src := $(obj)
这就把传递进来的值赋给了src,所以
src := scripts/basic
从第16行开始的两行把src (即scripts/basic)目录下的Makefile包含进来(如果有Kbuild则包含Kbuild)
kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
include $(if $(wildcard $(kbuild-dir)/Kbuild), $(kbuild-dir)/Kbuild, $(kbuild-dir)/Makefile)
在第19行包含了scripts/Makefile.lib进来,
在Makefile.build的第83行,是make在Makefile.build中遇到的第一个目标
__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
$(if $(KBUILD_MODULES),$(obj-m)) \
$(subdir-ym) $(always)
@:
KBUILD_BUILTIN在顶层Makefile的第207行定义
KBUILD_BUILTIN := 1
如果执行”make modules”,会在214行开始对其进行一些处理
ifeq ($(MAKECMDGOALS),modules)
KBUILD_BUILTIN := $(if $(CONFIG_MODVERSIONS),1)
endif
所以我们这里 KBUILD_BUILTIN :=1
KBUILD_MODULES在顶层Makefile的第206行定义,
KBUILD_MODULES :=
如果执行”make all”、”make _all”、”make modules”、”make”中任一个命令,则在222行开始会对这个变量进行处理
ifneq ($(filter all _all modules,$(MAKECMDGOALS)),)
KBUILD_MODULES := 1
endif
ifeq ($(MAKECMDGOALS),)
KBUILD_MODULES := 1
endif
因此,我们这里KBUILD_MODULES :=
分析了这两个变量后,上面的规则可重新写为
__build: $(builtin-target) $(lib-target) $(extra-y)) $(subdir-ym) $(always)
@:
这就是通过规则
scripts_basic:
$(Q)$(MAKE) -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj=scripts/basic
在scripts/Makefile.build文件中执行的第一个规则,
规 则中的依赖由几个变量$(builtin-target) $(lib-target) $(extra-y)) $(subdir-ym) $(always)表示。规则的命令是一个冒号命令”:”,冒号(:)命令是bash的内建命令,通常把它看作true命令。bash的help解释 (help :)为:No effect; the command does nothing. A zero exit code is returned.(没有效果,该命令是空操作,退出状态总是0)。
__build: $(builtin-target) $(lib-target) $(extra-y)) $(subdir-ym) $(always)
@:
构建一些依赖目标,这里主要是构建$(always)变量指定的目标。其他变量在scripts/basic/Makefile中并没有定义。
3、 outputmakefile
回到顶层Makefile中看规则
menuconfig: scripts_basic outputmakefile FORCE
$(Q)mkdir -p include/linux include/config
$(Q)$(MAKE) $(build)=scripts/kconfig menuconfig
中的outputmakefile参数构建规则在357行开始定义
outputmakefile:
ifneq ($(KBUILD_SRC),)
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile \
$(srctree) $(objtree) $(VERSION) $(PATCHLEVEL)
endif
这个规则的命令运行一个shell脚本scripts/mkmakefile,并传递四个参数。这个脚本主要是在$(objtree)参数指定的目录中生成一个Makefile文件。由于这里KBUILD_SRC为空,所以这个脚本并不会被执行
回头再看看刚才那个规则
menuconfig: scripts_basic outputmakefile FORCE
$(Q)mkdir -p include/linux include/config
$(Q)$(MAKE) $(build)=scripts/kconfig menuconfig
在他的依赖被处理完后,开始执行规则的命令。第一个命令创建了两个目录,第二个命令扩展后为
$(Q)$(MAKE) -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj =scripts/kconfig menuconfig
这 个命令依然是执行scripts/Makefile.build这个makefile文件。并执行它里面menuconfig的规则。根据上面的分析,在 Makefile.build会包含scripts/kconfig/Makefile文件。然后执行以menuconfig为目标的规则,在 scripts/kconfig/Makefile的13行定义
menuconfig: $(obj)/mconf
$< arch/$(ARCH)/Kconfig
从这个命令可以看出,最终会运行arch/arm/Kconfig这个脚本,出现配置界面