Kbuild 編譯 Linux 內核系列(五)
Author: Wei Yang
作者公眾號:楊小偉的世界
方才我們學習了史上最簡單可能是 kbuild 中最直接的小目標 – help。這次我們來看看稍微高級那麼一點點的目標 —— cscope 。
客官可能要著急了,這個 help 和 cscope 都還不能算是什麼真正的編譯目標,講這個我不愛聽啊。嗯,出門右轉,點擊下一個鏈接就是你真的愛聽的了。不過呢,東西有點多,恐怕你一下子接受不了。反正我第一次寫的時候都有一種寫到要吐的感覺。
你想我們平時要是很久沒有運動,突然讓你衝刺一百米是不是會頭暈眼花腿抽經?如果在奔跑前能讓你做個熱身,充分讓身體舒展開,你的感覺會不會好很多?所以我特意增加了這篇小進階,希望能幫助你在進入高難度之前,給你做個腦力上的熱身。
cscope 目標
打開根目錄下的 Makefile 文件,搜索 cscope 關鍵字。你找到了么?
tags TAGS cscope gtags: FORCE
$(call cmd,tags)
看來 kbuild 把相應的這幾個 tag 類目標都放在了一起。
不過後面這個 $(call cmd,tags) 是什麼鬼?原來這是 makefile 中定義函數的一種方式。我們來看一下手冊中是怎麼講的。 GNU make: call function
The call function is unique in that it can be used to create new parameterized functions. You can write a complex expression as the value of a variable, then use call to expand it with different values.
The syntax of the call function is:
$(call variable,param,param,…)
When make expands this function, it assigns each param to temporary variables $(1), $(2), etc.
知道了這個定義,再對照剛才的命令。
$(call cmd,tags)
意思就是有一個變數叫做 cmd ,需要在這裡展開,而 $(1) 會被替換成 tags 。嗯,有點像宏定義,對不。
那我們現在要去找一個名字為 cmd 的變數咯~
初次遇見 kbuild 函數
C 語言代碼都是有一定的層次結構的,變數定義,函數聲明都有各自的地方存放。比如定義要在源文件,而聲明要在頭文件。那宏定義呢? 是不是也在頭文件中定義的?
makefile 中也有類似的用法 —— include 。
在根 Makefile 中搜索 include 關鍵字,沒幾下就找到了這麼一行
include scripts/Kbuild.include
是不是看著眼熟?
而在這個文件中就會發現那個叫 cmd 的變數了。
cmd = @$(echo-cmd) $(cmd_$(1))
我們把變數 tags 代入,就得到了。
@$(echo-cmd) $(cmd_tags)
先不管 echo-cmd ,先來看 cmd_tags 長什麼樣子。
細心的童鞋可能一開始就看到了,其實它就在剛才 cscope 規則的上方。
# Generate tags for editors
# ----------------------------------
quiet_cmd_tags = GEN $@
cmd_tags = $(CONFIG_SHELL) $(srctree)/scripts/tags.sh $@
這下明白了,原來 cmd 就好像一個函數,而這個函數的參數就是一個回調函數~
tags.sh 腳本文件
嗯,這個文件咱就不細講了,畢竟和編譯和 kbuild 的關係不大。總體來說就是傳入什麼參數,就執行相應的動作來生成需要的輔助文件。
case "$1" in
"cscope")
docscope
;;
"gtags")
dogtags
;;
"tags")
rm -f tags
xtags ctags
remove_structs=y
;;
"TAGS")
rm -f TAGS
xtags etags
remove_structs=y
;;
esac
對 cscope 目標來講,就是執行 docscope 這個動作。
cscope 目標的層次結構
經過了一點小小掙扎,我們弄明白了 cscope 目標是如何通過 kbuild 系統生成的。怎麼樣,是不是和你相像的步驟略有不同? 是不是有學到一些 kbuild 的基本結構?
這裡我們來回顧一下整個 cscope 目標生成的步驟,我把它叫做層級結構。
Makefile <--- scripts/Kbuild.include
---------------
cscope: FORCE
$(call cmd,tags)
Makefile
---------------
cmd_tags
scripts/tags.sh $@
在 Kbuild.include 中定義了一些輔助函數,而整個 kbuild 系統都構建在這些輔助函數的基礎上。這次我們看到的例子著實簡單,看上去把規格在本地展開要更加清晰。不過隨著內核複雜度增加,每次都本地展開會顯得代碼冗長且不易維護。
雖然這麼些在理解上增加了一些難度,不過也經過了一些些努力就能水落石出。若能真的理解,就已經做好了 kbuild 系統探索的基本準備了。
本文是 LinuxStory 柴米油鹽計劃的投稿文章,由 LinuxStory 整理髮布。
原作者署名為:Wei Yang 。
轉載請註明出處,否則必究相關責任。
本文鏈接:https://linuxstory.org/kbuild-linux-5/