linux kernel makefile中的那些小伙伴们

这篇文章是内核编译探索的重要知识点汇总,类似一个工具,列举了我所见到的一些target, rule. 以此希望对内核编译更进一步了解。

然而如果没有实际内核编译的经验,可能会觉得比较枯燥。建议从这个内核编译探索系列开始阅读。

稍微谈一点架构

文章写到一大半,发现可以来谈谈“架构”了。把这部分放到开始,或许会对大家理解有点帮助。

整个内核代码从make的角度来看,可能是这样的。

 +--  Makefile
 |
 +--+ init     
 |  |   
 |  +-- Makefile
 |      
 +--+ fs   
 |  |   
 |  +-- Makefile
 |  |   
 |  +-+ ext4
 |    | 
 |    +-- Makefile 
 |      
 +--+ kernel   
 |  |   
 |  +-- Makefile
 |  |   
 |  +-+ sched
 |    | 
 |    +-- Makefile 
 |      
 +--    

其实说白了就是每个层次目录中的Makefile中定义好相应的目标,如果有下一层,则进入到下一层继续编译。而这个过程中比较重要的文件是Makefile.build.

[更正]: “进入下一层”的表达有误。 在整个内核编译过程中,当前目录都是内核源码树的根目录。对不同目标,不同路径下的目标的编译,是通过obj变量做到的。这一点需要细看Makefile.build文件。

据说make中多线程同时编译,就是要依靠这么进入下一层来实现的。

rules

if_changed_xxx

这个规则实在是太重要,曝光率也是超高。

一般用法是这样的

$(obj)/bzImage: $(obj)/setup.bin $(obj)/vmlinux.bin $(obj)/tools/build FORCE
    $(call if_changed,image)
    @echo 'Kernel: $@ is ready' ' (#'`cat .version`')'

那来展开一下该定义在scripts/Kbuild.include中

###
# if_changed      - execute command if any prerequisite is newer than
#                   target, or command line has changed
# if_changed_dep  - as if_changed, but uses fixdep to reveal dependencies
#                   including used config symbols
# if_changed_rule - as if_changed but execute rule instead
# See Documentation/kbuild/makefiles.txt for more info

恩,原来有兄弟三个呢。先来看看大哥的样子

# Execute command if command has changed or prerequisite(s) are updated.
#
if_changed = $(if $(strip $(any-prereq) $(arg-check)),                       \
    @set -e;                                                             \
    $(echo-cmd) $(cmd_$(1));                                             \
    printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd, @:)

第一眼看这么长,其实我的内心是有点抵触的。一层层来看吧

首先这是个if语句, 当条件为真,则执行一个,若为假,则执行另一个。这么来看,逐个击破~

判断条件

$(strip $(any-prereq) $(arg-check))

意思就是所有依赖条件和arg-check字符串中如果有字符串,那么就会执行相关命令。

有没有新的依赖
# Find any prerequisites that is newer than target or that does not exist.
# PHONY targets skipped in both cases.
any-prereq = $(filter-out $(PHONY),$?) $(filter-out $(PHONY) $(wildcard $^),$^)

人注释写得真到位,一个表示比目标更新的依赖,一个表示还不存在的依赖。
先看看两个自动变量,

  • $? The names of all the prerequisites that are newer than the target
  • $^ The names of all the prerequisites

第一个太明显,第二个要看一下wildcard函数的定义了,

This string, used anywhere in a makefile, is replaced by a
space-separated list of names of existing files that match one of the
given file name patterns

恩,就是用来找到现在已经有的文件的。那结合定义,就是先找到依赖中已经存在的文件,然后从所有依赖中去掉。那不就剩下还没有生成的依赖了么。

有没有arg-check变化
# Check if both arguments are the same including their order. Result is empty
# string if equal. User may override this check using make KBUILD_NOCMDDEP=1
arg-check = $(filter-out $(subst $(space),$(space_escape),$(strip $(cmd_$@))), \
                         $(subst $(space),$(space_escape),$(
  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值