我正在尝试使用一种原语来获取并建立外部依赖。设置如下。
[root] / WORKSPACE
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "gsl",
url = "https://mirror.freedif.org/GNU/gsl/gsl-latest.tar.gz",
build_file = '@//thirdparty:gsl.BUILD',
)
[root] /thirdparty/gsl.BUILD
genrule(
name = "gsl_genrule",
srcs = glob([
"gsl-2.5/**/*.c",
"gsl-2.5/**/*.h",
]),
outs = glob([
"gsl-2.5/install/lib/*.so",
"gsl-2.5/install/include/**/*.h",
]),
cmd = "mkdir install && ./configure --prefix=`pwd`/install && make -j && make install",
)
cc_library(
name = "gsl",
srcs = [":gsl_genrule"],
visibility = ["//visibility:public"],
)
[root] / src / BUILD
cc_binary(
name = "hello",
srcs = [
"hello.cc",
],
deps = [
"@gsl//:gsl"
],
)
此外,我在[Root] / thirdparty中有一个空的BUILD文件,可以防止bazel无法找到gsl.BUILD
的错误。 [1]
当我运行它时,genrule失败,如下所示。
$ bazel build -c dbg --sandbox_debug //src:*
INFO: Invocation ID: a698121f-fc3f-449a-9e36-eb2a5f59e06b
INFO: SHA256 (https://mirror.freedif.org/GNU/gsl/gsl-latest.tar.gz) = 0460ad7c2542caaddc6729762952d345374784100223995eb14d614861f2258d
ERROR: /home/buddhika/.cache/bazel/_bazel_buddhika/3fbc2046978475f6bf9fc76463e16ae5/external/gsl/BUILD.bazel:8:12: in outs attribute of genrule rule @gsl//:gsl_genrule: Genrules without outputs don't make sense
ERROR: Analysis of target '//src:hello.dwp' failed; build aborted: Analysis of target '@gsl//:gsl_genrule' failed; build aborted
INFO: Elapsed time: 11.261s
INFO: 0 processes.
FAILED: Build did NOT complete successfully (3 packages loaded, 1689 targets configured)
我有由上面gsl.BUILD
文件中所示的指定类型生成的输出。知道我在做什么错吗?
答案 0 :(得分:1)
我将首先关注您的问题(但是您可能要重新考虑将生成的一部分委派给自动工具的计划,并依靠慷慨大方地使用globbing)。错误消息实际上包含您的答案:
bazel在分析构建设置时,将(按照指示)查找所有(现有)"gsl-2.5/install/lib/*.so"
和"gsl-2.5/install/include/**/*.h"
文件,并且(在分析时)找不到任何文件。即outs
是一个空列表,就bazel而言,您的规则的确不会产生任何输出,从而使它毫无意义。
您可以列出您知道在那里的实际文件。或者,您必须使用与TreeArtifacts一起使用的自定义规则(将TreeArtifacts与(所有)库和标头一起吐出)。您还可以预先构建依赖关系,并依赖于生成的归档文件/树。或“ bazelify”其构建。 (根据其性质和使用方式,我可能更喜欢后两种选择之一。)
编辑:对评论进行更详细的解释。
Bazel首先必须分析并确定构建树的外观。在glob()
中使用outs
(基本上没有意义)时,它将在分析之前之前将outs
定义为全局文件列表(在分析阶段)规则已执行。
outs = ["concatenated.txt"]
很好,因为它说规则输出恰好是一个文件concatenated.txt
。但是:
outs = glob(["*.txt"])
甚至:
outs = glob(["concatenated.txt"])
与以下相同:
outs = []
因为在确定要构建的内容时(glob()
开始使用时),没有文件匹配(您可以将其认为是:在构建之前告诉构建结果将是{ {1}}或find
返回输出树,但现在在我实际构建之前)。断开连接是,您似乎希望ls
定义规则运行后(在构建步骤已完成的情况下)后的操作,但前提是用户必须先了解之前它执行任何规则,哪个步骤会产生什么结果,然后反过来需要做什么才能建立请求的目标。
TreeArtifacts和declare_directory与您在上面所说的相近,因为它告诉bazel根据规则,将存在一个目录(其中包含内容)。
您还可以逐字列出所有outs
和*.so
文件,因为它们是由构建产生的,这也将为您解决此问题。
对于预构建,我的意思是仅在bazel之外进行编译,打包结果,并从bazel构建中引用包含库和接口描述(标题)的存档。在以下情况下,该选项通常可以使用:
否则,值得将其构建“ Bazelizing”以使其成为您自己的树构建的一部分。