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