简体   繁体   English

使用bazel genrule添加外部依赖项失败,并显示错误“没有输出的Genrules没有意义”。

[英]Adding an external dependency using bazel genrule fails with error `Genrules without outputs don't make sense`

I am trying to use a genrule to fetch and build an external dependency. 我正在尝试使用一种原语来获取和建立外部依赖关系。 The setup is as follows. 设置如下。

[Root] /WORKSPACE [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 [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 [root] / src / BUILD

cc_binary(
    name = "hello",
    srcs = [
        "hello.cc",
    ],
    deps = [
        "@gsl//:gsl"
    ],
)

In addition I have an empty BUILD file inside [Root]/thirdparty which prevents an error where bazel cannot find gsl.BUILD . 另外,我在[Root] / thirdparty内部有一个空的BUILD文件,可以防止bazel无法找到gsl.BUILD的错误。 [1] [1]

When I run it the genrule fails as follows. 当我运行它时,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)

I have outputs to be generated by the genrule specified as shown in gsl.BUILD file above. 我有指定的生成规则生成的输出,如上面的gsl.BUILD文件所示。 Any idea what I am doing wrong? 知道我在做什么错吗?

[1] https://github.com/bazelbuild/bazel/issues/6873 [1] https://github.com/bazelbuild/bazel/issues/6873

I'll first focus on your question (but you may want to reconsider both the plan to delegate part of the build to autotools and rely on genrule and generous use of globbing). 我将首先关注您的问题(但是您可能要重新考虑将生成的一部分委派给自动工具并依靠自由行和慷慨使用的计划)。 The error message actually contains your answer: 错误消息实际上包含您的答案:

When bazel analyses the build setup, it will (as instructed) look for all the (existing) "gsl-2.5/install/lib/*.so" and "gsl-2.5/install/include/**/*.h" files and (at the time of analysis) find none. 当bazel分析构建设置时,它将(按照指示)查找所有(现有) "gsl-2.5/install/lib/*.so" "gsl-2.5/install/include/**/*.h" "gsl-2.5/install/lib/*.so""gsl-2.5/install/include/**/*.h"文件,并且(在分析时)找不到任何文件。 Ie outs is an empty list and as far as bazel is concerned, your rule indeed produces no output rendering it meaningless genrule. outs是一个空列表,就bazel而言,您的规则的确不会产生任何输出,从而使它毫无意义。

You could either list actual files you know that would be there. 您可以列出知道存在的实际文件。 Or you'd have to use a custom rule working with TreeArtifacts (spitting out TreeArtifacts with (all) libraries and headers). 或者,您必须使用与TreeArtifacts一起使用的自定义规则(将TreeArtifacts与(所有)库和标头一起吐出)。 You could also pre-build the dependency and depend on the resulting archive/tree. 您还可以预先构建依赖关系,并依赖于生成的归档文件/树。 Or "bazelify" its build. 或“ bazelify”其构建。 (Depending on its nature and how it's used, I'd probably prefer one of the latter two options.) (根据其性质和使用方式,我可能更喜欢后两种选择之一。)


EDIT: a bit more detailed explanation to address the comments. 编辑:一些更详细的解释来解决这些评论。

Bazel first has to analyze and determine what the build tree looks like. Bazel首先必须分析并确定构建树的外观。 When using glob() in outs (which basically doesn't make sense), it will define outs as list of globbed files (at analysis stage) before the rule was executed. outs使用glob()时(基本上没有意义),它将在执行规则之前outs定义为globated文件的列表(在分析阶段)。

outs = ["concatenated.txt"]

Is fine as it says the rule output is exactly one file concatenated.txt . 很好,因为它说规则输出正是一个concatenated.txt文件。 However: 然而:

outs = glob(["*.txt"])

or even: 甚至:

outs = glob(["concatenated.txt"])

is the same as: 是相同的:

outs = []

because when figuring out what is to be built (and when glob() gets its go) no files match yet (you can think of it as: telling before the build that results of the build will be exactly what find or ls return on output tree, but now before I actually build). 因为在确定要构建的内容时(以及glob()获得成功时),尚无文件匹配(您可以将其视为:在构建之前告诉构建结果将完全是findls返回的结果树,但现在我才真正构建)。 The disconnect is, you seem to expect outs to define what to do after the the rule was run (build step took place), but the bazel needs to understand before it executes any rules, what step yields what result and in turn what needs to be done in order to build requested targets. 断开是,你似乎期望outs定义规则已运行之后做什么(生成步骤发生),但巴泽尔需要了解它执行任何规则之前 ,有什么步骤产生什么结果,反过来需要什么完成以建立请求的目标。

TreeArtifacts and declare_directory is a bit closer to what you expected above in terms of it tells bazel there will be a directory (with stuff in it) as a result of a rule. TreeArtifacts和clarify_directory与您在上面所期望的内容有点接近,因为它告诉bazel作为规则的结果将存在一个目录(其中包含内容)。

You could also just verbatim list all *.so and *.h files as they would be produced by the build and that would also solve this problem for you. 您也可以逐字列出所有*.so*.h文件,因为它们是由构建生成的,这也将为您解决此问题。

With pre-built I meant just compile outside of bazel, package the result and refer to an archive with libraries and interface description (headers) from your bazel build. 对于预构建,我的意思是仅在bazel外部进行编译,打包结果并使用bazel构建中的库和接口描述(标题)引用存档。 This option would be mostly OK if: 如果出现以下情况,此选项通常可以使用:

  • your dependency does not get updated all the frequently 您的依赖关系不会经常更新
  • you do not have to worry about supporting wide or even unknown range of target system 您不必担心支持范围广泛甚至未知的目标系统

Otherwise "bazelifying" its build to make it part of your own tree build really could be worth considering. 否则,值得考虑的是将其构建“裸化”以使其成为您自己的树构建的一部分。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM