Bazel - 在 cc_library 上使用 -I 而不是 -isystem 或 -iquote 生成 gcc 命令时,hdrs 与 includes 之间的关系是什么?

Bazel - What is the relation between hdrs vs includes on a cc_library to generate gcc command with -I instead of -isystem or -iquote?

看起来使用 hdrsBUILD 文件上创建 cc_library 和使用 includes 生成 gcc 命令之间存在关系 -isystem-iquote-I.

Official Bazel doc

为了更好地解释我的问题,我有这个例子。

我有一个包含以下文件的 Bazel 项目:

依赖项是:

  1. main.cpp 需要 foo.hpp
  2. foo.hpp 需要访问 #include "bar.h",因此提供了库 hdrs-bar
  3. bar.h 需要访问 #include <system_bar.h>,因此提供了库 hdrs-system-bar。 (请注意,包含 <> 是必需的。)
  4. 创建了一个名为 demo 的二进制文件,其中包含所有这些依赖项

如 (1) 所述,main.cpp 包含:

#include "foo.hpp"

int main()
{
    // ...something which uses foo.hpp
    return 0;
}

如 (2) 所述,为了能够从 main.cpp 访问 foo.hpp,我需要从 git 存储库创建一个 Bazel 项目并创建一个 BUILD 文件为它使用 build_file_content ,它包含一个库,它将公开我需要的所有 *.h 文件(包括 bar.h)。

因此 WORKSPACE 文件包含:

load("@bazel_tools//tools/build_defs/repo:git.bzl", "new_git_repository")

new_git_repository(
    name = "bar-utils",
    remote = "https://github.com/someGitRepo/bar-utils.git",
    branch = "master",
    build_file_content = """

       package(default_visibility = ["//visibility:public"])
       cc_library(
           name = "hdrs-bar",
           hdrs = glob(["bar/*.h"], allow_empty=False),
           strip_include_prefix = "bar",
      )

""",
)

如 (3) 所述,WORKSPACE 文件还包含一个名为 hdrs-system-bar 的库的创建,其中包含 bar.h:

所需的系统头文件
new_local_repository(
    name = "bar-system",
    path = "/usr/local/bar/include",
    build_file_content = """
        cc_library(
          name = "hdrs-system-bar",
          hdrs = glob(["*.h"], allow_empty=False),
          visibility = ["//visibility:public"],
        )    
""",    
)

如(4)中所述,BUILD文件包含一个二进制文件,该二进制文件获取deps中的所有依赖项:

cc_binary(
    name = "demo",
    srcs = ["main.cpp"],
    deps = ["@bar-utils//:hdrs-bar", "@bar-system//:hdrs-system-bar"],
)

如果我编译:

$ bazel build //... --sandbox_debug

我得到以下版本 错误:

bazel-out/aarch64-fastbuild/bin/external/bar-utils/_virtual_includes/hdrs-bar/barUtils.h:7:10: fatal error: bar_runtime.h: No such file or directory #include <bar_runtime.h>

文件 bar_runtime.h 应该在库 hdrs-system-bar 中。 因此,如果我在 .../sandbox/linux-sandbox/4/execroot/__main__/ 上看到我的沙箱文件夹,我会得到以下目录:

external上,我有这两个文件夹,其中每个文件夹都包含我需要的所有头文件:

bazel-out 上,我有以下内容:

aarch64-fastbuild/bin/external/bar-utils/_virtual_includes/hdrs-bar/bar.h

我原以为 bazel-out external 里面还有 bar-system,但只有 bar-utils。这是为什么?

要添加更多信息,生成的 gcc 命令如下所示(为简单起见删除了所有不必要的参数):

/usr/bin/gcc -iquote external/bar-utils -iquote external/bar-system -c main.cpp 

如果我在创建所有库时只使用 include 而不是 hdrs,我会得到很多 -isystem 而不是 -iquote。但我需要的实际上是 -I<folder where the headers are>.

如果我手动将 gcc 命令更改为:

/usr/bin/gcc -iquote external/bar-utils -Iexternal/bar-system -c main.cpp 

然后就可以了。

如何强制它使用 -I?将 cc_libraries 更改为 srcsincludes 而不是 hdrs 无效。

解决方案是除了 hdrs 之外还使用 include 标志。这样它将显示在沙箱中,并且可以通过为 gcc 添加 -isystem 参数和您需要的文件夹来访问。

    cc_library(
      name = "hdrs-system-bar",
      hdrs = glob(["*.h"], allow_empty=False),
      include = ["."],
      visibility = ["//visibility:public"],
    )