如何在Bazel规则中提取命令行--platform参数详情传给Python程序
在Bazel中提取--platform参数并传递给Python程序
要从命令行的--platform参数中提取设备类型(如stm32f405ig)并传递给Python程序,你可以通过以下两种方式实现:
方法一:直接从平台标签提取名称
Bazel的规则上下文(ctx)可以获取当前指定的平台目标,通过其Label对象提取名称作为设备类型,再传递给Python脚本。
1. 定义自定义包装规则
在你的Bazel规则文件(如//:rules.bzl)中编写自定义规则,用于包装Python二进制目标并注入设备类型参数:
load("@rules_python//python:defs.bzl", "py_binary") def _py_with_device_impl(ctx): # 获取当前平台的Label对象,提取名称作为设备类型 platform_label = ctx.configuration.host_platform device_type = platform_label.name # 生成包装脚本,将设备类型作为参数传递给Python程序 wrapper = ctx.actions.declare_file(ctx.label.name) ctx.actions.run_shell( inputs = [ctx.attr.py_bin.executable], outputs = [wrapper], command = """ #!/bin/bash {py_exec} --device-type={device} "$@" """.format( py_exec = ctx.attr.py_bin.executable.path, device = device_type, ), ) ctx.actions.run_shell( inputs = [wrapper], command = "chmod +x {wrapper}".format(wrapper = wrapper.path), ) return DefaultInfo( executable = wrapper, runfiles = ctx.attr.py_bin.default_runfiles, ) py_with_device = rule( implementation = _py_with_device_impl, attrs = { "py_bin": attr.label( executable = True, cfg = "target", providers = [DefaultInfo], ), }, executable = True, )
2. 在BUILD文件中使用规则
load("//:rules.bzl", "py_with_device") # 原始Python二进制目标 py_binary( name = "my_script", srcs = ["my_script.py"], ) # 包装后的目标,会自动注入设备类型参数 py_with_device( name = "target", py_bin = ":my_script", )
3. Python脚本接收参数
在my_script.py中用argparse读取传递的设备类型:
import argparse parser = argparse.ArgumentParser() parser.add_argument("--device-type", required=True) args = parser.parse_args() print(f"当前设备类型: {args.device_type}")
执行命令
运行以下命令即可自动传递设备类型:
bazel run //target --platform=//platform:stm32f405ig
方法二:通过平台自定义设置传递(更灵活)
如果需要设备类型与平台名称解耦,可以在平台目标中定义自定义设置,再在规则中读取该值。
1. 定义设备类型设置规则
在//platform:defs.bzl中定义自定义provider:
DeviceInfo = provider( fields = ["device_type"], ) def _device_setting_impl(ctx): return DeviceInfo(device_type = ctx.attr.value) device_setting = rule( implementation = _device_setting_impl, attrs = {"value": attr.string()}, )
2. 关联平台与设备类型
在//platform:stm32f405ig/BUILD中定义平台和对应的设备设置:
load("//platform:defs.bzl", "device_setting") device_setting( name = "stm32f405ig_device", value = "stm32f405ig", # 可自定义任意值 ) platform( name = "stm32f405ig", settings = [":stm32f405ig_device"], )
3. 读取设置并传递给Python
修改自定义规则以读取平台中的DeviceInfo:
load("@rules_python//python:defs.bzl", "py_binary") load("//platform:defs.bzl", "DeviceInfo") def _py_with_device_impl(ctx): # 从平台设置中获取设备类型 device_type = ctx.attr._device_setting[DeviceInfo].device_type py_target = ctx.attr.py_bin # 注入参数 new_args = py_target.args + ["--device-type=" + device_type] return DefaultInfo( executable = py_target.executable, runfiles = py_target.default_runfiles, arguments = new_args, ) py_with_device = rule( implementation = _py_with_device_impl, attrs = { "py_bin": attr.label( executable = True, cfg = "target", providers = [DefaultInfo], ), "_device_setting": attr.label( cfg = "target", ), }, executable = True, )
4. 使用规则
在BUILD文件中指定对应的设备设置:
py_with_device( name = "target", py_bin = ":my_script", _device_setting = "//platform:stm32f405ig_device", )
这样即使平台名称变化,也能通过修改device_setting的value来保持设备类型的正确性。
内容的提问来源于stack exchange,提问作者Hema
相关产品推荐
相关产品推荐

