单源文件目录makefile

目录结构

由于只是用来编译简单的小型程序,所以目录尽量简洁:

.
├── build
│   ├── bin
│   ├── .dep
│   └── obj
├── makefile
└── src

这里用户需要创建的就只有makefile和src目录(里面放入项目.h.cpp文件)。
build目录下用于存放编译中间文件和最终的可执行程序,其中.dep用于记录.cpp文件的头文件依赖关系。

自动生成头文件依赖

利用g++命令中推导头文件依赖的功能生成每个.cpp文件对应的.d依赖文件,再将.d依赖文件include到makefile文件中,实现对依赖头文件的检测。
具体原理见:Auto-Dependency Generation

makefile

# 目录结构
# .
# ├── build
# │   ├── bin
# │   ├── .dep
# │   └── obj
# ├── makefile
# └── src

# 获取当前的makefile所在的目录绝对路径
# MAKEFILE_LIST是make工具定义的环境变量,最后一个值就是当前的makefile的启动路径(可以是相对路径)
TOP_DIR:=$(patsubst %/, %, $(dir $(abspath $(lastword $(MAKEFILE_LIST)))))

# 各项目录
BIN_DIR:=$(TOP_DIR)/build/bin
DEP_DIR:=$(TOP_DIR)/build/.dep
OBJ_DIR:=$(TOP_DIR)/build/obj
SRC_DIR:=$(TOP_DIR)/src

# 编译器,链接器
CXX:=g++
LD:=g++

# 生成依赖文件选项
DEPFLAGS=-MT $@ -MMD -MP -MF $(DEP_DIR)/$*.d

# 编译选项
CXXFLAGS:=-std=c++11 -Wall -Wextra -Og -g

# 宏定义
MACROS:=

# 链接选项
LDFLAGS:=

# 包含的头文件和库文件
INCS:=
LIBS:=

# 源文件以及中间目标文件和依赖文件
SRCS:=$(notdir $(wildcard $(SRC_DIR)/*.cpp))
OBJS:=$(addprefix $(OBJ_DIR)/, $(patsubst %.cpp, %.o, $(SRCS)))
DEPS:=$(addprefix $(DEP_DIR)/, $(patsubst %.cpp, %.d, $(SRCS)))

# 最终目标文件
TARGET:=$(BIN_DIR)/hello

# 默认最终目标
.PHONY:all
all:$(TARGET)

# 生成最终目标
$(TARGET):$(OBJS) | $(BIN_DIR)
	@echo -e "\e[32m""Linking executable $(TARGET)""\e[0m"
	@$(LD) $(LDFLAGS) -o $@ $^ $(LIBS)

# 若没有bin目录则自动生成
$(BIN_DIR):
	@mkdir -p $@

# 生成中间目标文件
$(OBJ_DIR)/%.o:$(SRC_DIR)/%.cpp $(DEP_DIR)/%.d | $(OBJ_DIR) $(DEP_DIR)
	@echo -e "\e[33m""Building object $@""\e[0m"
	@$(CXX) -c $(DEPFLAGS) $(CXXFLAGS) $(INCS) $(MACROS) -o $@ $<

# 若没有obj目录则自动生成
$(OBJ_DIR):
	@mkdir -p $@

# 若没有.dep目录则自动生成
$(DEP_DIR):
	@mkdir -p $@

# 依赖文件会在生成中间文件的时候自动生成,这里只是为了防止报错
$(DEPS):

# 引入中间目标文件头文件依赖关系
include $(wildcard $(DEPS))

# 删除build目录
.PHONY:clean
clean:
	@rm -rf $(TOP_DIR)/build
posted @ 2019-12-28 20:56  HachikoT  阅读(366)  评论(0编辑  收藏  举报