【发布时间】:2020-08-16 03:19:53
【问题描述】:
我一直在尝试调试有时会导致 make 构建失败的 makefile.am。在这个文件中,源是自动生成的 .c 文件,头文件是自动生成的 .h 文件。
..._SOURCES = @buildDirectory@/x.c
@buildDirectory@/y.c
@buildDirectory@/z.c
..._HEADERS = @buildDirectory@/x.h
@buildDirectory@/y.h
@buildDirectory@/z.h
失败是这样的
<failedproto>.proto: "symbol1" is not defined.
<failedproto>.proto: "symbol2" is not defined.
<failedproto>.proto: "symbol3" is not defined.
...
<failedproto>.proto: warning: Import <failedproto>.proto but not used.
make: *** [<failedproto>.c] Error 1
make: *** Waiting for unfinished jobs....
所有这些符号都出现在相应的 .h 中。这让我认为 .c 是在 .h 之前生成的,而且它只是一场直线比赛。我已将 ..._SOURCES 和 _HEADERS 添加到 BUILT_SOURCES,但我仍然看到失败。所以我的下一个直觉是在 .h 上为 .c 创建一个依赖项。我该怎么做,因为它们都是自动生成的?此外,也欢迎任何替代解决方案。
希望我的格式没有混乱。
编辑更多细节:
这些文件由 protoc-c 编译器自动生成:https://github.com/protobuf-c/protobuf-c protoc-c 把这些 .proto 文件,生成 .pb-c.c 和 .pb-c.h 文件,让我觉得这两个毕竟没有依赖关系。还运行一些内部代码,生成其他 .proto 文件,我将它们称为 nameX.proto 和 nameY.proto,它们依次生成 nameX.pb-cc/nameX.pb-ch 和 nameY.pb-cc/nameY .pb-ch Makefile.am 的一个更准确的例子是这样的:
..._SOURCES = @buildDirectory@/name.pb-c.c
@buildDirectory@/nameX.pb-c.c
@buildDirectory@/nameY.pb-c.c
..._HEADERS = @buildDirectory@/name.pb-c.h
@buildDirectory@/nameX.pb-c.h
@buildDirectory@/nameY.pb-c.h
我一直在尝试跟踪这些依赖关系,我将尝试描述我得出的结论。 nameX.pb-c.c 包含其对应的头文件 nameX.pb-c.h。该标头包含 nameY.pb-c.h,让我认为 nameX.proto 在 nameY.proto 可以编译之前被编译成 nameX.pb-c.c/nameX.pb-c.h。由于 nameX.pb-c.h 和 nameY.pb-c.h 之间存在包含关系,因此构建失败,因为 nameX.pb-c.h 需要 nameY.pb-c.h。这让我想到了两条我从一开始就怀疑的规则。这些规则概括如下:
$(OUT_DIRECTORY)/%nameX.proto:$(SRC_DIRECTORY)/name.proto $(SRC_DIRECTORY)/nameY.proto
command $(OUT_DIRECTORY) $(FLAGS) $<
$(OUT_DIRECTORY)/%nameX.proto:$(SRC_DIRECTORY)/name.proto
command $(OUT_DIRECTORY) $(FLAGS) $<
这可能是个问题吗?如果第二条规则确实需要第一条规则,是什么阻止它运行?
更糟糕的是,许多 .proto 文件都是中间文件(它们是在整个构建过程中生成然后丢弃的),所以我无法查看它们以了解它们的外观。
【问题讨论】:
-
重要的是要理解,仅仅因为一个源文件(或头文件)包含另一个源文件或头文件,并不意味着它们是 make 的先决条件看法。 Make 只关心需要运行的命令、命令的输出和命令的输入。因此,对于 C 编译器,输出是 object 文件,输入是 all the source/headers,源不依赖于 headers,而是依赖于目标文件在源文件及其所有包含的头文件上。
-
我不明白为什么您有两个具有相同目标模式的模式规则,以及在先决条件列表中未使用该模式的地方。这些规则中的每一个都说“如果你想构建一个与
$(OUT_DIRECTORY)/%nameX.proto匹配的目标,如果这些先决条件存在或可以构建,你就可以做到”。但是,如果您想构建两个都匹配该模式的目标,make 将运行该规则两次......这可能会生成相同的输出。为什么在这里使用模式规则? -
“我不明白为什么你有两个具有相同目标模式的模式规则” - 这是一个很好的问题。这个 Makefile 不是我写的,我为修复它的间歇性构建失败而苦恼。这是我第一次深入制作,所以我对作者在这个文件中所做的任何选择都不是非常有信心。当我继承它时,它的形状很糟糕。至于为什么我们有模式规则,是因为Makefile中列出了更多的_SOURCE和_HEADERS。
-
您显示的错误消息似乎不是来自 C 编译器。我猜它一定是由 protoc-c 发出的。在这种情况下,问题可能根本不在于
make依赖项,而在于您对 protoc-c 的输入。 -
@JohnBollinger 我同意这是一个 protoc-c 错误。但是,传递给 protoc-c 的文件也是在这个 Makefile 中生成的。所以我想这是我追踪汽车发电菊花链在哪里发生故障的问题......
标签: makefile dependencies protocol-buffers autotools automake