2017-06-12 62 views
1

我在這個場景中有一個「Parent」Bazel項目,其中包含一些shell腳本&宏。該項目必須由「兒童」項目重複使用。最小的 「工作」 的例子來重現問題定義如下:爲父項目和子項目導出的shell腳本

目錄結構

├── 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) > [email protected]", 
     tools = [":a_script_sh"], 
    ) 

父/ BUILD

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

父/工作區

# empty file 

兒童的項目文件

兒童/工作區

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") 
兒童

/BUILD文件,一切正常:

INFO: Found 2 targets... 
INFO: Elapsed time: 0.191s, Critical Path: 0.03s 

而文件use_script.txt已正確生成兒童/ bazel-genfiles目錄。

我的問題是

是否使用的

alias(name="a_script_sh",actual="@Parent//:a_script_sh") 

正確的方式做的事情嗎?

我曾期待這是巴澤爾的工作,以解決這種依賴

我沒想到有明確重新定義其中a_script.sh文件。我認爲這很尷尬,多餘且容易出錯。

我懷疑我沒有做正確的事情,我會非常感謝任何能清楚地向我們解釋如何正確做到這一點的人。

回答

3

首先,感謝您清楚徹底的repro指令!

您發現了一個非常有趣的場景!然而,一切都按預期工作。

a_command in Parent/a_command.bzltools=[":a_script_sh"]包裝了一個genrule。這是一個相對於當前包的相對標籤,其中「current」是使用宏的包,而不是聲明的位置。因此,Child的BUILD文件必須聲明一個「a_script_sh」目標(任何具有此名稱的目標),該示例將起作用。

這種行爲在glob的情況下更具有意義:如果Skylark宏使用srcs=glob([**])包裝規則,宏應該從當前包(使用宏的地方)中獲取文件,而不是外部文件(其中宏被聲明)。

在添加一個文件組兒童/ 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) > [email protected]", # 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 t ARGET。該宏不應該爲標籤添加一個存儲庫名稱(例如"@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) > [email protected]" % 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"}, 
) 
+0

感謝您的積極反饋和解釋。正如你自己寫的那樣:宏被擴展到使用它的地方(它畢竟只是一個宏:-)),並且我們不能在//::a_script_sh前綴,因爲我們不知道Child項目中的未來邊界。就像我在學習巴澤爾一樣,我擔心我錯過了什麼......再次感謝 –