Bazel在宏中组合多个规则
我的项目结构中有多个子模块,这些基本上是文件夹,它们本身也是项目 对于给定的python项目,每个项目都有子项目。我希望能够编写一个宏,可以创建一组对给定子项目采取的操作 基本上,在工作区内,有以下内容:Bazel在宏中组合多个规则,bazel,Bazel,我的项目结构中有多个子模块,这些基本上是文件夹,它们本身也是项目 对于给定的python项目,每个项目都有子项目。我希望能够编写一个宏,可以创建一组对给定子项目采取的操作 基本上,在工作区内,有以下内容: load("@io_bazel_rules_python//:python/pip.bzl", "pip_import" ) pip_import( name = "foo", requirements = "@subprojectname//:requirements.t
load("@io_bazel_rules_python//:python/pip.bzl",
"pip_import"
)
pip_import(
name = "foo",
requirements = "@subprojectname//:requirements.txt",
)
load("@foo//:requirements.bzl", "pip_install")
pip_install()
我想为多个子项目执行上述操作。但是,如果我将所有代码放入bzl文件中的函数中
pyrules.bzl
load("@io_bazel_rules_python//:python/pip.bzl",
"pip_import"
)
def doit(name):
pip_import(
name = "foo",
requirements = "@{repo}//:requirements.txt".format(repo=name)
)
load("@foo//:requirements.bzl", "pip_install")
pip_install()
我无法使用第二个load命令,因为“load处的语法错误:预期表达式”。如果没有将多个bzl文件加载到父工作区中,是否还有其他方法来创建可重用的逻辑块
更新1。
评论要求提供有关工作流的更多信息。警告,对于Bazel在其他地方的使用方式,我有一个非标准布局,即不是monorepo。但它应该有一个类似的实际布局
项目安排如下:
projectname/
WORKSPACE
BUILD
src/
stuff
submodule/ # < git modules that are checked out into folder
subproject1/
BUILD
src/
stuff
subproject2/
BUILD
src/
stuff
projectname/
工作空间
建造
src/
东西
子模块/#<签出到文件夹中的git模块
次级项目1/
建造
src/
东西
次级项目2/
建造
src/
东西
首先,我在工作区中加载了一个repository_规则,该规则查找子模块文件夹中的所有项目,并将它们添加为存储库。在子项目中,其中一些是python。我想加载它的requirements.txt文件。因此,总的问题是这些requirements.txt文件在哪里,并在其上进行pip安装。理想情况下,我希望子项目构建文件中的py_库定义知道子项目的需求文件存在依赖关系,但这可能并不重要,因为父构建文件是创建par_二进制文件等的唯一对象,因此只要pip_安装并设置依赖关系,项目本身应该是可用的
Bazel似乎不允许子项目像上面的pip_安装那样定义自己的存储库操作。我认为这是因为在构建文件中不能有存储库操作,并且子工作区文件似乎没有任何效果。因此,我不得不将其添加到父工作区文件中
如果它在父工作区中,我必须为我想要使用的每个子项目复制粘贴pip操作。然而,我更愿意只建立一个通用规则,它将定位需求文件并pip安装它们。但是,试图从中生成宏意味着我无法在其中使用load调用。所有pip操作似乎都需要与存储库操作交互,然后只需要从父工作区文件调用存储库操作 对于这种情况,似乎不存在任何合理的解决方案。然而,我认为重要的是要认识到,如果你愿意在内部支持,你所依赖的规则是可以修改的。我最终修改了rules_python存储库中的piptool.py,以便在一次调用中添加对多个requirements.txt文件的支持。然后将以下规则添加到我自己的内部使用的规则存储库中
#
# Python
#
def _pip_import_requirements_impl(repository_ctx):
"""Core implementation of pip_import."""
# Add an empty top-level BUILD file.
# This is because Bazel requires BUILD files along all paths accessed
# via //this/sort/of:path and we wouldn't be able to load our generated
# requirements.bzl without it.
repository_ctx.file("BUILD", "")
# To see the output, pass: quiet=False
result = repository_ctx.execute([
"python3", repository_ctx.path(repository_ctx.attr._script),
"--name", repository_ctx.attr.name,
"--input"
] +
[repository_ctx.path(r) for r in repository_ctx.attr.requirements] +
[
"--output", repository_ctx.path("requirements.bzl"),
"--directory", repository_ctx.path("")
],
quiet = repository_ctx.attr.quiet)
if result.return_code:
fail("pip_import failed: %s (%s)" % (result.stdout, result.stderr))
pip_import_requirements = repository_rule(
attrs = {
"quiet" : attr.bool(default = False),
"requirements": attr.label_list(
allow_files = True,
mandatory = True,
),
"_script": attr.label(
executable = True,
default = Label("@io_bazel_rules_python//tools:piptool.par"),
cfg = "host",
),
},
implementation = _pip_import_requirements_impl,
)
然后我可以在我的工作区中执行以下操作
pip_import_requirements(
name = "py_requirements",
requirements = [
"@mycore//:requirements.txt",
"@myother//:requirements.txt"
]
)
load(
"@py_requirements//:requirements.bzl",
"pip_install",
)
pip_install()
下面是我碰巧需要的任何构建文件。请注意,py_需求参考将始终适用于项目中的任何构建文件
load(
"@py_requirements//:requirements.bzl",
"all_requirements"
)
par_binary(
name = "funkyserver",
main = "src/main.py",
srcs = glob(["src/**/*.py"]),
deps = [
"@mycore//:core",
"@myother//:other"
] + all_requirements,
)
对于piptool.py。您需要使用RuleDeXyToeS.SH在RuleSyPython ReP.< /P>中重建PIPToo.Par。
diff --git a/rules_python/piptool.py b/rules_python/piptool.py
index f5d504a..ab520d8 100644
--- a/rules_python/piptool.py
+++ b/rules_python/piptool.py
@@ -87,7 +87,7 @@ def pip_main(argv):
parser.add_argument('--name', action='store',
help=('The namespace of the import.'))
-parser.add_argument('--input', action='store',
+parser.add_argument('--input', action='store', nargs='+',
help=('The requirements.txt file to import.'))
parser.add_argument('--output', action='store',
@@ -154,7 +154,8 @@ def main():
args = parser.parse_args()
# https://github.com/pypa/pip/blob/9.0.1/pip/__init__.py#L209
- if pip_main(["wheel", "-w", args.directory, "-r", args.input]):
+ if pip_main(["wheel", "-w", args.directory] + [p for x in [
+ ('-r', i) for i in args.input] for p in x]):
sys.exit(1)
# Enumerate the .whl files we downloaded.
@@ -219,7 +220,7 @@ def requirement(name):
if name_key not in _requirements:
fail("Could not find pip-provided dependency: '%s'" % name)
return _requirements[name_key]
-""".format(input=args.input,
+""".format(input=" ".join(args.input),
whl_libraries='\n'.join(map(whl_library, whls)) if whls else "pass",
mappings=whl_targets))
您希望这个pyrules.bzl文件放在哪里?父工作区将引用它们吗?怎么说?说得好。我做了一个非常复杂的变通方法,动态创建bzl文件,然后将其添加为假存储库。这是我在启动时解决文件问题的唯一方法,而不必事先手动描述所有文件。我认为如果你能提供更多关于你心目中的流程的上下文(比如克隆后)会有所帮助。你能分享你对piptool.py的修改吗?或者更好,你能做一个PR吗?