go.starlark.net@v0.0.0-20231101134539-556fd59b42f6/syntax/testdata/scan.star (about)

     1  # Copyright 2014 The Bazel Authors. All rights reserved.
     2  #
     3  # Licensed under the Apache License, Version 2.0 (the "License");
     4  # you may not use this file except in compliance with the License.
     5  # You may obtain a copy of the License at
     6  #
     7  #    http://www.apache.org/licenses/LICENSE-2.0
     8  #
     9  # Unless required by applicable law or agreed to in writing, software
    10  # distributed under the License is distributed on an "AS IS" BASIS,
    11  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  # See the License for the specific language governing permissions and
    13  # limitations under the License.
    14  
    15  # (From https://github.com/bazelbuild/rules_go/blob/master/go/def.bzl@a6f9d0c)
    16  
    17  load("//go/private:repositories.bzl", "go_repositories")
    18  load("//go/private:go_repository.bzl", "go_repository", "new_go_repository")
    19  load("//go/private:go_prefix.bzl", "go_prefix")
    20  load("//go/private:json.bzl", "json_marshal")
    21  
    22  """These are bare-bones Go rules.
    23  
    24  In order of priority:
    25  
    26  - BUILD file must be written by hand.
    27  
    28  - No support for SWIG
    29  
    30  - No test sharding or test XML.
    31  
    32  """
    33  
    34  _DEFAULT_LIB = "go_default_library"
    35  
    36  _VENDOR_PREFIX = "/vendor/"
    37  
    38  go_filetype = FileType([
    39      ".go",
    40      ".s",
    41      ".S",
    42      ".h",  # may be included by .s
    43  ])
    44  
    45  # be consistent to cc_library.
    46  hdr_exts = [
    47      ".h",
    48      ".hh",
    49      ".hpp",
    50      ".hxx",
    51      ".inc",
    52  ]
    53  
    54  cc_hdr_filetype = FileType(hdr_exts)
    55  
    56  # Extensions of files we can build with the Go compiler or with cc_library.
    57  # This is a subset of the extensions recognized by go/build.
    58  cgo_filetype = FileType([
    59      ".go",
    60      ".c",
    61      ".cc",
    62      ".cxx",
    63      ".cpp",
    64      ".s",
    65      ".S",
    66      ".h",
    67      ".hh",
    68      ".hpp",
    69      ".hxx",
    70  ])
    71  
    72  ################
    73  
    74  def go_environment_vars(ctx):
    75      """Return a map of environment variables for use with actions, based on
    76      the arguments. Uses the ctx.fragments.cpp.cpu attribute, if present,
    77      and picks a default of target_os="linux" and target_arch="amd64"
    78      otherwise.
    79  
    80      Args:
    81        The starlark Context.
    82  
    83      Returns:
    84        A dict of environment variables for running Go tool commands that build for
    85        the target OS and architecture.
    86      """
    87      default_toolchain = {"GOOS": "linux", "GOARCH": "amd64"}
    88      bazel_to_go_toolchain = {
    89          "k8": {"GOOS": "linux", "GOARCH": "amd64"},
    90          "piii": {"GOOS": "linux", "GOARCH": "386"},
    91          "darwin": {"GOOS": "darwin", "GOARCH": "amd64"},
    92          "darwin_x86_64": {"GOOS": "darwin", "GOARCH": "amd64"},
    93          "freebsd": {"GOOS": "freebsd", "GOARCH": "amd64"},
    94          "armeabi-v7a": {"GOOS": "linux", "GOARCH": "arm"},
    95          "arm": {"GOOS": "linux", "GOARCH": "arm"},
    96      }
    97      env = {}
    98      if hasattr(ctx.file, "go_tool"):
    99          env["GOROOT"] = ctx.file.go_tool.dirname + "/.."
   100      env.update(bazel_to_go_toolchain.get(ctx.fragments.cpp.cpu, default_toolchain))
   101      return env
   102  
   103  def _is_darwin_cpu(ctx):
   104      cpu = ctx.fragments.cpp.cpu
   105      return cpu == "darwin" or cpu == "darwin_x86_64"
   106  
   107  def _emit_generate_params_action(cmds, ctx, fn):
   108      cmds_all = [
   109          # Use bash explicitly. /bin/sh is default, and it may be linked to a
   110          # different shell, e.g., /bin/dash on Ubuntu.
   111          "#!/bin/bash",
   112          "set -e",
   113      ]
   114      cmds_all += cmds
   115      cmds_all_str = "\n".join(cmds_all) + "\n"
   116      f = ctx.actions.declare_file(fn)
   117      ctx.file_action(
   118          output = f,
   119          content = cmds_all_str,
   120          executable = True,
   121      )
   122      return f
   123  
   124  def _emit_go_asm_action(ctx, source, hdrs, out_obj):
   125      """Construct the command line for compiling Go Assembly code.
   126      Constructs a symlink tree to accommodate for workspace name.
   127      Args:
   128        ctx: The starlark Context.
   129        source: a source code artifact
   130        hdrs: list of .h files that may be included
   131        out_obj: the artifact (configured target?) that should be produced
   132      """
   133      params = {
   134          "go_tool": ctx.file.go_tool.path,
   135          "includes": [f.dirname for f in hdrs] + [ctx.file.go_include.path],
   136          "source": source.path,
   137          "out": out_obj.path,
   138      }
   139  
   140      inputs = hdrs + ctx.files.toolchain + [source]
   141      ctx.action(
   142          inputs = inputs,
   143          outputs = [out_obj],
   144          mnemonic = "GoAsmCompile",
   145          executable = ctx.executable._asm,
   146          arguments = [json_marshal(params)],
   147      )
   148  
   149  def _go_importpath(ctx):
   150      """Returns the expected importpath of the go_library being built.
   151  
   152      Args:
   153        ctx: The starlark Context
   154  
   155      Returns:
   156        Go importpath of the library
   157      """
   158      path = ctx.attr.importpath
   159      if path != "":
   160          return path
   161      path = ctx.attr.go_prefix.go_prefix
   162      if path.endswith("/"):
   163          path = path[:-1]
   164      if ctx.label.package:
   165          path += "/" + ctx.label.package
   166      if ctx.label.name != _DEFAULT_LIB:
   167          path += "/" + ctx.label.name
   168      if path.rfind(_VENDOR_PREFIX) != -1:
   169          path = path[len(_VENDOR_PREFIX) + path.rfind(_VENDOR_PREFIX):]
   170      if path[0] == "/":
   171          path = path[1:]
   172      return path
   173  
   174  def _emit_go_compile_action(ctx, sources, deps, libpaths, out_object, gc_goopts):
   175      """Construct the command line for compiling Go code.
   176  
   177      Args:
   178        ctx: The starlark Context.
   179        sources: an iterable of source code artifacts (or CTs? or labels?)
   180        deps: an iterable of dependencies. Each dependency d should have an
   181          artifact in d.transitive_go_libraries representing all imported libraries.
   182        libpaths: the set of paths to search for imported libraries.
   183        out_object: the object file that should be produced
   184        gc_goopts: additional flags to pass to the compiler.
   185      """
   186      if ctx.coverage_instrumented():
   187          sources = _emit_go_cover_action(ctx, sources)
   188  
   189      # Compile filtered files.
   190      args = [
   191          "-cgo",
   192          ctx.file.go_tool.path,
   193          "tool",
   194          "compile",
   195          "-o",
   196          out_object.path,
   197          "-trimpath",
   198          "-abs-.",
   199          "-I",
   200          "-abs-.",
   201      ]
   202      inputs = depset(sources + ctx.files.toolchain)
   203      for dep in deps:
   204          inputs += dep.transitive_go_libraries
   205      for path in libpaths:
   206          args += ["-I", path]
   207      args += gc_goopts + [("" if i.basename.startswith("_cgo") else "-filter-") + i.path for i in sources]
   208      ctx.action(
   209          inputs = list(inputs),
   210          outputs = [out_object],
   211          mnemonic = "GoCompile",
   212          executable = ctx.executable._filter_exec,
   213          arguments = args,
   214          env = go_environment_vars(ctx),
   215      )
   216  
   217      return sources
   218  
   219  def _emit_go_pack_action(ctx, out_lib, objects):
   220      """Construct the command line for packing objects together.
   221  
   222      Args:
   223        ctx: The starlark Context.
   224        out_lib: the archive that should be produced
   225        objects: an iterable of object files to be added to the output archive file.
   226      """
   227      ctx.action(
   228          inputs = objects + ctx.files.toolchain,
   229          outputs = [out_lib],
   230          mnemonic = "GoPack",
   231          executable = ctx.file.go_tool,
   232          arguments = ["tool", "pack", "c", out_lib.path] + [a.path for a in objects],
   233          env = go_environment_vars(ctx),
   234      )
   235  
   236  def _emit_go_cover_action(ctx, sources):
   237      """Construct the command line for test coverage instrument.
   238  
   239      Args:
   240        ctx: The starlark Context.
   241        sources: an iterable of Go source files.
   242  
   243      Returns:
   244        A list of Go source code files which might be coverage instrumented.
   245      """
   246      outputs = []
   247  
   248      # TODO(linuxerwang): make the mode configurable.
   249      count = 0
   250  
   251      for src in sources:
   252          if not src.path.endswith(".go") or src.path.endswith("_test.go"):
   253              outputs += [src]
   254              continue
   255  
   256          cover_var = "GoCover_%d" % count
   257          out = ctx.actions.declare_file(
   258              src.basename[:-3] + "_" + cover_var + ".cover.go",
   259              sibling = src,
   260          )
   261          outputs += [out]
   262          ctx.action(
   263              inputs = [src] + ctx.files.toolchain,
   264              outputs = [out],
   265              mnemonic = "GoCover",
   266              executable = ctx.file.go_tool,
   267              arguments = ["tool", "cover", "--mode=set", "-var=%s" % cover_var, "-o", out.path, src.path],
   268              env = go_environment_vars(ctx),
   269          )
   270          count += 1
   271  
   272      return outputs
   273  
   274  def go_library_impl(ctx):
   275      """Implements the go_library() rule."""
   276  
   277      sources = depset(ctx.files.srcs)
   278      go_srcs = depset([s for s in sources if s.basename.endswith(".go")])
   279      asm_srcs = [s for s in sources if s.basename.endswith(".s") or s.basename.endswith(".S")]
   280      asm_hdrs = [s for s in sources if s.basename.endswith(".h")]
   281      deps = ctx.attr.deps
   282      dep_runfiles = [d.data_runfiles for d in deps]
   283  
   284      cgo_object = None
   285      if hasattr(ctx.attr, "cgo_object"):
   286          cgo_object = ctx.attr.cgo_object
   287  
   288      if ctx.attr.library:
   289          go_srcs += ctx.attr.library.go_sources
   290          asm_srcs += ctx.attr.library.asm_sources
   291          asm_hdrs += ctx.attr.library.asm_headers
   292          deps += ctx.attr.library.direct_deps
   293          dep_runfiles += [ctx.attr.library.data_runfiles]
   294          if ctx.attr.library.cgo_object:
   295              if cgo_object:
   296                  fail("go_library %s cannot have cgo_object because the package " +
   297                       "already has cgo_object in %s" % (
   298                           ctx.label.name,
   299                           ctx.attr.library.name,
   300                       ))
   301              cgo_object = ctx.attr.library.cgo_object
   302      if not go_srcs:
   303          fail("may not be empty", "srcs")
   304  
   305      transitive_cgo_deps = depset([], order = "topological")
   306      if cgo_object:
   307          dep_runfiles += [cgo_object.data_runfiles]
   308          transitive_cgo_deps += cgo_object.cgo_deps
   309  
   310      extra_objects = [cgo_object.cgo_obj] if cgo_object else []
   311      for src in asm_srcs:
   312          obj = ctx.actions.declare_file(
   313              "%s.dir/%s.o" % (ctx.label.name, src.basename[:-2]),
   314              sibling = src,
   315          )
   316          _emit_go_asm_action(ctx, src, asm_hdrs, obj)
   317          extra_objects += [obj]
   318  
   319      lib_name = _go_importpath(ctx) + ".a"
   320      out_lib = ctx.actions.declare_file(lib_name)
   321      out_object = ctx.actions.declare_file(ctx.label.name + ".o")
   322      search_path = out_lib.path[:-len(lib_name)]
   323      gc_goopts = _gc_goopts(ctx)
   324      transitive_go_libraries = depset([out_lib])
   325      transitive_go_library_paths = depset([search_path])
   326      for dep in deps:
   327          transitive_go_libraries += dep.transitive_go_libraries
   328          transitive_cgo_deps += dep.transitive_cgo_deps
   329          transitive_go_library_paths += dep.transitive_go_library_paths
   330  
   331      go_srcs = _emit_go_compile_action(
   332          ctx,
   333          sources = go_srcs,
   334          deps = deps,
   335          libpaths = transitive_go_library_paths,
   336          out_object = out_object,
   337          gc_goopts = gc_goopts,
   338      )
   339      _emit_go_pack_action(ctx, out_lib, [out_object] + extra_objects)
   340  
   341      dylibs = []
   342      if cgo_object:
   343          dylibs += [d for d in cgo_object.cgo_deps if d.path.endswith(".so")]
   344  
   345      runfiles = ctx.runfiles(files = dylibs, collect_data = True)
   346      for d in dep_runfiles:
   347          runfiles = runfiles.merge(d)
   348  
   349      return struct(
   350          label = ctx.label,
   351          files = depset([out_lib]),
   352          runfiles = runfiles,
   353          go_sources = go_srcs,
   354          asm_sources = asm_srcs,
   355          asm_headers = asm_hdrs,
   356          cgo_object = cgo_object,
   357          direct_deps = ctx.attr.deps,
   358          transitive_cgo_deps = transitive_cgo_deps,
   359          transitive_go_libraries = transitive_go_libraries,
   360          transitive_go_library_paths = transitive_go_library_paths,
   361          gc_goopts = gc_goopts,
   362      )
   363  
   364  def _c_linker_options(ctx, blocklist = []):
   365      """Extracts flags to pass to $(CC) on link from the current context
   366  
   367      Args:
   368        ctx: the current context
   369        blocklist: Any flags starts with any of these prefixes are filtered out from
   370          the return value.
   371  
   372      Returns:
   373        A list of command line flags
   374      """
   375      cpp = ctx.fragments.cpp
   376      features = ctx.features
   377      options = cpp.compiler_options(features)
   378      options += cpp.unfiltered_compiler_options(features)
   379      options += cpp.link_options
   380      options += cpp.mostly_static_link_options(ctx.features, False)
   381      filtered = []
   382      for opt in options:
   383          if any([opt.startswith(prefix) for prefix in blocklist]):
   384              continue
   385          filtered.append(opt)
   386      return filtered
   387  
   388  def _gc_goopts(ctx):
   389      gc_goopts = [
   390          ctx.expand_make_variables("gc_goopts", f, {})
   391          for f in ctx.attr.gc_goopts
   392      ]
   393      if ctx.attr.library:
   394          gc_goopts += ctx.attr.library.gc_goopts
   395      return gc_goopts
   396  
   397  def _gc_linkopts(ctx):
   398      gc_linkopts = [
   399          ctx.expand_make_variables("gc_linkopts", f, {})
   400          for f in ctx.attr.gc_linkopts
   401      ]
   402      for k, v in ctx.attr.x_defs.items():
   403          gc_linkopts += ["-X", "%s='%s'" % (k, v)]
   404      return gc_linkopts
   405  
   406  def _extract_extldflags(gc_linkopts, extldflags):
   407      """Extracts -extldflags from gc_linkopts and combines them into a single list.
   408  
   409      Args:
   410        gc_linkopts: a list of flags passed in through the gc_linkopts attributes.
   411          ctx.expand_make_variables should have already been applied.
   412        extldflags: a list of flags to be passed to the external linker.
   413  
   414      Return:
   415        A tuple containing the filtered gc_linkopts with external flags removed,
   416        and a combined list of external flags.
   417      """
   418      filtered_gc_linkopts = []
   419      is_extldflags = False
   420      for opt in gc_linkopts:
   421          if is_extldflags:
   422              is_extldflags = False
   423              extldflags += [opt]
   424          elif opt == "-extldflags":
   425              is_extldflags = True
   426          else:
   427              filtered_gc_linkopts += [opt]
   428      return filtered_gc_linkopts, extldflags
   429  
   430  def _emit_go_link_action(
   431          ctx,
   432          transitive_go_library_paths,
   433          transitive_go_libraries,
   434          cgo_deps,
   435          libs,
   436          executable,
   437          gc_linkopts):
   438      """Sets up a symlink tree to libraries to link together."""
   439      config_strip = len(ctx.configuration.bin_dir.path) + 1
   440      pkg_depth = executable.dirname[config_strip:].count("/") + 1
   441  
   442      ld = "%s" % ctx.fragments.cpp.compiler_executable
   443      extldflags = _c_linker_options(ctx) + [
   444          "-Wl,-rpath,$ORIGIN/" + ("../" * pkg_depth),
   445      ]
   446      for d in cgo_deps:
   447          if d.basename.endswith(".so"):
   448              short_dir = d.dirname[len(d.root.path):]
   449              extldflags += ["-Wl,-rpath,$ORIGIN/" + ("../" * pkg_depth) + short_dir]
   450      gc_linkopts, extldflags = _extract_extldflags(gc_linkopts, extldflags)
   451  
   452      link_cmd = [
   453          ctx.file.go_tool.path,
   454          "tool",
   455          "link",
   456          "-L",
   457          ".",
   458      ]
   459      for path in transitive_go_library_paths:
   460          link_cmd += ["-L", path]
   461      link_cmd += [
   462          "-o",
   463          executable.path,
   464      ] + gc_linkopts + ['"${STAMP_XDEFS[@]}"']
   465  
   466      # workaround for a bug in ld(1) on Mac OS X.
   467      # http://lists.apple.com/archives/Darwin-dev/2006/Sep/msg00084.html
   468      # TODO(yugui) Remove this workaround once rules_go stops supporting XCode 7.2
   469      # or earlier.
   470      if not _is_darwin_cpu(ctx):
   471          link_cmd += ["-s"]
   472  
   473      link_cmd += [
   474          "-extld",
   475          ld,
   476          "-extldflags",
   477          "'%s'" % " ".join(extldflags),
   478      ] + [lib.path for lib in libs]
   479  
   480      # Avoided -s on OSX but but it requires dsymutil to be on $PATH.
   481      # TODO(yugui) Remove this workaround once rules_go stops supporting XCode 7.2
   482      # or earlier.
   483      cmds = ["export PATH=$PATH:/usr/bin"]
   484  
   485      cmds += [
   486          "STAMP_XDEFS=()",
   487      ]
   488  
   489      stamp_inputs = []
   490      if ctx.attr.linkstamp:
   491          # read workspace status files, converting "KEY value" lines
   492          # to "-X $linkstamp.KEY=value" arguments to the go linker.
   493          stamp_inputs = [ctx.info_file, ctx.version_file]
   494          for f in stamp_inputs:
   495              cmds += [
   496                  "while read -r key value || [[ -n $key ]]; do",
   497                  "  STAMP_XDEFS+=(-X \"%s.$key=$value\")" % ctx.attr.linkstamp,
   498                  "done < " + f.path,
   499              ]
   500  
   501      cmds += [" ".join(link_cmd)]
   502  
   503      f = _emit_generate_params_action(cmds, ctx, lib.basename + ".GoLinkFile.params")
   504  
   505      ctx.action(
   506          inputs = [f] + (list(transitive_go_libraries) + [lib] + list(cgo_deps) +
   507                          ctx.files.toolchain + ctx.files._crosstool) + stamp_inputs,
   508          outputs = [executable],
   509          command = f.path,
   510          mnemonic = "GoLink",
   511          env = go_environment_vars(ctx),
   512      )
   513  
   514  def go_binary_impl(ctx):
   515      """go_binary_impl emits actions for compiling and linking a go executable."""
   516      lib_result = go_library_impl(ctx)
   517      _emit_go_link_action(
   518          ctx,
   519          transitive_go_libraries = lib_result.transitive_go_libraries,
   520          transitive_go_library_paths = lib_result.transitive_go_library_paths,
   521          cgo_deps = lib_result.transitive_cgo_deps,
   522          libs = lib_result.files,
   523          executable = ctx.outputs.executable,
   524          gc_linkopts = _gc_linkopts(ctx),
   525      )
   526  
   527      return struct(
   528          files = depset([ctx.outputs.executable]),
   529          runfiles = lib_result.runfiles,
   530          cgo_object = lib_result.cgo_object,
   531      )
   532  
   533  def go_test_impl(ctx):
   534      """go_test_impl implements go testing.
   535  
   536      It emits an action to run the test generator, and then compiles the
   537      test into a binary."""
   538  
   539      lib_result = go_library_impl(ctx)
   540      main_go = ctx.actions.declare_file(ctx.label.name + "_main_test.go")
   541      main_object = ctx.actions.declare_file(ctx.label.name + "_main_test.o")
   542      main_lib = ctx.actions.declare_file(ctx.label.name + "_main_test.a")
   543      go_import = _go_importpath(ctx)
   544  
   545      cmds = [
   546          "UNFILTERED_TEST_FILES=(%s)" %
   547          " ".join(["'%s'" % f.path for f in lib_result.go_sources]),
   548          "FILTERED_TEST_FILES=()",
   549          "while read -r line; do",
   550          '  if [ -n "$line" ]; then',
   551          '    FILTERED_TEST_FILES+=("$line")',
   552          "  fi",
   553          'done < <(\'%s\' -cgo "${UNFILTERED_TEST_FILES[@]}")' %
   554          ctx.executable._filter_tags.path,
   555          " ".join([
   556              "'%s'" % ctx.executable.test_generator.path,
   557              "--package",
   558              go_import,
   559              "--output",
   560              "'%s'" % main_go.path,
   561              '"${FILTERED_TEST_FILES[@]}"',
   562          ]),
   563      ]
   564      f = _emit_generate_params_action(
   565          cmds,
   566          ctx,
   567          ctx.label.name + ".GoTestGenTest.params",
   568      )
   569      inputs = (list(lib_result.go_sources) + list(ctx.files.toolchain) +
   570                [f, ctx.executable._filter_tags, ctx.executable.test_generator])
   571      ctx.action(
   572          inputs = inputs,
   573          outputs = [main_go],
   574          command = f.path,
   575          mnemonic = "GoTestGenTest",
   576          env = dict(go_environment_vars(ctx), RUNDIR = ctx.label.package),
   577      )
   578  
   579      _emit_go_compile_action(
   580          ctx,
   581          sources = depset([main_go]),
   582          deps = ctx.attr.deps + [lib_result],
   583          libpaths = lib_result.transitive_go_library_paths,
   584          out_object = main_object,
   585          gc_goopts = _gc_goopts(ctx),
   586      )
   587      _emit_go_pack_action(ctx, main_lib, [main_object])
   588      _emit_go_link_action(
   589          ctx,
   590          transitive_go_library_paths = lib_result.transitive_go_library_paths,
   591          transitive_go_libraries = lib_result.transitive_go_libraries,
   592          cgo_deps = lib_result.transitive_cgo_deps,
   593          libs = [main_lib],
   594          executable = ctx.outputs.executable,
   595          gc_linkopts = _gc_linkopts(ctx),
   596      )
   597  
   598      # TODO(bazel-team): the Go tests should do a chdir to the directory
   599      # holding the data files, so open-source go tests continue to work
   600      # without code changes.
   601      runfiles = ctx.runfiles(files = [ctx.outputs.executable])
   602      runfiles = runfiles.merge(lib_result.runfiles)
   603      return struct(
   604          files = depset([ctx.outputs.executable]),
   605          runfiles = runfiles,
   606      )
   607  
   608  go_env_attrs = {
   609      "toolchain": attr.label(
   610          default = Label("//go/toolchain:toolchain"),
   611          allow_files = True,
   612          cfg = "host",
   613      ),
   614      "go_tool": attr.label(
   615          default = Label("//go/toolchain:go_tool"),
   616          single_file = True,
   617          allow_files = True,
   618          cfg = "host",
   619      ),
   620      "go_prefix": attr.label(
   621          providers = ["go_prefix"],
   622          default = Label(
   623              "//:go_prefix",
   624              relative_to_caller_repository = True,
   625          ),
   626          allow_files = False,
   627          cfg = "host",
   628      ),
   629      "go_src": attr.label(
   630          default = Label("//go/toolchain:go_src"),
   631          allow_files = True,
   632          cfg = "host",
   633      ),
   634      "go_include": attr.label(
   635          default = Label("//go/toolchain:go_include"),
   636          single_file = True,
   637          allow_files = True,
   638          cfg = "host",
   639      ),
   640      "go_root": attr.label(
   641          providers = ["go_root"],
   642          default = Label(
   643              "//go/toolchain:go_root",
   644          ),
   645          allow_files = False,
   646          cfg = "host",
   647      ),
   648      "_filter_tags": attr.label(
   649          default = Label("//go/tools/filter_tags"),
   650          cfg = "host",
   651          executable = True,
   652          single_file = True,
   653      ),
   654      "_filter_exec": attr.label(
   655          default = Label("//go/tools/filter_exec"),
   656          cfg = "host",
   657          executable = True,
   658          single_file = True,
   659      ),
   660      "_asm": attr.label(
   661          default = Label("//go/tools/builders:asm"),
   662          cfg = "host",
   663          executable = True,
   664          single_file = True,
   665      ),
   666  }
   667  
   668  go_library_attrs = go_env_attrs + {
   669      "data": attr.label_list(
   670          allow_files = True,
   671          cfg = "data",
   672      ),
   673      "srcs": attr.label_list(allow_files = go_filetype),
   674      "deps": attr.label_list(
   675          providers = [
   676              "transitive_go_library_paths",
   677              "transitive_go_libraries",
   678              "transitive_cgo_deps",
   679          ],
   680      ),
   681      "importpath": attr.string(),
   682      "library": attr.label(
   683          providers = [
   684              "direct_deps",
   685              "go_sources",
   686              "asm_sources",
   687              "cgo_object",
   688              "gc_goopts",
   689          ],
   690      ),
   691      "gc_goopts": attr.string_list(),
   692  }
   693  
   694  _crosstool_attrs = {
   695      "_crosstool": attr.label(
   696          default = Label("//tools/defaults:crosstool"),
   697      ),
   698  }
   699  
   700  go_link_attrs = go_library_attrs + _crosstool_attrs + {
   701      "gc_linkopts": attr.string_list(),
   702      "linkstamp": attr.string(),
   703      "x_defs": attr.string_dict(),
   704  }
   705  
   706  go_library = rule(
   707      go_library_impl,
   708      attrs = go_library_attrs + {
   709          "cgo_object": attr.label(
   710              providers = [
   711                  "cgo_obj",
   712                  "cgo_deps",
   713              ],
   714          ),
   715      },
   716      fragments = ["cpp"],
   717  )
   718  
   719  go_binary = rule(
   720      go_binary_impl,
   721      attrs = go_library_attrs + _crosstool_attrs + go_link_attrs,
   722      executable = True,
   723      fragments = ["cpp"],
   724  )
   725  
   726  go_test = rule(
   727      go_test_impl,
   728      attrs = go_library_attrs + _crosstool_attrs + go_link_attrs + {
   729          "test_generator": attr.label(
   730              executable = True,
   731              default = Label(
   732                  "//go/tools:generate_test_main",
   733              ),
   734              cfg = "host",
   735          ),
   736      },
   737      executable = True,
   738      fragments = ["cpp"],
   739      test = True,
   740  )
   741  
   742  def _pkg_dir(workspace_root, package_name):
   743      if workspace_root and package_name:
   744          return workspace_root + "/" + package_name
   745      if workspace_root:
   746          return workspace_root
   747      if package_name:
   748          return package_name
   749      return "."
   750  
   751  def _exec_path(path):
   752      if path.startswith("/"):
   753          return path
   754      return "${execroot}/" + path
   755  
   756  def _cgo_filter_srcs_impl(ctx):
   757      srcs = ctx.files.srcs
   758      dsts = []
   759      cmds = []
   760      for src in srcs:
   761          stem, _, ext = src.path.rpartition(".")
   762          dst_basename = "%s.filtered.%s" % (stem, ext)
   763          dst = ctx.actions.declare_file(dst_basename, sibling = src)
   764          cmds += [
   765              "if '%s' -cgo -quiet '%s'; then" %
   766              (ctx.executable._filter_tags.path, src.path),
   767              "  cp '%s' '%s'" % (src.path, dst.path),
   768              "else",
   769              "  echo -n >'%s'" % dst.path,
   770              "fi",
   771          ]
   772          dsts.append(dst)
   773  
   774      if ctx.label.package == "":
   775          script_name = ctx.label.name + ".CGoFilterSrcs.params"
   776      else:
   777          script_name = ctx.label.package + "/" + ctx.label.name + ".CGoFilterSrcs.params"
   778      f = _emit_generate_params_action(cmds, ctx, script_name)
   779      ctx.action(
   780          inputs = [f, ctx.executable._filter_tags] + srcs,
   781          outputs = dsts,
   782          command = f.path,
   783          mnemonic = "CgoFilterSrcs",
   784      )
   785      return struct(
   786          files = depset(dsts),
   787      )
   788  
   789  _cgo_filter_srcs = rule(
   790      implementation = _cgo_filter_srcs_impl,
   791      attrs = {
   792          "srcs": attr.label_list(
   793              allow_files = cgo_filetype,
   794          ),
   795          "_filter_tags": attr.label(
   796              default = Label("//go/tools/filter_tags"),
   797              cfg = "host",
   798              executable = True,
   799              single_file = True,
   800          ),
   801      },
   802      fragments = ["cpp"],
   803  )
   804  
   805  def _cgo_codegen_impl(ctx):
   806      go_srcs = ctx.files.srcs
   807      srcs = go_srcs + ctx.files.c_hdrs
   808      linkopts = ctx.attr.linkopts
   809      copts = ctx.fragments.cpp.c_options + ctx.attr.copts
   810      deps = depset([], order = "topological")
   811      for d in ctx.attr.deps:
   812          srcs += list(d.cc.transitive_headers)
   813          deps += d.cc.libs
   814          copts += ["-D" + define for define in d.cc.defines]
   815          for inc in d.cc.include_directories:
   816              copts += ["-I", _exec_path(inc)]
   817          for hdr in ctx.files.c_hdrs:
   818              copts += ["-iquote", hdr.dirname]
   819          for inc in d.cc.quote_include_directories:
   820              copts += ["-iquote", _exec_path(inc)]
   821          for inc in d.cc.system_include_directories:
   822              copts += ["-isystem", _exec_path(inc)]
   823          for lib in d.cc.libs:
   824              if lib.basename.startswith("lib") and lib.basename.endswith(".so"):
   825                  linkopts += ["-L", lib.dirname, "-l", lib.basename[3:-3]]
   826              else:
   827                  linkopts += [lib.path]
   828          linkopts += d.cc.link_flags
   829  
   830      p = _pkg_dir(ctx.label.workspace_root, ctx.label.package) + "/"
   831      if p == "./":
   832          p = ""  # workaround when cgo_library in repository root
   833      out_dir = (ctx.configuration.bin_dir.path + "/" +
   834                 p + ctx.attr.outdir)
   835      cc = ctx.fragments.cpp.compiler_executable
   836      cmds = [
   837          # We cannot use env for CC because $(CC) on OSX is relative
   838          # and '../' does not work fine due to symlinks.
   839          "export CC=$(cd $(dirname {cc}); pwd)/$(basename {cc})".format(cc = cc),
   840          "export CXX=$CC",
   841          'objdir="%s/gen"' % out_dir,
   842          "execroot=$(pwd)",
   843          'mkdir -p "$objdir"',
   844          "unfiltered_go_files=(%s)" % " ".join(["'%s'" % f.path for f in go_srcs]),
   845          "filtered_go_files=()",
   846          'for file in "${unfiltered_go_files[@]}"; do',
   847          '  stem=$(basename "$file" .go)',
   848          '  if %s -cgo -quiet "$file"; then' % ctx.executable._filter_tags.path,
   849          '    filtered_go_files+=("$file")',
   850          "  else",
   851          '    grep --max-count 1 "^package " "$file" >"$objdir/$stem.go"',
   852          '    echo -n >"$objdir/$stem.c"',
   853          "  fi",
   854          "done",
   855          "if [ ${#filtered_go_files[@]} -eq 0 ]; then",
   856          "  echo no buildable Go source files in %s >&1" % str(ctx.label),
   857          "  exit 1",
   858          "fi",
   859          '"$GOROOT/bin/go" tool cgo -objdir "$objdir" -- %s "${filtered_go_files[@]}"' %
   860          " ".join(['"%s"' % copt for copt in copts]),
   861          # Rename the outputs using glob so we don't have to understand cgo's mangling
   862          # TODO(#350): might be fixed by this?.
   863          'for file in "${filtered_go_files[@]}"; do',
   864          '  stem=$(basename "$file" .go)',
   865          '  mv "$objdir/"*"$stem.cgo1.go" "$objdir/$stem.go"',
   866          '  mv "$objdir/"*"$stem.cgo2.c" "$objdir/$stem.c"',
   867          "done",
   868          "rm -f $objdir/_cgo_.o $objdir/_cgo_flags",
   869      ]
   870  
   871      f = _emit_generate_params_action(cmds, ctx, out_dir + ".CGoCodeGenFile.params")
   872  
   873      inputs = (srcs + ctx.files.toolchain + ctx.files._crosstool +
   874                [f, ctx.executable._filter_tags])
   875      ctx.action(
   876          inputs = inputs,
   877          outputs = ctx.outputs.outs,
   878          mnemonic = "CGoCodeGen",
   879          progress_message = "CGoCodeGen %s" % ctx.label,
   880          command = f.path,
   881          env = go_environment_vars(ctx) + {
   882              "CGO_LDFLAGS": " ".join(linkopts),
   883          },
   884      )
   885      return struct(
   886          label = ctx.label,
   887          files = depset(ctx.outputs.outs),
   888          cgo_deps = deps,
   889      )
   890  
   891  _cgo_codegen_rule = rule(
   892      _cgo_codegen_impl,
   893      attrs = go_env_attrs + _crosstool_attrs + {
   894          "srcs": attr.label_list(
   895              allow_files = go_filetype,
   896              non_empty = True,
   897          ),
   898          "c_hdrs": attr.label_list(
   899              allow_files = cc_hdr_filetype,
   900          ),
   901          "deps": attr.label_list(
   902              allow_files = False,
   903              providers = ["cc"],
   904          ),
   905          "copts": attr.string_list(),
   906          "linkopts": attr.string_list(),
   907          "outdir": attr.string(mandatory = True),
   908          "outs": attr.output_list(
   909              mandatory = True,
   910              non_empty = True,
   911          ),
   912      },
   913      fragments = ["cpp"],
   914  )
   915  
   916  def _cgo_codegen(
   917          name,
   918          srcs,
   919          c_hdrs = [],
   920          deps = [],
   921          copts = [],
   922          linkopts = [],
   923          go_tool = None,
   924          toolchain = None):
   925      """Generates glue codes for interop between C and Go
   926  
   927      Args:
   928        name: A unique name of the rule
   929        srcs: list of Go source files.
   930          Each of them must contain `import "C"`.
   931        c_hdrs: C/C++ header files necessary to determine kinds of
   932          C/C++ identifiers in srcs.
   933        deps: A list of cc_library rules.
   934          The generated codes are expected to be linked with these deps.
   935        linkopts: A list of linker options,
   936          These flags are passed to the linker when the generated codes
   937          are linked into the target binary.
   938      """
   939      outdir = name + ".dir"
   940      outgen = outdir + "/gen"
   941  
   942      go_thunks = []
   943      c_thunks = []
   944      for s in srcs:
   945          if not s.endswith(".go"):
   946              fail("not a .go file: %s" % s)
   947          basename = s[:-3]
   948          if basename.rfind("/") >= 0:
   949              basename = basename[basename.rfind("/") + 1:]
   950          go_thunks.append(outgen + "/" + basename + ".go")
   951          c_thunks.append(outgen + "/" + basename + ".c")
   952  
   953      outs = struct(
   954          name = name,
   955          outdir = outgen,
   956          go_thunks = go_thunks,
   957          c_thunks = c_thunks,
   958          c_exports = [
   959              outgen + "/_cgo_export.c",
   960              outgen + "/_cgo_export.h",
   961          ],
   962          c_dummy = outgen + "/_cgo_main.c",
   963          gotypes = outgen + "/_cgo_gotypes.go",
   964      )
   965  
   966      _cgo_codegen_rule(
   967          name = name,
   968          srcs = srcs,
   969          c_hdrs = c_hdrs,
   970          deps = deps,
   971          copts = copts,
   972          linkopts = linkopts,
   973          go_tool = go_tool,
   974          toolchain = toolchain,
   975          outdir = outdir,
   976          outs = outs.go_thunks + outs.c_thunks + outs.c_exports + [
   977              outs.c_dummy,
   978              outs.gotypes,
   979          ],
   980          visibility = ["//visibility:private"],
   981      )
   982      return outs
   983  
   984  def _cgo_import_impl(ctx):
   985      cmds = [
   986          (ctx.file.go_tool.path + " tool cgo" +
   987           " -dynout " + ctx.outputs.out.path +
   988           " -dynimport " + ctx.file.cgo_o.path +
   989           " -dynpackage $(%s %s)" % (
   990               ctx.executable._extract_package.path,
   991               ctx.file.sample_go_src.path,
   992           )),
   993      ]
   994      f = _emit_generate_params_action(cmds, ctx, ctx.outputs.out.path + ".CGoImportGenFile.params")
   995      ctx.action(
   996          inputs = (ctx.files.toolchain +
   997                    [
   998                        f,
   999                        ctx.file.go_tool,
  1000                        ctx.executable._extract_package,
  1001                        ctx.file.cgo_o,
  1002                        ctx.file.sample_go_src,
  1003                    ]),
  1004          outputs = [ctx.outputs.out],
  1005          command = f.path,
  1006          mnemonic = "CGoImportGen",
  1007          env = go_environment_vars(ctx),
  1008      )
  1009      return struct(
  1010          files = depset([ctx.outputs.out]),
  1011      )
  1012  
  1013  _cgo_import = rule(
  1014      _cgo_import_impl,
  1015      attrs = go_env_attrs + {
  1016          "cgo_o": attr.label(
  1017              allow_files = True,
  1018              single_file = True,
  1019          ),
  1020          "sample_go_src": attr.label(
  1021              allow_files = True,
  1022              single_file = True,
  1023          ),
  1024          "out": attr.output(
  1025              mandatory = True,
  1026          ),
  1027          "_extract_package": attr.label(
  1028              default = Label("//go/tools/extract_package"),
  1029              executable = True,
  1030              cfg = "host",
  1031          ),
  1032      },
  1033      fragments = ["cpp"],
  1034  )
  1035  
  1036  def _cgo_genrule_impl(ctx):
  1037      return struct(
  1038          label = ctx.label,
  1039          go_sources = ctx.files.srcs,
  1040          asm_sources = [],
  1041          asm_headers = [],
  1042          cgo_object = ctx.attr.cgo_object,
  1043          direct_deps = ctx.attr.deps,
  1044          gc_goopts = [],
  1045      )
  1046  
  1047  _cgo_genrule = rule(
  1048      _cgo_genrule_impl,
  1049      attrs = {
  1050          "srcs": attr.label_list(allow_files = FileType([".go"])),
  1051          "cgo_object": attr.label(
  1052              providers = [
  1053                  "cgo_obj",
  1054                  "cgo_deps",
  1055              ],
  1056          ),
  1057          "deps": attr.label_list(
  1058              providers = [
  1059                  "direct_deps",
  1060                  "transitive_go_library_paths",
  1061                  "transitive_go_libraries",
  1062                  "transitive_cgo_deps",
  1063              ],
  1064          ),
  1065      },
  1066      fragments = ["cpp"],
  1067  )
  1068  
  1069  """Generates symbol-import directives for cgo
  1070  
  1071  Args:
  1072    cgo_o: The loadable object to extract dynamic symbols from.
  1073    sample_go_src: A go source which is compiled together with the generated file.
  1074      The generated file will have the same Go package name as this file.
  1075    out: Destination of the generated codes.
  1076  """
  1077  
  1078  def _cgo_object_impl(ctx):
  1079      arguments = _c_linker_options(ctx, blocklist = [
  1080          # never link any dependency libraries
  1081          "-l",
  1082          "-L",
  1083          # manage flags to ld(1) by ourselves
  1084          "-Wl,",
  1085      ])
  1086      arguments += [
  1087          "-o",
  1088          ctx.outputs.out.path,
  1089          "-nostdlib",
  1090          "-Wl,-r",
  1091      ]
  1092      if _is_darwin_cpu(ctx):
  1093          arguments += ["-shared", "-Wl,-all_load"]
  1094      else:
  1095          arguments += ["-Wl,-whole-archive"]
  1096  
  1097      lo = ctx.files.src[-1]
  1098      arguments += [lo.path]
  1099  
  1100      ctx.action(
  1101          inputs = [lo] + ctx.files._crosstool,
  1102          outputs = [ctx.outputs.out],
  1103          mnemonic = "CGoObject",
  1104          progress_message = "Linking %s" % ctx.outputs.out.short_path,
  1105          executable = ctx.fragments.cpp.compiler_executable,
  1106          arguments = arguments,
  1107      )
  1108      runfiles = ctx.runfiles(collect_data = True)
  1109      runfiles = runfiles.merge(ctx.attr.src.data_runfiles)
  1110      return struct(
  1111          files = depset([ctx.outputs.out]),
  1112          cgo_obj = ctx.outputs.out,
  1113          cgo_deps = ctx.attr.cgogen.cgo_deps,
  1114          runfiles = runfiles,
  1115      )
  1116  
  1117  _cgo_object = rule(
  1118      _cgo_object_impl,
  1119      attrs = _crosstool_attrs + {
  1120          "src": attr.label(
  1121              mandatory = True,
  1122              providers = ["cc"],
  1123          ),
  1124          "cgogen": attr.label(
  1125              mandatory = True,
  1126              providers = ["cgo_deps"],
  1127          ),
  1128          "out": attr.output(
  1129              mandatory = True,
  1130          ),
  1131      },
  1132      fragments = ["cpp"],
  1133  )
  1134  
  1135  """Generates _all.o to be archived together with Go objects.
  1136  
  1137  Args:
  1138    src: source static library which contains objects
  1139    cgogen: _cgo_codegen rule which knows the dependency cc_library() rules
  1140      to be linked together with src when we generate the final go binary.
  1141  """
  1142  
  1143  def _setup_cgo_library(name, srcs, cdeps, copts, clinkopts, go_tool, toolchain):
  1144      go_srcs = [s for s in srcs if s.endswith(".go")]
  1145      c_hdrs = [s for s in srcs if any([s.endswith(ext) for ext in hdr_exts])]
  1146      c_srcs = [s for s in srcs if not s in (go_srcs + c_hdrs)]
  1147  
  1148      # Split cgo files into .go parts and .c parts (plus some other files).
  1149      cgogen = _cgo_codegen(
  1150          name = name + ".cgo",
  1151          srcs = go_srcs,
  1152          c_hdrs = c_hdrs,
  1153          deps = cdeps,
  1154          copts = copts,
  1155          linkopts = clinkopts,
  1156          go_tool = go_tool,
  1157          toolchain = toolchain,
  1158      )
  1159  
  1160      # Filter c_srcs with build constraints.
  1161      c_filtered_srcs = []
  1162      if len(c_srcs) > 0:
  1163          c_filtered_srcs_name = name + "_filter_cgo_srcs"
  1164          _cgo_filter_srcs(
  1165              name = c_filtered_srcs_name,
  1166              srcs = c_srcs,
  1167          )
  1168          c_filtered_srcs.append(":" + c_filtered_srcs_name)
  1169  
  1170      pkg_dir = _pkg_dir(
  1171          "external/" + REPOSITORY_NAME[1:] if len(REPOSITORY_NAME) > 1 else "",
  1172          PACKAGE_NAME,
  1173      )
  1174  
  1175      # Platform-specific settings
  1176      native.config_setting(
  1177          name = name + "_windows_setting",
  1178          values = {
  1179              "cpu": "x64_windows_msvc",
  1180          },
  1181      )
  1182      platform_copts = select({
  1183          ":" + name + "_windows_setting": ["-mthreads"],
  1184          "//conditions:default": ["-pthread"],
  1185      })
  1186      platform_linkopts = select({
  1187          ":" + name + "_windows_setting": ["-mthreads"],
  1188          "//conditions:default": ["-pthread"],
  1189      })
  1190  
  1191      # Bundles objects into an archive so that _cgo_.o and _all.o can share them.
  1192      native.cc_library(
  1193          name = cgogen.outdir + "/_cgo_lib",
  1194          srcs = cgogen.c_thunks + cgogen.c_exports + c_filtered_srcs + c_hdrs,
  1195          deps = cdeps,
  1196          copts = copts + platform_copts + [
  1197              "-I",
  1198              pkg_dir,
  1199              "-I",
  1200              "$(GENDIR)/" + pkg_dir + "/" + cgogen.outdir,
  1201              # The generated thunks often contain unused variables.
  1202              "-Wno-unused-variable",
  1203          ],
  1204          linkopts = clinkopts + platform_linkopts,
  1205          linkstatic = 1,
  1206          # _cgo_.o and _all.o keep all objects in this archive.
  1207          # But it should not be very annoying in the final binary target
  1208          # because _cgo_object rule does not propagate alwayslink=1
  1209          alwayslink = 1,
  1210          visibility = ["//visibility:private"],
  1211      )
  1212  
  1213      # Loadable object which cgo reads when it generates _cgo_import.go
  1214      native.cc_binary(
  1215          name = cgogen.outdir + "/_cgo_.o",
  1216          srcs = [cgogen.c_dummy],
  1217          deps = cdeps + [cgogen.outdir + "/_cgo_lib"],
  1218          copts = copts,
  1219          linkopts = clinkopts,
  1220          visibility = ["//visibility:private"],
  1221      )
  1222      _cgo_import(
  1223          name = "%s.cgo.importgen" % name,
  1224          cgo_o = cgogen.outdir + "/_cgo_.o",
  1225          out = cgogen.outdir + "/_cgo_import.go",
  1226          sample_go_src = go_srcs[0],
  1227          go_tool = go_tool,
  1228          toolchain = toolchain,
  1229          visibility = ["//visibility:private"],
  1230      )
  1231  
  1232      _cgo_object(
  1233          name = cgogen.outdir + "/_cgo_object",
  1234          src = cgogen.outdir + "/_cgo_lib",
  1235          out = cgogen.outdir + "/_all.o",
  1236          cgogen = cgogen.name,
  1237          visibility = ["//visibility:private"],
  1238      )
  1239      return cgogen
  1240  
  1241  def cgo_genrule(
  1242          name,
  1243          srcs,
  1244          copts = [],
  1245          clinkopts = [],
  1246          cdeps = [],
  1247          **kwargs):
  1248      cgogen = _setup_cgo_library(
  1249          name = name,
  1250          srcs = srcs,
  1251          cdeps = cdeps,
  1252          copts = copts,
  1253          clinkopts = clinkopts,
  1254          toolchain = None,
  1255          go_tool = None,
  1256      )
  1257      _cgo_genrule(
  1258          name = name,
  1259          srcs = cgogen.go_thunks + [
  1260              cgogen.gotypes,
  1261              cgogen.outdir + "/_cgo_import.go",
  1262          ],
  1263          cgo_object = cgogen.outdir + "/_cgo_object",
  1264          **kwargs
  1265      )
  1266  
  1267  def cgo_library(
  1268          name,
  1269          srcs,
  1270          toolchain = None,
  1271          go_tool = None,
  1272          copts = [],
  1273          clinkopts = [],
  1274          cdeps = [],
  1275          **kwargs):
  1276      """Builds a cgo-enabled go library.
  1277  
  1278      Args:
  1279        name: A unique name for this rule.
  1280        srcs: List of Go, C and C++ files that are processed to build a Go library.
  1281          Those Go files must contain `import "C"`.
  1282          C and C++ files can be anything allowed in `srcs` attribute of
  1283          `cc_library`.
  1284        copts: Add these flags to the C++ compiler.
  1285        clinkopts: Add these flags to the C++ linker.
  1286        cdeps: List of C/C++ libraries to be linked into the binary target.
  1287          They must be `cc_library` rules.
  1288        deps: List of other libraries to be linked to this library target.
  1289        data: List of files needed by this rule at runtime.
  1290  
  1291      NOTE:
  1292        `srcs` cannot contain pure-Go files, which do not have `import "C"`.
  1293        So you need to define another `go_library` when you build a go package with
  1294        both cgo-enabled and pure-Go sources.
  1295  
  1296        ```
  1297        cgo_library(
  1298            name = "cgo_enabled",
  1299            srcs = ["cgo-enabled.go", "foo.cc", "bar.S", "baz.a"],
  1300        )
  1301  
  1302        go_library(
  1303            name = "go_default_library",
  1304            srcs = ["pure-go.go"],
  1305            library = ":cgo_enabled",
  1306        )
  1307        ```
  1308      """
  1309      cgogen = _setup_cgo_library(
  1310          name = name,
  1311          srcs = srcs,
  1312          cdeps = cdeps,
  1313          copts = copts,
  1314          clinkopts = clinkopts,
  1315          go_tool = go_tool,
  1316          toolchain = toolchain,
  1317      )
  1318  
  1319      go_library(
  1320          name = name,
  1321          srcs = cgogen.go_thunks + [
  1322              cgogen.gotypes,
  1323              cgogen.outdir + "/_cgo_import.go",
  1324          ],
  1325          cgo_object = cgogen.outdir + "/_cgo_object",
  1326          go_tool = go_tool,
  1327          toolchain = toolchain,
  1328          **kwargs
  1329      )