使用Bazel构建具有不同编译器/链接器选项的C/C++依赖关系

Building C/C++ Dependencies with Different Compiler/Linker options with Bazel

本文关键字:选项 C++ 关系 依赖 链接 使用 构建 编译器 Bazel      更新时间:2023-10-16

因此,我正在修改一个项目,使其使用clang++和消毒程序(用于模糊处理)构建,而不是仅使用g++。它使用集市建造。

该项目目前下载了一些构建依赖项(m4/bison/flex),并使用中的make_configure规则构建这些依赖项https://github.com/bazelbuild/rules_foreign_cc.重要的是,这些只是用于代码生成,而不是针对它们进行链接/编译。

不幸的是,这些依赖关系恰好存在各种消毒剂问题。这意味着,如果我们使用--copt="-fsanitize=address"进行构建,那么我们就不能使用它们来生成代码,构建就会失败!现在,如果我们遇到关联依赖关系的敏感问题,这将是不可避免的,我们需要与维护人员合作来解决,但现在我们真的更愿意解决这些问题,因为它们不会直接影响我们正在编译的实际目标的安全性和可靠性。

有没有一种简单的方法可以或多或少地为规则指定"请忽略命令行上传递的编译器标志/链接器选项等,只针对此目标,而使用其他集合"?在大多数情况下,通过命令行(或全局配置)传递的linkopts/cpts/cxopts似乎是可添加的,我们希望避免这种情况。如果没有,解决这个问题的最佳方法是什么?在包装实际构建规则的自定义规则中保存/取消设置/重置所有变量?

谢谢,Everett

所以,我终于找到了答案。

有几种方法可能会在这里起作用。一个是自定义SkyLark规则,它覆盖了命令行提供的工具。与其他命令行选项相比,这确实具有更"经得起未来考验"的潜在优势,这些选项可能无法很好地与传递给编译器/链接器的某些选项配合使用。

然而,最终更容易的是了解到这样一个事实,即gcc/clang编译器家族有一个有趣的行为,可以很好地与bazel配合使用——如果您指定了"冲突"的命令行参数,那么似乎总是采用后面的参数。因此,我们所要做的就是确保"-fno sanitize=address"被传递到我们想要关闭ASAN的目标的构建规则中,同时我们将"-fsanitize=address"传递到全局构建中。

希望这能帮助其他陷入这种问题的人。--Everett

"正确的方法"是定义自己的工具链,并在其中添加一个功能,例如:

asan_feature = feature(
name = "address_sanitizer",
enabled = True,
flag_set(
actions = all_compile_actions + all_link_actions,
flag_groups = [
flag_group(flags = ["-fsanitize=address"]),
],
),
],
)

features一起传递给create_cc_toolchain_config_info()

您可以默认或不为任何给定的工具链设置此功能enabled,并且您可以控制CLI上构建范围内使用的功能、每个包和每个目标(例如cc_binary):

cc_binary(
...
features = ["-address_sanitizer"],
)

明显的缺点是,这涉及到一些初步工作。

好处是,编译器配置/行为实际上(应该)是工具链配置的一个函数,而不是每个目标都可以摆弄的东西。您可以得到一个抽象结构,它独立于任何给定工具链下的特定编译器。