github.com/bazelbuild/rules_go@v0.47.2-0.20240515105122-e7ddb9ea474e/go/private/actions/archive.bzl (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  load(
    16      "//go/private:common.bzl",
    17      "as_tuple",
    18      "split_srcs",
    19  )
    20  load(
    21      "//go/private:mode.bzl",
    22      "LINKMODE_C_ARCHIVE",
    23      "LINKMODE_C_SHARED",
    24      "mode_string",
    25  )
    26  load(
    27      "//go/private:providers.bzl",
    28      "GoArchive",
    29      "GoArchiveData",
    30      "effective_importpath_pkgpath",
    31      "get_archive",
    32  )
    33  load(
    34      "//go/private/actions:compilepkg.bzl",
    35      "emit_compilepkg",
    36  )
    37  load(
    38      "//go/private/rules:cgo.bzl",
    39      "cgo_configure",
    40  )
    41  
    42  def emit_archive(go, source = None, _recompile_suffix = "", recompile_internal_deps = None, is_external_pkg = False):
    43      """See go/toolchains.rst#archive for full documentation."""
    44  
    45      if source == None:
    46          fail("source is a required parameter")
    47  
    48      split = split_srcs(source.srcs)
    49      testfilter = getattr(source.library, "testfilter", None)
    50      pre_ext = ""
    51      if go.mode.link == LINKMODE_C_ARCHIVE:
    52          pre_ext = "_"  # avoid collision with go_binary output file with .a extension
    53      elif testfilter == "exclude":
    54          pre_ext = ".internal"
    55      elif testfilter == "only":
    56          pre_ext = ".external"
    57      if _recompile_suffix:
    58          pre_ext += _recompile_suffix
    59      out_lib = go.declare_file(go, name = source.library.name, ext = pre_ext + ".a")
    60  
    61      # store export information for compiling dependent packages separately
    62      out_export = go.declare_file(go, name = source.library.name, ext = pre_ext + ".x")
    63      out_cgo_export_h = None  # set if cgo used in c-shared or c-archive mode
    64      out_facts = None
    65      nogo = go.get_nogo(go)
    66      if nogo:
    67          out_facts = go.declare_file(go, name = source.library.name, ext = pre_ext + ".facts")
    68  
    69      direct = [get_archive(dep) for dep in source.deps]
    70      runfiles = source.runfiles
    71      data_files = runfiles.files
    72  
    73      files = []
    74      for a in direct:
    75          files.append(a.runfiles)
    76          if a.source.mode != go.mode:
    77              fail("Archive mode does not match {} is {} expected {}".format(a.data.label, mode_string(a.source.mode), mode_string(go.mode)))
    78      runfiles = runfiles.merge_all(files)
    79  
    80      importmap = "main" if source.library.is_main else source.library.importmap
    81      importpath, _ = effective_importpath_pkgpath(source.library)
    82  
    83      if source.cgo and not go.mode.pure:
    84          # TODO(jayconrod): do we need to do full Bourne tokenization here?
    85          cppopts = [f for fs in source.cppopts for f in fs.split(" ")]
    86          copts = [f for fs in source.copts for f in fs.split(" ")]
    87          cxxopts = [f for fs in source.cxxopts for f in fs.split(" ")]
    88          clinkopts = [f for fs in source.clinkopts for f in fs.split(" ")]
    89          cgo = cgo_configure(
    90              go,
    91              srcs = split.go + split.c + split.asm + split.cxx + split.objc + split.headers + split.syso,
    92              cdeps = source.cdeps,
    93              cppopts = cppopts,
    94              copts = copts,
    95              cxxopts = cxxopts,
    96              clinkopts = clinkopts,
    97          )
    98          if go.mode.link in (LINKMODE_C_SHARED, LINKMODE_C_ARCHIVE):
    99              out_cgo_export_h = go.declare_file(go, path = "_cgo_install.h")
   100          cgo_deps = cgo.deps
   101          runfiles = runfiles.merge(cgo.runfiles)
   102          emit_compilepkg(
   103              go,
   104              sources = split.go + split.c + split.asm + split.cxx + split.objc + split.headers + split.syso,
   105              cover = source.cover,
   106              embedsrcs = source.embedsrcs,
   107              importpath = importpath,
   108              importmap = importmap,
   109              archives = direct,
   110              out_lib = out_lib,
   111              out_export = out_export,
   112              out_facts = out_facts,
   113              nogo = nogo,
   114              out_cgo_export_h = out_cgo_export_h,
   115              gc_goopts = source.gc_goopts,
   116              cgo = True,
   117              cgo_inputs = cgo.inputs,
   118              cppopts = cgo.cppopts,
   119              copts = cgo.copts,
   120              cxxopts = cgo.cxxopts,
   121              objcopts = cgo.objcopts,
   122              objcxxopts = cgo.objcxxopts,
   123              clinkopts = cgo.clinkopts,
   124              testfilter = testfilter,
   125              is_external_pkg = is_external_pkg,
   126          )
   127      else:
   128          cgo_deps = depset()
   129          emit_compilepkg(
   130              go,
   131              sources = split.go + split.c + split.asm + split.cxx + split.objc + split.headers + split.syso,
   132              cover = source.cover,
   133              embedsrcs = source.embedsrcs,
   134              importpath = importpath,
   135              importmap = importmap,
   136              archives = direct,
   137              out_lib = out_lib,
   138              out_export = out_export,
   139              out_facts = out_facts,
   140              nogo = nogo,
   141              gc_goopts = source.gc_goopts,
   142              cgo = False,
   143              testfilter = testfilter,
   144              recompile_internal_deps = recompile_internal_deps,
   145              is_external_pkg = is_external_pkg,
   146          )
   147  
   148      data = GoArchiveData(
   149          # TODO(#2578): reconsider the provider API. There's a lot of redundant
   150          # information here. Some fields are tuples instead of lists or dicts
   151          # since GoArchiveData is stored in a depset, and no value in a depset
   152          # may be mutable. For now, new copied fields are private (named with
   153          # a leading underscore) since they may change in the future.
   154  
   155          # GoLibrary fields
   156          name = source.library.name,
   157          label = source.library.label,
   158          importpath = source.library.importpath,
   159          importmap = source.library.importmap,
   160          importpath_aliases = source.library.importpath_aliases,
   161          pathtype = source.library.pathtype,
   162  
   163          # GoSource fields
   164          srcs = as_tuple(source.srcs),
   165          orig_srcs = as_tuple(source.orig_srcs),
   166          _orig_src_map = tuple([source.orig_src_map.get(src, src) for src in source.srcs]),
   167          _cover = as_tuple(source.cover),
   168          _embedsrcs = as_tuple(source.embedsrcs),
   169          _x_defs = tuple(source.x_defs.items()),
   170          _gc_goopts = as_tuple(source.gc_goopts),
   171          _cgo = source.cgo,
   172          _cdeps = as_tuple(source.cdeps),
   173          _cppopts = as_tuple(source.cppopts),
   174          _copts = as_tuple(source.copts),
   175          _cxxopts = as_tuple(source.cxxopts),
   176          _clinkopts = as_tuple(source.clinkopts),
   177          _cgo_exports = as_tuple(source.cgo_exports),
   178  
   179          # Information on dependencies
   180          _dep_labels = tuple([d.data.label for d in direct]),
   181          _dep_importmaps = tuple([d.data.importmap for d in direct]),
   182  
   183          # Information needed by dependents
   184          file = out_lib,
   185          export_file = out_export,
   186          facts_file = out_facts,
   187          data_files = as_tuple(data_files),
   188          _cgo_deps = as_tuple(cgo_deps),
   189      )
   190      x_defs = dict(source.x_defs)
   191      for a in direct:
   192          x_defs.update(a.x_defs)
   193      cgo_exports_direct = list(source.cgo_exports)
   194  
   195      # Ensure that the _cgo_export.h of the current target comes first when cgo_exports is iterated
   196      # by prepending it and specifying the order explicitly. This is required as the CcInfo attached
   197      # to the archive only exposes a single header rather than combining all headers.
   198      if out_cgo_export_h:
   199          cgo_exports_direct.insert(0, out_cgo_export_h)
   200      cgo_exports = depset(direct = cgo_exports_direct, transitive = [a.cgo_exports for a in direct], order = "preorder")
   201      return GoArchive(
   202          source = source,
   203          data = data,
   204          direct = direct,
   205          libs = depset(direct = [out_lib], transitive = [a.libs for a in direct]),
   206          transitive = depset([data], transitive = [a.transitive for a in direct]),
   207          x_defs = x_defs,
   208          cgo_deps = depset(transitive = [cgo_deps] + [a.cgo_deps for a in direct]),
   209          cgo_exports = cgo_exports,
   210          runfiles = runfiles,
   211          mode = go.mode,
   212      )