协议缓冲区文件的 Makefile 自动依赖关系问题

Posted

技术标签:

【中文标题】协议缓冲区文件的 Makefile 自动依赖关系问题【英文标题】:Makefile Automatic Dependencies Issues With Protocol Buffer Files 【发布时间】:2013-06-30 18:56:00 【问题描述】:

我无法在我的 Makefile 中建立自动依赖关系。目标是从许多 Protocol Buffer 文件中创建一个 C++ 库,其中一些可能位于只读目录中。为了绕过写权限,我想在 Makefile 目录中生成 C++ 文件。实际的 Makefile 是从 Makefile.am 创建的。下面的简化脚本应该可以解决构建自动依赖关系的技巧,但它没有:

mypbfiles = /usr/share/project/my_file.proto
MY_PB_FILES = $(notdir $mypbfiles)
MY_SOURCE_FILES = $MY_PB_FILES:.proto=.pb.cc

lib_LTLIBRARIES = lib@PACKAGE_NAME@_protobuf.la
lib@PACKAGE_NAME@_protobuf_la_SOURCES = $MY_SOURCE_FILES
lib@PACKAGE_NAME@_protobuf_la_LDFLAGS = -version-info @MAJOR_VERSION@:@MINOR_VERSION@:0

$(MY_SOURCE_FILES): $(mypbfiles)
    @for proto_file in $(mypbfiles); do \
        gen_file=`echo $proto_file | perl -pe 's/\.proto/\.pb\.cc/; s|.*/||'`;\
        echo "*** Building $gen_file from $$proto_file ***"; \
        protoc -I$mypbdir --cpp_out=./ $$proto_file;\
done

LTLIBRARIES = $(lib_LTLIBRARIES)
all: Makefile $(LTLIBRARIES)

然后我决定在脚本中添加以下两行:

foo:
    echo $MY_SOURCE_FILES

运行 'make foo' 显示以下输出:

echo my_file.pb.cc
my_file.pb.cc

所以 MY_SOURCE_FILES 确实包含正确的值,但没有建立依赖关系。但是,在脚本中进行以下更改可以解决问题:

lib@PACKAGE_NAME@_protobuf_la_SOURCES = my_file.pb.cc

您可能会问,为什么不做出改变并对此感到满意呢?问题是 Makefile.am 被提供给处理“lib@PACKAGE_NAME@_protobuf_xxx”的程序。所以我必须想办法让事情顺利进行!我怀疑使用 'notdir' 函数不会以我想要的方式扩展变量 'MY_PB_FILES'。

我对 GNU Makefile 不是很精通,因此非常感谢任何建议或帮助。

【问题讨论】:

在你的例子中你使用lib@PACKAGE_NAME@_protobuf_la_SOURCES,在你的“固定”例子中你使用lib@PACKAGE_NAME@_protobuf_la_SOURCE(没有S)。这是问题中的错字吗?此外,您没有具体说明“未建立依赖关系”的确切含义......您希望发生什么但不会发生? 那是一个错字。我会编辑帖子。感谢您的关注。我想要发生的是看到以下声明: *** Building my_file.pb.cc from /usr/share/project/my_file.proto *** 对我来说这看起来像一个自动制作文件。我认为您需要与汽车制造商讨论它。我的怀疑是 automake 正在为您处理一些可以与my_file.pb.cc 等静态字符​​串一起正常工作的东西,但不会扩展像$MY_SOURCE_FILES 这样的变量,所以它不能那样工作。 我也想过这个问题,但不确定这是否是 automake 问题。如果您手动修改生成的 makefile 并将 my_file.pb.cc 静态分配给 $MY_SOURCE_FILES,则 make 按预期工作。 是的,这就是我上面所说的“automake 正在为你处理一些事情”。也就是说,automake 可能正在查看 makefile 并对源文件做一些特殊的事情。但是由于 automake 不是 make,它要求变量中的值是显式的,而不是变量中的值。我对 automake 了解不多,无法告诉你,所以我建议你问问 automake 的人。 【参考方案1】:

目标是从许多 Protocol Buffer 文件中创建一个 C++ 库,其中一些可能位于只读目录中。

你不能把它们复制到$(top_builddir) 来解决这个问题吗?

为了绕过写权限,我想在 Makefile 目录中生成 C++ 文件。

所以这些也将在$(top_builddir) 中。

您可能应该查看给出的答案here,它设置了协议缓冲区编译器,更重要的是设置了 Makefile.am 中的规则。您可能需要根据您的情况对其进行一些修改。

所以基本上是这样的:

my_file.proto : /usr/share/project/my_file.proto
    cp $< $@

%.pb.cc %.pb.h: %.proto
    $(PROTOC) --proto_path=$(dir $^) --cpp_out=$(dir $^) $^

lib_LTLIBRARIES = lib@PACKAGE_NAME@_protobuf.la
lib@PACKAGE_NAME@_protobuf_la_SOURCES = my_file.pb.cc
lib@PACKAGE_NAME@_protobuf_la_LDFLAGS = -version-info @MAJOR_VERSION@:@MINOR_VERSION@:0

我在这里看到的唯一棘手的事情是:当调用make dist 时,tarball 中的内容是什么? 你真的要分发my_file.pb.cc吗?

【讨论】:

目标是避免手动包含 my_file.proto 和 my_file.pb.cc 的需要。 Makefile.am 可能包含许多 .proto 文件,或者文件在其生命周期中经历了多次修改。期望开发人员一直记住这种情况是不合理的。正如@MadScientist 正确指出的那样,问题与automake 无法扩展 MY_SOURCE_FILES 以建立依赖关系有关。我已经向汽车制造商提出了类似的问题,但还没有收到任何人的消息。

以上是关于协议缓冲区文件的 Makefile 自动依赖关系问题的主要内容,如果未能解决你的问题,请参考以下文章

Makefile-自动依赖

makefile(05)_自动生成依赖关系

(转)makefile中的自动依赖规则

Makefile 7——自动生成依赖关系 三颗星

Makefile学习7————自动生成依赖关系 三颗星

makefile自动生成依赖关系 可自动检测头文件变化