$(OBJDIR)/NetStats.o: ../../../source/network/NetStats.cpp $(GCH) | prebuild
$(CXX) $(CXXFLAGS) -MF $(OBJDIR)/NetStats.d -MT "$@" -o "$@" -c "$<"
NetStats.o
依赖于3
对象,但编译中只涉及第一个($<
),这是什么原理?
-MF -MT 是什么意思?
第一的,
-MF $(OBJDIR)/NetStats.d
生成依赖文件,如果头文件发生变化,则允许自动重建源文件。
因此,如果 NetStats.cpp 发生更改,它将在您使用依赖于 NetStats.o 的目标运行 make 后立即重建
其次,来自 GCC 文档:
-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 开关。
通常情况下,目标文件可能依赖于比您必须编译的更多的东西。经典例子:
myprog.o: myprog.c header1.h header2.h
gcc -c -o myprog.o myprog.c
在这种情况下,您不要将标头提供给编译行,它们是在处理源代码时由编译器本身购买的。
但是您仍然需要依赖项,因为如果包含的任何标头myprog.c
发生更改,您需要重新编译。