前言
前两天在工作中用到了Makefile的自动增量编译,发现它非常好用,尤其在工程中,你添加了新的模块,仅仅需要在Makefile里添加你模块文件夹的路径,就可以推导出该文件夹下的.c或者.cpp文件的编译。
实例
首先,我在一个test的文件夹下创建了三个文件夹include test1 test2,这三个文件夹下分别放着test2.h\test1.c\test2.c ,然后在创建一个Makefile文件,如下图所示。
test2.h内容如下:
#define NUM 1122
int fun(void);
test2.c内容如下:
#include <stdio.h>
#include "test2.h"
int fun(void)
{
printf("---------test2----------\n");
return 0;
}
test1.c内容如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "test2.h"
int main()
{
fun();
printf("test1-----%d-\n",NUM);
return 0;
}
从代码可以看出,test1.c调用了test2.c的fun函数和test2.h的宏定义,接下来需要做的就是写好Makefile了。
Makefile代码解析
default: all #如果不输入参数,默认会make all
CC = gcc #使用的编译器
MAKE_DIR := $(shell pwd) #当前路径
SRC_DIR = $(MAKE_DIR)/test1 #存放.c文件的路径
SRC_DIR += $(MAKE_DIR)/test2
SRC_FILE_LIST := $(foreach DIR,$(SRC_DIR),$(wildcard $(DIR)/*.c)) #for循环遍历各个文件,
#获取它们下面的.c文件
SRC_NAME_LIST := $(notdir $(SRC_FILE_LIST)) #将目录前缀去掉,只要文件名
OBJ_DIR := $(MAKE_DIR)/object #生成的.o文件存放的地方
INC_DIR = -I $(MAKE_DIR)/include #.h头文件存放的地方
OBJS_FILE_LIST := $(SRC_NAME_LIST:.c=.o) #将.c后缀换成.o后缀
TARGET := mytest #最后生成的可执行文件的名称
vpath %.c $(SRC_DIR) #告诉Makefile去你定义的目录下去寻找.c文件
.PHONY: all clean $(OBJS_FILE_LIST_T) link_all #声明你要编译的项
all: mk_obj_dir $(OBJS_FILE_LIST) link_all #定义all所依赖的项
mk_obj_dir: #创建object文件夹,用于 存放.o文件
@-mkdir -p $(OBJ_DIR)
$(OBJS_FILE_LIST):%.o:%.c #将所有的.c文件编译成.o文件
@echo "==== Compile objects: [$<] ===="
$(CC) $(INC_DIR) -g -o $(OBJ_DIR)/$@ -c $<
link_all: #链接.o文件
@echo "==== $(OBJ_DIR)/ ===="
@$(CC) -g -o $(TARGET) $(addprefix $(OBJ_DIR)/,$(OBJS_FILE_LIST))
clean: #清除文件
@rm -f $(OBJ_DIR)/*
@rm -f $(MAKE_DIR)/$(TARGET)
这样,我们就不用每次加.c文件都需要新建一个属于它的编译规则了。最后,make一下编译,查看测试结果如下图所示,说明我们的测试是成功的了。