gpt4 book ai didi

bazel - 如何在 Bazel 中进行配置和变体处理?

转载 作者:行者123 更新时间:2023-12-04 14:02:23 32 4
gpt4 key购买 nike

一遍又一遍地阅读 Bazel 文档,以至于没有什么新鲜的地方,但我似乎无法掌握如何为 native 以外的变体设置配置和变体,例如--cpu--compilation_mode

为了解释我对配置和变体的含义,请考虑这个包含配置行、变体点列和变体单元格的表格(制作此表格,希望它至少具有抽象意义):

<表类="s-表"><头><日> 有硬件模块X已连接接口(interface)快速失败<正文>客户配置1是以太网是客户配置2是USB是客户配置3没有USB没有调试硬件配置没有串口是

从 Bazel 用户的角度来看:

  • 默认情况下,所有目标都应该可以针对所有配置构建
    • 在添加配置时到处添加“客户配置 X”是不行的
    • 特定于配置的组件应该能够明确说明它特定于哪个配置
      • 我认为这就是 constraint_value 的用途
  • 规则应根据配置添加标志
    • 例如 -DVARIANT_POINT_CONNECTED_ETH 用于以太网连接,-DVARIANT_POINT_CONNECTED_USB 用于 USB 连接
  • 我想要一个简单的构建命令来构建/测试/运行单个配置
    • 类似bazel build//my/target --//:configuration=debughw
    • 认为它有一些东西in the skylark config docs ,但没有看到如何从示例转到在规则中使用 constraint_values 和 select()

最佳答案

您正在寻找 platforms . Build settings (你首先发现的)对于独立的配置部分更好,在这种情况下,将它们设置为任何排列都是有用的,而平台则将所有部分捆绑在一起。然后,生成的设置和约束可用于驱动编译器标志并将目标限制为特定配置。

对于你的例子,我认为这样的事情是有道理的:

constraint_setting(name = "has_x")

constraint_value(
name = "x_v1",
constraint_setting = ":has_x",
)

constraint_value(
name = "x_v2",
constraint_setting = ":has_x",
)

constraint_value(
name = "x_none",
constraint_setting = ":has_x",
)

constraint_setting(name = "interface")

constraint_value(
name = "interface_usb",
constraint_setting = ":interface",
)

constraint_value(
name = "interface_ethernet",
constraint_setting = ":interface",
)

constraint_value(
name = "interface_uart",
constraint_setting = ":interface",
)

constraint_setting(name = "failure_reporting")

constraint_value(
name = "fail_fast",
constraint_setting = ":failure_reporting",
)

constraint_value(
name = "fail_bugreport",
constraint_setting = ":failure_reporting",
)

platform(
name = "customer_1",
constraint_values = [
"@platforms//os:linux",
"@platforms//cpu:x86_64",
":x_v1",
":interface_ethernet",
":fail_fast",
],
)

platform(
name = "customer_2",
constraint_values = [
"@platforms//os:linux",
"@platforms//cpu:x86_64",
":x_v1",
":interface_usb",
":fail_fast",
],
)

platform(
name = "customer_3",
constraint_values = [
"@platforms//os:linux",
"@platforms//cpu:x86_64",
":x_none",
":interface_usb",
":fail_bugreport",
],
)

platform(
name = "debug_hw",
constraint_values = [
"@platforms//os:linux",
"@platforms//cpu:x86_64",
":x_none",
":interface_uart",
":fail_fast",
],
)

请注意每个平台如何为每个约束指定设置。给定的编译器命令(由 configured target 创建)将只使用一个平台。此外,即使输出相同,每个文件也会针对每个平台单独编译。平台旨在限制实际构建约束的哪些排列。如果要删除重复约束,platform.parents让你构建一个 inheritance tree的平台,您不能同时使用两个平台。

target_compatible_with属性将目标限制为特定的约束值。默认情况下,每个目标都被认为与所有平台兼容。如果您使用 target_compatible_with 来限制这一点,那么不兼容的目标将在您尝试显式构建它们或只是 skipped 时产生错误。如果包含在通配符中。对于您的用例,此目标将为任何平台构建:

cc_library(
name = "generic_linked_list",
<etc>
)

但是这个只会为 customer_1customer_2 构建:

cc_library(
name = "hardware_x_driver",
target_compatible_with = [":x_v1", ":x_v2"],
<etc>
)

cc_library(
name = "ethernet_driver",
# Or you could have a separate constraint for "has ethernet hardware",
# to use for some platforms which have the hardware but don't use it
# as the primary interface.
target_compatible_with = [":interface_ethernet"],
<etc>
)

为不同的平台使用不同的编译器标志、依赖项或大多数其他规则属性是通过 select 完成的。 . Select可以直接读取constraint_value。所以你可以这样写:

cc_library(
name = "selected_connection",
copts = select({
":interface_usb": [ "-DVARIANT_POINT_CONNECTED_USB" ],
":interface_ethernet": ["-DVARIANT_POINT_CONNECTED_ETH" ],
":interface_uart": ["-DVARIANT_POINT_CONNECTED_UART" ],
}),
deps = select({
":interface_ethernet": [ ":ethernet_driver" ],
"//conditions:default": [],
}),
<etc>
)

请注意,如果您希望定义传播到相关目标,请使用 cc_library.defines而不是 copts。此外,使用 cc_library.local_defines将提供相同的非继承语义,并且还与为此使用不同命令行标志的编译器兼容。

指定平台的最简单方法是使用 --platforms .在这种情况下,使用类似 --platforms=//:customer_1 的内容进行构建。您可以直接在命令行上指定它或将其放入 .bazelrc config section像这样:

build:customer_1 --platforms=//some/long/and/annoying/package:customer_1

您将与 --config=customer_1 一起使用。

关于bazel - 如何在 Bazel 中进行配置和变体处理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69580604/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com