我如何理解这个makefile规则的细节?

时间:2012-05-15 11:32:37

标签: c++ makefile

$(OBJDIR)/NetStats.o: ../../../source/network/NetStats.cpp $(GCH) | prebuild
    $(CXX) $(CXXFLAGS) -MF $(OBJDIR)/NetStats.d -MT "$@" -o "$@" -c "$<"

NetStats.o取决于3个对象,但只有第一个($<)参与编译,理由是什么?

-MF -MT是什么意思?

2 个答案:

答案 0 :(得分:2)

首先,

 -MF $(OBJDIR)/NetStats.d

生成依赖文件,如果标题中发生了某些变化,则允许自动重建源。

因此,NetStats.cpp已更改,只要您使用依赖于NetStats.o的目标运行make,就会重建它。

其次,来自GCC docs:

 -MT target

更改依赖关系生成所发出的规则的目标。默认情况下,CPP获取主输入文件的名称,包括任何路径,删除任何文件后缀,如“.c”,并附加平台的常用对象后缀。结果是目标。

-MT选项会将目标设置为您指定的字符串。如果需要多个目标,可以将它们指定为-MT的单个参数,或使用多个-MT选项。

例如,-MT'$(objpfx)foo.o'可能会给出           $(objpfx)foo.o:foo.c


.d文件看起来就像是makefile的一部分。以下是Canvas.d对我的一个项目的摘录:

 Out/Mac/ppc64/Obj/Canvas.o: Src/Linderdaum/Renderer/Canvas.cpp \
     Src/Linderdaum/Renderer/Canvas.h Src/Linderdaum/Core/iObject.h \
    /usr/include/c++/4.0.0/deque /usr/include/c++/4.0.0/bits/functexcept.h \
    /usr/include/c++/4.0.0/exception_defines.h \
    .....

基本上,预处理器会搜索.cpp文件中的所有依赖项,并生成一个额外的目标来指定这些依赖项。

要查看哪些.d文件可能会尝试编写test.c

 #include <stdio.h>
 #include <stdlib.h>
 int main() { return 0; }

并运行gcc -MD -c test.c命令

对于我的MingW环境,它是

test.o: test.c \
 c:\eqmingw\bin\../lib/gcc/x86_64-w64-mingw32/4.6.0/../../../../x86_64-w64-mingw32/include/stdio.h \
 c:\eqmingw\bin\../lib/gcc/x86_64-w64-mingw32/4.6.0/../../../../x86_64-w64-mingw32/include/_mingw.h \
 c:\eqmingw\bin\../lib/gcc/x86_64-w64-mingw32/4.6.0/../../../../x86_64-w64-mingw32/include/_mingw_mac.h \
 c:\eqmingw\bin\../lib/gcc/x86_64-w64-mingw32/4.6.0/../../../../x86_64-w64-mingw32/include/vadefs.h \
 c:\eqmingw\bin\../lib/gcc/x86_64-w64-mingw32/4.6.0/../../../../x86_64-w64-mingw32/include/sdks/_mingw_directx.h \
 c:\eqmingw\bin\../lib/gcc/x86_64-w64-mingw32/4.6.0/../../../../x86_64-w64-mingw32/include/sdks/_mingw_ddk.h \
 c:\eqmingw\bin\../lib/gcc/x86_64-w64-mingw32/4.6.0/../../../../x86_64-w64-mingw32/include/_mingw_print_push.h \
 c:\eqmingw\bin\../lib/gcc/x86_64-w64-mingw32/4.6.0/../../../../x86_64-w64-mingw32/include/sec_api/stdio_s.h \
 c:\eqmingw\bin\../lib/gcc/x86_64-w64-mingw32/4.6.0/../../../../x86_64-w64-mingw32/include/_mingw_print_pop.h \
 c:\eqmingw\bin\../lib/gcc/x86_64-w64-mingw32/4.6.0/../../../../x86_64-w64-mingw32/include/stdlib.h \
 c:\eqmingw\bin\../lib/gcc/x86_64-w64-mingw32/4.6.0/include-fixed/limits.h \
 c:\eqmingw\bin\../lib/gcc/x86_64-w64-mingw32/4.6.0/include-fixed/syslimits.h \
 c:\eqmingw\bin\../lib/gcc/x86_64-w64-mingw32/4.6.0/../../../../x86_64-w64-mingw32/include/limits.h \
 c:\eqmingw\bin\../lib/gcc/x86_64-w64-mingw32/4.6.0/../../../../x86_64-w64-mingw32/include/sec_api/stdlib_s.h \
 c:\eqmingw\bin\../lib/gcc/x86_64-w64-mingw32/4.6.0/../../../../x86_64-w64-mingw32/include/malloc.h

要从依赖项列表中排除系统包含文件,也可以使用-MM开关。

答案 1 :(得分:1)

通常情况下,目标文件可能依赖于比编译更多的东西。经典例子:

myprog.o: myprog.c header1.h header2.h
    gcc -c -o myprog.o myprog.c

在这种情况下,您不会将标题提供给编译行,它们在处理源时由编译器本身购买。

但是仍然想要依赖项,因为如果myprog.c包含的任何标题发生更改,您需要重新编译。