在 BAZEL 中,有没有办法防止依赖 C/C++ 头文件传播到依赖库?

log*_*cor 5 c c++ bazel

例如: lib_a是一个内部库。它公开接口标头alpha.h

lib_b是一个 API 库。它包括alpha.hbeta.c并暴露接口头beta.h不包括alpha.h

exe_c是一个测试应用程序,利用lib_b. 由于它是 API 库的“外部” lib_b,它不应该访问内部库lib_a的头文件,即alpha.h.

现在,有没有办法防止将 的包含路径alpha.h添加到exe_c的编译命令行?

rni*_*ckb 4

22 年 5 月 24 日更新:Bazel 添加了implementation_deps功能。

这可以通过自定义规则和宏来实现。

这是编写宏的方法,my_cc_library以便您可以执行类似的操作

my_cc_library(
    name = "b",
    hdrs = [
        "b.h",
    ],
    srcs = [
        "b.cc",
    ]
    impl_deps = [
        "//a:a",
    ],
)
Run Code Online (Sandbox Code Playgroud)

并且依赖的目标b将无法包含依赖项中的标头a

步骤1

添加一个自定义规则,该规则采用基础库并形成一个新的CcInfo提供程序,其中仅包含您要公开的标头。

def _my_cc_slim_library(ctx):
  cc_info = ctx.attr.base_library[CcInfo]
  compilation_ctx = cc_info.compilation_context

  compilation_ctx_p = cc_common.create_compilation_context(
      headers = depset(direct=ctx.files.hdrs),
      includes = compilation_ctx.includes,
      quote_includes = compilation_ctx.quote_includes,
  )

  dep_cc_infos = [dep[CcInfo] for dep in ctx.attr.deps]

  cc_info_p = cc_common.merge_cc_infos(
      cc_infos = [
          CcInfo(
              compilation_context = compilation_ctx_p,
              linking_context = cc_info.linking_context,
          )
      ] + dep_cc_infos,
  )
  
  return [cc_info_p]

my_cc_slim_library = rule(
    implementation = _my_cc_slim_library,
    attrs = {
        "base_library": attr.label(mandatory=True, providers = [CcInfo]),
        "hdrs": attr.label_list(allow_files=True),
        "deps": attr.label_list(providers = [CcInfo]),
    },
)
Run Code Online (Sandbox Code Playgroud)

第2步

添加自定义宏my_cc_library。该宏将创建一个基础库,然后使用该规则my_cc_slim_library去除不需要的标头依赖项。

def my_cc_library(
    name,
    hdrs = [],
    deps = [],
    impl_deps = [],
    **kwargs):
  native.cc_library(
      name = name + "-base",
      hdrs = hdrs,
      deps = deps + impl_deps,
      **kwargs)
  my_cc_slim_library(
      name = name,
      hdrs = hdrs,
      base_library = name + "-base",
      deps = deps,
  )
Run Code Online (Sandbox Code Playgroud)

例子

现在介绍如何在示例中使用它。

bazel/my_cc_library.bzl<- 包含自定义规则和宏

a/a.h

int do_a();
Run Code Online (Sandbox Code Playgroud)

a/a.cc

#include "a/a.h"

int do_a() {
  return 1;
}
Run Code Online (Sandbox Code Playgroud)

a/BUILD

package(default_visibility = ["//visibility:public"])

cc_library(
    name = "a",
    hdrs = [
        "a.h",
    ],
    srcs = [
        "a.cc",
    ],
)
Run Code Online (Sandbox Code Playgroud)

b/b.h

int do_b();
Run Code Online (Sandbox Code Playgroud)

b/b.cc

#include "a/a.h"

int do_b() {
  return do_a() + 2;
}
Run Code Online (Sandbox Code Playgroud)

b/BUILD

load(
    "//bazel:my_cc_library.bzl",
    "my_cc_library",
)

package(default_visibility = ["//visibility:public"])

my_cc_library(
    name = "b",
    hdrs = [
        "b.h",
    ],
    srcs = [
        "b.cc",
    ],
    impl_deps = [
        "//a:a",
    ],
)
Run Code Online (Sandbox Code Playgroud)

main.cc

#include <iostream>

// #include "a/a.h"   <- this would cause an error
#include "b/b.h"

int main() {
  std::cout << do_b() << std::endl;
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

BUILD

cc_binary(
    name = "exe",
    srcs = [
        "main.cc",
    ],
    deps = [
        "//b:b",
    ],
)
Run Code Online (Sandbox Code Playgroud)

  • 这是一个很大的努力,但我现在知道这是如何工作的,因为我对“bazel”的了解比我问问题时要多得多。感谢您发布答案。 (2认同)