天天看點

【linux】一個通用驅動Makefile-V2-支援編譯多目錄

目錄

前言

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