makefile文件案例

#////////////////////////////////
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

 

posted @ 2024-08-27 16:43  zbl1118  阅读(51)  评论(0)    收藏  举报