为父母和&amp ;;导出的shell脚本子项目

时间:2017-06-12 11:17:27

标签: bazel

我的情况是我有一个"父母" Bazel项目包含一些shell脚本&宏。该项目必须由" Child"项目。最小的工作"重现问题的示例定义如下:

目录结构

├── Child
│   ├── BUILD
│   └── WORKSPACE
└── Parent
    ├── a_command.bzl
    ├── a_script.sh
    ├── BUILD
    └── WORKSPACE

父项目文件

父/ a_script.sh

#!/bin/bash
date

父/ a_command.bzl

def a_command(name):
    native.genrule(
        name = name,
        srcs = [],
        outs = [name+".txt"],
        cmd = "$(location :a_script_sh) > $@",
        tools = [":a_script_sh"],
    )

父/ BUILD

sh_binary(
    name = "a_script_sh",
    srcs = ["a_script.sh"],
    visibility = ["//visibility:public"],
)

Parent / WORKSPACE

# empty file

子项目文件

儿童/ WORKSPACE

local_repository(
    name = "Parent",
    path = "../Parent/",    
)

儿童/ 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 文件所在的位置。我认为这很笨拙,多余且容易出错。

我怀疑我没有以正确的方式做事,我会非常感谢那些能够清楚地向我们解释如何正确行事的人。

1 个答案:

答案 0 :(得分:2)

首先,感谢您提供清晰彻底的责备指示!

你发现了一个非常有趣的场景!然而一切都按预期工作。

a_command中的{p> Parent/a_command.bzltools=[":a_script_sh"]包含了一个genoule。这是相对于当前包的相对标签,其中" current"是使用宏的包,而不是声明它的位置。因此,Child的BUILD文件必须声明一个" a_script_sh" target(具有此名称的任何目标),该示例将起作用。

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"},
)