如何在Bazel的$(locations)中结合.format()拼接目标标签?
问题:Bazel genrule中如何结合$(locations)与字符串格式化获取目标文件路径
问题描述
我需要在Bazel的genrule的cmd中,根据传入的变量templateName组装目标标签(最终要得到//project/test:fileList),再用$(locations)获取该目标下的文件列表。直接写$(locations //project/test:fileList)一切正常,但尝试在$(locations)内部用'//project/test:{}'.format(templateName)组装标签时,抛出错误:
invalid label in $(locations) expression: invalid package name '"//project/test': package names may not contain '//' path separators
显然是变量templateName在字符串内部无法被正确解析,请问该如何正确结合$(locations)与.format()?
原代码示例
def test_genrule(templateName): native.genrule( name = "example", srcs = "//project/test:{}.format(templateName)", outs = result, cmd = ["$(execpath //project/tools:tool)"] + "$(locations '//project/test:{}'.format(templateName))", tools = ["//project/tools:tool"] )
解决方案
核心问题是你把Python的字符串格式化操作放到了Bazel的$(locations)表达式内部,导致Bazel先解析$(locations)内容,而非先执行Python的格式化逻辑。正确做法是先在Python层面组装好完整的目标标签,再传入$(locations)。
修正后的代码如下:
def test_genrule(templateName): # 先在Python层面生成完整的目标标签 target_label = "//project/test:{}".format(templateName) native.genrule( name = "example", srcs = [target_label], outs = result, cmd = "$(execpath //project/tools:tool) $(locations {})".format(target_label), tools = ["//project/tools:tool"] )
关键修正点:
- 提前用Python的
.format()生成完整目标标签,存入target_label变量 - 将
target_label作为元素传入srcs列表(原代码中src应为srcs,且需是列表类型) - 在
cmd中,把$(locations {})作为模板,用.format(target_label)填充完整标签,让Bazel最终解析到正确的$(locations //project/test:fileList)表达式
另外需注意原代码的语法错误:
src应为srcs,Bazel genrule的srcs接受列表类型- 字符串引号未闭合、
cmd行末尾缺失逗号 cmd无需用列表拼接,直接字符串格式化更简洁
内容的提问来源于stack exchange,提问作者Ventu
相关产品推荐
相关产品推荐

