首页 > 解决方案 > bazel:如何创建一个规则来去除子文件夹中所有文件的相对路径

问题描述

我正在尝试为GSL编写一个 bazel BUILD

问题是它在子文件夹中有各种 gsl_*.h 头文件,但它们总是被包含在内#include <gsl/gsl_somename.h>,例如位于 gsl/err/gsl_errno.h 中的头文件 gsl_errno.h 被包含#include <gsl/gsl_errno.h>gsl_math.hgsl/gsl_math 中.h 也包含在#include <gsl/gsl_math.h>.

我尝试为每个文件夹创建一个单独的 cc_library 并使用strip_include_prefix如下include_prefix

cc_library(
    name = "gsl_sys",
    visibility = ["//visibility:public"],
    srcs = [
        "sys/minmax.c",
        "sys/prec.c",
        "sys/hypot.c",
        "sys/log1p.c",
        "sys/expm1.c",
        "sys/coerce.c",
        "sys/invhyp.c",
        "sys/pow_int.c",
        "sys/infnan.c",
        "sys/fdiv.c",
        "sys/fcmp.c",
        "sys/ldfrexp.c",
    ],
    hdrs = glob(
        include = ["sys/*.h"],
    ),
    strip_include_prefix = "sys/",
    include_prefix = "gsl/",
)

但问题是,如果我按文件夹进行操作,则存在循环依赖项(例如 gsl/gsl_math.h 包括 gsl/sys/gsl_sys.h 但 gsl/sys 中的某些文件包括 gsl_*.h 位于 gsl/ 根目录中的文件文件夹。

我认为最好有一个包含所有 gsl_*.h 文件的 cc_library,但这样它们都可以#include <gsl/gsl_*.h>独立于它们所在的子文件夹进行访问。

我怎样才能做到这一点?

标签: bazel

解决方案


我会将它们全部复制到一个新文件夹中,然后将这些新复制的版本用于您的cc_library. genrule是执行此操作的最简单方法在顶层的 BUILD 文件中存在类似的内容(不要将 BUILD 文件放在任何子文件夹中;您希望它们都放在同一个包中,这样一条规则就可以处理所有文件):

# You could list all the headers instead of the glob, or something
# similar, if you only want a subset of them.
all_headers = glob(["gsl/*/*.h"])
# This is the logic for actually remapping the paths. Consider a macro
# instead of writing it inline like this if it gets more complicated.
unified_header_paths = ["unified_gsl/" + p.split("/")[-1] for p in all_headers]
genrule(
    name = "unified_gsl"
    srcs = all_headers,
    outs = unified_header_paths,
    cmd = "\n".join(["cp $(location %s) $(location %s)" %
        (src, dest) for src, dest in zip(all_headers, unified_header_paths)]),
)

复制后文件最终会是这样:

unified_gsl/gsl/gsl_math.h
unified_gsl/gsl/gsl_sys.h

然后你可以写一个 cc_library 像:

cc_library(
    name = "gsl_headers",
    hdrs = [":unified_gsl"],
    strip_include_prefix = "unified_gsl/",
)

cc_library.hdrs正在寻找文件,所以它会从genrule.

如果您想对文件做更复杂的事情,而不仅仅是移动它们,请考虑使用完整的自定义规则。如果您将所有复制的标头包含在您的 中DefaultInfo.files,那么只需将目标的标签传递给cc_library.hdrs就可以像使用 genrule 一样工作。


推荐阅读