每次在Linux 下开发都要百度个makefile 最近遇到一个蛋疼的博友、执行make 的时候把我的工程全部删除气死我了、一周的辛苦白费了、为了避免类似的情况出现、so 决定自己写一个万能的Makefile、
#-Wall 是打开警告开关
# Wno-unused 变量定义未使用
# Wno-format 含NUL字节的格式字符串
#-O代表默认优化,可选:-O0不优化,-O1低级优化,-O2中级优化,-O3高级优化,-Os代码空间优化。
#-g是生成调试信息,生成的可执行文件具有和源代码关联的可调试的信息
# filter-out 过滤函数
#-dl ,是显式加载动态库的动态函数库
#so编译
# CFLAGS需要加上 -fPIC
# LINKFLAGS需要加上 -shared -fPIC
#可执行文件编译
# CFLAGS不需要 -fPIC
# LINKFLAGS为空
####################################
# 万能makefile ####
# Created on: 2019年9月11日 ####
# Author: 汪伟 QQ:506772362 ####
####################################
# 设置目标类型(app, ar, so), 及目标名字
TARGET_TYPE := so
TARGET_TYPE := $(strip $(TARGET_TYPE))
TARGET_NAME := Bin/$(shell basename $(PWD))
# 初始化编译器
CROSS_COMPILE :=
GCC := $(CROSS_COMPILE)gcc
CXX := $(CROSS_COMPILE)g++
AR := $(CROSS_COMPILE)ar
# 源文件可能的后缀
SRCEXTS := c C cc cpp CPP c++ cxx cp
HDREXTS := h H hh hpp HPP h++ hxx hp
# 其他变量
DEFS := -DDEBUG
OPTIMIZE := -O2
WARNINGS := -Wall -Wno-unused -Wno-format
# 指定源文件目录, 以及目标文件生成目录
PROJECT_DIR := $(shell pwd)
INC_PATH := $(PROJECT_DIR)/ \
$(PROJECT_DIR)/include/ \
$(PROJECT_DIR)/Qos/include/
SRC_PATH := $(PROJECT_DIR)/ \
$(PROJECT_DIR)/src/ \
$(PROJECT_DIR)/Qos/src/
OBJ_PATH := $(PROJECT_DIR)/obj/
LIBA_PATH := $(PROJECT_DIR)/lib/
LIBS_PATH := $(PROJECT_DIR)/Bin/
LIBA :=
LIBS :=
# 初始化编译选项
INCLUDE :=
CFLAGS := $(OPTIMIZE) $(WARNINGS) $(DEFS)
CPPFLAGS:= -g -Wall -O2
LDFLAGS := -L$(LIBA_PATH) -L$(LIBS_PATH) -lm -ldl -lpthread $(LIBA) $(LIBS)
# 额外增加的源文件或者排除不编译的源文件
SPECIAL_SRC :=
EXCLUDE_SRC :=
ifeq ($(TARGET_TYPE), so)
TARGET_NAME := Bin/lib$(shell basename $(PWD).so)
else
ifeq ($(TARGET_TYPE), ar)
TARGET_NAME := lib/lib$(shell basename $(PWD).a)
endif
endif
# 追加搜索目录
SRC_PATH += $(dir $(SPECIAL_SRC))
INC_PATH += $(SRC_PATH)
# 源文件, 头文件, 链接文件
SOURCES = $(filter-out $(EXCLUDE_SRC), $(foreach d, $(SRC_PATH), $(wildcard $(addprefix $(d)/*., $(SRCEXTS)))))
HEADERS = $(foreach d, $(INC_PATH), $(wildcard $(addprefix $(d)/*., $(HDREXTS))))
OBJECTS = $(addprefix $(OBJ_PATH)/, $(addsuffix .o, $(basename $(notdir $(SOURCES)))))
# 配置编译选项
INCLUDE += $(foreach d, $(sort $(INC_PATH)), -I$d)
ifeq ($(TARGET_TYPE), so)
CFLAGS += -fpic -shared
LDFLAGS += -shared
endif
# 定义伪目标
PHONY = all .mkdir clean
all: .mkdir $(TARGET_NAME)
# 函数: 添加%.x依赖文件的路径
define add_vpath
$1
endef
# 函数: 生成中间文件
define gen_o_cmd
$2/%.o: %.$1
$(CXX) $(INCLUDE) -Wp,-MT,$$@ -Wp,-MMD,$$@.d $(CFLAGS) $(CPPFLAGS) -c -o $$@ $$<
endef
# 执行函数, make会将函数里的内容当Makefile解析, 注意$$符号
$(eval $(foreach i, $(SRCEXTS), $(foreach d, $(SRC_PATH), $(call add_vpath,vpath %.$i $d))))
$(eval $(foreach i, $(SRCEXTS), $(call gen_o_cmd,$i,$(OBJ_PATH))))
# 静态, 动态, 可执行
ifeq ($(TARGET_TYPE), ar)
$(TARGET_NAME): $(OBJECTS)
rm -f $@
$(AR) rcvs $@ $(OBJECTS)
else
$(TARGET_NAME): LD=$(if $(filter-out %.c %.C, $(SOURCES)),$(CXX),$(GCC))
$(TARGET_NAME): $(OBJECTS)
$(LD) $(OBJECTS) -o $@ $(LDFLAGS)
endif
.mkdir:
@echo "=============================================="
@if [ ! -d $(OBJ_PATH) ]; then mkdir -p $(OBJ_PATH); fi
@echo "====== create object directory successfully, $(OBJ_PATH) ===="
ifeq ($(TARGET_TYPE), ar)
@if [ ! -d $(LIBA_PATH) ]; then mkdir -p $(LIBA_PATH); fi
@echo "====== create object directory successfully, $(LIBA_PATH) ===="
else
@if [ ! -d $(LIBS_PATH) ]; then mkdir -p $(LIBS_PATH); fi
@echo "====== create object directory successfully, $(LIBS_PATH) ===="
endif
@echo "=============================================="
clean:
rm -rf $(OBJ_PATH) $(TARGET_NAME)
run:$(TARGET_NAME)
@$(TARGET_NAME)
.PHONY: $(PHONY)
若遇到问题请及时留言 及时修改以免误人