已为父项目和子项目导出 shell 个脚本
Exported shell scripts for parent & child projects
我的场景是 "Parent" Bazel 项目,其中包含一些 shell 脚本和宏。此项目必须由 "Child" 项目重复使用。重现问题的最小 "working" 示例定义如下:
目录结构
├── Child
│ ├── BUILD
│ └── WORKSPACE
└── Parent
├── a_command.bzl
├── a_script.sh
├── BUILD
└── WORKSPACE
父项目文件
Parent/a_script.sh
#!/bin/bash
date
Parent/a_command.bzl
def a_command(name):
native.genrule(
name = name,
srcs = [],
outs = [name+".txt"],
cmd = "$(location :a_script_sh) > $@",
tools = [":a_script_sh"],
)
Parent/BUILD
sh_binary(
name = "a_script_sh",
srcs = ["a_script.sh"],
visibility = ["//visibility:public"],
)
Parent/WORKSPACE
# empty file
子项目文件
Child/WORKSPACE
local_repository(
name = "Parent",
path = "../Parent/",
)
Child/BUILD
load("@Parent//:a_command.bzl","a_command")
# Uncomment me for a working solution
# alias(name="a_script_sh",actual="@Parent//:a_script_sh")
a_command("use_script")
现在我的问题
如果我输入 子项目目录
bazel build //...
我明白了
INFO: Found 1 target...
ERROR: missing input file '//:a_script_sh'.
ERROR: PATH/Child/BUILD:5:1: //:use_script: missing input file '//:a_script_sh'.
Target //:use_script failed to build
Use --verbose_failures to see the command lines of failed build steps.
ERROR: PATH/Child/BUILD:5:1 1 input file(s) do not exist.
INFO: Elapsed time: 0.162s, Critical Path: 0.00s
现在,如果我取消注释行
alias(name="a_script_sh",actual="@Parent//:a_script_sh")
在Child/BUILD文件中,一切正常:
INFO: Found 2 targets...
INFO: Elapsed time: 0.191s, Critical Path: 0.03s
并且文件use_script.txt正确生成到Child/bazel-genfiles目录中。
我的问题是:
是否使用
alias(name="a_script_sh",actual="@Parent//:a_script_sh")
是正确的做事方式吗?
我原以为 Bazel 工作会解决此依赖关系。
我没想到 必须明确地重新定义 a_script.sh 文件所在的位置。我认为这是笨拙、多余且容易出错的。
我怀疑我做事的方式不正确,如果有人能清楚地向我们解释如何正确地做这件事,我将非常感谢。
首先,感谢您提供清晰彻底的重现说明!
你发现了一个非常有趣的场景!然而一切都按预期工作。
a_command
in Parent/a_command.bzl
用 tools=[":a_script_sh"]
包装一个类。这是一个相对标签,相对于当前包,其中 "current" 是使用宏的包,而不是声明它的地方。因此,Child 的 BUILD 文件必须声明一个 "a_script_sh" 目标(具有此名称的任何目标)并且该示例将起作用。
这种行为在 glob
的情况下更有意义:如果 Skylark 宏用 srcs=glob([**])
包装规则,宏应该从当前包中获取文件(使用宏的地方) ), 而不是外来的(声明宏的地方)。
除了将文件组添加到 child/BUILD 之外,我还稍微修改了 genrule 以打印 "a_script_sh" 的路径而不是执行它:
parent/a_command.bzl
:
def a_command(name):
native.genrule(
name = name,
srcs = [],
outs = [name+".txt"],
cmd = "echo $(location :a_script_sh) > $@", # modified
tools = [":a_script_sh"],
)
child/BUILD
:
load("@Parent//:a_command.bzl","a_command")
# Uncomment me for a working solution
# alias(name="a_script_sh",actual="@Parent//:a_script_sh")
a_command("use_script")
filegroup(name = 'a_script_sh', srcs = ['BUILD']) # added
我找不到任何方法来确保宏始终使用父包的 //:a_script_sh
目标。宏不应在标签前加上存储库名称(例如 "@Parent//:a_script_sh"
),因为无法保证此存储库将绑定为 "Parent".
我发现解决此问题的唯一方法是像这样注入 tools
依赖项:
parent/a_command.bzl
:
def a_command(name, tools):
native.genrule(
name = name,
srcs = [],
outs = [name+".txt"],
cmd = "echo $(location %s) > $@" % tools['a_script_sh'],
tools = [tools['a_script_sh']],
)
child/BUILD
:
load("@Parent//:a_command.bzl","a_command")
a_command(
"use_script",
tools = {"a_script_sh": "@Parent//:a_script_sh"},
)
我的场景是 "Parent" Bazel 项目,其中包含一些 shell 脚本和宏。此项目必须由 "Child" 项目重复使用。重现问题的最小 "working" 示例定义如下:
目录结构
├── Child
│ ├── BUILD
│ └── WORKSPACE
└── Parent
├── a_command.bzl
├── a_script.sh
├── BUILD
└── WORKSPACE
父项目文件
Parent/a_script.sh
#!/bin/bash
date
Parent/a_command.bzl
def a_command(name):
native.genrule(
name = name,
srcs = [],
outs = [name+".txt"],
cmd = "$(location :a_script_sh) > $@",
tools = [":a_script_sh"],
)
Parent/BUILD
sh_binary(
name = "a_script_sh",
srcs = ["a_script.sh"],
visibility = ["//visibility:public"],
)
Parent/WORKSPACE
# empty file
子项目文件
Child/WORKSPACE
local_repository(
name = "Parent",
path = "../Parent/",
)
Child/BUILD
load("@Parent//:a_command.bzl","a_command")
# Uncomment me for a working solution
# alias(name="a_script_sh",actual="@Parent//:a_script_sh")
a_command("use_script")
现在我的问题
如果我输入 子项目目录
bazel build //...
我明白了
INFO: Found 1 target...
ERROR: missing input file '//:a_script_sh'.
ERROR: PATH/Child/BUILD:5:1: //:use_script: missing input file '//:a_script_sh'.
Target //:use_script failed to build
Use --verbose_failures to see the command lines of failed build steps.
ERROR: PATH/Child/BUILD:5:1 1 input file(s) do not exist.
INFO: Elapsed time: 0.162s, Critical Path: 0.00s
现在,如果我取消注释行
alias(name="a_script_sh",actual="@Parent//:a_script_sh")
在Child/BUILD文件中,一切正常:
INFO: Found 2 targets...
INFO: Elapsed time: 0.191s, Critical Path: 0.03s
并且文件use_script.txt正确生成到Child/bazel-genfiles目录中。
我的问题是:
是否使用
alias(name="a_script_sh",actual="@Parent//:a_script_sh")
是正确的做事方式吗?
我原以为 Bazel 工作会解决此依赖关系。
我没想到 必须明确地重新定义 a_script.sh 文件所在的位置。我认为这是笨拙、多余且容易出错的。
我怀疑我做事的方式不正确,如果有人能清楚地向我们解释如何正确地做这件事,我将非常感谢。
首先,感谢您提供清晰彻底的重现说明!
你发现了一个非常有趣的场景!然而一切都按预期工作。
a_command
in Parent/a_command.bzl
用 tools=[":a_script_sh"]
包装一个类。这是一个相对标签,相对于当前包,其中 "current" 是使用宏的包,而不是声明它的地方。因此,Child 的 BUILD 文件必须声明一个 "a_script_sh" 目标(具有此名称的任何目标)并且该示例将起作用。
这种行为在 glob
的情况下更有意义:如果 Skylark 宏用 srcs=glob([**])
包装规则,宏应该从当前包中获取文件(使用宏的地方) ), 而不是外来的(声明宏的地方)。
除了将文件组添加到 child/BUILD 之外,我还稍微修改了 genrule 以打印 "a_script_sh" 的路径而不是执行它:
parent/a_command.bzl
:
def a_command(name):
native.genrule(
name = name,
srcs = [],
outs = [name+".txt"],
cmd = "echo $(location :a_script_sh) > $@", # modified
tools = [":a_script_sh"],
)
child/BUILD
:
load("@Parent//:a_command.bzl","a_command")
# Uncomment me for a working solution
# alias(name="a_script_sh",actual="@Parent//:a_script_sh")
a_command("use_script")
filegroup(name = 'a_script_sh', srcs = ['BUILD']) # added
我找不到任何方法来确保宏始终使用父包的 //:a_script_sh
目标。宏不应在标签前加上存储库名称(例如 "@Parent//:a_script_sh"
),因为无法保证此存储库将绑定为 "Parent".
我发现解决此问题的唯一方法是像这样注入 tools
依赖项:
parent/a_command.bzl
:
def a_command(name, tools):
native.genrule(
name = name,
srcs = [],
outs = [name+".txt"],
cmd = "echo $(location %s) > $@" % tools['a_script_sh'],
tools = [tools['a_script_sh']],
)
child/BUILD
:
load("@Parent//:a_command.bzl","a_command")
a_command(
"use_script",
tools = {"a_script_sh": "@Parent//:a_script_sh"},
)