最近在學習裝置驅動程式,編寫完之後進行編譯之前,要在Kconfig和Makefile檔案裡面添加一些内容,參考了
其他的源碼,發現源碼樹目錄下幾乎都有Kconfig和Makefile檔案,并且在核心編譯之前,要使用make menuconfig
(或者xconfig)生成配置檔案。那麼到底這些檔案對于核心的編譯有什麼作用?它們之間是怎麼樣的關系,網上
參考了一些文章,然後自己實地操作了一番,現簡單總結下來:
一、核心編譯及Kconfig,.config和Makefile三者關系
1.1 當我們在寫驅動程式的時候,可以選擇把它之間編譯進核心,也可以以子產品的形式(module)存在,
編譯成子產品(編譯成子產品的好處就是 我們修改了核心,但是編譯的時候不會全部重新編譯整個
核心,而是隻編譯子產品這一小部分,節省時間,并且可以随時插入或者删除子產品更加靈活)。
在編寫完某個驅動程式比如vfio-ccw.c的時候,我們如何把它以核心或者子產品編譯,或者不編譯?
我們需要修改兩個檔案: Makefile和Konconfig
1. 參考一些源代碼,我們在Makefile中看到了類似的: obj-m+= ccw.o
obj-y += vfio.o
obj-x + = ccw-xx.o
obj-$(CONFIG_KVM) += vfio-ccw.o
就是這些類似的語句(目标定義)用來定義哪些内容(檔案)要作為子產品編譯,或者直接編譯進核心,
或不編譯,或根據某個配置選項的選擇來進行何種編譯。我們平常所用的make指令就是根據Makefile
裡面的規則來進行編譯的。
2. 那麼這些配置變量CONFIG_KVM的值從哪裡獲得呢?
make指令從源目錄/Linux-2.6.16中的.config檔案獲得,裡面每一行都是一個配置變量的指派。那麼
這個.config檔案從何而來?裡面的配置變量何時指派?
3. 在我們新得到linux源碼的時候,在主目錄裡面并沒有.config檔案,我們需要使用autoconfig生成或者
手動指派.config檔案,但是這樣的方法要麼缺乏靈活性(不能實作按需定制的要求。如果要添加或
删掉某個驅動,将要在.config檔案中找到相應的項進行修改。非常的不友善。)要麼手動工作量太大。
那麼就引入了Kconfig和make menuconfig. 對于每個配置選項(eg CONFIG_KVM),我們在Kconfig
檔案裡面進行定義, 設定它的 選項, 然後在make之前,先使用make menuconfig進入配置選項設定
的菜單,然後在菜單界面上找到你想要設定的配置選項(這裡是CONFIG_KVM 對應的描述,找到後,
按空格鍵選擇*代表y,編譯進核心,m代表m,編譯為子產品,空代表不編譯。
這樣就為CONFIG_KVM進行了指派,在make時候讀取Makefile,就 可以給$(CONFIG_KVM)指派了
可以知道将obj-$(CONFIG_KVM) +=vfio-ccw.o中的vfio-ccw.o如何編譯,
也即将我們的驅動程式如何編譯。
4. 由此,我們可以看到Makefile,.config.Kconfig三者之間的關系。
Makefile:一個文本形式的檔案,其中包含一些規則告訴make編譯哪些檔案以及怎樣編譯這些檔案。
.config:檔案是在進行核心配置的時候,經過配置後生成的核心編譯參考檔案。
Kconfig:一個文本形式的檔案,其中主要作用是在核心配置時候,作為配置選項。
Kconfig(配置選項) ---->make menuconfig (菜單選擇)--->.config(生成值)-->Makefile(使用選項)---->make (make modules)
二、Kconfig,Makefile的結構及其編寫規則
核心源碼樹目錄下都有兩個檔案Kconfig和Makefile,分布到各目錄的Kconfig構成了一個分布式的核心
配置資料庫,每個Kconfig描述了所屬目錄源檔案相關的核心配置菜單。在Kconfig檔案中,一般的核心
配置菜單如下:
menu "Virtulization"
config KVM
select KVM_VFIO
select VFIO_IOMMU_ADAPTER if (VFIO_IOMMU)
config XEN
....
endmenu
config VFIO_IOMMU
bool “VFIO IOMMU"
depends on VFIO
default n
help
this is vfio iommu driver
config VFIO_IOMMU_TYPE1
....
1.每個菜單項(config定義的)就是menu/endmenu中Virtualization這個菜單的菜單項。
2. config下面bool,depends on, default,help,select等為config的屬性,用來定義該配置
選項的類型,依賴,預設值,描述等。
3. config的類型定義:bool(y or m), tristate(y,m or n), string(字元串), hex(16進制)
integer(整型),一般情況下選擇bool或者tristate的多。
例如: 上面的例子 bool 類型的隻能選中或不選中,顯示為[ ]; tristate類型的菜單項多了
編譯成核心子產品的選項,顯示為< > , 假如選擇編譯成核心子產品,則會在.config中生成一個
CONFIG_VFIO_IOMMU=m的配置,假如選擇内建,就是直接編譯成核心影響,就會
在.config中生成一個 CONFIG_VFIO_IOMMU=y的配置. hex十六進制類型顯示為( )。
4. depends on說明該配置選項的生效要依賴于後面的這個配置選項才能有效, select則與
depends on正好相反。如上面的例子,還可以使用if (VFIO_IOMMU)來進行限定。
5. Kconfig目錄層次疊代
在drivers/vfio/Kconfig中source "driver/vfio/pci/Kconfig” 這樣的語句用來嵌套子目錄或者
其他目錄的Kconfig檔案,這樣的好處就是不同的目錄各種管理自己的配置選項,而不用
都寫在同一個檔案裡面。
Makefile:
2.6核心的Makefile分為5個部分:
* 最頂層的Makefile(在編譯之前可更改上面幾行版本名字,這樣生成的新核心就是特定的名字)
* 核心的.config配置檔案
* 在arch/$(ARCH)目錄下的體系結構相關的Makefile
* 在s目錄下的Makefile.*檔案,是一些Makefile的通用規則
* 各級目錄下的大概約500個kbuild Makefile檔案
頂層的Makefile檔案讀取.config檔案的内容,并總體上負責build核心和子產品,各級體系架構的
Makefile負責架構相關的資訊。s目錄下的Makefile檔案包含了所有用來根據kbuild Makefile
建構核心所需要的定義和規則。
makefile檔案的編寫可以參考:一起來寫makefile
三、具體執行個體
我們根據一個簡單的例子來說明這幾個檔案的關系:
要實作一個vfio-ccw的驅動,在/Linux/drivers/vfio/ccw目錄下完成vfio-ccw.c檔案,然後想要将其編譯
為子產品或者子產品或者不編譯,它要依賴與VFIO, CCW和VFIO_IOMMU這幾個配置選項。
1. 編寫Kconfig
1.1由于ccw是建立的目錄,是以首先在ccw目錄下面添加Kconfig檔案,添加菜單項
config VFIO_CCW
tristate "VFIO support for CCW devices"
depends on VFIO && CCW && VFIO_IOMMU
help
*****
因為還有上級目錄vfio,是以在vfio目錄的Kconfig裡面添加source "drivers/vfio/ccw/Kconfig"
1.2 我們使用make menuconfig進入配置選擇菜單,根據源碼目錄,我們找到一級級的菜單項進入。

在VFIO support for CCW devices前面選擇M, 表示要把該選項編譯為子產品,按空格鍵可以選擇*或者空,
1.3 儲存退出後,在.config檔案中我們找到了:
CONFIG_VFIO=m
CONFIG_VFIO_CCW=m
2. 編寫Makefile
通過上一步,我們雖然可以在配置核心的時候進行選擇,但實際上此時執行編譯核心
還是不能把vfio-ccw.c 編譯進去的,還需要在Makefile 中把核心配置選項和真正的源
代碼聯系起來,在ccw下面建立Makefile檔案,添加:
vfio-ccw-y := vfio_ccw.o
obj-$(CONFIG_VFIO_CCW) += vfio-ccw.o
這樣make時候,根據Makefile裡面obj-$(CONFIG_VFIO_CCW) += vfio-ccw.o,
意味着将vfio-ccw.o編譯為子產品。