linux核心學習粗略kbuild Makefile編譯流程
轉自:http://gisyhy.blog.163.com/blog/static/1293903432010111591845942/
今天看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 [email protected]
%config: scripts_basic outputmakefile FORCE
$(Q)mkdir -p include/linux include/config
$(Q)$(MAKE) $(build)=scripts/kconfig [email protected]
“%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 [email protected]
還有個mkdir -p,呵呵,就是建立個目錄嘛(如果沒有)。後面重點來了。翻譯一下。"[email protected]"這個符號不用多說吧,就是目標menuconfig。
$(Q)make -f $(srctree)/scripts/Makefile.build obj=scripts/kconfig menuconfig
顯然了,估計就是靠scripts/kconfig裡面的檔案來處理,然後製作出一個選單介面來供使用者選擇,然後將配置引數存入.config檔案中。好像不怎麼複雜,呵呵,如果要仔細分析形成過程,又得花上很長時間的。不過我們知道這樣一個過程即可。畢竟這不是重點嘛!
好了,“make menuconfig”這個命令就說到這兒吧!按照這種方法分析後面的估計就會簡單些,希望如此。還是得感謝網路,很多知識點都有。時間不早了,寢室要熄燈了,哇!真夠累的!明天可能有點事情。。
結合:http://www.360doc.com/content/12/0103/19/6828497_177031793.shtml
相關推薦
linux核心學習粗略kbuild Makefile編譯流程
轉自:http://gisyhy.blog.163.com/blog/static/1293903432010111591845942/ 今天看Makefile檔案,我頭大了,此Makefile非彼Makefile,裡面多了很多內建命令,比如origin、patsubst等
linux 核心學習過程(1)-硬體特性和核心設計之間的聯絡
該貼用來作為自己學習linux核心的記錄和筆記,很多東西都是自己理解後整理的內容,各位看官若覺得有問題的地方,可以留言或自行查閱。 linux核心在設計的過程中很多都是依據硬體晶片特性來設計,晶片在設計的過程中很多時候需要保持相容性,這樣就留下了很多令人費解的概念,比如分段和分頁機制,
linux核心學習資料連結
1. 核心學習方法,編譯、除錯等常見問題 1.1 關於編譯升級核心到2.6.0的一些問題 作者:ommm http://linux.chinaunix.net/bbs/thread-281831-1-5.html 1.2 VMWare
Linux核心學習書籍
轉自: https://blog.csdn.net/21aspnet/article/details/6585602 關於核心學習我建議不要上來就讀核心而是先了解核心的構成和特性,然後通過思考發現疑問這時再去讀核心原始碼。即先了解概貌在讀區域性細節。而且核心分成好多部分,不要只是按照順序去讀,應
Linux 核心學習經驗總結
Linux 核心學習經驗總結 學習核心,每個人都有自己的學習方法,仁者見仁智者見智。以下是我在學習過程中總結出來的東西,對自身來說,我認為比較有效率,拿出來跟大家交流一下。 核心學習,一偏之見;疏漏難免,懇請指正。 為什麼寫這篇部落格 剛開始學核心的時候,不要執著於一個方面,不要專
Linux核心學習筆記(2)—— 程序
來源:《Linux核心設計與實現(第2版)》第三章 Robert Love 知識點很少,蝸牛慢慢爬~~~ 1. 什麼是程序? 程序是處於執行期的程式以及它所包含的資源的總稱。所謂的資源,像開啟的檔案、掛起的訊號、核心內部資料、處理器狀態、地址空間、一
Linux核心模組(Module)的單獨編譯
模組檔案 /* * file name: hello.c */ #include<linux/module.h> #include<linux/init.h>
嵌入式Linux核心配置、裁剪與編譯淺析(ARM版)
/*====================*/ 9、Device Drivers ---> 9.1、Generic Driver Options ---> 9.1.1、() path to uevent helper 9.1.2、[ ] Maintain a devtmpfs fil
linux核心學習筆記------iP選項處理(一)
ip首部分為固定部分和選項部分;固定部分為20個位元組,而選項部分則是變長的,最長不超過40個位元組。選項的格式分為單位元組和多位元組兩種。單位元組只包括一個位元組的選項型別,而多位元組則除一個位元組的型別之外,還包括選項長度以及選項資料。包括以下幾種ip選項: 1、選項列
Linux核心學習實踐之GPIO面板按鍵
說明:本分析基於AM6C平臺Linux3.0.8核心,其他核心版本僅供參考。 一、platform設備註冊的按鍵對映 common/customer/boards/board-m6tv-h32.c
【Linux核心學習筆記四】記憶體管理-夥伴系統
1.夥伴系統演算法描述 linux系統採用夥伴系統演算法來解決外碎片問題。主要做法是記錄現存的空閒連續頁框塊的情況,以儘量避免為滿足對小塊的請求而分割大的空閒塊。 夥伴系統演算法中,把所有的空閒頁框分為11個組,每個組對應一個連結串列,每個連結串列分
linux核心學習筆記------ip報文組裝
ip報文有分片就會有組裝。在接收方,只有報文的所有分片被重新組合後才會提交到上層協議。核心組裝ip報文用到了ipq結構體:(注,這系列原始碼中的註釋都來自:http://blog.csdn.net/justlinux2010) struct ipq { struct in
史上最經典的Linux核心學習方法論
轉載 待到山花爛漫時,還是那些經典在微笑。 有關核心的書籍可以用汗牛充棟來形容,不過只有一些經典的神作經住了考驗。首先是5本久經考驗的神作(個人概括為“2+1+2”,第一個2是指2本全面講 解核心的書,中間的1指1本講解驅動開發的書,後面的2則指2本有關核心具體
Linux核心學習遇到的問題
(1)今天第一個遇到的比較棘手的問題就是編譯模組wr_thread WARNING: "mcount" [/home/ams/Music/test/kernel_test/wr_thread/wr_thread.ko] 解決的方法是升級了gcc 從gcc4.
對linux核心學習的一點感受
跟著這門課不知不覺已經學了8個星期了,對Linux核心有了一個基本的認識,可以說是入門了。既然是課程總結,我大概描述一下這個課程,供對Linux核心感興趣的同學參考。 這門課沒講什麼 在學習作業系統的時候,我們知道了作業系統將CPU抽象為程序,將記
Linux核心學習-misc雜項裝置驅動
Linux裡面的misc雜項裝置是主裝置號為10的驅動裝置,它的註冊跟使用比較的簡單,所以比較適用於功能簡單的裝置。它有自己的裝置結構體: struct miscdevice { int minor; const char *name; const
linux核心學習之網路篇——IP和TCP結構體原始碼
今天只是看一下IP協議的結構體和TCP的結構體所控制的欄位。 首先看一下IP的欄位,就是傳說中ip協議中的包頭欄位。 struct iphdr { #if defined(__LITTLE_ENDIAN_BITFIELD) __u8 ihl:4, version:4
Linux核心學習筆記(一)——Linux核心簡介
Unix系統業已演化成一個具有相似應用程式程式設計介面(API),並且基於相似設計理念的作業系統家族。 1、Unix的歷史 Unix是從貝爾實驗室的一個失敗的多使用者作業系統Multics中涅槃而生的。 時間 事件 19
我的Linux核心學習之路
現在回首看看,接觸Linux已經很長時間了。 在大三的時候開始學習Java, 但是一直學Java的話, 感覺有點膩, 就嘗試找點其他東西來學習。 所以當時就選擇學習了Linux。 至於為什麼要學習Linux, 有以下三個原因。 一是我比較喜歡開源的東西, 當時學習Jav
Linux核心學習的一些國外網站
http://www.kernel.org The Linux Kernel Archivesftp://ftp.kernel.org 本站點是Linux核心開發的主站點,其中包含了最新的核心發行版本以及相關 資訊。注意該FTP站點的映象已遍佈全球,因此可以選擇最近的映象下載Linux原始碼。http://w