我正在使用 GCC 生成依赖文件,但我的构建规则将输出放入子目录中。有没有办法告诉 GCC 将我的子目录前缀放入它为我生成的依赖文件中?

gcc $(INCLUDES) -E -MM $(CFLAGS) $(SRC) >>$(DEP)
有帮助吗?

解决方案

答案就在 海湾合作委员会手册:使用 -MT 旗帜。

-MT target

更改依赖项生成发出的规则的目标。默认情况下,CPP 采用主输入文件的名称,删除任何目录组件和任何文件后缀,例如 .c, ,并附加平台的常用对象后缀。结果就是目标。

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

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

$(objpfx)foo.o: foo.c

其他提示

我假设您正在使用 GNU Make 和 GCC。首先添加一个变量来保存依赖文件列表。假设您已经拥有一个列出了我们所有来源的列表:

SRCS = \
        main.c \
        foo.c \
        stuff/bar.c

DEPS = $(SRCS:.c=.d)

然后将生成的依赖项包含在 makefile 中:

include $(DEPS)

然后添加此模式规则:

# 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

“$@”是目标(位于左侧的东西:),“$<”是先决条件(右边的东西:)。表达式“$(<:.c=.o)”将 .c 扩展名替换为 .o。

这里的技巧是通过添加 -MT 两次来生成具有两个目标的规则;这使得 .o 文件和 .d 文件都依赖于源文件及其标头;这样,只要任何相应的 .c 或 .h 文件发生更改,依赖文件就会自动重新生成。

如果头文件丢失,-MG 和 -MP 选项可以防止 make 崩溃。

您可能会喜欢这个简短的版本 唐·麦考伊的回答:

SRCS = \
    main.c \
    foo.c \
    stuff/bar.c

DEPS = $(SRCS:.c=.d)

添加 -include $(DEPS) 请注意 - 前缀,如果 .d 文件尚不存在。

不需要单独的模式规则来生成依赖项文件。只需添加 -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.

详细介绍 D金特里的回答, ,这对我来说效果很好:

.depend: $(SOURCES)
    $(CC) $(CFLAGS) -MM $(SOURCES) | sed 's|[a-zA-Z0-9_-]*\.o|$(OBJDIR)/&|' > ./.depend

这也适用于只有一个依赖文件包含所有源文件的依赖规则的情况。

好吧,只是为了确保我的问题是正确的:我假设你有 test.c 包括 test.h, ,并且你想生成 subdir/test.d (尽管 不是 生成 subdir/test.o) 在哪里 subdir/test.d 包含

subdir/test.o: test.c test.h

而不是

test.o: test.c test.h

这就是你现在得到的。是对的吗?

我无法想出一种简单的方法来完全满足您的要求。然而,看着 依赖项生成改进, ,如果你想创建 .d 在生成 .o 文件时,您可以使用:

gcc $(INCLUDES) -MMD $(CFLAGS) $(SRC) -o $(SUBDIR)/$(OBJ)

(鉴于 SRC=test.c, SUBDIR=subdir, , 和 OBJ=test.o.) 这将创建 subdir/test.o 和 subdir/test.d,其中 subdir/test.d 包含如上所述的所需输出。

如果海湾合作委员会有理由这样做,我不知道那是什么。我们最终通过管道输出依赖项 sed 重写所有出现的 <blah>.o 作为 ${OBJDIR}/<blah>.o.

  1. 如果您不将输出放在当前目录中,[GNU] make 会生气。您确实应该从构建目录运行 make,并使用 VPATH make 变量来定位源代码。如果你对编译器撒谎,它迟早会报复。

  2. 如果您坚持在其他目录中生成对象和依赖项,则需要使用 -o 论证,如 埃米尔回答.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top