本文目录
1、前言
最近在调试一个解码器工程时,编写了一个简单的makefile,通过makefile实现工程demo的编译,涉及到makefile使用的相关知识,分享出来供大家学习。
makefile旨在构建目标文件,实现工程的自动化编译。
2、makefile使用相关知识
2.1 规则语法:
target ... : prerequisites ...
command
...
2.2 VPATH的使用
示例1 - 当前目录中找不到文件时, 按顺序从 src目录, ../parent-dir目录中查找文件
VPATH src:../parent-dir示例2 - .h结尾的文件都从 ./header 目录中查找
VPATH %.h ./header
2.3 变量的定义
- = 延迟赋值 ,将整个makefile中的所有变量的值都计算完之后,确定该变量的值。
- := 立即赋值,:=只能使用前面定义好的变量。
- += 追加赋值
- ?= 条件赋值
2.4 自动变量
- $@ 所有目标的集合
- $^ 所有依赖目标的集合, 会去除重复的依赖目标
- $+ 所有依赖目标的集合, 不会去除重复的依赖目标
- $? 比目标新的依赖目标的集合
2.5 伪目标
并不是一个”目标(target)”, 不像真正的目标那样会生成一个目标文件.
典型的伪目标是 Makefile 中用来清理编译过程中中间文件的 clean 伪目标, 一般格式如下:
.PHONY: clean <-- 这句没有也行, 但是最好加上
clean:
-rm -f *.o
2.6 变量替换和变量引用
#变量替换
SRCS := programA.c programB.c programC.c
OBJS := $(SRCS:%.c=%.o)
#变量引用
$(SRCS)
echo $(SRCS)
2.7 C相关命令和参数定义
命令 | 含义 | 示例 |
---|---|---|
RM | rm -f | RM=rm -f |
AR | ar | AR=ar |
CC | gcc | CC=gcc |
CXX | g++ | CXX=g++ |
ARFLAGS | AR命令的参数 | -crus |
CFLAGS | C语言编译器的参数 | CFLGAS+=-Wall -O3 -fPIC -fsigned-char |
CXXFLAGS | C++语言编译器的参数 | 同上 |
LDFLAGS | ld链接器的参数 | 同上 |
3、makefile工程编译模板
#指定后缀名和伪目标
.SUFFIXES: .c,.o,.cpp,.S,.s
.PHONY: all,clean
#设置相关工具
CC = gcc
CXX = g++
AR = ar
LD = ld
#设置相关路径
VPATH %.h ./inc
ROOTSRC = ./src
INCLUDES = ./inc
#设置工具的相关参数
BIN_TARGET = DEMO
CFLAGS += -Wall -O3 -g -I$(INCLUDES)
CXXFLAGS += -Wall -g
LDFLAGS += -Wall -O3 -g
ARFLAGS += -crus
#以下获取OBJS文件的方式适用于含有少量文件的编译
SRCS = $(ROOTSRC)/file1.c \
$(ROOTSRC)/file2.cpp \
$(ROOTSRC)/file3.s \
$(ROOTSRC)/file4.S
OBJS = $(patsubst %.s, %.o, $(patsubst %.cpp,%.o, $(patsubst %.c,%.o,$(SRCS))))
#以下通过通配符和字符串函数获取OBJS的方式适用于较大工程(含有大量文件)的编译
SRCOBJS := $(patsubst %.cpp, %.o, $(wildcard $(SRCDIR)/*.cpp))
TESTOBJS := $(patsubst %.cpp, %.o, $(wildcard $(TESTDIR)/*.cpp))
OBJS := $(SRCOBJS) $(TESTOBJS)
#编译规则
all: clean $(BIN_TARGET)
BIN_TARGET: $(OBJS)
$(CXX) -o $@ $(OBJS) $(LDFLAGS)
rm $(OBJS)
%.o: %.c
$(CC) -c $< $(CFLAGS) -o $@
%.o: %.cpp
$(CXX) -c $< $(CXXFLAGS) -o $@
clean:
rm $(OBJS)
rm $(BIN_TARGET)
关于第二种获取OBJS方式的说明:
这是通过make的两个内置函数wildcard和patsubst实现的。wildcard返回所有符合给定模式的匹配。在上面的例子中,我们要匹配所有处于$(SRCDIR)和$(TESTDIR)目录下的.cpp文件,并将其路径作为变量传入另一个函数patsubst,它会将每个路径中的.cpp替换成.o,最后存入我们指定的变量中。
关于写一个通用makefile的相关知识更多可以参考:
- https://bitmingw.com/2015/03/21/general-makefile/
- https://www.cnblogs.com/vamei/archive/2013/04/29/3051062.html
4、更加完善的makefile编译模板
(1)系统或架构相关宏、FLAGS配置在config.mk中:
#检测系统
OS = $(shell uname)
#设置是否调试
ifeq ($(DEBUG), 0)
DEBUG_FLAGS := -O3
else
DEBUG_FLAGS := -G
endif
#########################################
############linux系统 ###################
ifeq ($(findstring Linux, $(OS)), Linux)
CROSS ?=
CC := $(CROSS)gcc -fPIC -DPIC
CPP := $(CROSS)g++ -fPIC -DPIC
LD := $(CROSS)ld
AR := $(CROSS)ar
ASM := yasm -DPIC
###ARM32架构
ifeq ($(platform), arm32)
ARCH_DEF :=
EXTRA_CFLAGS := -march=armv7-a -marm $(ARCH_DEF)
EXTRA_LFLAGS := -march=armv7-a -marm
EXTRA_AFLAGS := -march=armv7-a $(ARCH_DEF)
OUT_DIR := ./bin/arm32
endif
###ARM64架构
ifeq ($(platform), arm64)
ARCH_DEF :=
EXTRA_CFLAGS := -march=armv8-a $(ARCH_DEF)
EXTRA_LFLAGS := -march=armv8-a
EXTRA_AFLAGS := -march=armv8-a $(ARCH_DEF)
OUT_DIR := ./bin/arm64
endif
###X86_32架构
ifeq ($(platform), x86_32)
ARCH_DEF :=
EXTRA_CFLAGS := -m32 $(ARCH_DEF)
EXTRA_LFLAGS := -m32 -shared
EXTRA_AFLAGS := -m x86 $(ARCH_DEF)
OUT_DIR := ./bin/x86m32
endif
###X86_64架构
ifeq ($(platform), x86_64)
ARCH_DEF :=
EXTRA_CFLAGS := -m64 $(ARCH_DEF)
EXTRA_LFLAGS := -m64 -shared -Wl, -Bsymbolic
EXTRA_AFLAGS := -m amd64 $(ARCH_DEF)
OUT_DIR := ./bin/x86m64
endif
endif
#########################################
############MAC/IOS系统 ###################
ifeq ($(findstring Darwin, $(OS)), Darwin)
###MAC平台
ifeq ($(target_plat), mac)
CROSS ?=
CC := $(CROSS)gcc -fPIC -DPIC
CPP := $(CROSS)g++ -fPIC -DPIC
AR := $(CROSS)ar
ASM := yasm -DPIC
##X86_32架构
ifeq ($(platform), x86_32)
ARCH_DEF :=
EXTRA_CFLAGS := -m32
EXTRA_LFLAGS := -m32 -dynamiclib -Wl, -dynamic -Wl, -read_only_relocs, suppress
EXTRA_AFLAGS := -f macho32 -m x86
OUT_DIR := ./bin/mac32
endif
##X86_64架构
ifeq ($(platform), x86_64)
ARCH_DEF :=
EXTRA_CFLAGS := -m64
EXTRA_LFLAGS := -m64 -dynamiclib -Wl, -dynamic
EXTRA_AFLAGS := -f macho64 -m amd64
OUT_DIR := ./bin/mac64
endif
endif
###IOS平台
ifeq ($(target_plat), ios)
CROSS := iphone
ifeq ($(platform), ios32)
CC := xcrun -sdk $(CROSS)os clang
CPP := g++
AR := ar
ASM := gas-preprocessor.pl -arch arm -as-type apple-clang --$(CC)
ARCH_DEF :=
EXTRA_CFLAGS := -arch armv7 -mios-version-min=6.0
EXTRA_LFLAGS := -arch armv7 -mios-version-min=6.0
EXTRA_AFLAGS := -arch armv7 -mios-version-min=6.0
OUT_DIR := ./bin/ios32
endif
ifeq ($(platform), ios64)
CC := xcrun -sdk $(CROSS)os clang
CPP := g++
AR := ar
ASM := gas-preprocessor.pl -arch aarch64 -as-type apple-clang --$(CC)
ARCH_DEF :=
EXTRA_CFLAGS := -arch arm64 -mios-version-min=6.0
EXTRA_LFLAGS := -arch arm64 -mios-version-min=6.0
EXTRA_AFLAGS := -arch arm64 -mios-version-min=6.0
OUT_DIR := ./bin/ios64
endif
ifeq ($(platform), ios_sim32)
CC := xcrun -sdk $(CROSS)simulators clang
CPP := g++
AR := ar
ASM := yasm
ARCH_DEF :=
EXTRA_CFLAGS := -arch i386 -mios-simulator-version-min=6.0
EXTRA_LFLAGS := -arch i386 -mios-simulator-version-min=6.0 -Wl, -Bsymbolic-functions -read_only_relocs suppress
EXTRA_AFLAGS := -f macho32 -m x86
OUT_DIR := ./bin/ios_sim
endif
ifeq ($(platform), ios_sim64)
CC := xcrun -sdk $(CROSS)simulators clang
CPP := g++
AR := ar
ASM := yasm
ARCH_DEF :=
EXTRA_CFLAGS := -arch x86_64 -mios-simulator-version-min=6.0
EXTRA_LFLAGS := -arch x86_64 -mios-simulator-version-min=6.0
EXTRA_AFLAGS := -f macho64 -m amd64
OUT_DIR := ./bin/ios_sim
endif
endif ##ifeq ($(target_plat), ios)
endif
(2)构建法则在Makefile中
include config.mk
SRC_PATH := ../src
INCLUDE_PATH:= ../include
LIB_PATH := $(OUT_DIR)
LIB_NAME := xxx
ARFLAGS := cru
CFLAGS := $(DEBUG_FLAGS)
CFLAGS +=$(EXTRA_CFLAGS) -I$(INCLUDE_PATH)
ASMFLAGS :=
ASMFLAGS += $(EXTRA_AFLAGS) -I$(INCLUDE_PATH)
LDFALGS := -lm -ldl
LDFALGS += $(EXTRA_LFLAGS)
LIB := $(LIB_PATH)/$(LIB_NAME).a $(LIB_PATH)/$(LIB_NAME).so
OBJS := $(SRC_PATH)/x.o \
$(SRC_PATH)/y.o
all: clean $(LIB)
$(filter %.a, $(LIB)):$(OBJS)
$(AR) $(ARFLAGS) $@ $^
$(filter %.so, $(LIB)):$(OBJS)
$(CC) $(LDFALGS) -shared -o $@ $^
%.o:%.c
$(CC) -o $< $(CFLAGS) -c -o $@
%.o:%.asm
$(ASM) $< $(ASMFLAGS) -c -o $@
clean:
rm -rf $(OBJS)
rm -rf $(LIB)
5、参考
https://www.cnblogs.com/wang_yb/p/3990952.html
https://www.cnblogs.com/yyangblog/p/4159778.html
https://bitmingw.com/2015/03/21/general-makefile/
https://github.com/switchbrew/34c3-demo/blob/master/Makefile
https://blog.csdn.net/listener51/article/details/84930829
THE END!
本博文只能阅读,谢绝转载,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 2963033731@qq.com