#////////////////////////////////
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
标签:文件,gcc,led,makefile,案例,objects,linux,main,DIR From: https://www.cnblogs.com/zblblog/p/18382980