github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/tools/defs.bzl (about)

     1  """Wrappers for common build rules.
     2  
     3  These wrappers apply common BUILD configurations (e.g., proto_library
     4  automagically creating cc_ and go_ proto targets) and act as a single point of
     5  change for Google-internal and bazel-compatible rules.
     6  """
     7  
     8  load("//tools/go_stateify:defs.bzl", "go_stateify")
     9  load("//tools/go_marshal:defs.bzl", "go_marshal", "marshal_deps", "marshal_test_deps")
    10  load("//tools/nogo:defs.bzl", "nogo_test")
    11  load("//tools/bazeldefs:defs.bzl", _arch_genrule = "arch_genrule", _build_test = "build_test", _bzl_library = "bzl_library", _coreutil = "coreutil", _default_installer = "default_installer", _default_net_util = "default_net_util", _more_shards = "more_shards", _most_shards = "most_shards", _proto_library = "proto_library", _select_arch = "select_arch", _select_system = "select_system", _short_path = "short_path", _version = "version")
    12  load("//tools/bazeldefs:cc.bzl", _cc_binary = "cc_binary", _cc_flags_supplier = "cc_flags_supplier", _cc_grpc_library = "cc_grpc_library", _cc_library = "cc_library", _cc_proto_library = "cc_proto_library", _cc_test = "cc_test", _cc_toolchain = "cc_toolchain", _gbenchmark = "gbenchmark", _grpcpp = "grpcpp", _gtest = "gtest", _vdso_linker_option = "vdso_linker_option")
    13  load("//tools/bazeldefs:go.bzl", _bazel_worker_proto = "bazel_worker_proto", _gazelle = "gazelle", _go_binary = "go_binary", _go_embed_data = "go_embed_data", _go_grpc_and_proto_libraries = "go_grpc_and_proto_libraries", _go_library = "go_library", _go_path = "go_path", _go_proto_library = "go_proto_library", _go_rule = "go_rule", _go_test = "go_test", _select_goarch = "select_goarch", _select_goos = "select_goos")
    14  load("//tools/bazeldefs:pkg.bzl", _pkg_deb = "pkg_deb", _pkg_tar = "pkg_tar")
    15  load("//tools/bazeldefs:platforms.bzl", _default_platform = "default_platform", _platforms = "platforms")
    16  load("//tools/bazeldefs:tags.bzl", "go_suffixes")
    17  
    18  # Core rules.
    19  arch_genrule = _arch_genrule
    20  build_test = _build_test
    21  bzl_library = _bzl_library
    22  default_installer = _default_installer
    23  default_net_util = _default_net_util
    24  select_arch = _select_arch
    25  select_system = _select_system
    26  short_path = _short_path
    27  coreutil = _coreutil
    28  more_shards = _more_shards
    29  most_shards = _most_shards
    30  version = _version
    31  
    32  # C++ rules.
    33  cc_binary = _cc_binary
    34  cc_flags_supplier = _cc_flags_supplier
    35  cc_grpc_library = _cc_grpc_library
    36  cc_library = _cc_library
    37  cc_test = _cc_test
    38  cc_toolchain = _cc_toolchain
    39  gbenchmark = _gbenchmark
    40  gtest = _gtest
    41  grpcpp = _grpcpp
    42  vdso_linker_option = _vdso_linker_option
    43  
    44  # Go rules.
    45  gazelle = _gazelle
    46  go_path = _go_path
    47  select_goos = _select_goos
    48  select_goarch = _select_goarch
    49  go_embed_data = _go_embed_data
    50  go_proto_library = _go_proto_library
    51  bazel_worker_proto = _bazel_worker_proto
    52  
    53  # Packaging rules.
    54  pkg_deb = _pkg_deb
    55  pkg_tar = _pkg_tar
    56  
    57  # Platform options.
    58  default_platform = _default_platform
    59  platforms = _platforms
    60  
    61  def _go_add_tags(ctx):
    62      """ Adds tags to the given source file. """
    63      output = ctx.outputs.out
    64      runner = ctx.actions.declare_file(ctx.label.name + ".sh")
    65      lines = ["#!/bin/bash"]
    66      lines += ["echo '// +build %s' >> %s" % (tag, output.path) for tag in ctx.attr.go_tags]
    67      lines.append("echo '' >> %s" % output.path)
    68      lines += ["cat %s >> %s" % (f.path, output.path) for f in ctx.files.src]
    69      lines.append("")
    70      ctx.actions.write(runner, "\n".join(lines), is_executable = True)
    71      ctx.actions.run(
    72          inputs = ctx.files.src,
    73          outputs = [output],
    74          executable = runner,
    75      )
    76      return [DefaultInfo(
    77          files = depset([output]),
    78      )]
    79  
    80  go_add_tags = _go_rule(
    81      rule,
    82      implementation = _go_add_tags,
    83      attrs = {
    84          "go_tags": attr.string_list(doc = "Go build tags to be added.", mandatory = True),
    85          "src": attr.label(doc = "Source file.", allow_single_file = True, mandatory = True),
    86          "out": attr.output(doc = "Output file.", mandatory = True),
    87      },
    88  )
    89  
    90  def go_binary(name, nogo = True, pure = False, static = False, x_defs = None, **kwargs):
    91      """Wraps the standard go_binary.
    92  
    93      Args:
    94        name: the rule name.
    95        nogo: enable nogo analysis.
    96        pure: build a pure Go (no CGo) binary.
    97        static: build a static binary.
    98        x_defs: additional linker definitions.
    99        **kwargs: standard go_binary arguments.
   100      """
   101      _go_binary(
   102          name = name,
   103          pure = pure,
   104          static = static,
   105          x_defs = x_defs,
   106          **kwargs
   107      )
   108      if nogo:
   109          # Note that the nogo rule applies only for go_library and go_test
   110          # targets, therefore we construct a library from the binary sources.
   111          # This is done because the binary may not be in a form that objdump
   112          # supports (i.e. a pure Go binary).
   113          _go_library(
   114              name = name + "_nogo_library",
   115              srcs = kwargs.get("srcs", []),
   116              deps = kwargs.get("deps", []),
   117              testonly = 1,
   118          )
   119          nogo_test(
   120              name = name + "_nogo",
   121              config = "//:nogo_config",
   122              srcs = kwargs.get("srcs", []),
   123              deps = [":" + name + "_nogo_library"],
   124              tags = ["nogo"],
   125          )
   126  
   127  def calculate_sets(srcs):
   128      """Calculates special Go sets for templates.
   129  
   130      Args:
   131        srcs: the full set of Go sources.
   132  
   133      Returns:
   134        A dictionary of the form:
   135  
   136        "": [src1.go, src2.go]
   137        "suffix": [src3suffix.go, src4suffix.go]
   138  
   139        Note that suffix will typically start with '_'.
   140      """
   141      result = dict()
   142      for file in srcs:
   143          if not file.endswith(".go"):
   144              continue
   145          target = ""
   146          for suffix in go_suffixes:
   147              if file.endswith(suffix + ".go"):
   148                  target = suffix
   149          if not target in result:
   150              result[target] = [file]
   151          else:
   152              result[target].append(file)
   153      return result
   154  
   155  def go_imports(name, src, out):
   156      """Simplify a single Go source file by eliminating unused imports."""
   157      native.genrule(
   158          name = name,
   159          srcs = [src],
   160          outs = [out],
   161          tools = ["@org_golang_x_tools//cmd/goimports:goimports"],
   162          cmd = ("$(location @org_golang_x_tools//cmd/goimports:goimports) $(SRCS) > $@"),
   163      )
   164  
   165  def go_library(name, srcs, deps = [], imports = [], stateify = True, marshal = False, marshal_debug = False, nogo = True, **kwargs):
   166      """Wraps the standard go_library and does stateification and marshalling.
   167  
   168      The recommended way is to use this rule with mostly identical configuration as the native
   169      go_library rule.
   170  
   171      These definitions provide additional flags (stateify, marshal) that can be used
   172      with the generators to automatically supplement the library code.
   173  
   174      load("//tools:defs.bzl", "go_library")
   175  
   176      go_library(
   177          name = "foo",
   178          srcs = ["foo.go"],
   179      )
   180  
   181      Args:
   182        name: the rule name.
   183        srcs: the library sources.
   184        deps: the library dependencies.
   185        imports: imports required for stateify.
   186        stateify: whether statify is enabled (default: true).
   187        marshal: whether marshal is enabled (default: false).
   188        marshal_debug: whether the gomarshal tools emits debugging output (default: false).
   189        nogo: enable nogo analysis.
   190        **kwargs: standard go_library arguments.
   191      """
   192      all_srcs = srcs
   193      all_deps = deps
   194      dirname, _, _ = native.package_name().rpartition("/")
   195      full_pkg = dirname + "/" + name
   196      if stateify:
   197          # Only do stateification for non-state packages without manual autogen.
   198          # First, we need to segregate the input files via the special suffixes,
   199          # and calculate the final output set.
   200          state_sets = calculate_sets(srcs)
   201          for (suffix, src_subset) in state_sets.items():
   202              go_stateify(
   203                  name = name + suffix + "_state_autogen_with_imports",
   204                  srcs = src_subset,
   205                  imports = imports,
   206                  package = full_pkg,
   207                  out = name + suffix + "_state_autogen_with_imports.go",
   208              )
   209              go_imports(
   210                  name = name + suffix + "_state_autogen",
   211                  src = name + suffix + "_state_autogen_with_imports.go",
   212                  out = name + suffix + "_state_autogen.go",
   213              )
   214          all_srcs = all_srcs + [
   215              name + suffix + "_state_autogen.go"
   216              for suffix in state_sets.keys()
   217          ]
   218  
   219          if "//pkg/state" not in all_deps:
   220              all_deps = all_deps + ["//pkg/state"]
   221  
   222      if marshal:
   223          # See above.
   224          marshal_sets = calculate_sets(srcs)
   225          for (suffix, src_subset) in marshal_sets.items():
   226              go_marshal(
   227                  name = name + suffix + "_abi_autogen",
   228                  srcs = src_subset,
   229                  debug = select({
   230                      "//tools/go_marshal:marshal_config_verbose": True,
   231                      "//conditions:default": marshal_debug,
   232                  }),
   233                  imports = imports,
   234                  package = name,
   235              )
   236          extra_deps = [
   237              dep
   238              for dep in marshal_deps
   239              if not dep in all_deps
   240          ]
   241          all_deps = all_deps + extra_deps
   242          all_srcs = all_srcs + [
   243              name + suffix + "_abi_autogen_unsafe.go"
   244              for suffix in marshal_sets.keys()
   245          ]
   246  
   247      _go_library(
   248          name = name,
   249          srcs = all_srcs,
   250          deps = all_deps,
   251          **kwargs
   252      )
   253      if nogo:
   254          nogo_test(
   255              name = name + "_nogo",
   256              config = "//:nogo_config",
   257              srcs = all_srcs,
   258              deps = [":" + name],
   259              tags = ["nogo"],
   260          )
   261  
   262      if marshal:
   263          # Ignore importpath for go_test.
   264          kwargs.pop("importpath", None)
   265  
   266          # See above.
   267          marshal_sets = calculate_sets(srcs)
   268          for (suffix, _) in marshal_sets.items():
   269              _go_test(
   270                  name = name + suffix + "_abi_autogen_test",
   271                  srcs = [
   272                      name + suffix + "_abi_autogen_test.go",
   273                      name + suffix + "_abi_autogen_unconditional_test.go",
   274                  ],
   275                  library = ":" + name,
   276                  deps = marshal_test_deps,
   277                  **kwargs
   278              )
   279  
   280  def go_test(name, nogo = True, **kwargs):
   281      """Wraps the standard go_test.
   282  
   283      Args:
   284        name: the rule name.
   285        nogo: enable nogo analysis.
   286        **kwargs: standard go_test arguments.
   287      """
   288      _go_test(
   289          name = name,
   290          **kwargs
   291      )
   292      if nogo:
   293          nogo_test(
   294              name = name + "_nogo",
   295              config = "//:nogo_config",
   296              srcs = kwargs.get("srcs", []),
   297              deps = [":" + name],
   298              tags = ["nogo"],
   299          )
   300  
   301  def proto_library(name, srcs, deps = None, has_services = 0, **kwargs):
   302      """Wraps the standard proto_library.
   303  
   304      Given a proto_library named "foo", this produces up to five different
   305      targets:
   306      - foo_proto: proto_library rule.
   307      - foo_go_proto: go_proto_library rule.
   308      - foo_cc_proto: cc_proto_library rule.
   309      - foo_go_grpc_proto: go_grpc_library rule.
   310      - foo_cc_grpc_proto: cc_grpc_library rule.
   311  
   312      Args:
   313        name: the name to which _proto, _go_proto, etc, will be appended.
   314        srcs: the proto sources.
   315        deps: for the proto library and the go_proto_library.
   316        has_services: 1 to build gRPC code, otherwise 0.
   317        **kwargs: standard proto_library arguments.
   318      """
   319      _proto_library(
   320          name = name + "_proto",
   321          srcs = srcs,
   322          deps = deps,
   323          has_services = has_services,
   324          **kwargs
   325      )
   326      if has_services:
   327          _go_grpc_and_proto_libraries(
   328              name = name,
   329              deps = deps,
   330              **kwargs
   331          )
   332      else:
   333          _go_proto_library(
   334              name = name,
   335              deps = deps,
   336              **kwargs
   337          )
   338      _cc_proto_library(
   339          name = name + "_cc_proto",
   340          deps = [":" + name + "_proto"],
   341          **kwargs
   342      )
   343      if has_services:
   344          _cc_grpc_library(
   345              name = name + "_cc_grpc_proto",
   346              srcs = [":" + name + "_proto"],
   347              deps = [":" + name + "_cc_proto"],
   348              **kwargs
   349          )