Makefile目录和文件依赖

1、目录的自动创建和删除

--foo.h--
#ifndef __FOO_H
#define __FOO_H

void foo();

#endif
--foo.c--
#include <stdio.h>
#include "foo.h"

void foo()
{
	printf("This is foo()!\n");
}
--main.c--
#include "foo.h"

int main ()
{
	foo();
	return 0;
}
--Makefile--
.PHONY: all clean

MAKE = mingw32-make
MKDIR = mkdir
RM = rm
RMFLAGS = -fr
CC = gcc

DIR_OBJS = objs
DIR_EXES = exes
DIRS = $(DIR_OBJS) $(DIR_EXES)
EXE = $(DIR_EXES)/complicated.exe
SRCS = $(wildcard *.c)
OBJS = $(SRCS:.c=.o)
OBJS := $(addprefix $(DIR_OBJS)/, $(OBJS))

all: $(DIRS) $(EXE)

$(DIRS):
	$(MKDIR) $@
$(EXE): $(OBJS)
	$(CC) -o $@ $^
$(DIR_OBJS)/%.o: %.c
	$(CC) -o $@ -c $^

clean:
	$(RM) $(RMFLAGS) $(DIRS)
①、$(DIRS) 目标会自动创建两个文件夹 objs 和 exes
②、将所有的中间文件 .o 放在 objs 下,将可执行文件 .exe 放在 exes 下
③、最后只要递归的删除这两个文件夹即可
但是上面的 Makefile 有个缺陷:所有目标中都没有 foo.h,现假设该项目已经成功 make,然后修改 foo.h 如下:

--foo.h--

#ifndef __FOO_H
#define __FOO_H

void foo(int i);

#endif
正常编译时应该报错,但是由于规则中并不包含 foo.h,所有现在更改 foo.h,Makefile 并不会检查到,当然这也肯定是不对的,有什么解决办法呢?一种显而易见的方法是,修改 Makefile 的第 23、24 两行如下:
$(DIR_OBJS)/%.o: %.c foo.h
$(CC) -o $@ -c $<

将 foo.h 添加进先决条件,但在编译命令中不包含它。但当项目复杂时,这种做法不具操作性。

2、自动生成文件依赖关系

更改 Makefile 文件如下:
--Makefile--
.PHONY: all clean

MAKE = mingw32-make
MKDIR = mkdir
RM = rm
RMFLAGS = -fr
CC = gcc

DIR_OBJS = objs
DIR_EXES = exes
DIR_DEPS = deps
DIRS = $(DIR_OBJS) $(DIR_EXES) $(DIR_DEPS)
EXE = complicated.exe
EXE := $(addprefix $(DIR_EXES)/, $(EXE))
SRCS = $(wildcard *.c)
OBJS = $(SRCS:.c=.o)
OBJS := $(addprefix $(DIR_OBJS)/, $(OBJS))
DEPS = $(SRCS:.c=.dep)
DEPS := $(addprefix $(DIR_DEPS)/, $(DEPS))

all: $(DIRS) $(DEPS) $(EXE)

$(DIRS):
	$(MKDIR) $@
$(EXE): $(OBJS)
	$(CC) -o $@ $^
$(DIR_OBJS)/%.o: %.c
	$(CC) -o $@ -c $^
$(DIR_DEPS)/%.dep: %.c
	@echo "Creating $@ ..."
	@set -e;\
	$(RM) $(RMFLAGS) $@.tmp ;\
	$(CC) -E -MM $^ > $@.tmp ;\
	sed 's,\(.*\)\.o[ :]*,objs/\1.o: ,g' < $@.tmp > $@ ;\
	$(RM) $(RMFLAGS) $@.tmp

clean:
	$(RM) $(RMFLAGS) $(DIRS)
①、增加了 deps 文件夹存放  *.dep  文件
②、*.dep 存放了目标文件 *.o 的依赖文件关系
③、 all 目标增加 $(DEPS) 的依赖
④、 -set e 的作用是告诉 shell,在生成依赖关系文件的过程中如果出现任何错误就直接退出
⑤、规则中每一条的命令都是在一个新的 shell 中运行的,如果希望多个命令在同一个 shell 中运行,可以用 ";"  将这些命令连接起来。
⑥、当命令很长时,可以使用 "\" 将命令分在多行书写
⑦、gcc 的 -E 选项表示 gcc 只做预处理而不进行程序编译; -MM 生成文件关联的信息。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值