昨天写的Makefile自动产生依赖文件(一)是我以前用的方法总结,但近期发现了GCC本来就有这个功能,只是我没发现罢了-_-!!!。
这还说着摆弄Eclipse CDT开发环境时,无意中发现Eclipse产生的Makefile异常简洁,其核心的src/subdir.mk文件如下:
CPP_SRCS +=
../src/HelloWorld.cpp
OBJS +=
./src/HelloWorld.o
CPP_DEPS +=
./src/HelloWorld.d
src/%.o: ../src/%.cpp
@echo 'Building file:
lt;' @echo 'Invoking: Cygwin C++ Compiler' g++ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "
lt;" @echo 'Finished building:
lt;' @echo ' '
细看src/%.o: ../src/%.cpp的隐规则,发现多了几个参数”-MMD -MP -MF -MT”。”-MMD“我还认的,就是直接产生.d文件而不是输出到屏幕,其他就陌生了。遇到问题找Man啦,发现正好解决了我前一篇博客所说的两个问题,gcc果然不我欺也。
- -MP: 解决重命名头文件导致的依赖破裂,跟上次的思路一样,生成了dummy目标。
- -MF: 这个是指定输出的.d文件格式。
- -MT: 这个解决了输出的目标文件不带路径问题,可以指定目标文件的格式。
现在可以抛弃之前的makedepend,一个Makefile文件搞定一切:)。
更新
今天发现头文件更新不起作用,看来一下.d文件如下:
xxx.d: xxx.h //这里应为xxx.o:xxx.h
xxx.h:
惊讶的发现竟然没有xxx.o的依赖,再仔细检查了gcc的依赖选项发现之前没仔细看-MT修改了依赖项变成了.d了。其实-MT不用加上,加上就修改了目标名,最后的命令是:
$(OBJS):%.o:%.c
gcc -c $(CFLAGS) -MMD -MP -MF"$(@:%.o=%.d)" -o $@
lt;
这里用到了makefile静态规则(要详细看那边《跟我一起学Makefile》),这样就保证文件名不会被gcc给截断造成依赖文件的目标名错误。
最后贴个标准的吧:
SRC_DIR= src others
CFLAGS+=-Wall -g
CFLAGS+=$(addprefix -I, $(SRC_DIR))
CFILES=$(shell find $(SRC_DIR) -maxdepth 1 -name "*.c")
OBJS=$(CFILES:%.c=%.o)
LIBS+=
all:$(TARGET)
-include $(addsuffix /*.d, $(SRC_DIR))
$(TARGET):$(OBJS)
gcc $(LDFLAGS) $^ -o $@ $(LIBS)
$(OBJS):%.o:%.c
gcc -c $(CFLAGS) -MMD -MP -MF"$(@:%.o=%.d)" -o $@
lt; clean: -rm -f $(addsuffix /*.d, $(SRC_DIR)) $(addsuffix /*.o, $(SRC_DIR)) $(TARGET)