目錄
前言
1. 特點
2. 分析
2.1 簡要原理
2.2 具體分析
3. 源碼
該 Makefile 已經通過基于核心 Linux5.4 版本驗證通過。
因為編寫這通用驅動 Makefile 時遇到了頭檔案指定路徑失敗的問題。使用過 ccflags-y 、INCDIR 、EXTRA_CFLAGS 、-L 等等參數都無效。就是因為我使用了 <code>$(shell pwd)</code>。導緻這些參數的路徑都為核心源碼路徑下,而非子產品路徑。後面重新檢視核心文檔,看核心的推薦寫法才解決了,使用 $(src) 來擷取子產品源碼路徑。正确指向自定義的頭檔案路徑。是以有以下建議:
建議:對于不同的 Linux 核心,應該去該核心文檔看看 makefiel 和 Kbuild 的文法及特點。(Documentation/kbuild)**
參考連接配接:
核心文檔html
李柱明部落格:https://www.cnblogs.com/lizhuming/
本文連結:https://www.cnblogs.com/lizhuming/p/14539434.html
支援編譯多目錄Linux核心驅動
支援多目錄源檔案及頭檔案編譯
相容性高,修改接口宏即可
由于驅動程式中包含了很多來自核心的頭檔案,編譯驅動程式時需要指定闆子所用的同一版本的核心源碼(編譯後,以下無特别說明也是編譯後)路徑。
簡要原理其實是主要由核心源碼中的 Makefile 來進行編譯并生成驅動檔案。是以目前 Makefile 隻需要提供參數和跳轉到核心源碼路徑執行其頂層 Makefile 即可。
核心路徑:
<code>KERNEL_DIR = /home/lss/work/kernel/imx6/ebf-buster-linux/build_image/build</code>:指出編譯後的核心源碼路徑。
架構及編譯器:
<code>ARCH = arm</code>:提供架構名稱。
<code>CROSS_COMPILE = arm-linux-gnueabihf-</code>:提供交叉編譯器名稱。
<code>CC = $(CROSS_COMPILE)gcc</code>:用于測試用例APP使用的編譯器(無測試用例可屏蔽)。
<code>export ARCH CROSS_COMPILE</code>:共享架構名稱及交叉編譯器名稱到 sub-Makefile,這裡即是核心源碼中的頂層Makefile及其sub-Makefile。
路徑變量:
<code>PWD := $(shell pwd)</code>:運作時的 make 路徑。并不是目前檔案路徑。
<code>MODDIR := $(src)</code>:目前子產品的頂層路徑。
核心源碼原話:$(src) provides the absolute path by pointing to the directory where the currently executing kbuild file is located.
Kbuild可以看作Makefile。(雖然不嚴謹)
$(src) 是由核心 Makefile 提供的。為目前被執行的 子Makefile 的絕對路徑。在這裡也可以看出 M= 的路徑。
因為當核心頂層 Makefile 使用 -C 跳到核心頂層 Makefile ,如果使用 <code>$(shell pwd)</code> 的話,該指令的值為 核心頂層 Makefile 的絕對路徑,而不是核心頂層 Makefile 的路徑。( $(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) modules 中的 M=$(CURDIR) 例外,因為它在目前 Makefile 生效後再跳轉到 -C 的 )
目标:
<code>TARGET_DRV := led_device_driver</code>:子產品目标名稱。
<code>TARGET_APP := led_app</code>:測試用例目标名稱。
資源檔案和子產品目标定義
<code>$(TARGET_DRV)-y += led_module.o</code>:目标子產品所需源檔案。
<code>$(TARGET_DRV)-y += ./device/led_dev_a.o</code>:目标子產品所需源檔案。
<code>$(TARGET_DRV)-y += ./driver/led_drv.o</code>:目标子產品所需源檔案。
<code>obj-m := $(TARGET_DRV).o</code>:目标。告訴核心要編譯成子產品。
obj-y:編譯驅動到核心。 obj-m:編譯驅動為子產品。 obj-n:不編譯。
驅動子產品的多源檔案編譯:obj-m := $(TARGET).o 是告訴 makefile 最總的編譯目标。而 $(TARGET)-y 則是告訴 makefile 該總目标依賴哪些目标檔案。(為固定格式,如總目标為 <code>xxx.o</code>,那麼它依賴的源檔案應該這樣指定 <code>xxx-y +=</code>)(也可以使用 xxx-objs)
編譯參數:
<code>ccflags-y := -I$(MODDIR)/include</code>:指定自定義頭檔案路徑。這裡隻能使用 $(src) 來擷取子產品檔案路徑。
External modules tend to place header files in a separate include/ directory where their source is located, although this is not the usual kernel style. To inform kbuild of the directory, use either ccflags-y or CFLAGS_.o.
目标 all:
<code>$(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) modules</code>:原型是 <code>make modules</code>,即是編譯子產品目标,其它都是參數。
-C $(KERNEL_DIR):把工作目錄跳轉到核心源碼中。
M=$(CURDIR):表示編譯子產品時,可以到該路徑尋找子產品源碼進行編譯。
推薦:觀看核心文檔 Documentation/kbuild/modules.rst