bazel:如何创建规则以去除子文件夹中所有文件的相对路径

问题描述

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

问题在于它在子文件夹中具有各种gsl _ *。h头文件,但它们始终作为#include <gsl/gsl_somename.h>包含在内,因此例如包含了位于gsl / err / gsl_errno.h中的头gsl_errno.h居住在gsl / gsl_math.h中的#include <gsl/gsl_errno.h>gsl_math.h也包含在#include <gsl/gsl_math.h>中。

我尝试为每个文件夹创建一个单独的cc_library,并像这样使用strip_include_prefixinclude_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>进行访问。

我该如何实现?

解决方法

我会将它们全部复制到一个新文件夹,然后将这些新复制的版本用于您的cc_librarygenrule是执行此操作的最简单方法。这样的事情在顶层的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的所有输出。

如果您想对文件进行更复杂的处理而不只是移动它们,请考虑使用完整的custom rule。如果您将所有复制的标头都包含在DefaultInfo.files中,则只需将目标的标签传递到cc_library.hdrs就可以像使用原规则一样工作。