這是一個常見的 Makefile 小技巧,判斷 KERNELRELEASE 是否定義來執行不同的設定。
如下列是compat-wireless的Makefile,就用到這樣的技巧:
- (SKIP)
- ifneq ($(KERNELRELEASE),)
- NOSTDINC_FLAGS := -I$(M)/include/ \
- -include $(M)/include/linux/compat-2.6.h \
- $(CFLAGS)
- obj-y := compat/
- obj-$(CONFIG_COMPAT_RFKILL) += net/rfkill/
- ifeq ($(BT),)
- obj-$(CONFIG_COMPAT_WIRELESS) += net/wireless/ net/mac80211/
- obj-$(CONFIG_COMPAT_WIRELESS_MODULES) += drivers/net/wireless/
- endif
- else
- export PWD := $(shell pwd)
- CFLAGS += \
- -DCOMPAT_BASE_TREE="\"$(shell cat compat_base_tree)\"" \
- -DCOMPAT_BASE_TREE_VERSION="\"$(shell cat compat_base_tree_version)\"" \
- -DCOMPAT_PROJECT="\"Compat-wireless\"" \
- -DCOMPAT_VERSION="\"$(shell cat compat_version)\""
- # These exported as they are used by the scripts
- # to check config and compat autoconf
- export COMPAT_CONFIG=config.mk
- export CONFIG_CHECK=.$(COMPAT_CONFIG)_md5sum.txt
- export COMPAT_AUTOCONF=include/linux/compat_autoconf.h
- export CREL=$(shell cat $(PWD)/compat_version)
- export CREL_PRE:=.compat_autoconf_
- export CREL_CHECK:=$(CREL_PRE)$(CREL)
- include $(PWD)/$(COMPAT_CONFIG)
- all: modules
- modules: $(CREL_CHECK)
- @./scripts/check_config.sh
- $(MAKE) -C $(KLIB_BUILD) M=$(PWD) modules
- @touch $@
- (SKIP)
- endif
當從 shell 執行 make 時,因為 KERNELRELEASE 沒有定義,所以第23行到第39行之間的一些變數和 CFLAGS 會被設定,然後第45行會呼叫 kbuild 的 Makefile:
$(MAKE) -C $(KLIB_BUILD) M=$(PWD) modules
之後 compat-wireless 的 Makefile 又會被呼叫一次,此時 KERNELRELEASE 已經被 kbuild 所定義,所以第5行到第18行會被執行。而做的事情就如同一般的 module Makefile 將 driver 的路徑加入 obj-$CONFIG_* 中,如第15行:
obj-$(CONFIG_COMPAT_WIRELESS_MODULES) += drivers/net/wireless/
※
不過,DKMS 在 build module 時會自己傳入 KERNELRELEASE 這個參數,如在 /usr/sbin/dkms:function do_build():
local the_make_command=`echo $make_command | sed "s/^make/make KERNELRELEASE=${kernelver_array[0]}/"`
我們可以看到,在 compat-wireless 的 Makefile 中,當 KERNELRELEASE 變數已被設值時,並沒有 target 可以 build,必須是經由 kbuild 的 Makefile 來 make 才可以。
所以一個 workaround 是在 dkms.conf 中將 MAKE[0] 寫成 make -C /lib/modules/`uname -r`/build M=`pwd` modules。但是在這個例子中我們還必須先在 CLFAGS 中加入一些 define。直接呼叫kbuild的話,這些 CFLAGS 都沒設定,這樣並無法正確的 build 出 module。
所以,一個可行的辦法是將 Makefile 拆開,然後在 dkms.conf:MAKE[0] 中自行指定 Makefile,如:
make -f dkms.mk
雖然必須更改原始的 Makefile,但是卻可讓 DKMS 正確運作。