柴米油鹽計劃

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/

對這篇文章感覺如何?

太棒了
0
不錯
0
愛死了
0
不太好
0
感覺很糟
0
這裡是柴米油鹽計劃投稿的發布賬號。

    You may also like

    Leave a reply

    您的電子郵箱地址不會被公開。 必填項已用 * 標註

    此站點使用Akismet來減少垃圾評論。了解我們如何處理您的評論數據