github.com/bazelbuild/rules_go@v0.47.2-0.20240515105122-e7ddb9ea474e/go/private/actions/stdlib.bzl (about)

     1  # Copyright 2019 The Bazel Go Rules 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      "COVERAGE_OPTIONS_DENYLIST",
    18      "GO_TOOLCHAIN_LABEL",
    19  )
    20  load(
    21      "//go/private:mode.bzl",
    22      "LINKMODE_NORMAL",
    23      "extldflags_from_cc_toolchain",
    24      "link_mode_args",
    25  )
    26  load(
    27      "//go/private:providers.bzl",
    28      "GoStdLib",
    29  )
    30  load("//go/private:sdk.bzl", "parse_version")
    31  load("//go/private/actions:utils.bzl", "quote_opts")
    32  
    33  def emit_stdlib(go):
    34      """Returns a standard library for the target configuration.
    35  
    36      If the precompiled standard library is suitable, it will be returned.
    37      Otherwise, the standard library will be compiled for the target.
    38  
    39      Returns:
    40          A list of providers containing GoLibrary and GoSource. GoSource.stdlib
    41          will point to a new GoStdLib.
    42      """
    43      library = go.new_library(go, resolver = _stdlib_library_to_source)
    44      source = go.library_to_source(go, {}, library, False)
    45      return [source, library]
    46  
    47  def _stdlib_library_to_source(go, _attr, source, _merge):
    48      if _should_use_sdk_stdlib(go):
    49          source["stdlib"] = _sdk_stdlib(go)
    50      else:
    51          source["stdlib"] = _build_stdlib(go)
    52  
    53  def _should_use_sdk_stdlib(go):
    54      version = parse_version(go.sdk.version)
    55      if version and version[0] <= 1 and version[1] <= 19 and go.sdk.experiments:
    56          # The precompiled stdlib shipped with 1.19 or below doesn't have experiments
    57          return False
    58      return (go.sdk.libs and  # go.sdk.libs is non-empty if sdk ships with precompiled .a files
    59              go.mode.goos == go.sdk.goos and
    60              go.mode.goarch == go.sdk.goarch and
    61              not go.mode.race and  # TODO(jayconrod): use precompiled race
    62              not go.mode.msan and
    63              not go.mode.pure and
    64              not go.mode.gc_goopts and
    65              go.mode.link == LINKMODE_NORMAL)
    66  
    67  def _build_stdlib_list_json(go):
    68      out = go.declare_file(go, "stdlib.pkg.json")
    69      cache_dir = go.declare_directory(go, "gocache")
    70      args = go.builder_args(go, "stdliblist")
    71      args.add("-sdk", go.sdk.root_file.dirname)
    72      args.add("-out", out)
    73      args.add("-cache", cache_dir.path)
    74  
    75      inputs = go.sdk_files
    76      if not go.mode.pure:
    77          inputs += go.crosstool
    78  
    79      go.actions.run(
    80          inputs = inputs,
    81          outputs = [out, cache_dir],
    82          mnemonic = "GoStdlibList",
    83          executable = go.toolchain._builder,
    84          arguments = [args],
    85          env = _build_env(go),
    86          toolchain = GO_TOOLCHAIN_LABEL,
    87      )
    88      return out
    89  
    90  def _build_env(go):
    91      env = go.env
    92  
    93      if go.mode.pure:
    94          env.update({"CGO_ENABLED": "0"})
    95          return env
    96  
    97      # NOTE(#2545): avoid unnecessary dynamic link
    98      # go std library doesn't use C++, so should not have -lstdc++
    99      # Also drop coverage flags as nothing in the stdlib is compiled with
   100      # coverage - we disable it for all CGo code anyway.
   101      # NOTE(#3590): avoid forcing static linking.
   102      ldflags = [
   103          option
   104          for option in extldflags_from_cc_toolchain(go)
   105          if option not in ("-lstdc++", "-lc++", "-static") and option not in COVERAGE_OPTIONS_DENYLIST
   106      ]
   107      env.update({
   108          "CGO_ENABLED": "1",
   109          "CC": go.cgo_tools.c_compiler_path,
   110          "CGO_CFLAGS": " ".join(go.cgo_tools.c_compile_options),
   111          "CGO_LDFLAGS": " ".join(ldflags),
   112      })
   113  
   114      return env
   115  
   116  def _sdk_stdlib(go):
   117      return GoStdLib(
   118          _list_json = _build_stdlib_list_json(go),
   119          libs = go.sdk.libs,
   120          root_file = go.sdk.root_file,
   121      )
   122  
   123  def _build_stdlib(go):
   124      pkg = go.declare_directory(go, path = "pkg")
   125      args = go.builder_args(go, "stdlib")
   126      args.add("-out", pkg.dirname)
   127      if go.mode.race:
   128          args.add("-race")
   129      args.add("-package", "std")
   130      if not go.mode.pure:
   131          args.add("-package", "runtime/cgo")
   132      args.add_all(link_mode_args(go.mode))
   133  
   134      args.add("-gcflags", quote_opts(go.mode.gc_goopts))
   135  
   136      inputs = (go.sdk.srcs +
   137                go.sdk.headers +
   138                go.sdk.tools +
   139                [go.sdk.go, go.sdk.package_list, go.sdk.root_file] +
   140                go.crosstool)
   141  
   142      if go.mode.pgoprofile:
   143          args.add("-pgoprofile", go.mode.pgoprofile)
   144          inputs.append(go.mode.pgoprofile)
   145  
   146      outputs = [pkg]
   147      go.actions.run(
   148          inputs = inputs,
   149          outputs = outputs,
   150          mnemonic = "GoStdlib",
   151          executable = go.toolchain._builder,
   152          arguments = [args],
   153          env = _build_env(go),
   154          toolchain = GO_TOOLCHAIN_LABEL,
   155      )
   156      return GoStdLib(
   157          _list_json = _build_stdlib_list_json(go),
   158          libs = [pkg],
   159          root_file = pkg,
   160      )