寫內(nèi)核模塊Makefile的技巧
hansel@163.com
2007.11.07
Linux 2.6的內(nèi)核使用Kbuild來編譯內(nèi)核模塊。Kbuild能夠編譯內(nèi)核樹目錄內(nèi)的內(nèi)核模塊,也能夠編譯內(nèi)核樹目錄外的內(nèi)核模塊(外部內(nèi)核模塊)。
.編譯外部內(nèi)核模塊的命令:
#cd <your-module-dir>
#make -C <path-to-kernel> M=`pwd`
其中<your-module-dir>為要編譯的內(nèi)核模塊所在目錄,<path-to-kernel> 為內(nèi)核源碼所在的目錄。
對于發(fā)行版本的Linux,可以用:
#make -C /lib/modules/`uname -r`/build M=`pwd`
注意:使用Kbuild之前,必須先成功編譯過內(nèi)核源碼。
說明:
.#make -C <path-to-kernel> M=`pwd` modules
作用與上面的命令一樣
.以前的內(nèi)核版本可以使用
#make -C <path-to-kernel> SUBDIRS=`pwd` modules
.安裝外部內(nèi)核模塊
#make -C <path-to-kernel> M=`pwd` modules_install
默認安裝目錄為:/lib/modules/`uname -r`/extra,可以通過INSTALL_MOD_PATH宏在默認安裝路徑前加前綴。
例如:
#make -C <path-to-kernel> INSTALL_MOD_PATH=/opt M=`pwd` modules_install
則編譯后的模塊會放在/opt/lib/modules/`uname -r`/extra
通過宏INSTALL_MOD_DIR可以修改是否放在'extra'下,例如:
#make -C <path-to-kernel> INSTALL_MOD_DIR=golf M=`pwd` modules_install
則編譯后的模塊會放在/lib/modules/`uname -r`/golf
.編譯單個文件
#make -C <path-to-kernel> M=`pwd` <filename>
.其他命令
#make -C <path-to-kernel> M=`pwd` clean
#make -C <path-to-kernel> M=`pwd` help
.Kbuild文件
Linux的Kbuild會在內(nèi)核模塊目錄下查找Kbuild文件,如果有,則在編譯時會使用該文件。
示例:
假設有這么幾個文件:8123_if.c 8123_if.h 8123_pci.c 8123_bin.o_shipped(二進制的模塊文件)
Kbuild文件的內(nèi)容:
obj-m := 8123.o
8123-y:8123_if.o 8123_pci.o 8123_bin.o
Makefile的內(nèi)容:
#為了兼容舊版本的Kbuild
ifneq($(KERNELRELEASE),)
include Kbuild
else
#正常的Makefile
KDIR:=/lib/modules/`uname -r`/build
all::
$(MAKE) -C $(KDIR) M=`pwd` $@
#其他target
genbin:
echo "X" > 8123_bin_shipped
endif
注意,沒有源碼的二進制.o文件必須以原文件名加_shipped結尾,例如8123_bin.o_shipped,KBuild會把8123_bin.o_shipped
復制為8123_bin.o,然后一起編譯。
.Makefile中如何包括自己的include文件
由于采用Kbuild編譯外部內(nèi)核模塊時,編譯路徑切換到了內(nèi)核源碼樹的目錄,因此如果在Makefile中使用相對路徑來包含另一個文件
時,會找不到該文件。因此,不能用
include ../config.mk
應該用:
ifeq ($(obj),)
obj= .
endif
include $(obj)/../config.mk