为什么 bazel 看不到 bazelrc 中定义的包含项?

Why does bazel not see includes defined in bazelrc?

我正在将大型遗留 makefile 项目迁移到 bazel。项目用于在构建之前将所有源和 header 复制到单个“构建目录”,因此所有源和 header 文件都使用单级包含,没有任何前缀 (#include "1.hpp") .

Bazel 要求模块(库)使用 header 的相对路径,从 WORKSPACE 文件开始,但是我的目标是引入 bazel 构建文件,这需要对源代码进行 0 次修改。

我使用 bazelrc 全局设置包含的路径,就好像结构是扁平的一样: .bazelrc:

build --copt=-Ia/b/c

/a/b/BUILD

cc_library(
  name = "lib",
  srcs = ["c/1.cpp"],
  hdrs = ["c/1.hpp"],
  visibility = ["//visibility:public"]
)

当我构建这个目标时,我在编译器调用中看到我的 -I 标志,但是编译失败,因为 bazel 找不到 header 1.hpp:

$ bazel build -s //a/b:lib
...
a/b/c/1.cpp:13:10: fatal error: 1.hpp: No such file or directory
   13 | #include "1.hpp"
      |

有趣的是,它打印出它在构建过程中调用的 gcc 命令,如果我 运行 这个命令,编译器能够找到 1.hpp 和 1.cpp 编译。

如何让 bazel“看到”这包括?除了全局 -I 标志之外,我真的需要为每个目标额外指定 copts 吗?

Bazel 使用sandboxing:为每个动作(编译一个C++文件,link一个库)准备了特定的构建目录。该目录仅包含文件(使用 symlinks 和其他 Linux 魔法),对于给定目标明确定义为 dependency/source/header。

使用 --copt=-Ia/b/c 的技巧是个坏主意,因为该选项仅适用于目标,而目标取决于 //a/b:lib

改为使用 includes or strip_include_prefix 属性:

cc_library(
  name = "lib",
  srcs = ["c/1.cpp"],
  hdrs = ["c/1.hpp"],
  strip_include_prefix = "c",
  visibility = ["//visibility:public"]
)

并添加 lib 作为每个目标的依赖,需要访问这些 headers:

cc_binary(
  name = "some bin",
  srcs = ["foo.cpp"],
  deps = ["//a/b:lib"],
)