Python 工具链未下载工具

Python 工具链未下载工具,python,bazel,skylark,starlark,Python,Bazel,Skylark,Starlark,嗨,我正在为Fn项目建立一个工具链。方法是为GitHub中可用的每个二进制文件建立一个工具链,然后在理论上在规则中使用它 我有一个通用包,其中包含可用的二进制文件: default_version = "0.5.44" os_list = [ "linux", "mac", "windows" ] def get_bin_name(os): return "fn_cli_%s_bin" % os 下载部分如下所示: load(":common.bzl",

嗨,我正在为Fn项目建立一个工具链。方法是为GitHub中可用的每个二进制文件建立一个工具链,然后在理论上在规则中使用它

我有一个通用包,其中包含可用的二进制文件:

default_version = "0.5.44"

os_list = [
    "linux",
    "mac",
    "windows"
]

def get_bin_name(os):
    return "fn_cli_%s_bin" % os

下载部分如下所示:

load(":common.bzl", "get_bin_name", "os_list", "default_version")

_url = "https://github.com/fnproject/cli/releases/download/{version}/{file}"
_os_to_file = {
    "linux" : "fn_linux",
    "mac" : "fn_mac",
    "windows" : "fn.exe",
}

def _fn_binary(os):
    name = get_bin_name(os)
    file = _os_to_file.get(os)
    url = _url.format(
        file = file,
        version = default_version
    )
    native.http_file(
        name = name,
        urls = [url],
        executable = True
    )

def fn_binaries():
    """
    Installs the hermetic binary for Fn.
    """
    for os in os_list:
        _fn_binary(os)

load(":common.bzl", "get_bin_name", "os_list")

_toolchain_type = "toolchain_type"

FnInfo = provider(
    doc = "Information about the Fn Framework CLI.",
    fields = {
        "bin" : "The Fn Framework binary."
    }
)

def _fn_cli_toolchain(ctx):
  toolchain_info = platform_common.ToolchainInfo(
      fn_info = FnInfo(
          bin = ctx.attr.bin
      )
  )
  return [toolchain_info]

fn_toolchain = rule(
    implementation = _fn_cli_toolchain,
    attrs = {
        "bin" : attr.label(mandatory = True)
    }
)

def _add_toolchain(os):
    toolchain_name = "fn_cli_%s" % os
    native_toolchain_name = "fn_cli_%s_toolchain" % os
    bin_name = get_bin_name(os)
    compatibility = ["@bazel_tools//platforms:%s" % os]

    fn_toolchain(
        name = toolchain_name,
        bin = ":%s" % bin_name,
        visibility = ["//visibility:public"]
    )

    native.toolchain(
        name = native_toolchain_name,
        toolchain = ":%s" % toolchain_name,
        toolchain_type = ":%s" % _toolchain_type,
        target_compatible_with = compatibility
    )

def setup_toolchains():
    """
    Macro te set up the toolchains for the different platforms
    """
    native.toolchain_type(name = _toolchain_type)

    for os in os_list:
      _add_toolchain(os)

def fn_register():
    """
    Registers the Fn toolchains.
    """
    path = "//tools/bazel_rules/fn/internal/cli:fn_cli_%s_toolchain"

    for os in os_list:
      native.register_toolchains(path % os)

_toolchain = "//tools/bazel_rules/fn/cli:toolchain_type"

def _fn(ctx):
  print("HEY")
  bin = ctx.toolchains[_toolchain].fn_info.bin
  print(bin)

# TEST RULE
fn = rule(
    implementation = _fn,
    toolchains = [_toolchain]
)

然后我像这样设置工具链:

load(":common.bzl", "get_bin_name", "os_list", "default_version")

_url = "https://github.com/fnproject/cli/releases/download/{version}/{file}"
_os_to_file = {
    "linux" : "fn_linux",
    "mac" : "fn_mac",
    "windows" : "fn.exe",
}

def _fn_binary(os):
    name = get_bin_name(os)
    file = _os_to_file.get(os)
    url = _url.format(
        file = file,
        version = default_version
    )
    native.http_file(
        name = name,
        urls = [url],
        executable = True
    )

def fn_binaries():
    """
    Installs the hermetic binary for Fn.
    """
    for os in os_list:
        _fn_binary(os)

load(":common.bzl", "get_bin_name", "os_list")

_toolchain_type = "toolchain_type"

FnInfo = provider(
    doc = "Information about the Fn Framework CLI.",
    fields = {
        "bin" : "The Fn Framework binary."
    }
)

def _fn_cli_toolchain(ctx):
  toolchain_info = platform_common.ToolchainInfo(
      fn_info = FnInfo(
          bin = ctx.attr.bin
      )
  )
  return [toolchain_info]

fn_toolchain = rule(
    implementation = _fn_cli_toolchain,
    attrs = {
        "bin" : attr.label(mandatory = True)
    }
)

def _add_toolchain(os):
    toolchain_name = "fn_cli_%s" % os
    native_toolchain_name = "fn_cli_%s_toolchain" % os
    bin_name = get_bin_name(os)
    compatibility = ["@bazel_tools//platforms:%s" % os]

    fn_toolchain(
        name = toolchain_name,
        bin = ":%s" % bin_name,
        visibility = ["//visibility:public"]
    )

    native.toolchain(
        name = native_toolchain_name,
        toolchain = ":%s" % toolchain_name,
        toolchain_type = ":%s" % _toolchain_type,
        target_compatible_with = compatibility
    )

def setup_toolchains():
    """
    Macro te set up the toolchains for the different platforms
    """
    native.toolchain_type(name = _toolchain_type)

    for os in os_list:
      _add_toolchain(os)

def fn_register():
    """
    Registers the Fn toolchains.
    """
    path = "//tools/bazel_rules/fn/internal/cli:fn_cli_%s_toolchain"

    for os in os_list:
      native.register_toolchains(path % os)

_toolchain = "//tools/bazel_rules/fn/cli:toolchain_type"

def _fn(ctx):
  print("HEY")
  bin = ctx.toolchains[_toolchain].fn_info.bin
  print(bin)

# TEST RULE
fn = rule(
    implementation = _fn,
    toolchains = [_toolchain]
)

在我的构建文件中,我称之为setup\u工具链:

load(":toolchain.bzl", "setup_toolchains")
setup_toolchains()
通过这种设置,我有一个规则如下所示:

load(":common.bzl", "get_bin_name", "os_list", "default_version")

_url = "https://github.com/fnproject/cli/releases/download/{version}/{file}"
_os_to_file = {
    "linux" : "fn_linux",
    "mac" : "fn_mac",
    "windows" : "fn.exe",
}

def _fn_binary(os):
    name = get_bin_name(os)
    file = _os_to_file.get(os)
    url = _url.format(
        file = file,
        version = default_version
    )
    native.http_file(
        name = name,
        urls = [url],
        executable = True
    )

def fn_binaries():
    """
    Installs the hermetic binary for Fn.
    """
    for os in os_list:
        _fn_binary(os)

load(":common.bzl", "get_bin_name", "os_list")

_toolchain_type = "toolchain_type"

FnInfo = provider(
    doc = "Information about the Fn Framework CLI.",
    fields = {
        "bin" : "The Fn Framework binary."
    }
)

def _fn_cli_toolchain(ctx):
  toolchain_info = platform_common.ToolchainInfo(
      fn_info = FnInfo(
          bin = ctx.attr.bin
      )
  )
  return [toolchain_info]

fn_toolchain = rule(
    implementation = _fn_cli_toolchain,
    attrs = {
        "bin" : attr.label(mandatory = True)
    }
)

def _add_toolchain(os):
    toolchain_name = "fn_cli_%s" % os
    native_toolchain_name = "fn_cli_%s_toolchain" % os
    bin_name = get_bin_name(os)
    compatibility = ["@bazel_tools//platforms:%s" % os]

    fn_toolchain(
        name = toolchain_name,
        bin = ":%s" % bin_name,
        visibility = ["//visibility:public"]
    )

    native.toolchain(
        name = native_toolchain_name,
        toolchain = ":%s" % toolchain_name,
        toolchain_type = ":%s" % _toolchain_type,
        target_compatible_with = compatibility
    )

def setup_toolchains():
    """
    Macro te set up the toolchains for the different platforms
    """
    native.toolchain_type(name = _toolchain_type)

    for os in os_list:
      _add_toolchain(os)

def fn_register():
    """
    Registers the Fn toolchains.
    """
    path = "//tools/bazel_rules/fn/internal/cli:fn_cli_%s_toolchain"

    for os in os_list:
      native.register_toolchains(path % os)

_toolchain = "//tools/bazel_rules/fn/cli:toolchain_type"

def _fn(ctx):
  print("HEY")
  bin = ctx.toolchains[_toolchain].fn_info.bin
  print(bin)

# TEST RULE
fn = rule(
    implementation = _fn,
    toolchains = [_toolchain]
)

工作空间:

workspace(name = "basicwindow")

load("//tools/bazel_rules/fn:defs.bzl", "fn_binaries", "fn_register")
fn_binaries()
fn_register()

当我使用
bazel query//tools/bazel_rules/fn/internal/cli:fn_cli_linux_bin
查询不同的二进制文件时,它们在那里,但是调用
bazel build//…
会导致一个错误,该错误会导致:

ERROR: /Users/marcguilera/Code/Marc/basicwindow/tools/bazel_rules/fn/internal/cli/BUILD.bazel:2:1: in bin attribute of fn_toolchain rule //tools/bazel_rules/fn/internal/cli:fn_cli_windows: rule '//tools/bazel_rules/fn/internal/cli:fn_cli_windows_bin' does not exist. Since this rule was created by the macro 'setup_toolchains', the error might have been caused by the macro implementation in /Users/marcguilera/Code/Marc/basicwindow/tools/bazel_rules/fn/internal/cli/toolchain.bzl:35:15
ERROR: Analysis of target '//tools/bazel_rules/fn/internal/cli:fn_cli_windows' failed; build aborted: Analysis of target '//tools/bazel_rules/fn/internal/cli:fn_cli_windows' failed; build aborted
INFO: Elapsed time: 0.079s
INFO: 0 processes.
FAILED: Build did NOT complete successfully (0 packages loaded, 0 targets configured)
我试图按照文档中的工具链教程进行操作,但无法使其正常工作。另一件有趣的事情是,我实际上在使用mac,所以工具链的兼容性似乎也是错误的

我在回购中使用此工具链,因此路径会有所不同,但回购仅包含fn内容,以便于阅读。

两件事:

第一,我怀疑这是你真正的问题: 问题的核心是,如果工具链类型目标位于外部存储库中,则始终需要使用完全限定名来引用它,而不是使用本地限定名

第二个是更基本的一点:这里有很多Starlark宏生成其他目标,很难阅读。实际上,删除大量宏要简单得多,例如_fn_binary、fn_binary和_add_工具链。只需让setup_工具链直接创建所需的
native.toolchain
目标,并使用一个repository宏调用
http_archive
三次来声明三组不同的二进制文件。这将使代码更易于阅读,从而更易于调试

对于调试工具链,我遵循两个步骤:首先,我验证工具库是否存在并且可以直接访问,然后检查工具链注册和解析

深入几层之后,您似乎正在调用http_archive,命名新存储库
@linux
,并下载特定的二进制文件。这不是http_归档的工作方式:它希望获取一个zip文件(或tar.gz文件),将其解压缩,并在其中找到一个工作区和至少一个构建文件

我的建议是:简化宏,明确定义外部存储库,然后使用工具链解析来选择正确的存储库


我很乐意根据需要回答更多问题。

嘿,谢谢你的详细回答。我将简化代码并尝试按照您提到的进行调试。但有两个问题:1)我使用的是
http\u文件
,而不是
http\u存档
。这就是你的意思吗?2) 当您指出如何调试工具链时,如何检查工具链注册和解析?如果我查询
bazel query//tools/bazel_rules/fn/internal/cli:toolschain_type
,我会得到适当的结果。(注意:我不喜欢SO注释编辑器,它意外地节省了这几次时间。对于重复的通知,我深表歉意)。第1部分:哎哟,关于http\U归档和http\U文件,你说得对,我错了。我可能没有使用与您相同的git存储库,因为我没有看到//tools/bazel_rules/fn包。您是否试图将这些规则添加到Bazel源代码树中?我已经通过toolchains分支签出了您提到的git存储库()。看起来它们已经注册(通过宏),所以Bazel应该可以使用它们。但是,查看宏生成后的文件,我发现有些东西有点混乱。在
bazel查询--output=build//internal/tools/cli:all
中,我看到了这样一个信息:``fn_工具链(name=“fn_cli_linux”,visibility=[“//visibility:public”],bin=“//internal/tools/cli:fn_cli_linux_bin)”``第3部分:但是,没有名为“fn_cli_linux__bin”的目标。我认为这应该是从http_文件创建的外部存储库,但同样,使用深度嵌套的宏很难判断。下一步是测试需要工具链的构建,但要使用
--toolchain\u resolution\u debug
标志启用工具链调试。这会产生大量信息,但会导致Bazel调试它正在考虑哪些工具链,哪些被丢弃(以及为什么要丢弃的一些细节),哪些被选中。