C++ 为不同的输出目录生成 GCC 依赖项
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/97338/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
GCC dependency generation for a different output directory
提问by KPexEA
I'm using GCC to generate a dependency file, but my build rules put the output into a subdirectory. Is there a way to tell GCC to put my subdirectory prefix in the dependency file it generates for me?
我使用 GCC 生成依赖文件,但我的构建规则将输出放入子目录。有没有办法告诉 GCC 将我的子目录前缀放在它为我生成的依赖文件中?
gcc $(INCLUDES) -E -MM $(CFLAGS) $(SRC) >>$(DEP)
采纳答案by bk1e
The answer is in the GCC manual: use the -MT
flag.
答案在GCC 手册中:使用-MT
标志。
-MT target
Change the target of the rule emitted by dependency generation. By default CPP takes the name of the main input file, deletes any directory components and any file suffix such as
.c
, and appends the platform's usual object suffix. The result is the target.An
-MT
option will set the target to be exactly the string you specify. If you want multiple targets, you can specify them as a single argument to-MT
, or use multiple-MT
options.For example,
-MT '$(objpfx)foo.o'
might give$(objpfx)foo.o: foo.c
-MT target
更改依赖生成发出的规则的目标。默认情况下,CPP 采用主输入文件的名称,删除任何目录组件和任何文件后缀,例如
.c
,并附加平台的常用对象后缀。结果就是目标。一个
-MT
选项会将目标设置为您指定的字符串。如果需要多个目标,可以将它们指定为 的单个参数-MT
,或使用多个-MT
选项。例如,
-MT '$(objpfx)foo.o'
可能会给$(objpfx)foo.o: foo.c
回答by Don McCaughey
I'm assuming you're using GNU Make and GCC. First add a variable to hold your list of dependency files. Assuming you already have one that lists all our sources:
我假设您正在使用 GNU Make 和 GCC。首先添加一个变量来保存您的依赖文件列表。假设你已经有一个列出我们所有来源的:
SRCS = \
main.c \
foo.c \
stuff/bar.c
DEPS = $(SRCS:.c=.d)
Then include the generated dependencies in the makefile:
然后在 makefile 中包含生成的依赖项:
include $(DEPS)
Then add this pattern rule:
然后添加这个模式规则:
# automatically generate dependency rules
%.d : %.c
$(CC) $(CCFLAGS) -MF"$@" -MG -MM -MP -MT"$@" -MT"$(<:.c=.o)" "$<"
# -MF write the generated dependency rule to a file
# -MG assume missing headers will be generated and don't stop with an error
# -MM generate dependency rule for prerequisite, skipping system headers
# -MP add phony target for each header to prevent errors when header is missing
# -MT add a target to the generated dependency
"$@" is the target (the thing on the left side of the : ), "$<" is the prerequisite (the thing on the right side of the : ). The expression "$(<:.c=.o)" replaces the .c extension with .o.
“$@”是目标(: 左侧的东西),“$<”是先决条件(: 右侧的东西)。表达式“$(<:.c=.o)”用 .o 替换了 .c 扩展名。
The trick here is to generate the rule with two targets by adding -MT twice; this makes both the .o file and the .d file depend on the source file and its headers; that way the dependency file gets automatically regenerated whenever any of the corresponding .c or .h files are changed.
这里的技巧是通过添加 -MT 两次来生成具有两个目标的规则;这使得 .o 文件和 .d 文件都依赖于源文件及其头文件;这样,只要相应的 .c 或 .h 文件发生更改,依赖文件就会自动重新生成。
The -MG and -MP options keep make from freaking out if a header file is missing.
如果头文件丢失, -MG 和 -MP 选项可以防止 make 出错。
回答by Steve Pitchers
You may like this briefer version of Don McCaughey's answer:
您可能会喜欢Don McCaughey 回答的这个简短版本:
SRCS = \
main.c \
foo.c \
stuff/bar.c
DEPS = $(SRCS:.c=.d)
DEPS = $(SRCS:.c=.d)
Add -include $(DEPS)
note the -
prefix, which silences errors if the .d
files don't yet exist.
添加-include $(DEPS)
注意-
前缀,如果.d
文件尚不存在,则会消除错误。
There's no need for a separate pattern rule to generate the dependency files. Simply add -MD
or -MMD
to your normal compilation line, and the .d
files get generated at the same time your source files are compiled. For example:
不需要单独的模式规则来生成依赖文件。只需将-MD
或添加-MMD
到您的正常编译行,.d
文件就会在编译源文件的同时生成。例如:
%.o: %.c
gcc $(INCLUDE) -MMD -c $< -o $@
# -MD can be used to generate a dependency output file as a side-effect of the compilation process.
回答by rsp1984
Detailing on DGentry's answer, this has worked well for me:
详细介绍DGentry 的回答,这对我来说效果很好:
.depend: $(SOURCES)
$(CC) $(CFLAGS) -MM $(SOURCES) | sed 's|[a-zA-Z0-9_-]*\.o|$(OBJDIR)/&|' > ./.depend
This also works in the case where there is only one dependency file that contains the dependency rules for all source files.
这也适用于只有一个依赖文件包含所有源文件的依赖规则的情况。
回答by rsp1984
Ok, just to make sure I've got the question right: I'm assuming you have test.c
which includes test.h
, and you want to generate subdir/test.d
(while notgenerating subdir/test.o
) where subdir/test.d
contains
好的,只是为了确保我的问题是正确的:我假设您有test.c
which includes test.h
,并且您想要生成subdir/test.d
(同时不生成subdir/test.o
) where subdir/test.d
contains
subdir/test.o: test.c test.h
rather than
而不是
test.o: test.c test.h
which is what you get right now. Is that right?
这就是你现在得到的。那正确吗?
I was not able to come up with an easy way to do exactly what you're asking for. However, looking at Dependency Generation Improvements, if you want to create the .d
file while you generate the .o file, you can use:
我无法想出一种简单的方法来完全满足您的要求。但是,查看Dependency Generation Improvements,如果要.d
在生成 .o 文件时创建文件,可以使用:
gcc $(INCLUDES) -MMD $(CFLAGS) $(SRC) -o $(SUBDIR)/$(OBJ)
(Given SRC=test.c
, SUBDIR=subdir
, and OBJ=test.o
.) This will create both subdir/test.o and subdir/test.d, where subdir/test.d
contains the desired output as above.
(给定SRC=test.c
、SUBDIR=subdir
和OBJ=test.o
。)这将创建 subdir/test.o 和 subdir/test.d,其中subdir/test.d
包含上述所需的输出。
回答by florin
[GNU] make gets angry if you don't place the output in the current directory. You should really run make from the build directory, and use the VPATH make variable to locate the source code. If you lie to a compiler, sooner or later it will take its revenge.
If you insist on generating your objects and dependencies in some other directory, you need to use the
-o
argument, as answered by Emile.