linux Kbuild詳解關于fixdep、Q、quiet、escsq

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;導致焊接層產生空洞、裂紋等缺陷。最新…