大家好,又见面了,我是你们的朋友全栈君。
一、Makefile规则格式
Makefile是由一系列的单一规则指令组合起来:
目标XX1:依赖文件
<TAB>命令1
<TAB>命令2
目标XX2:依赖文件
<TAB>命令1
<TAB>命令2
... ...
指令1:
命令1
命令2
指令2:
命令1
命令2
... ...
示例:
Tag:a.o b.o c.o
gcc -o Tag a.o b.o c.o
a.o: a.c
gcc -c a.c
b.o: b.c
gcc -c b.c
c.o: c.c
clean:
rm .o
rm Tag
二、Makefile变量
1、赋值符号“=”
实验结果显示被“=”赋值的变量,其值取决于最后一次赋值。
指令“print”中echo前加上“@”和省略其命令执行过程,结果如下:
2、赋值符“:=”
不再像“=”一样显示最后一次赋值。
3、赋值符“?=”
如果“name”已经被赋值则用之前的值“zhao”,否则用“li”
4、变量追加“+=”
在变量“name”之后追加“wang”
三:Makefile模式规则
a.o : a.c
gcc -c a.c
b.o : b.c
gcc -c b.c
运行模式规则“%”:当目标中重现“%”时,目标中“%”所代表的值决定了依赖文件中的“%”的值
%.o : %.c
gcc -c $<
四、Makefile伪目标
伪目标主要是为了避免Makefile中定义的执行指令和工作目录下的实际文件出现名字冲突。
举例说明:当前目录下如果有一个名为“clean”的文件,执行make clean指令,因为没有依赖文件,所以后续的rm指令不会被执行。解决方法为在Makefiel中将指令声明为伪目标即可“.PHONY”
.PHONY
clean:
rm *.o
... ...
五、Makefile函数
1、函数“subst”:完成字符串替换
$(subst <from>, <to>, <text>)
$(subst aaa, AAA, 3a transform 3A aaa)
将字符串“3a transform 3A aaa ”中的“aaa”替换为“AAA”即:“3a transform 3A AAA”
2、函数“patsubst”:完成模式字符串替换
$(patsubst <pattern>, <replacement>, <text>)
$(patsubst %.c, %.o, a.c b.c c.c)
将字符串“a.c b.c c.c”替换为“a.o b.o c.o”
如果text = a.c b.c c.c
那么,“$(text: .c = .o)”等同于“$(patsubst %.c, %.o, $(text))”
3、函数“dir”:获取目录
$(dir <name...>)
$(dir </src/a.c>)
提取文件“/src/a.c”的目录部分“/src”
4、函数“notdir”:提取目录名
$(notdir <name...>)
$(notdir <src/a.c>)
提取文件“/src/a.c”的非目录部分“a.c”
5、函数“foreach”:完成循环
6、函数“wildcard”:在非规则模式下即变量定义和函数中等同于“%”通配符,将相应对象展开
$(foreach <var>, <list>, <text>)
SRCDIRS := dira dirb dirc
$(foreach dir, $(SRCDIRS), $(wildcard $(dir) / *.c))
循环将SRCDIRS中的各个目录放进dir变量中,调用wildcard函数提取dir目录下所有.c文件
六、Makefile自动化变量
七、Makefile示例
示例1:裸板程序
1:原始Makefile
main.bin:a.o b.o c.o
arm-linux-gnueabihf-ld -Txxx.lds -o main.elf a.o b.o c.o
arm-linux-gnueabihf-objcopy -o binary -s -g main.elf main.bin
arm-linux-gnueabihf-objdump -D main.elf > main.dis
a.o : a.c
arm-linux-gnueabihf-gcc -c a.c -o a.o
b.o : b.c
arm-linux-gnueabihf-gcc -c b.c -o b.o
c.o : c.s
arm-linux-gnueabihf-gcc -c c.s -o c.o
clean:
rm -rf *.o main.bin main.elf main.dis
2:替换为自动变量和规则模式
objs := a.o b.o c.o
main.bin:$(objs)
arm-linux-gnueabihf-ld -Txxx.lds -o main.elf $^ /*(1)*/
arm-linux-gnueabihf-objcopy -o binary -s -g main.elf $@ /*(2)*/
arm-linux-gnueabihf-objdump -D main.elf > main.dis
%.o : %.c
arm-linux-gnueabihf-gcc -c $< -o $@ /*(3)*/
%.o : %.s
arm-linux-gnueabihf-gcc -c $< -o $@
clean:
rm -rf *.o main.bin main.elf main.dis
(1)$^:a.o b.o c.o
(2)$@:main.bin
(3)$<:%.c ; $@:%.o
3:替换为变量
CROSS_COMPILE ?= arm-linux-gnueabihf-
NAME ?= main
CC := $(CROSS_COMPILE)gcc
LD := $(CROSS_COMPILE)ld
OBJCOPY := $(CROSS_COMPILE)objcopy
OBJDUMP := $(CROSS_COMPILE)objdump
OBJS := a.o b.o c.o
$(NAME).bin = $(OBJS)
$(LD) -Txxx.lds -o $(NAME).elf $^
$(OBJCOPY) -o binary -s -g $(NAME).elf $@
$(OBJDUMP) -D $(NAME).elf > $(NAME).dis
%.o : %.c
$(CC) -c $< -o $@
%.o : %.s
$(CC) -c $< -o $@
clean:
rm -rf *.o $(NAME).bin $(NAME).elf $(NAME).dis
4:多文件工程
CROSS_COMPILE ?= arm-linux-gnueabihf-
TARGET ?= main
CC := $(CROSS_COMPILE)gcc
LD := $(CROSS_COMPILE)ld
OBJCOPY := $(CROSS_COMPILE)objcopy
OBJDUMP := $(CROSS_COMPILE)objdump
INCDIRS := dira \
dirb \
dirc \
SRCDIRS := dira dirb dirc
INCLUDE := $(patsubst %, -I %, $(INCDIRS)) /*(1)*/
SFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir) / *.s))
CFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir) / *.c)) /*(2)*/
SFILENDIR := $(notdir $(SFILES))
CFILENDIR := $(notdir $(CFILES)) /*(3)*/
SOBJS := $(patsubst %, obj/%, $(SFILENDIR:.s=.o))
COBJS := $(patsubst %, obj/%, $(CFILENDIR:.c=.o)) /*(4)*/
OBJS := $(SOBJS) $(COBJS) /*(5)*/
VPATH := $(SRCDIRS) /*(6)*/
.PHONY: clean
$(TARGET).bin : $(OBJS)
$(LD) -Txxx.lds -o $(TARGET).elf $^
$(OBJCOPY) -o binary -s %(TARGET) $@
$(OBJDUMP) -D -m arm $(TARGET).elf > $(TARGET).dis
$(SOBJS) : obj/%.o : %.s
$(CC) -Wall -nostdlib -c -o2 $(INCLUDE) -o $@ $<
$(COBJS) : obj/%.o : %.c
$(CC) -Wall -nostdlib -c -o2 $(INCLUDE) -o $@ $<
clean:
rm -rf $(TARGET).elf $(TARGET).dis $(TARGET).bin $(COBJS) $(SOBJS)
(1):INCLUDE := -I dira -I dirb -I dirc
将字符串目录前加“-I”,Makefile语法要求头文件目录需加“-I”
(2):CFILES := dira/a.c dirb/b.c
将SRCDIRS各个目录下的“c”文件提取出来
(3):CFILENDIR := a.c b.c
提取CFILES中的文件名,省略路径
(4):COBJS := obj/a.o obj/b.o
将原目录下各个c文件s文件编译为.o文件,并将其放置obj目录下。
(5):OBJS = obj/a.o obj/b.o obj/c.o
整合SOBJS和COBJS。
(6):指定编译时查询目录
示例2:带三方库的自动变量和规则模式(工作记录)
TOP_PATH := $(shell pwd)
CROSS_COMPILE := $(TOP_PATH)/../../../../prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/arm-linux-gnueabihf
INCLUDE := -I$(TOP_PATH)/../usr/include/dbus-1.0/ -I$(TOP_PATH)/../../serialport/include/ -I$(TOP_PATH)/../json/
LIBS_PATH := -L$(TOP_PATH)/../usr/lib/ -L$(TOP_PATH)/../../serialport/lib/
LIBS := -ldbus-1 -lcserialport
CC := $(CROSS_COMPILE)-g++
TARGET := dbus-client
SRCDIRS := ./ \
./../json/
CFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.cpp))
CFILENDIR := $(CFILES)
COBJS := $(patsubst %, %, $(CFILENDIR:.cpp=.o))
.PHONY: clean
$(TARGET):$(COBJS)
$(CC) $^ $(INCLUDE) $(LIBS_PATH) $(LIBS) -o $(TOP_PATH)/../build/$@
$(COBJS) : %.o : %.cpp
$(CC) -c $< $(INCLUDE) $(LIBS_PATH) $(LIBS) -o $@
clean:
@rm *.o ../json/*.o
@rm $(TOP_PATH)/../build/$(TARGET)
示例3:轻量级工程范例可用来生成动态链接库so(工作记录)
CUR_DIR=.
SRC_DIR=${CUR_DIR}
INC_DIR= -I${CUR_DIR}/
LIB_DIR= -L${CUR_DIR}/ -l cid1000m -l cserialport
CROSS_COMPILE := $(CUR_DIR)/../buildroot/output/rockchip_rv1126_rv1109_ba8300_facial_gate/host/bin/arm-linux-gnueabihf
SRC = ${SRC_DIR}/demo.c
OBJ = ${SRC}
TARGET=demo
CC=$(CROSS_COMPILE)-g++
# include header
CCFLAGS += ${INC_DIR}
# lib
CCFLAGS += ${LIB_DIR}
# so
CCFLAGS += -fPIC -shared
# pthread support
# CCFLAGS += -lpthread
${TARGET}: ${OBJ}
${CC} ${OBJ} ${CCFLAGS} -o ${TARGET}
@echo "Compile library done."
clean:
@rm -f ${TARGET}
@echo "Clean target files done."
@echo "Clean done."
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/161651.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...