linux Kbuild详解关于if_changed_rule的any-prereq和arg-check原理及info调试关于fixdep没有展开,这里说下。

文章目录

  • 1. escsq
  • 2. Q、quiet
    • 2. 1 make V=(0、1、2)
    • 2. 2 make V=(0、1)来控制Q、quiet
  • 3. fixdep
    • 3. 1 fixdep是什么
    • 3. 2 fixdep为什么
      • 3.2.1 .config和autoconf.h的关系
      • 3.2.2 autoconf.h被引用
      • 3.2.3 GNU产生的依赖均包含autoconf.h
      • 3.2.4 全局头文件autoconf.h改动的影响
      • 3.2.5 fixdep登场了
    • 3. 3 fixdep怎么做
      • 3.3.1 fixdep参数depfile
      • 3.3.2 fixdep参数target
      • 3.3.3 fixdep参数cmdline
      • 3.3.4 fixdep输出
      • 3.3.5 过程总结
  • 4. 参考

1. escsq

quote   := "
squote  := '
# Escape single quote for use in echo statements
escsq = $(subst $(squote),'\$(squote)',$1)

escsq :转义(escape)单引号 (single quote)
$(subst $from, $to, $var)的用法:将$var中的$from部分替换成$to。
因此上述代码就很明确了:$(squote)是单引号,'$(squote)'是双引号,替换。

2. Q、quiet

2. 1 make V=(0、1、2)

V含义为verbose,表示详细的,即打印更多的信息 。

@echo  '  make V=0|1 [targets] 0 => quiet build (default), 1 => verbose build'
@echo  '  make V=2   [targets] 2 => give reason for rebuild of target'
  • V=0:表示不输出编译信息。在编译时不指定V时,默认 V=0。
  • V=1:表示输出详尽编译信息。
  • V=2:给出重新编译目标的理由。

2. 2 make V=(0、1)来控制Q、quiet

  • 控制Q
ifeq ("$(origin V)", "command line")KBUILD_VERBOSE = $(V)
endif
#如果V值来源于命令行,则KBUILD_VERBOSE从$(V)获取值ifeq ($(KBUILD_VERBOSE),1)	#V=1quiet =Q =
else						#V=0quiet=quiet_Q = @
endif

示例如下:

%o: %c$(Q)$(CC) -c $< -o $@

如Q=@就能控制编译$(CC)命令不输出。那还需要quiet做什么?

  • 控制quiet
    quiet有什么神奇的力量?其实quiet并没有什么神通的力量,只是一个普通的变量,用于生成特定区分详细程度或参数不同(如quiet_cmd_xx、cmd_xx)的命令。
    看一个例子:
quiet_cmd_checksrc     = CHECK   $<
cmd_checksrc     = $(CHECK) $(CHECKFLAGS) $(c_flags) $< ;

两条命令可化成一条命令为:$(quiet)cmd_checksrc 进行操作了。

3. fixdep

3. 1 fixdep是什么

fixdep是一个用Host主机从源文件fixdep.c编译得到的整理依赖的可执行工具:

xx@xx-vb:~/Downloads/linux$ file scripts/basic/fixdep 
scripts/basic/fixdep: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=3b57a9ce45b07c8ea86176d2002706756d35e692, for GNU/Linux 3.2.0, not stripped

执行提示如下:

xx@xx-vb:~/Downloads/linux$ scripts/basic/fixdep 
Usage: fixdep [-e] <depfile> <target> <cmdline>-e  insert extra dependencies given on stdin

代码在scripts/basic/fixdep.c,逻辑不复杂,代码中更像详细点的介绍:

 * It is invoked as**   fixdep <depfile> <target> <cmdline>** and will read the dependency file <depfile>** The transformed dependency snipped is written to stdout.** It first generates a line**   cmd_<target> = <cmdline>** and then basically copies the .<target>.d file to stdout, in the* process filtering out the dependency on autoconf.h and adding* dependencies on include/config/MY_OPTION for every* CONFIG_MY_OPTION encountered in any of the prerequisites.

简而言之:它输入<depfile>,<target>,和编译该<target>的编译命令<cmdline>,基本上拷贝.<target>.d的文件内容到标准输出,但移除其中的对autoconf.h的依赖,将依赖文件中形如CONFIG_MY_OPTION的配置项转成include/config/MY_OPTION的文件作为依赖。可能迷糊的你,依然好奇,这是个啥玩意?!先看fixdep为什么。

3. 2 fixdep为什么

3.2.1 .config和autoconf.h的关系

编译内核前,通常需要进行make [xx]config,生成.config和各种由此产生的文件如tristate.conf、auto.conf、autoconf.h等(生成过程可参考文章 auto.conf, auto.conf.cmd, autoconf.h)。可以把 .config看作其他配置文件的来源,其形式为:

...
CONFIG_X86=y
CONFIG_HZ=250
CONFIG_INSTRUCTION_DECODER=y
...

而C文件不能使用这样的信息,kbuild conf从.config转换得到autoconf.h作为所有C文件公共配置项头文件,其形式为:

...
#define CONFIG_X86 1
#define CONFIG_HZ 250
#define CONFIG_INSTRUCTION_DECODER 1
...

3.2.2 autoconf.h被引用

在scripts/Kbuild.include中:

cmd_and_fixdep =                                                              \
272     $(echo-cmd) $(cmd_$(1));                                              \
273     scripts/basic/fixdep $(depfile) $@ '$(make-cmd)' > $(dot-target).tmp; \
274     rm -f $(depfile);                                                     \
275     mv -f $(dot-target).tmp $(dot-target).cmd;其中$(1)为 cmd_cc_o_c:
177 	cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $< 

272行执行编译命令展开为177行,其中c_flags在scripts/Makefile.lib中:

154 c_flags        = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE)     \
155                  -include $(srctree)/include/linux/compiler_types.h       \
156                  $(__c_flags) $(modkern_cflags)                           \
157                  $(basename_flags) $(modname_flags)

154行包含$(LINUXINCLUDE)

LINUXINCLUDE在Makefile中定义如下:

 412 LINUXINCLUDE    := \413                 -I$(srctree)/arch/$(SRCARCH)/include \414                 -I$(objtree)/arch/$(SRCARCH)/include/generated \415                 $(if $(KBUILD_SRC), -I$(srctree)/include) \416                 -I$(objtree)/include \417                 $(USERINCLUDE)

415行-I$(srctree)/include包含include目录下的头文件,这里包括 include/generated/autoconf.h

3.2.3 GNU产生的依赖均包含autoconf.h

154行-Wp,-MD,$(depfile):编译器的–MD FILE选项将会把依赖文件输入到FILE中:

--MD FILE   write dependency information in FILE (default none)

这个选项在cmd_and_fixdep的273行会将编译依赖生成到$(depfile)也即.<target>.d文件中,以init/main.c为例,其在177行cmd_cc_o_c命令下编译同时生成的init/.main.o.d文件,内容包含了autoconf.h,如下第一行:

main.o: init/main.c include/linux/kconfig.h include/generated/autoconf.h \  #autoconf.hinclude/linux/compiler_types.h include/linux/compiler-gcc.h \include/linux/types.h include/uapi/linux/types.h \...

其他文件大部分都会包含include/generated/autoconf.h,因为这是个全局的配置项头文件。想查看形如init/.main.o.d(一般化为$(depfile))文件内容的需要改下scripts/Kbuild.include,因为正常不使用它作为依赖根据,处理后$(depfile)就被删除了。为调试研究,我们将删除项去掉,如下:

xx@xx-vb:~/Downloads/linux$ git diff
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
index ce53639a864a..598489621347 100644
--- a/scripts/Kbuild.include
+++ b/scripts/Kbuild.include
@@ -271,7 +271,6 @@ ifndef CONFIG_TRIM_UNUSED_KSYMScmd_and_fixdep =                                                             \$(echo-cmd) $(cmd_$(1));                                             \scripts/basic/fixdep $(depfile) $@ '$(make-cmd)' > $(dot-target).tmp;\
-       rm -f $(depfile);                                                    \mv -f $(dot-target).tmp $(dot-target).cmd;else

3.2.4 全局头文件autoconf.h改动的影响

上文描述了全局头文件autoconf.h被普遍引用的过程,如果使用-Wp,-MD,$(depfile)生成的$(depfile)中的依赖关系作为增量编译的判断依据,存在的问题是:A文件有个配置如CONFIG_HZ=250,B文件的配置CONFIG_INSTRUCTION_DECODER 1,两者可能不相关,但是A文件改动了配置为CONFIG_HZ=500,从而更新了autoconf.h。由于B也引用了autoconf.h,且B的依赖关系中也依赖autoconf.h文件,从而导致几乎所有的依赖关系包含autoconf.h的文件需要重新编译,这个显然不符合增量编译的设计。

3.2.5 fixdep登场了

fixdep就是来处理这个问题的,它需要把A:autoconf.h、B:autoconf.h的方式改为A:CONFIG_HZ、B:CONFIG_INSTRUCTION_DECODER的方式,这样互相就不会扯到蛋了。
具体改成依赖小写空文件的形式:

GNU -MD生成式fixdep调整
A:autoconf.h(CONFIG_HZ)A: include/config/hz.h
B:autoconf.h(CONFIG_INSTRUCTION_DECODER)B: include/config/instruction/decoder.h

所有依赖CONFIG_HZ的文件都只依赖 include/config/hz.h,而不是依赖公共的autoconf.h,这样就做到了依赖的分离。

3. 3 fixdep怎么做

还是以init/main.c为例,就fixdep的参数depfile、target、cmdline及输出展开:

fixdep <depfile> <target> <cmdline>

fixdep使用实例:

cmd_and_fixdep =                                                              \
272     $(echo-cmd) $(cmd_$(1));                                              \
273     scripts/basic/fixdep $(depfile) $@ '$(make-cmd)' > $(dot-target).tmp; \
274     rm -f $(depfile);                                                     \
275     mv -f $(dot-target).tmp $(dot-target).cmd;

3.3.1 fixdep参数depfile

对应273行的$(depfile)

#ini/main.o => ini/.main.o
dot-target = $(dir $@).$(notdir $@)# 如果有逗号替换为_,这里返回的是ini/.main.o.d
depfile = $(subst $(comma),_,$(dot-target).d)

这里的$(depfile)=init/.main.o.d,这个文件哪里来的?它是272行执行cmd_cc_o_c,其中c_flags = -Wp,-MD,$(depfile) … 编译目标ini/main.o文件同时生成的。

3.3.2 fixdep参数target

对应273行的$@=ini/main.o

3.3.3 fixdep参数cmdline

对应273行的’$(make-cmd)’

make-cmd = $(call escsq,$(subst $(pound),$$(pound),$(subst $$,$$$$,$(cmd_$(1)))))
#--------------------------------------------------------------------------------
$(cmd_$(1))展开为:
177 	cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<

这里的’$(make-cmd)'=gcc -Wp,-MD,init/.main.o.d -nostdinc -isystem /usr/lib/gcc/x86_64-linux-gnu/9/include -I./arch/x86/include -I./arch/x86/include/generated …很长。

3.3.4 fixdep输出

对应273行的输出$(dot-target).tmp后经275行的重命名得到$(dot-target).cmd=init/.main.o.cmd,有兴趣可以看看其内容([…]有省略):

cmd_init/main.o := gcc -Wp,-MD,init/.main.o.d  -nostdinc -isystem /usr/lib/gcc/x86_64-linux-gnu/9/include -I./arch/x86/include -I./arch/x86/include/generated  -I./include -I./arch/x86/include/uapi -I./arch/x86/include/generated/uapi -I./include/uapi -I./include/generated/uapi -include ./include/linux/kconfig.h -include ./include/linux/compiler_types.h -D__KERNEL__ -Wall -Wundef [...] -DKBUILD_BASENAME='"main"' -DKBUILD_MODNAME='"main"' -c -o init/main.o init/main.csource_init/main.o := init/main.cdeps_init/main.o := \$(wildcard include/config/init/env/arg/limit.h) \$(wildcard include/config/smp.h) \[...]  $(wildcard include/config/strict/module/rwx.h) \include/linux/kconfig.h \$(wildcard include/config/cpu/big/endian.h) \$(wildcard include/config/booger.h) \$(wildcard include/config/foo.h) \include/linux/compiler_types.h \$(wildcard include/config/have/arch/compiler/h.h) \$(wildcard include/config/enable/must/check.h) \[...]include/trace/events/initcall.h \include/trace/define_trace.h \init/main.o: $(deps_init/main.o)$(deps_init/main.o):

3.3.5 过程总结

fixdep调整过的依赖关系保存文件$(depfile)中保存了:编译命令变量、源文件名称变量、fixdep修改后的依赖变量、声明fixdep修改后依赖关系。

#1.编译命令变量
cmd_$@ := '$(make-cmd)'#2.源文件名称变量
source_$@ := $(depfile)中C源文件#3.fixdep修改后的依赖变量
deps_$@ := $(depfile)中去除autoconf.h,并依据源码中CONFIG_X_Y增加$(wildcard include/config/x/y.h)依赖项#4.声明fixdep修改后依赖关系
$@: deps_$@
deps_$@:

如下图片看不清除,可以点击放大看

  1. 编译命令变量
    在这里插入图片描述

  2. 源文件名称变量
    在这里插入图片描述

  3. fixdep修改后的依赖变量
    在这里插入图片描述
    生成依赖变量deps_$@ ,包含两部分:第一部分从$(depfile) (图中右侧绿色框),移除红框autoconf.h和main.c,剩下都包含进来;第二部分查找main.c中CONFIG_X_Y的宏,添加为$(wildcard include/config/x/y.h) \的依赖项。

  4. 声明了fixdep修改后依赖关系
    使用fixdep修改依赖关系后,不再使用GNU -MD生成的依赖关系作为判断依赖是否更新的依据,从而避免了依赖共享autoconf.h导致依赖关联的问题。

4. 参考

  1. linux Kbuild详解系列(8)-Kbuild中其他通用函数与变量
  2. auto.conf, auto.conf.cmd, autoconf.h

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/921549.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/921549.shtml
英文地址,请注明出处:http://en.pswp.cn/news/921549.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

notepad++ 正则表达式

在 Notepad 中&#xff0c;正则表达式&#xff08;Regular Expressions, Regex&#xff09; 是一个强大的搜索和替换工具&#xff0c;可以高效地处理文本。以下是 Notepad 正则表达式 的指南&#xff1a;1. 如何在 Notepad 中使用正则表达式打开搜索窗口&#xff1a;快捷键 Ctr…

MySQL Cluster核心优缺点

MySQL Cluster 是 MySQL 官方提供的 分布式、内存优先、高可用 的数据库解决方案&#xff08;基于 NDB 存储引擎&#xff09;。它采用 Share-Nothing 架构&#xff0c;数据自动分片&#xff08;Sharding&#xff09;并分布在多个节点上&#xff0c;适用于需要极高可用性和实时性…

训练+评估流程

训练评估流程1、要求2、训练评估&#xff08;PyTorch TensorBoard &#xff09;完整代码&#xff08;单文件示例&#xff09;运行方法功能对应表3、pytorch自定义评估要继承哪个类&#xff1f;4、HF Trainer和SB35、 汇总1. PyTorch Lightning TensorBoard ModelCheckpoint …

【开题答辩全过程】以 基于Android的点餐系统为例,包含答辩的问题和答案

个人简介一名14年经验的资深毕设内行人&#xff0c;语言擅长Java、php、微信小程序、Python、Golang、安卓Android等开发项目包括大数据、深度学习、网站、小程序、安卓、算法。平常会做一些项目定制化开发、代码讲解、答辩教学、文档编写、也懂一些降重方面的技巧。感谢大家的…

【音视频】Http-FLV 介绍

一、Http-FLV 原理 HTTP-FLV 是基于 HTTP 协议的 FLV&#xff08;Flash Video&#xff09;流媒体传输方式。它使用 HTTP 协议而不是传统的 RTMP 协议来传输 FLV 格式的视频流。HTTP-FLV 在 Web 视频直播场景中得到了广泛应用&#xff0c;尤其是在不支持或不希望使用 RTMP 协议的…

uniapp vue页面传参到webview.nvue页面的html或者另一vue中

在app内部使用 uni.$emit(collectiones, { data: gx });传到webview.nvue页面 在webview.nvue页面接受 uni.$on(collectiones, (data) > {console.log(接收到的数据:, data.data);});使用evalJS方法 nvue webview通信示例 这块使用receiveMessageFromNvue方法这样传入的 u…

美团大模型“龙猫”登场,能否重塑本地生活新战局?

美团大模型“龙猫”登场&#xff0c;能否重塑本地生活新战局&#xff1f; 美团大模型登场&#xff1a;行业投下重磅炸弹 在大模型技术迅猛发展的当下&#xff0c;每一次新模型的发布都如投入湖面的石子&#xff0c;激起层层涟漪。美团推出的龙猫大模型 LongCat-Flash&#xff0…

shell(十三)参数代换

shell参数代换xargs. 产生命令的参数1. cut -d : -f 1 /etc/passwd | head -n 3 | xargs finger2. 执行前询问用户cut -d : -f 1 /etc/passwd | head -n 3 | xargs -p finger如果直接按回车就退出3. 指定查阅参数个数cut -d : -f 1 /etc/passwd | xargs -p -n 5 finger4. 指定遇…

Proteus 仿真 + STM32CubeMX 协同开发全教程:从配置到仿真一步到位

为帮助你精准掌握「Proteus 仿真 STM32CubeMXSTM32F103R6」的协同开发流程&#xff0c;本文将聚焦该芯片的特性&#xff0c;从工具适配、分步实操到进阶案例&#xff0c;用富文本格式清晰呈现细节&#xff0c;尤其适合新手入门 32 位单片机开发&#xff1a;ProteusSTM32CubeMX…

WIN10+ubuntu22.04.05双系统装机教程

最近DIY了一台5070TI显卡主机&#xff0c;目的是跑IsaacSim5.0仿真&#xff0c;记录双系统装机过程。 1.Ubuntu22.04.05系统盘制作 参考教程&#xff1a;01_【U盘制作ubuntu22.04启动盘并为电脑安装系统记录】_制作ubuntu22.04安装u盘-CSDN博客 U盘因为是64G的&#xff0c;而…

构建高可用二级缓存系统

二级缓存机制原理详解1. 整体架构MyBatis-Plus二级缓存采用装饰器模式实现&#xff0c;核心组件包括&#xff1a;‌Cache接口‌&#xff1a;定义缓存基本操作‌PerpetualCache‌&#xff1a;基础缓存实现&#xff08;HashMap&#xff09;‌装饰器‌&#xff1a;如LruCache、Fif…

MacOS微信双开,亲测有效

本机配置打开终端运行以下命令 第一步&#xff1a;sudo cp -R /Applications/WeChat.app /Applications/WeChat2.app第二步&#xff1a;sudo /usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier com.tencent.xinWeChat2" /Applications/WeChat2.app/Contents/Info…

Drupal XSS漏洞复现:原理详解+环境搭建+渗透实践(CVE-2019-6341)

目录 一、Drupal XSS漏洞 二、环境搭建 1、确保系统已安装 Docker 和 Docker-Compose 2、下载 Vulhub 3、进入漏洞环境 4、启动漏洞环境 5、查看环境状态 6、初始化Drupal环境 &#xff08;1&#xff09;访问 Drupal 安装页面 &#xff08;2&#xff09;完成图形化安…

Redis复制延迟全解析:从毫秒到秒级的优化实战指南

Redis主从延迟飙升导致数据不一致&#xff1f;订单丢失、缓存穿透频发&#xff1f;本文深入剖析8大复制延迟元凶&#xff0c;并提供解决方案&#xff0c;让你的复制延迟从秒级降到毫秒级&#xff01; 一、复制延迟:分布式系统的隐形杀手 ⚠️ 什么是复制延迟&#xff1f; 当主…

数据预处理与特征工程全流程指南:数据清洗、缺失值填补、类别特征编码、特征缩放归一化、特征选择与降维(PCA/LDA)实战解析

1. 数据预处理与特征工程 “数据清洗、缺失值填补、类别特征编码、特征缩放/归一化、特征选择与降维&#xff08;PCA、LDA&#xff09;” 等流程&#xff0c;虽然被反复提到&#xff0c;但要在复杂的实际数据集中一步步落实&#xff0c;难度很大。 摘要 在机器学习与深度学习…

小迪安全v2023学习笔记(七十九讲)—— 中间件安全IISApacheTomcatNginxCVE

文章目录前记服务攻防——第七十九天中间件安全&IIS&Apache&Tomcat&Nginx&弱口令&不安全配置&CVE中间件 - IIS-短文件&解析&蓝屏等中间件 - Nginx-文件解析&命令执行等常见漏洞介绍漏洞复现中间件 - Apache-RCE&目录遍历&文件…

《云原生微服务治理进阶:隐性风险根除与全链路能力构建》

云原生微服务架构已成为企业支撑业务快速迭代的核心载体&#xff0c;但治理能力的滞后却常常成为制约发展的短板。许多企业在完成服务容器化、部署自动化后&#xff0c;便陷入了“架构先进但治理粗放”的困境—服务数量激增导致依赖关系失控&#xff0c;流量波动加剧引发资源配…

因泰立科技:用激光雷达重塑智能工厂物流生态

应对AGV碰撞困局——激光雷达如何重塑智能工厂物流在现代化工厂中&#xff0c;AGV&#xff08;自动引导车&#xff09;与移动机器人已成为提升生产效率的重要设备。然而&#xff0c;这些智能设备在忙碌的工厂环境中&#xff0c;却时常面临碰撞的困扰。这不仅影响了生产效率&…

Remove.bg:精准自动抠图工具,高效解决图片去背景需求

有没有做设计时被 “抠图去背景” 搞到崩溃的朋友&#xff1f;上次小索奇帮同事做活动海报&#xff0c;要把人物图从复杂背景里抠出来&#xff0c;用 PS 选了半天钢笔工具&#xff0c;头发丝还是漏一块缺一块&#xff0c;折腾半小时都没弄好 —— 后来被设计圈的朋友安利了 Rem…

功率器件固晶挑战:抗高温翘曲治具提升IGBT焊接强度30%

功率器件封装新突破&#xff1a;耐高温防变形工装助力IGBT模块焊接强度提升30%在功率半导体封装领域&#xff0c;IGBT模块的芯片贴装工艺正面临严峻挑战。随着功率密度不断提升&#xff0c;传统固晶工装在高温环境下易发生形变&#xff0c;导致焊接层产生空洞、裂纹等缺陷。最新…