今天看Makefile檔案,我頭大了,此Makefile非彼Makefile,裡面多了很多內建命令,比如origin、patsubst等等啦,這
些都沒聽說過,更可惡的是,連網上都沒有,可見,這是一件多麼傷人的事情,分析這樣的,真是讓人折壽啊!沒辦法,大半天都沒找出個頭緒來,於是我也沒什麼
辦法了,只好利用跟蹤的分析方法,就是按照安裝的步驟來,通過make命令來找到突破口。這種方法的確好使。沒用多久,我就稍微有了點頭緒,也算今天沒白
白浪費掉。
先來個“make
menuconfig”,這個核心編譯的第一步,配置核心。因此我開啟Makefile檔案,尋找目標--menuconfig,我操,怎麼會沒有,這是
算是一個坎吧,怎麼辦呢,得想法子啊,我操,那換個,"config",我日啊,找了好長時間,發現有兩個目標,很不容易。
config: scripts_basic outputmakefile FORCE
$(Q)mkdir -p include/linux include/config
$(Q)$(MAKE) $(build)=scripts/kconfig $@
%config: scripts_basic outputmakefile FORCE
$(Q)mkdir -p include/linux include/config
$(Q)$(MAKE) $(build)=scripts/kconfig $@
“%config”這是什麼,沒錯,有點常識的都知道,一個匹配而已,真的算運氣到位啊。如果是第一次執行這個肯定會找目標“script_basic”,在哪裡,同樣尋找一下。
PHONY += scripts_basic
scripts_basic:
$(Q)$(MAKE) $(build)=scripts/basic
$(Q)rm -f .tmp_quiet_recordmcount
這個目標沒有依賴關係,那麼肯定每次都得執行一遍,來了,“$(Q)”是什麼,尋找。
ifeq ($(KBUILD_VERBOSE),1)
quiet =
Q =
else
quiet=quiet_
Q = @
endif
看到沒有,其實就是為空白或者"@",如果熟悉Makefile文法就知道,在指令前加上它,表示執行時,不列印這條命令,當然你可以
"make -s",就是不列印命令,但是這個會將所有的命令都屏蔽掉,想靈活一點就用“@”。
繼
續回到script_basic,“$(MAKE)”,放心,MAKE不是Makefile裡面的變數了,是make命令內建的環境變數,就
是"make"。重點來了,“$(build)”,這個就很難找了,如果沒有一些時間,真的很難發現它究竟在哪裡。討論到這裡我得說說Makefile的
執行過程了,其實網上一大堆。
1、讀取工作目錄下的預設makefile檔案(makefile,Makefile) (開始讀我們的寫的makefile主檔案了)
2、依次讀取工作目錄makefile檔案中使用指示符"include"包含的檔案 (makefile主檔案中包含的其他檔案也讀進來了)
3、尋找重建所有已讀取的makefile檔案的規則(如果存在一個目標是當前讀取的某一個makefile檔案,則執行此規則重建此makefile檔案,
完成以後從第一步開始重新執行) (makefile主檔案極其包含的makefile檔案有需要動態修改的,先修改在重新讀進來)
4、初始設定變數值並展開那些需要立即展開的變數和函數並根據預設條件確定執行分支 (相當於預先處理過程吧?)
5、根據"終極目標"以及其他目標的依賴關係建立依賴關係鏈表 (開始整理我們的寫的規則準備執行了,相當於編譯連結過程)
6、執行除"終極目標"以外的所有的目標的規則(規則中如果所依賴的檔案中一個時間戳記比目標檔案新,則根據規則所定義的命令重新建立目標) (最後兩步就是執行了)
7、執行"終極目標"所在的規則
有點多,但是建議還是看看。Makefile裡面還可以包含其它檔案,首先就會將其它檔案的內容給填進來合在一起。一般會用關鍵字
"inlclude"來包含,和C程式類似。於是找找,關注所有在“$(build)”上邊的包含檔案吧,你將會發現。
include
$(srctree)/scripts/Kbuild.include
但是這裡的“$(srctree)”,尋找一下。
srctree := $(if $(KBUILD_SRC),$(KBUILD_SRC),$(CURDIR))
注意:尋找的時候,應該在尋找行之上尋找,畢竟肯定出現在這行之前嘛,這不是廢話嗎,但是會有人不注意的,
我靠,這樣搞來搞去,出現的不認識的更多啊,不要緊的,事情總在前進,我們總會想到法子的。首先看“$(KBUILD_SRC)”,繼續尋找,
# KBUILD_SRC is set on invocation of make in OBJ directory
# KBUILD_SRC is not intended to be used by the regular user (for now)
ifeq ($(KBUILD_SRC),)
這是最開始的一行,顯然這個變數不是Makefile裡的,那麼還會是哪裡的呢,還有一種情況就make KBUILD_SRC=XX menuconfig
其實這個也是我的估測,但是我非常有把握的。因為很有可能在srctree前,會給它賦值,既然這裡有個ifeq,就是如果相等的意思,這個恐怕每個人都知道。
ifeq ($(KBUILD_SRC),)
。。。。。。
ifneq ($(KBUILD_OUTPUT),)
。。。。。
sub-make: FORCE
$(if $(KBUILD_VERBOSE:1=),@)$(MAKE) -C $(KBUILD_OUTPUT) /
KBUILD_SRC=$(CURDIR) /
KBUILD_EXTMOD="$(KBUILD_EXTMOD)" -f $(CURDIR)/Makefile /
$(filter-out _all sub-make,$(MAKECMDGOALS))
。。。。。
endif # ifneq ($(KBUILD_OUTPUT),)
endif # ifeq ($(KBUILD_SRC),)
。。。。。
srctree := $(if $(KBUILD_SRC),$(KBUILD_SRC),$(CURDIR))
中間省略了一些,果真有,紅色的注意一下,但是分析一下會發現,不會執行的,因為注意到還有個變數沒有“$(KBUILD_OUTPUT)”,這個變數和“KBUILD_SRC”差不多,都是傳進來的,其實我們可在文檔中找到它的解釋,
Documentation/kbuild/kbuld.txt,如是說:
KBUILD_OUTPUT
--------------------------------------------------
Specify the output directory when building the kernel.
The output directory can also be specified using "O=...".
Setting "O=..." takes precedence over KBUILD_OUTPUT.
其實就是定義了一個外部的目錄。
好了,繞了這麼大一圈回到:
srctree := $(if $(KBUILD_SRC),$(KBUILD_SRC),$(CURDIR))
那麼還得解釋裡面那個if是怎麼回事啊,其實不要怎麼解釋,我的理解就是。
if (KBUILD_SRC==空)
KBUILD_SRC=$(KBUILD_SRC);
else
KBUILD_SRC=$(CURDIR)
也
就是說這裡的srctree=$(CURDIR),那麼後面那個又是什麼,哇塞,這種分析夠煩的。有的考察我們知識面了,我們可能又想到說在去裡面找找,
我們發現它和之前那個KBUILD_SRC差不多的,我們要採取特殊手法也就是排除法,我們自己寫個Makefile來測試這個變數即可,和之前那個
“$(MAKE)”其實是一樣的,這也是我確定KBUILD_SRC肯定不是make內建的環境變數的理由。不知道就直接寫個命令測試,很簡單的。顧名思
義嘛,就是目前的目錄,即原始碼的頂級目錄。所以嘛,srctree意思翻譯過來就是原始碼樹,就是樹的根目錄嘛。那麼我們再次回到。
include
$(srctree)/scripts/Kbuild.include
開啟這個Kbuild.include檔案尋找build變數。
build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj
看到賦值了吧,這裡又出現KBUILD_SRC,還是為空白,那麼build=-f $(srctree)/scripts/Makefile.build obj。這裡有個“-f”選項,
make help 看看-f選項是什麼意思。這裡就不說了,帶回去。
scripts_basic:
$(Q)make -f $(srctree)/scripts/Makefile.build obj=
scripts/basic
$(Q)rm -f .tmp_quiet_recordmcount
意思現在還蠻明顯的,就是利用
Makefile.build指令碼,這裡既然涉及到kbuild的問題,我們先放放,裡面是什麼還沒看。但是我們可以知道就是處理一下
scripts/basic目錄裡面的一些檔案而已,估計後面會用得著。回到%config:,看後面的那個目標“outputmakefile”。
outputmakefile:
ifneq ($(KBUILD_SRC),)
$(Q)ln -fsn $(srctree) source
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile /
$(srctree) $(objtree) $(VERSION) $(PATCHLEVEL)
endif
可以自己試著分析一下。繼續啊。
%config: scripts_basic outputmakefile FORCE
$(Q)mkdir -p include/linux include/config
$(Q)$(MAKE) $(build)=scripts/kconfig $@
還有個mkdir -p,呵呵,就是建立個目錄嘛(如果沒有)。後面重點來了。翻譯一下。"$@"這個符號不用多說吧,就是目標menuconfig。
$(Q)make
-f $(srctree)/scripts/Makefile.build obj=
scripts/kconfig menuconfig
顯然了,估計就是靠scripts/kconfig裡面的檔案來處理,然後製作出一個菜單介面來供使用者選擇,然後將配置參數存入.config檔案中。好像不怎麼複雜,呵呵,如果要仔細分析形成過程,又得花上很長時間的。不過我們知道這樣一個過程即可。畢竟這不是重點嘛!
好了,“make menuconfig”這個命令就說到這兒吧!按照這種方法分析後面的估計就會簡單些,希望如此。還是得感謝網路,很多知識點都有。時間不早了,寢室要熄燈了,哇!真夠累的!明天可能有點事情。。