makefile檔案案例

zbl1118發表於2024-08-27

#////////////////////////////////
Makefile五大特性:顯式規則、隱晦規則、變數定義$、檔案指示和註釋(#)
#Tab鍵開始


#//////////////////////////////////
#標準寫法

objects = main.o led.o uart.o /
gpio.o spi.o

edit : $(objects)
gcc -o edit $(objects)
main.o : main.c includes.h
gcc -c main.c
led.o : led.c led.h includes.h
gcc -c led.c
uart.o : uart.c uart.h includes.h
gcc -c uart.c
gpio.o : gpio.c gpio.h includes.h
gcc -c gpio.c
spi.o : spi.c spi.h includes.h
gcc -c spi.c
clean :
rm edit $(objects)

#////////////////////////////
#自動依賴檔案寫法(如找到led.o檔案,那麼led.c就會變為依賴檔案,同時會推匯出 gcc -c led.c)

objects = main.o led.o uart.o \
gpio.o spi.o

edit : $(objects)
gcc -o edit $(objects)
main.o : includes.h
led.o : led.h includes.h
uart.o : uart.h includes.h
gpio.o : gpio.h includes.h
spi.o : spi.h includes.h

#偽目標檔案
.PHONY : clean

clean :
rm edit $(objects)

#///////////////////////////
#最新另類寫法

objects = main.o led.o uart.o \
gpio.o spi.o

edit : $(objects)
gcc -o edit $(objects)
$(objects) : includes.h
led.o : led.h
uart.o : uart.h
gpio.o : gpio.h
spi.o : spi.h

#偽目標檔案
.PHONY : clean

clean :
-rm edit $(objects)

#////////////////////////

#更簡潔寫法

#wildcard : 擴充套件萬用字元
#notdir : 去除路徑
#patsubst :替換萬用字元
src = $(wildcard *.c ./bsp/*.c) # wildcard把 指定目錄 ./ 和 ./bsp/ 下的所有字尾是c的檔案全部展開;得到main.c ./bps/led.c
file = $(notdir $(src)) #notdir把展開的檔案去除掉路徑資訊; 得到main.c led.c
obj = $(patsubst%.c,%.o,$(src)) #patsubst把$(file)中的變數符合字尾是.c的全部替換成.o;得到main.o led.o
#編譯並連結所有.c和.o檔案
objects = $(patsubst %.c, %.o, $(wildcard *.c))
main : $(objects)
gcc -o main $(objects)

#檔案搜尋
#"src"和“../headers”兩個路徑順序搜尋,:進行分隔。
VPATH = src : ../headers
#要求make在“../headers”目錄下搜尋所有以 .h 結尾的檔案
vpath %.h ../headers

#偽目標
.PHONY : clean
clean
rm -f *.o #刪除所有.o檔案

all :prog1 prog2 prog3
.PHONY : all

#自動生成依賴

#/////////////////////////////

1、編譯驅動一般將驅動編譯成模組(.ko檔案),然後載入到核心,這用到make modules命令

//=======================================================//
2、單個.c檔案編譯成一個.ko檔案

#linux核心原始碼目錄
KERNEL_DIR := /home/alientek/workspace/im6ull-kernel/linux-imx-rel_imx_4.1.15_2.1.0_ga_alientek
#當前路徑
CURRENT_DIR := $(shell pwd)
#obj-m 編譯為獨立的驅動模組
obj-m := led.o

build : kernel_modules
kernel_modules:
$(MAKE) -C(KERNEL_DIR) M=$(CURRENT_DIR) modules

.PHONY:clean
clean:
$(MAKE) -C((KERNEL_DIR) ) M=$(CURRENT_DIR) clean

//========================================================//
3、多個檔案編譯成一個.ko檔案

假設我們要將 add.c、sub.c 編譯成一個ko檔案,只有 add.c 包含了模組初始化函式(module_init),sub.c 只是add.c 的依賴原始檔。大體和上面單檔案單模組類似,不同之處如下:
obj-m += 模組名.o
模組名-objs += 原始檔名.o ...

#linux核心原始碼目錄
KERNEL_DIR := /home/alientek/workspace/im6ull-kernel/linux-imx-rel_imx_4.1.15_2.1.0_ga_alientek
#當前路徑
CURRENT_DIR := $(shell pwd)
#obj-m += 模組名.o
obj-m += led.o
#模組名-objs += 原始檔名.o ...
led-obj += add.o sub.o

build : kernel_modules
kernel_modules:
$(MAKE) -C(KERNEL_DIR) M=$(CURRENT_DIR) modules

.PHONY:clean
clean:
$(MAKE) -C((KERNEL_DIR) ) M=$(CURRENT_DIR) clean

//===================================================//
4、多個模組編譯

#linux核心原始碼目錄
KERNEL_DIR := /home/alientek/workspace/im6ull-kernel/linux-imx-rel_imx_4.1.15_2.1.0_ga_alientek
#當前路徑
CURRENT_DIR := $(shell pwd)
#obj-m += 模組名1.o 模組名2.o
obj-m += led.o uart.o usb.o

build : kernel_modules
kernel_modules:
$(MAKE) -C(KERNEL_DIR) M=$(CURRENT_DIR) modules

.PHONY:clean
clean:
$(MAKE) -C((KERNEL_DIR) ) M=$(CURRENT_DIR) clean

//===================================================//

#RK3566的gpio-led核心級應用程式的makefile

PWD ?= $(shell pwd)

KERNELDIR := /home/zbl/tspi-rk3566/sdk/linux/kernel
CROSS_COMPILE ?= /home/zbl/tspi-rk3566/sdk/linux/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
CC := $(CROSS_COMPILE)gcc

obj-m += gpioled.o

module:
make -C $(KERNELDIR) M=$(PWD) ARCH=arm64 modules
@# -C 表示從當前目錄切換到核心原始碼目錄下,藉助核心原始碼makefile進行make編譯
@# M=$(PWD) 表示只編譯當前目錄下的驅動
@# ARCH=arm64 指定編譯架構

$(CC) gpioledapp.c -o app
@# 交叉編譯應用程式

.PHONE:clean

clean:
make -C $(KERNELDIR) M=$(PWD) ARCH=arm64 clean
rm app

相關文章