我不明白为什么他们没有通过 cc_binary 构建规则在编译器命令行上为每个编译的文件提供使用 -include 的方法。毕竟他们已经定义了 = []。
一般来说,bazel 并没有提供很多这样的机制,因为它可能会导致大型存储库中出现扩展问题。例如。说 project1 和 project2 依赖于 1000 个 cc_library 目标的同一棵树。将它们一起构建会导致构建 1000 个 cc_library 目标。但是如果 cc_binary 有办法改变其依赖项的编译方式,并且 project2 做了类似的事情,那么现在一起构建两个项目需要构建 2000 个 cc_library 目标,这会增加一倍内存需求、远程缓存需求、远程执行需求,增加分析时间。
对于defines 属性,它会影响依赖于defines 目标的事物,但不会影响该目标的依赖关系(它会“向上”构建图,而不是“向下”,如果cc_binary 位于顶部)。
也就是说,有一些方法可以改变目标的依赖关系的编译方式,这些被称为“配置转换”。 (例如 android_binary 使用一个在单个应用程序中编译多个 cpu 架构,但从 [x86] 到 [x86, arm64] 〜双倍如上)。不过,配置转换很少涉及。
在命令行上有更简单的选项,例如--copt,它们会影响整个构建,这可能会起作用。下面的示例可能会满足您的需要。它依赖于被“#ifndef”包围的宏。如果没有#ifndef,它似乎不起作用,一些粗略的搜索说源代码中的宏无法在命令行上替换(我自己不是 c/c++ 专家)。如果重写宏确实需要它位于源文件中,这很棘手,因为没有直接的方法可以将文件添加到每个 cc 操作(或某个子集)的输入中。如果它确实有效,您可以将build --copt=... 添加到工作区根目录下的.bazelrc 文件中,这样您就不必将其添加到命令行。否则,我能想到的唯一其他事情就是自定义工具链,正如其他人提到的那样。
repo1$ bazel run foo
INFO: Analyzed target //:foo (1 packages loaded, 160 targets configured).
INFO: Found 1 target...
Target //:foo up-to-date:
bazel-bin/foo
INFO: Elapsed time: 0.318s, Critical Path: 0.09s
INFO: 5 processes: 1 internal, 4 linux-sandbox.
INFO: Build completed successfully, 5 total actions
INFO: Build completed successfully, 5 total actions
bar is 16
repo1$ bazel run foo --copt=-DBAZ=15
INFO: Build option --copt has changed, discarding analysis cache.
INFO: Analyzed target //:foo (0 packages loaded, 160 targets configured).
INFO: Found 1 target...
Target //:foo up-to-date:
bazel-bin/foo
INFO: Elapsed time: 0.252s, Critical Path: 0.09s
INFO: 5 processes: 1 internal, 4 linux-sandbox.
INFO: Build completed successfully, 5 total actions
INFO: Build completed successfully, 5 total actions
bar is 38
repo1/BUILD:
cc_binary(
name = "foo",
srcs = ["foo.c", "foo.h"],
deps = ["@repo2//:bar"],
)
repo1/WORKSPACE:
local_repository(
name = "repo2",
path = "../repo2",
)
repo1/foo.c:
#include "foo.h"
#include "bar.h"
#include "stdio.h"
int main() {
printf("bar is %d\n", bar());
return 0;
}
repo1/foo.h:
repo2/BUILD:
cc_library(
name = "bar",
srcs = ["bar.c"],
hdrs = ["bar.h"],
deps = [":baz"],
visibility = ["//visibility:public"],
)
cc_library(
name = "baz",
srcs = ["baz.c"],
hdrs = ["baz.h"],
visibility = ["//visibility:public"],
)
repo2/WORKSPACE:
repo2/bar.c:
#include "bar.h"
#include "baz.h"
int bar() {
return baz() + BAR;
}
repo2/bar.h:
#define BAR 8
int bar();
repo2/baz.c:
#include "baz.h"
int baz() {
return BAZ * 2;
}
repo2/baz.h:
#ifndef BAZ
#define BAZ 4
#endif
int baz();