0

我正在尝试使用 Bazel 构建遗留​​的 C/C++ 嵌入式代码库。代码被分成软件集。因为系统是嵌入式的,所以有一个环境头包含作为参数传递给每个软件集的编译器。标头路径使用#define 定义:

software_set_b 的源文件可能以:

#include MY_ENV

编译指令会将 MY_ENV 定义为 software_set_a 中环境头的绝对路径,例如:

gcc -DMY_ENV=/path/to/software_set_a/headers/MyEnvironmentHeader.h

是否可以使用 Bazel 来实现这一点,而无需显式传入/path/to/software_set_a/headers/MyEnvironment.h参数--definebazel build或硬编码 software_set_b 的 BUILD 文件中的值,例如:

cc_library(
  name = 'software_set_b',
  defines = [
    'MY_ENV=/path/to/software_set_a/headers/MyEnvironment.h'
  ],
  ...
)

理想情况下,程序员可以选择带有参数的包,例如bazel build //:software_set_b --//:from_env=software_set_a在 BUILD 脚本中使用类似于以下内容的片段:

File: software_set_b/BUILD

string_flag(
  name = 'from_env',
  build_setting_default = ''
)

def deps_from_env():
  from_env = get_flag_value('from_env') # A function that gets the value of the flag.
  return '@' + from_env + '//:env' # Evaluate to e.g. '@software_set_a//:env'

cc_library(
  name = 'software_set_b',
  deps = [
    deps_from_env()
  ]
)

File: software_set_a/BUILD

cc_library(
  name = 'env',
  defines = [
    # Something to give me '/path/to/software_set_a/headers/MyEnvironment.h'
    'MY_ENV=$(rootpath)/headers/MyEnvironment.h'
  ],
  ...
)
4

1 回答 1

0

这相对简单,例如在software_set_a 和software_set_b 下创建一个环境目标。

# File: //software_set_a:BUILD
cc_library(
  name = 'env',
  defines = [
    'MY_ENV=$(rootpath)/headers/MyEnvironment.h'
  ],
)

cc_library(
  name = 'software_set_a',
  deps = [
    # Top level switchable target. NOTE: This is NOT ":env".
    "//:from_env",
  ]
)
# File: //software_set_b:BUILD
cc_library(
  name = 'env',
  defines = [
    'MY_ENV=$(rootpath)/headers/MyEnvironment.h'
  ],
)

cc_library(
  name = 'software_set_b',
  deps = [
      # Top level switchable target. NOTE: This is NOT ":env".
      "//:from_env",
  ]
)

现在当然这本身是行不通的。所以我们需要创建一个可切换的顶级env目标。

# //:BUILD
label_flag(
   name = "from_env",
   build_setting_default = "//software_set_b:env",
)

现在默认情况下,环境定义将从软件集 b 中提取。但可以用命令覆盖。

bazel build //:software_set_b --//:from_env=software_set_a:env

请注意,您可以通过简单地创建 acc_library(name="empty")并将 default_build_setting 指向它来获得一个空的默认值。constraint_setting此外,您可能会发现/ constraint_value/ platform/周围的配置select模式对您来说是一种更有用的模式,而不是基于标志的方法。另请注意,您可以通过将标签标志指向可选的多路复用器目标来组合两者。更高级的示例可以在文件下的bazelembedded/rules_cc_toolchain中找到;

  • 配置/rules_cc_toolchain_config.BUILD
  • config/BUILD.bazel
于 2022-02-17T09:04:35.600 回答