【问题标题】:How do you handle include dependencies passed as #defines in Bazel?您如何处理在 Bazel 中作为 #defines 传递的包含依赖项?
【发布时间】:2022-01-09 14:50:50
【问题描述】:

我正在尝试使用 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 来实现此目的,而无需在 bazel build--define 参数中显式传递 /path/to/software_set_a/headers/MyEnvironment.h,或者在 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'
  ],
  ...
)

【问题讨论】:

    标签: c build bazel legacy starlark


    【解决方案1】:

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

    # 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
    

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

    • config/rules_cc_toolchain_config.BUILD
    • config/BUILD.bazel

    【讨论】:

      猜你喜欢
      • 2021-02-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-12
      • 2018-07-16
      • 2018-01-03
      • 2022-01-20
      相关资源
      最近更新 更多