【问题标题】:Why does bazel not see includes defined in bazelrc?为什么 bazel 看不到 bazelrc 中定义的包含?
【发布时间】:2021-05-01 15:58:49
【问题描述】:

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

Bazel 要求模块(库)使用从 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 找不到头文件 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 吗?

【问题讨论】:

    标签: c++ bazel


    【解决方案1】:

    Bazel 使用sandboxing:为每个操作(编译 C++ 文件、链接库)准备特定的构建目录。该目录仅包含文件(使用符号链接和其他 Linux 巫术),这些文件被明确定义为给定目标的依赖项/源/头。

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

    改用includesstrip_include_prefix 属性:

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

    并将lib 添加为每个需要访问这些标头的目标的依赖项:

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

    【讨论】:

    • Afaik includes 添加了 -isystem 标志,这使得编译器将所有包含视为系统(这些不会产生警告)。我更喜欢使用 -I 包含标志。
    • 但我认为你是对的,除了使用 strip_include_prefix 之外,没有办法实现我想要的。谢谢!
    猜你喜欢
    • 2021-04-29
    • 2022-11-19
    • 2019-09-16
    • 1970-01-01
    • 1970-01-01
    • 2014-10-02
    • 1970-01-01
    • 1970-01-01
    • 2018-07-31
    相关资源
    最近更新 更多