Sunday, April 26, 2009

Makefile 指定 gcc 文件输出路径

最近因为常常在 Linux 下写程序的原因,时常用到 Makefile ,以便于方便 C/C++ 程序的开发。不得不感叹 make 这个工具实在是好用,减轻了大量的工作负担。

最近才知道 Makefile 中存在“潜规则”,也就是默认的预定义依赖关系,比如 .o 文件是默认依赖于同名的 .c 文件的,并且 make 会自动执行这个依赖关系的命令本体,也就是说会自动将 .c 文件编译为 .c 文件。因此,如果你需要写一个 Makefile 将 prog.c 编译为 prog 的话,可以这样写:

all : prog

prog : prog.o
gcc prog.o -o prog

在这个 Makefile 里就没有写 prog.o 对 prog.c 的依赖。

然而这样有一个问题,就是生成的 .o 文件以及可执行文件都和源代码在同一个目录下,整个目录结构比较乱。我就希望能把生成的 .o 文件放置到一个 obj 目录下,然后可执行文件放到 bin 目录下。但要实现这个目标的话,岂不是要一个个文件改编译命令?如果工程量较大,上百个文件写起来会累死人的!

好在今天看到一个解决的方法,是通过修改“潜规则”来实现的。就用我现在的工程说明把。我的源程序都放在一个目录下(没有子目录),我希望把 .o 和可执行程序分别放到 obj 和 bin目录里。那么 Makefile 就这样写:

CC = gcc 编译器名
CFLAGS = -MD -Wall -O3 编译选项
LIBS = -lpthread 附加的库
OBJDIR = obj .o 输出目录
BINDIR = bin 可执行程序输出目录

.PRECIOUS: $(OBJDIR)/%.o 阻止 make 删除中间文件(不然以后还要编译)
默认目标
all: mkdirs $(BINDIR)/rpctest $(BINDIR)/headquarters \
$(BINDIR)/node_manager $(BINDIR)/extent_server

建立子文件夹
mkdirs : $(BINDIR) $(OBJDIR)

“潜规则”,OBJDIR 下的 .o 文件依赖于当前目录的同名 .c 文件
$(OBJDIR)/%.o : %.c
$(CC) -c $(CFLAGS) $(GCC_WALL_FLAG) $< -o $@

“潜规则",BINDIR 下的可执行程序依赖于 OBJDIR 下的同名 .o 文件
$(BINDIR)/% : $(OBJDIR)/%.o
$(CC) $(CFLAGS) $(GCC_WALL_FALG) $(LIBS) $< -o $@

建立文件夹
$(OBJDIR):
mkdir -p $@

$(BINDIR):
mkdir -p $@
添加 gcc 生成的依赖关系(-MD的输出)
-include $(OBJDIR)/*.d

clean :
rm -rf $(BINDIR) $(OBJDIR)

0 comments: