makefile常用模板
# 指令编译器和选项
# GCC编译选项CFLAGS参数
# 选项 说明
# -c 用于把源码文件编译成 .o 对象文件,不进行链接过程
# -o 用于连接生成可执行文件,在其后可以指定输出文件的名称
# -g 用于在生成的目标可执行文件中,添加调试信息,可以使用GDB进行调试
# -Idir 用于把新目录添加到include路径上,可以使用相对和绝对路径,“-I.”、“-I./include”、“-I/opt/include”
# -Wall 生成常见的所有告警信息,且停止编译,具体是哪些告警信息,请参见GCC手册,一般用这个足矣!
# -w 关闭所有告警信息
# -O 表示编译优化选项,其后可跟优化等级0\1\2\3,默认是0,不优化, 使用: -O1,-O2,-O3
# -fPIC 用于生成位置无关的代码
# -v (在标准错误)显示执行编译阶段的命令,同时显示编译器驱动程序,预处理器,编译器的版本号
# -fopenmp 打开nmp并行编译选项,防止老版本的gcc不包含OpenMP的支持
# GCC链接选项LDFLAGS参数
# 选项 说明
# -llibrary 链接时在标准搜索目录中寻找库文件,搜索名为liblibrary.a 或 liblibrary.so
# -Ldir 用于把新目录添加到库搜索路径上,可以使用相对和绝对路径,“-L.”、“-L./include”、“-L/opt/include”
# -Wl,option 把选项 option 传递给连接器,如果 option 中含有逗号,就在逗号处分割成多个选项
# -static 使用静态库链接生成目标文件,避免使用共享库,生成目标文件会比使用动态链接库大
# -m32 生成32位的代码。
# -m64 生成64位的代码。
# = 是最基本的赋值 #不推荐使用,容易搞混淆,不推荐使用
# := 是覆盖之前的值 #表示直接赋值,赋予当前位置的值
# ?= 是如果没有被赋值过就赋予等号后面的值 #表示如果该变量没有被赋值,则赋予等号后的值
# += 是添加等号后面的值 #将等号后面的值添加到前面的变量上
# '@' 符号的使用
# 通常makefile会将其执行的命令行在执行前输出到屏幕上。如果将‘@’添加到命令行前,这个命令将不被make回显出来。
# '-' 符号的使用
# 通常删除,创建文件如果碰到文件不存在或者已经创建,那么希望忽略掉这个错误,继续执行,就可以在命令前面添加 -,
# -rm dir;
# -mkdir aaadir;
# '$' 符号的使用
# 美元符号$,主要扩展打开makefile中定义的变量
# '$$' 符号的使用
# $$ 符号主要扩展打开makefile中定义的shell变量
# $@ 表示规则中的目标文件集。在模式规则中,如果有多个目标,那么,"$@"就是匹配于目标中模式定义的集合。
# $% 仅当目标是函数库文件中,表示规则中的目标成员名。例如,如果一个目标是"foo.a(bar.o)",那么,"$%"就是"bar.o",
# "$@"就是"foo.a"。如果目标不是函数库文件(Unix下是[.a],Windows下是[.lib]),那么,其值为空。
# $< 依赖目标中的第一个目标名字。如果依赖目标是以模式(即"%")定义的,那么"$<"将是符合模式的一系列的文件集。注意,其是一个一个取出来的。
# $? 所有比目标新的依赖目标的集合。以空格分隔。
# $^ 所有的依赖目标的集合。以空格分隔。如果在依赖目标中有多个重复的,那个这个变量会去除重复的依赖目标,只保留一份。
# .PHONY 是一个伪目标,可以防止在Makefile中定义的只执行命令的目标和工作目录下的实际文件出现名字冲突,另一种是提交执行makefile时的效率。
# makefile 语法规则
# TARGETS : PREREQUISITES
# [Tab]COMMAND
#或
# TARGETS : PREREQUISITES;COMMAND
# addprefix 添加前缀
# addsuffix 添加后缀
# wildcard 获取文件名列表
# notdir 去除目录
# basename 去除后缀
# patsubst 模式替换
# info 显示变量
# lastword 获取路径无关的文件名
# makefile中的shell命令用法: $(shell shell_command...)
# dirname 获取文件路径(shell命令)
# pwd 获取当前路径(shell命令)
# 连接库
# -l 指定连接时期望连接的库的名字
# -L 指定连接库的搜索路径
# 参考:https://www.cnblogs.com/shaochuanhe/articles/14495457.html
# $(foreach <var>,<list>,<text>) 语法
# 这个函数的意思是,把参数<list>;中的单词逐一取出放到参数<var>;所指定的变量中,然后再执行< text>;所包含的表达式。
# 每一次<text>;会返回一个字符串,循环过程中,<text>;的所返回的每个字符串会以空格分隔,最后当整个循环结束时,<text>;
# 所返回的每个字符串所组成的整个字符串(以空格分隔)将会是foreach函数的返回值。
# 所以,<var>;最好是一个变量名,<list>;可以是一个表达式,而<text>;中一般会使用<var>;这个参数来依次枚举<list>;
# 中的单词。举个例子:
# names := a b c d
# files := $(foreach n,$(names),$(n).o)
# 上面的例子中,$(name)中的单词会被挨个取出,并存到变量“n”中,“$(n).o”每次根据“$(n)”计算出一个值,这些值以空格分隔,
# 最后作为foreach函数的返回,所以,$(files)的值是“a.o b.o c.o d.o”。
# $(filter PATTERN…,<text>)
# 函数名称:过滤函数—filter。
# 函数功能:过滤掉字串<text>中所有不符合模式“PATTERN”的单词,保留所有符合此模式的单词。可以使用多个模式。
# 模式中一般需要包含模式字符“%”。存在多个模式时,模式表达式之间使用空格分割。
# 返回值:空格分割的<text>字串中所有符合模式“PATTERN”的字串。
# 函数说明:“filter”函数可以用来去除一个变量中的某些字符串,
# $(filter-out <pattern>,<text>)
# 函数名称:反过滤函数,与filter函数功能相反
# 函数说明:函数的功能是功能和 filter 函数正好相反,但是用法相同。去除符合模式
# pattern 的字符串,保留符合的字符串。返回值是保留的字符串。
# $(strip, <text>) 去空字符语句,去掉字串中开头和结尾的空字符(空字符包括空格、[Tab]等不可显示字符)。
# $(patsubst pattern, replacement, text)
# 寻找text中符合pattern格式的内容,用replacement代替他们。
#------------- compile using -------------------
# make clean
# make deep clean
# make solution=debug #debug solution
# make #release solution -> TARGET_NAME
# make type=.a #libtt_xxx.a
# make type=.so #libtt_xxx.so
# make type=test #lib test.exe
#------------- omp code using -------------------
# pragma omp parallel //C,C++使用以#pragma omp开头的标准预处理指令
# pragma omp parallel for
#pragma omp parallel for num_threads(4)
#------------- compile marcros -----------------
solution = release
type = main
# .c
# CC := gcc
# .cpp
CC := g++
SYS_PLATFORM := _LINUX#pre marco define
CCFLAG :=
CCFILE := %.c
ifeq ($(CC), g++)
CCFLAG += -std=c++11
CCFILE := %.cpp
endif
ifeq ($(solution), debug)
CCFLAG += -g
else
#optimization level option
CCFLAG += -O3 -static -fopenmp
# CCFLAG = -O3 -shared -fopenmp
endif
# CCFLAG += -Wall
# CCFLAG += -m64
# CCFLAG += -w#close warnning
CCFLAG += $(addprefix -D , $(SYS_PLATFORM))#pre-define marco, 为 c/c++代码传递宏参数
CCOBJFLAG := $(CCFLAG) -c
#-------------- path marcros -------------------
BIN_PATH := ./prj#bin file path
OBJ_PATH := ./obj#object file path
SRC_PATH := .#src file root path
#-------------- compile marcros -----------------
# optional: TARGET_NAME
#------------------------------------------------
ifeq ($(type), main)
TARGET_NAME := main.exe
FILE_LIST := main.flist
else ifeq ($(type), test)
TARGET_NAME := test.exe
FILE_LIST := test.flist
else
TARGET_NAME := libtt_xxx$(type)
FILE_LIST := lib.flist
endif
TARGET := $(BIN_PATH)/$(TARGET_NAME)
$(info $(FILE_LIST))
#-------------- source marcros ------------------
FILE_TEXT := $(shell cat $(FILE_LIST)) #获取文件内容
$(strip,$(FILE_TEXT)) #去掉字串中开头和结尾的空字符(空字符包括空格、[Tab]等不可显示字符)
VARIABLE := $(foreach n,$(FILE_TEXT),$(n)) #消除回车符号等特殊字符
HEADER := $(filter-out $(CCFILE), $(VARIABLE))
HEADER := $(foreach n,$(HEADER),-I$(SRC_PATH)/$(n))
SRC := $(filter $(CCFILE), $(VARIABLE))
# SRC := $(addprefix $(SRC_PATH)/, $(SRC))
OBJ := $(patsubst $(CCFILE), %.o, $(SRC))
OBJ_DIR := $(addprefix $(OBJ_PATH)/, $(sort $(shell dirname $(SRC))))
# #-------------- library marcros -----------------
# # INC_PATH := $(HEADER) -I./ffmpeg/include # header file path
INC_PATH := $(HEADER)# header file path
# #LIBS = -ldiv #dynamic library
# ## LIBS = libdiv.a #static library
LIB_PATH := #-L/usr/local/lib
# # LIBS := -lavformat -lavcodec -lswscale -lswresample -lavutil -lavfilter -lavdevice -lpostproc
# # LIBS += -lm -lz -lpthread -lx264 -lx265
LIBS := -lm
LIBS += $(shell pkg-config --libs opencv4)
INC_PATH += $(shell pkg-config --cflags opencv4)
# clean files list
CLEAN_LIST := $(addprefix $(OBJ_PATH)/, $(OBJ))
DEEPCLEAN_LIST := $(TARGET) $(CLEAN_LIST)
# $(info $(FILE_TEXT) )
# $(info $(CCFLAG) )
# $(info $(VARIABLE) )
# $(info $(HEADER) )
# $(info $(SRC) )
# $(info $(OBJ) )
# $(info $(BIN_PATH) )
# $(info $(OBJ_DIR) )
# $(info $(INC_PATH) )
# $(info $(CLEAN_LIST) )
# $(info $(DEEPCLEAN_LIST) )
# default rule
default : all
#-------------- create directionary----------------
$(shell mkdir -p $(BIN_PATH))
$(shell mkdir -p $(OBJ_DIR))
#-------------- bin -------------------------------
# link
$(TARGET): $(OBJ)
$(CC) -o $@ $(addprefix $(OBJ_PATH)/, $^) -lm $(LIB_PATH) $(LIBS)
# compile
%.o: %.c*
@echo $@
@echo $<
$(CC) $(CCOBJFLAG) -o $(addprefix $(OBJ_PATH)/, $@) $(addprefix $(SRC_PATH)/, $<) $(INC_PATH)
#-------------- phonies ----------------------------
.PHONY : all
all : $(TARGET)
# .PHONY : lib
# all : $(TARGET)
.PHONY: clean
clean:
@echo clean $(CLEAN_LIST)
@rm -f $(CLEAN_LIST)
.PHONY: deepclean
deepclean:
@echo deep-clean $(DEEPCLEAN_LIST)
@rm -f $(DEEPCLEAN_LIST)
@rm -r $(OBJ_PATH)
配套main.flist文件列表
文件路径相对于makefile当前目录
include
... 添加其他头文件目录
src/main.cpp
... 添加其它相关.c/.cpp文件
使用
命令如下
make
make solution=debug
make solution=release
make solution=release type=main
make solution=release type=test
make solution=release type=.a
make solution=release type=.so
根据自己的项目修改makefile中的名称和main.flist文件内容即可,支持main/test/.a/.so的4种类型的项目属性