1*9bb1b549SSpandan Das# Copyright 2017 The Bazel Authors. All rights reserved. 2*9bb1b549SSpandan Das# 3*9bb1b549SSpandan Das# Licensed under the Apache License, Version 2.0 (the "License"); 4*9bb1b549SSpandan Das# you may not use this file except in compliance with the License. 5*9bb1b549SSpandan Das# You may obtain a copy of the License at 6*9bb1b549SSpandan Das# 7*9bb1b549SSpandan Das# http://www.apache.org/licenses/LICENSE-2.0 8*9bb1b549SSpandan Das# 9*9bb1b549SSpandan Das# Unless required by applicable law or agreed to in writing, software 10*9bb1b549SSpandan Das# distributed under the License is distributed on an "AS IS" BASIS, 11*9bb1b549SSpandan Das# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*9bb1b549SSpandan Das# See the License for the specific language governing permissions and 13*9bb1b549SSpandan Das# limitations under the License. 14*9bb1b549SSpandan Das 15*9bb1b549SSpandan Dasload( 16*9bb1b549SSpandan Das "@bazel_tools//tools/cpp:toolchain_utils.bzl", 17*9bb1b549SSpandan Das "find_cpp_toolchain", 18*9bb1b549SSpandan Das) 19*9bb1b549SSpandan Dasload( 20*9bb1b549SSpandan Das "@bazel_tools//tools/build_defs/cc:action_names.bzl", 21*9bb1b549SSpandan Das "CPP_COMPILE_ACTION_NAME", 22*9bb1b549SSpandan Das "CPP_LINK_DYNAMIC_LIBRARY_ACTION_NAME", 23*9bb1b549SSpandan Das "CPP_LINK_EXECUTABLE_ACTION_NAME", 24*9bb1b549SSpandan Das "CPP_LINK_STATIC_LIBRARY_ACTION_NAME", 25*9bb1b549SSpandan Das "C_COMPILE_ACTION_NAME", 26*9bb1b549SSpandan Das "OBJCPP_COMPILE_ACTION_NAME", 27*9bb1b549SSpandan Das "OBJC_COMPILE_ACTION_NAME", 28*9bb1b549SSpandan Das) 29*9bb1b549SSpandan Dasload( 30*9bb1b549SSpandan Das ":go_toolchain.bzl", 31*9bb1b549SSpandan Das "GO_TOOLCHAIN", 32*9bb1b549SSpandan Das) 33*9bb1b549SSpandan Dasload( 34*9bb1b549SSpandan Das ":providers.bzl", 35*9bb1b549SSpandan Das "CgoContextInfo", 36*9bb1b549SSpandan Das "EXPLICIT_PATH", 37*9bb1b549SSpandan Das "EXPORT_PATH", 38*9bb1b549SSpandan Das "GoArchive", 39*9bb1b549SSpandan Das "GoConfigInfo", 40*9bb1b549SSpandan Das "GoContextInfo", 41*9bb1b549SSpandan Das "GoLibrary", 42*9bb1b549SSpandan Das "GoSource", 43*9bb1b549SSpandan Das "GoStdLib", 44*9bb1b549SSpandan Das "INFERRED_PATH", 45*9bb1b549SSpandan Das "get_source", 46*9bb1b549SSpandan Das) 47*9bb1b549SSpandan Dasload( 48*9bb1b549SSpandan Das ":mode.bzl", 49*9bb1b549SSpandan Das "get_mode", 50*9bb1b549SSpandan Das "installsuffix", 51*9bb1b549SSpandan Das) 52*9bb1b549SSpandan Dasload( 53*9bb1b549SSpandan Das ":common.bzl", 54*9bb1b549SSpandan Das "COVERAGE_OPTIONS_DENYLIST", 55*9bb1b549SSpandan Das "as_iterable", 56*9bb1b549SSpandan Das "goos_to_extension", 57*9bb1b549SSpandan Das "goos_to_shared_extension", 58*9bb1b549SSpandan Das "is_struct", 59*9bb1b549SSpandan Das) 60*9bb1b549SSpandan Dasload( 61*9bb1b549SSpandan Das "//go/platform:apple.bzl", 62*9bb1b549SSpandan Das "apple_ensure_options", 63*9bb1b549SSpandan Das) 64*9bb1b549SSpandan Dasload( 65*9bb1b549SSpandan Das "@bazel_skylib//rules:common_settings.bzl", 66*9bb1b549SSpandan Das "BuildSettingInfo", 67*9bb1b549SSpandan Das) 68*9bb1b549SSpandan Dasload( 69*9bb1b549SSpandan Das "//go/private/rules:transition.bzl", 70*9bb1b549SSpandan Das "request_nogo_transition", 71*9bb1b549SSpandan Das) 72*9bb1b549SSpandan Das 73*9bb1b549SSpandan Das# cgo requires a gcc/clang style compiler. 74*9bb1b549SSpandan Das# We use a denylist instead of an allowlist: 75*9bb1b549SSpandan Das# - Bazel's auto-detected toolchains used to set the compiler name to "compiler" 76*9bb1b549SSpandan Das# for gcc (fixed in 6.0.0), which defeats the purpose of an allowlist. 77*9bb1b549SSpandan Das# - The compiler name field is free-form and user-defined, so we would have to 78*9bb1b549SSpandan Das# provide a way to override this list. 79*9bb1b549SSpandan Das# TODO: Convert to a denylist once we can assume Bazel 6.0.0 or later and have a 80*9bb1b549SSpandan Das# way for users to extend the list. 81*9bb1b549SSpandan Das_UNSUPPORTED_C_COMPILERS = { 82*9bb1b549SSpandan Das "msvc-cl": None, 83*9bb1b549SSpandan Das "clang-cl": None, 84*9bb1b549SSpandan Das} 85*9bb1b549SSpandan Das 86*9bb1b549SSpandan Das_COMPILER_OPTIONS_DENYLIST = dict({ 87*9bb1b549SSpandan Das # cgo parses the error messages from the compiler. It can't handle colors. 88*9bb1b549SSpandan Das # Ignore both variants of the diagnostics color flag. 89*9bb1b549SSpandan Das "-fcolor-diagnostics": None, 90*9bb1b549SSpandan Das "-fdiagnostics-color": None, 91*9bb1b549SSpandan Das 92*9bb1b549SSpandan Das # cgo also wants to see all the errors when it is testing the compiler. 93*9bb1b549SSpandan Das # fmax-errors limits that and causes build failures. 94*9bb1b549SSpandan Das "-fmax-errors=": None, 95*9bb1b549SSpandan Das "-Wall": None, 96*9bb1b549SSpandan Das 97*9bb1b549SSpandan Das # Symbols are needed by Go, so keep them 98*9bb1b549SSpandan Das "-g0": None, 99*9bb1b549SSpandan Das 100*9bb1b549SSpandan Das # Don't compile generated cgo code with coverage. If we do an internal 101*9bb1b549SSpandan Das # link, we may have undefined references to coverage functions. 102*9bb1b549SSpandan Das "--coverage": None, 103*9bb1b549SSpandan Das "-ftest-coverage": None, 104*9bb1b549SSpandan Das "-fprofile-arcs": None, 105*9bb1b549SSpandan Das "-fprofile-instr-generate": None, 106*9bb1b549SSpandan Das "-fcoverage-mapping": None, 107*9bb1b549SSpandan Das}, **COVERAGE_OPTIONS_DENYLIST) 108*9bb1b549SSpandan Das 109*9bb1b549SSpandan Das_LINKER_OPTIONS_DENYLIST = { 110*9bb1b549SSpandan Das "-Wl,--gc-sections": None, 111*9bb1b549SSpandan Das} 112*9bb1b549SSpandan Das 113*9bb1b549SSpandan Das_UNSUPPORTED_FEATURES = [ 114*9bb1b549SSpandan Das # These toolchain features require special rule support and will thus break 115*9bb1b549SSpandan Das # with CGo. 116*9bb1b549SSpandan Das # Taken from https://github.com/bazelbuild/rules_rust/blob/521e649ff44e9711fe3c45b0ec1e792f7e1d361e/rust/private/utils.bzl#L20. 117*9bb1b549SSpandan Das "thin_lto", 118*9bb1b549SSpandan Das "module_maps", 119*9bb1b549SSpandan Das "use_header_modules", 120*9bb1b549SSpandan Das "fdo_instrument", 121*9bb1b549SSpandan Das "fdo_optimize", 122*9bb1b549SSpandan Das] 123*9bb1b549SSpandan Das 124*9bb1b549SSpandan Dasdef _match_option(option, pattern): 125*9bb1b549SSpandan Das if pattern.endswith("="): 126*9bb1b549SSpandan Das return option.startswith(pattern) 127*9bb1b549SSpandan Das else: 128*9bb1b549SSpandan Das return option == pattern 129*9bb1b549SSpandan Das 130*9bb1b549SSpandan Dasdef _filter_options(options, denylist): 131*9bb1b549SSpandan Das return [ 132*9bb1b549SSpandan Das option 133*9bb1b549SSpandan Das for option in options 134*9bb1b549SSpandan Das if not any([_match_option(option, pattern) for pattern in denylist]) 135*9bb1b549SSpandan Das ] 136*9bb1b549SSpandan Das 137*9bb1b549SSpandan Dasdef _child_name(go, path, ext, name): 138*9bb1b549SSpandan Das if not name: 139*9bb1b549SSpandan Das name = go.label.name 140*9bb1b549SSpandan Das if path or not ext: 141*9bb1b549SSpandan Das # The '_' avoids collisions with another file matching the label name. 142*9bb1b549SSpandan Das # For example, hello and hello/testmain.go. 143*9bb1b549SSpandan Das name += "_" 144*9bb1b549SSpandan Das if path: 145*9bb1b549SSpandan Das name += "/" + path 146*9bb1b549SSpandan Das if ext: 147*9bb1b549SSpandan Das name += ext 148*9bb1b549SSpandan Das return name 149*9bb1b549SSpandan Das 150*9bb1b549SSpandan Dasdef _declare_file(go, path = "", ext = "", name = ""): 151*9bb1b549SSpandan Das return go.actions.declare_file(_child_name(go, path, ext, name)) 152*9bb1b549SSpandan Das 153*9bb1b549SSpandan Dasdef _declare_directory(go, path = "", ext = "", name = ""): 154*9bb1b549SSpandan Das return go.actions.declare_directory(_child_name(go, path, ext, name)) 155*9bb1b549SSpandan Das 156*9bb1b549SSpandan Dasdef _new_args(go): 157*9bb1b549SSpandan Das # TODO(jayconrod): print warning. 158*9bb1b549SSpandan Das return go.builder_args(go) 159*9bb1b549SSpandan Das 160*9bb1b549SSpandan Dasdef _builder_args(go, command = None): 161*9bb1b549SSpandan Das args = go.actions.args() 162*9bb1b549SSpandan Das args.use_param_file("-param=%s") 163*9bb1b549SSpandan Das args.set_param_file_format("shell") 164*9bb1b549SSpandan Das if command: 165*9bb1b549SSpandan Das args.add(command) 166*9bb1b549SSpandan Das args.add("-sdk", go.sdk.root_file.dirname) 167*9bb1b549SSpandan Das args.add("-installsuffix", installsuffix(go.mode)) 168*9bb1b549SSpandan Das args.add_joined("-tags", go.tags, join_with = ",") 169*9bb1b549SSpandan Das return args 170*9bb1b549SSpandan Das 171*9bb1b549SSpandan Dasdef _tool_args(go): 172*9bb1b549SSpandan Das args = go.actions.args() 173*9bb1b549SSpandan Das args.use_param_file("-param=%s") 174*9bb1b549SSpandan Das args.set_param_file_format("shell") 175*9bb1b549SSpandan Das return args 176*9bb1b549SSpandan Das 177*9bb1b549SSpandan Dasdef _new_library(go, name = None, importpath = None, resolver = None, importable = True, testfilter = None, is_main = False, **kwargs): 178*9bb1b549SSpandan Das if not importpath: 179*9bb1b549SSpandan Das importpath = go.importpath 180*9bb1b549SSpandan Das importmap = go.importmap 181*9bb1b549SSpandan Das else: 182*9bb1b549SSpandan Das importmap = importpath 183*9bb1b549SSpandan Das pathtype = go.pathtype 184*9bb1b549SSpandan Das if not importable and pathtype == EXPLICIT_PATH: 185*9bb1b549SSpandan Das pathtype = EXPORT_PATH 186*9bb1b549SSpandan Das 187*9bb1b549SSpandan Das return GoLibrary( 188*9bb1b549SSpandan Das name = go.label.name if not name else name, 189*9bb1b549SSpandan Das label = go.label, 190*9bb1b549SSpandan Das importpath = importpath, 191*9bb1b549SSpandan Das importmap = importmap, 192*9bb1b549SSpandan Das importpath_aliases = go.importpath_aliases, 193*9bb1b549SSpandan Das pathtype = pathtype, 194*9bb1b549SSpandan Das resolve = resolver, 195*9bb1b549SSpandan Das testfilter = testfilter, 196*9bb1b549SSpandan Das is_main = is_main, 197*9bb1b549SSpandan Das **kwargs 198*9bb1b549SSpandan Das ) 199*9bb1b549SSpandan Das 200*9bb1b549SSpandan Dasdef _merge_embed(source, embed): 201*9bb1b549SSpandan Das s = get_source(embed) 202*9bb1b549SSpandan Das source["srcs"] = s.srcs + source["srcs"] 203*9bb1b549SSpandan Das source["orig_srcs"] = s.orig_srcs + source["orig_srcs"] 204*9bb1b549SSpandan Das source["orig_src_map"].update(s.orig_src_map) 205*9bb1b549SSpandan Das source["embedsrcs"] = source["embedsrcs"] + s.embedsrcs 206*9bb1b549SSpandan Das source["cover"] = source["cover"] + s.cover 207*9bb1b549SSpandan Das source["deps"] = source["deps"] + s.deps 208*9bb1b549SSpandan Das source["x_defs"].update(s.x_defs) 209*9bb1b549SSpandan Das source["gc_goopts"] = source["gc_goopts"] + s.gc_goopts 210*9bb1b549SSpandan Das source["runfiles"] = source["runfiles"].merge(s.runfiles) 211*9bb1b549SSpandan Das if s.cgo and source["cgo"]: 212*9bb1b549SSpandan Das fail("multiple libraries with cgo enabled") 213*9bb1b549SSpandan Das source["cgo"] = source["cgo"] or s.cgo 214*9bb1b549SSpandan Das source["cdeps"] = source["cdeps"] or s.cdeps 215*9bb1b549SSpandan Das source["cppopts"] = source["cppopts"] or s.cppopts 216*9bb1b549SSpandan Das source["copts"] = source["copts"] or s.copts 217*9bb1b549SSpandan Das source["cxxopts"] = source["cxxopts"] or s.cxxopts 218*9bb1b549SSpandan Das source["clinkopts"] = source["clinkopts"] or s.clinkopts 219*9bb1b549SSpandan Das source["cgo_deps"] = source["cgo_deps"] + s.cgo_deps 220*9bb1b549SSpandan Das source["cgo_exports"] = source["cgo_exports"] + s.cgo_exports 221*9bb1b549SSpandan Das 222*9bb1b549SSpandan Dasdef _dedup_deps(deps): 223*9bb1b549SSpandan Das """Returns a list of deps without duplicate import paths. 224*9bb1b549SSpandan Das 225*9bb1b549SSpandan Das Earlier targets take precedence over later targets. This is intended to 226*9bb1b549SSpandan Das allow an embedding library to override the dependencies of its 227*9bb1b549SSpandan Das embedded libraries. 228*9bb1b549SSpandan Das 229*9bb1b549SSpandan Das Args: 230*9bb1b549SSpandan Das deps: an iterable containing either Targets or GoArchives. 231*9bb1b549SSpandan Das """ 232*9bb1b549SSpandan Das deduped_deps = [] 233*9bb1b549SSpandan Das importpaths = {} 234*9bb1b549SSpandan Das for dep in deps: 235*9bb1b549SSpandan Das if hasattr(dep, "data") and hasattr(dep.data, "importpath"): 236*9bb1b549SSpandan Das importpath = dep.data.importpath 237*9bb1b549SSpandan Das else: 238*9bb1b549SSpandan Das importpath = dep[GoLibrary].importpath 239*9bb1b549SSpandan Das if importpath in importpaths: 240*9bb1b549SSpandan Das continue 241*9bb1b549SSpandan Das importpaths[importpath] = None 242*9bb1b549SSpandan Das deduped_deps.append(dep) 243*9bb1b549SSpandan Das return deduped_deps 244*9bb1b549SSpandan Das 245*9bb1b549SSpandan Dasdef _library_to_source(go, attr, library, coverage_instrumented): 246*9bb1b549SSpandan Das #TODO: stop collapsing a depset in this line... 247*9bb1b549SSpandan Das attr_srcs = [f for t in getattr(attr, "srcs", []) for f in as_iterable(t.files)] 248*9bb1b549SSpandan Das generated_srcs = getattr(library, "srcs", []) 249*9bb1b549SSpandan Das srcs = attr_srcs + generated_srcs 250*9bb1b549SSpandan Das embedsrcs = [f for t in getattr(attr, "embedsrcs", []) for f in as_iterable(t.files)] 251*9bb1b549SSpandan Das source = { 252*9bb1b549SSpandan Das "library": library, 253*9bb1b549SSpandan Das "mode": go.mode, 254*9bb1b549SSpandan Das "srcs": srcs, 255*9bb1b549SSpandan Das "orig_srcs": srcs, 256*9bb1b549SSpandan Das "orig_src_map": {}, 257*9bb1b549SSpandan Das "cover": [], 258*9bb1b549SSpandan Das "embedsrcs": embedsrcs, 259*9bb1b549SSpandan Das "x_defs": {}, 260*9bb1b549SSpandan Das "deps": getattr(attr, "deps", []), 261*9bb1b549SSpandan Das "gc_goopts": _expand_opts(go, "gc_goopts", getattr(attr, "gc_goopts", [])), 262*9bb1b549SSpandan Das "runfiles": _collect_runfiles(go, getattr(attr, "data", []), getattr(attr, "deps", [])), 263*9bb1b549SSpandan Das "cgo": getattr(attr, "cgo", False), 264*9bb1b549SSpandan Das "cdeps": getattr(attr, "cdeps", []), 265*9bb1b549SSpandan Das "cppopts": _expand_opts(go, "cppopts", getattr(attr, "cppopts", [])), 266*9bb1b549SSpandan Das "copts": _expand_opts(go, "copts", getattr(attr, "copts", [])), 267*9bb1b549SSpandan Das "cxxopts": _expand_opts(go, "cxxopts", getattr(attr, "cxxopts", [])), 268*9bb1b549SSpandan Das "clinkopts": _expand_opts(go, "clinkopts", getattr(attr, "clinkopts", [])), 269*9bb1b549SSpandan Das "cgo_deps": [], 270*9bb1b549SSpandan Das "cgo_exports": [], 271*9bb1b549SSpandan Das "cc_info": None, 272*9bb1b549SSpandan Das } 273*9bb1b549SSpandan Das if coverage_instrumented: 274*9bb1b549SSpandan Das source["cover"] = attr_srcs 275*9bb1b549SSpandan Das for dep in source["deps"]: 276*9bb1b549SSpandan Das _check_binary_dep(go, dep, "deps") 277*9bb1b549SSpandan Das for e in getattr(attr, "embed", []): 278*9bb1b549SSpandan Das _check_binary_dep(go, e, "embed") 279*9bb1b549SSpandan Das _merge_embed(source, e) 280*9bb1b549SSpandan Das source["deps"] = _dedup_deps(source["deps"]) 281*9bb1b549SSpandan Das x_defs = source["x_defs"] 282*9bb1b549SSpandan Das for k, v in getattr(attr, "x_defs", {}).items(): 283*9bb1b549SSpandan Das v = _expand_location(go, attr, v) 284*9bb1b549SSpandan Das if "." not in k: 285*9bb1b549SSpandan Das k = "{}.{}".format(library.importmap, k) 286*9bb1b549SSpandan Das x_defs[k] = v 287*9bb1b549SSpandan Das source["x_defs"] = x_defs 288*9bb1b549SSpandan Das if not source["cgo"]: 289*9bb1b549SSpandan Das for k in ("cdeps", "cppopts", "copts", "cxxopts", "clinkopts"): 290*9bb1b549SSpandan Das if getattr(attr, k, None): 291*9bb1b549SSpandan Das fail(k + " set without cgo = True") 292*9bb1b549SSpandan Das for f in source["srcs"]: 293*9bb1b549SSpandan Das # This check won't report directory sources that contain C/C++ 294*9bb1b549SSpandan Das # sources. compilepkg will catch these instead. 295*9bb1b549SSpandan Das if f.extension in ("c", "cc", "cxx", "cpp", "hh", "hpp", "hxx"): 296*9bb1b549SSpandan Das fail("source {} has C/C++ extension, but cgo was not enabled (set 'cgo = True')".format(f.path)) 297*9bb1b549SSpandan Das if library.resolve: 298*9bb1b549SSpandan Das library.resolve(go, attr, source, _merge_embed) 299*9bb1b549SSpandan Das source["cc_info"] = _collect_cc_infos(source["deps"], source["cdeps"]) 300*9bb1b549SSpandan Das return GoSource(**source) 301*9bb1b549SSpandan Das 302*9bb1b549SSpandan Dasdef _collect_runfiles(go, data, deps): 303*9bb1b549SSpandan Das """Builds a set of runfiles from the deps and data attributes. 304*9bb1b549SSpandan Das 305*9bb1b549SSpandan Das srcs and their runfiles are not included.""" 306*9bb1b549SSpandan Das files = depset(transitive = [t[DefaultInfo].files for t in data]) 307*9bb1b549SSpandan Das runfiles = go._ctx.runfiles(transitive_files = files) 308*9bb1b549SSpandan Das for t in data: 309*9bb1b549SSpandan Das runfiles = runfiles.merge(t[DefaultInfo].data_runfiles) 310*9bb1b549SSpandan Das for t in deps: 311*9bb1b549SSpandan Das runfiles = runfiles.merge(get_source(t).runfiles) 312*9bb1b549SSpandan Das return runfiles 313*9bb1b549SSpandan Das 314*9bb1b549SSpandan Dasdef _collect_cc_infos(deps, cdeps): 315*9bb1b549SSpandan Das cc_infos = [] 316*9bb1b549SSpandan Das for dep in cdeps: 317*9bb1b549SSpandan Das if CcInfo in dep: 318*9bb1b549SSpandan Das cc_infos.append(dep[CcInfo]) 319*9bb1b549SSpandan Das for dep in deps: 320*9bb1b549SSpandan Das # dep may be a struct, which doesn't support indexing by providers. 321*9bb1b549SSpandan Das if is_struct(dep): 322*9bb1b549SSpandan Das continue 323*9bb1b549SSpandan Das if GoSource in dep: 324*9bb1b549SSpandan Das cc_infos.append(dep[GoSource].cc_info) 325*9bb1b549SSpandan Das return cc_common.merge_cc_infos(cc_infos = cc_infos) 326*9bb1b549SSpandan Das 327*9bb1b549SSpandan Dasdef _check_binary_dep(go, dep, edge): 328*9bb1b549SSpandan Das """Checks that this rule doesn't depend on a go_binary or go_test. 329*9bb1b549SSpandan Das 330*9bb1b549SSpandan Das go_binary and go_test may return provides with useful information for other 331*9bb1b549SSpandan Das rules (like go_path), but go_binary and go_test may not depend on other 332*9bb1b549SSpandan Das go_binary and go_binary targets. Their dependencies may be built in 333*9bb1b549SSpandan Das different modes, resulting in conflicts and opaque errors. 334*9bb1b549SSpandan Das """ 335*9bb1b549SSpandan Das if (type(dep) == "Target" and 336*9bb1b549SSpandan Das DefaultInfo in dep and 337*9bb1b549SSpandan Das getattr(dep[DefaultInfo], "files_to_run", None) and 338*9bb1b549SSpandan Das dep[DefaultInfo].files_to_run.executable): 339*9bb1b549SSpandan Das fail("rule {rule} depends on executable {dep} via {edge}. This is not safe for cross-compilation. Depend on go_library instead.".format( 340*9bb1b549SSpandan Das rule = str(go.label), 341*9bb1b549SSpandan Das dep = str(dep.label), 342*9bb1b549SSpandan Das edge = edge, 343*9bb1b549SSpandan Das )) 344*9bb1b549SSpandan Das 345*9bb1b549SSpandan Dasdef _check_importpaths(ctx): 346*9bb1b549SSpandan Das paths = [] 347*9bb1b549SSpandan Das p = getattr(ctx.attr, "importpath", "") 348*9bb1b549SSpandan Das if p: 349*9bb1b549SSpandan Das paths.append(p) 350*9bb1b549SSpandan Das p = getattr(ctx.attr, "importmap", "") 351*9bb1b549SSpandan Das if p: 352*9bb1b549SSpandan Das paths.append(p) 353*9bb1b549SSpandan Das paths.extend(getattr(ctx.attr, "importpath_aliases", ())) 354*9bb1b549SSpandan Das 355*9bb1b549SSpandan Das for p in paths: 356*9bb1b549SSpandan Das if ":" in p: 357*9bb1b549SSpandan Das fail("import path '%s' contains invalid character :" % p) 358*9bb1b549SSpandan Das 359*9bb1b549SSpandan Dasdef _infer_importpath(ctx): 360*9bb1b549SSpandan Das DEFAULT_LIB = "go_default_library" 361*9bb1b549SSpandan Das VENDOR_PREFIX = "/vendor/" 362*9bb1b549SSpandan Das 363*9bb1b549SSpandan Das # Check if paths were explicitly set, either in this rule or in an 364*9bb1b549SSpandan Das # embedded rule. 365*9bb1b549SSpandan Das attr_importpath = getattr(ctx.attr, "importpath", "") 366*9bb1b549SSpandan Das attr_importmap = getattr(ctx.attr, "importmap", "") 367*9bb1b549SSpandan Das embed_importpath = "" 368*9bb1b549SSpandan Das embed_importmap = "" 369*9bb1b549SSpandan Das for embed in getattr(ctx.attr, "embed", []): 370*9bb1b549SSpandan Das if GoLibrary not in embed: 371*9bb1b549SSpandan Das continue 372*9bb1b549SSpandan Das lib = embed[GoLibrary] 373*9bb1b549SSpandan Das if lib.pathtype == EXPLICIT_PATH: 374*9bb1b549SSpandan Das embed_importpath = lib.importpath 375*9bb1b549SSpandan Das embed_importmap = lib.importmap 376*9bb1b549SSpandan Das break 377*9bb1b549SSpandan Das 378*9bb1b549SSpandan Das importpath = attr_importpath or embed_importpath 379*9bb1b549SSpandan Das importmap = attr_importmap or embed_importmap or importpath 380*9bb1b549SSpandan Das if importpath: 381*9bb1b549SSpandan Das return importpath, importmap, EXPLICIT_PATH 382*9bb1b549SSpandan Das 383*9bb1b549SSpandan Das # Guess an import path based on the directory structure 384*9bb1b549SSpandan Das # This should only really be relied on for binaries 385*9bb1b549SSpandan Das importpath = ctx.label.package 386*9bb1b549SSpandan Das if ctx.label.name != DEFAULT_LIB and not importpath.endswith(ctx.label.name): 387*9bb1b549SSpandan Das importpath += "/" + ctx.label.name 388*9bb1b549SSpandan Das if importpath.rfind(VENDOR_PREFIX) != -1: 389*9bb1b549SSpandan Das importpath = importpath[len(VENDOR_PREFIX) + importpath.rfind(VENDOR_PREFIX):] 390*9bb1b549SSpandan Das if importpath.startswith("/"): 391*9bb1b549SSpandan Das importpath = importpath[1:] 392*9bb1b549SSpandan Das return importpath, importpath, INFERRED_PATH 393*9bb1b549SSpandan Das 394*9bb1b549SSpandan Dasdef go_context(ctx, attr = None): 395*9bb1b549SSpandan Das """Returns an API used to build Go code. 396*9bb1b549SSpandan Das 397*9bb1b549SSpandan Das See /go/toolchains.rst#go-context 398*9bb1b549SSpandan Das """ 399*9bb1b549SSpandan Das if not attr: 400*9bb1b549SSpandan Das attr = ctx.attr 401*9bb1b549SSpandan Das toolchain = ctx.toolchains[GO_TOOLCHAIN] 402*9bb1b549SSpandan Das cgo_context_info = None 403*9bb1b549SSpandan Das go_config_info = None 404*9bb1b549SSpandan Das stdlib = None 405*9bb1b549SSpandan Das coverdata = None 406*9bb1b549SSpandan Das nogo = None 407*9bb1b549SSpandan Das if hasattr(attr, "_go_context_data"): 408*9bb1b549SSpandan Das go_context_data = _flatten_possibly_transitioned_attr(attr._go_context_data) 409*9bb1b549SSpandan Das if CgoContextInfo in go_context_data: 410*9bb1b549SSpandan Das cgo_context_info = go_context_data[CgoContextInfo] 411*9bb1b549SSpandan Das go_config_info = go_context_data[GoConfigInfo] 412*9bb1b549SSpandan Das stdlib = go_context_data[GoStdLib] 413*9bb1b549SSpandan Das coverdata = go_context_data[GoContextInfo].coverdata 414*9bb1b549SSpandan Das nogo = go_context_data[GoContextInfo].nogo 415*9bb1b549SSpandan Das if getattr(attr, "_cgo_context_data", None) and CgoContextInfo in attr._cgo_context_data: 416*9bb1b549SSpandan Das cgo_context_info = attr._cgo_context_data[CgoContextInfo] 417*9bb1b549SSpandan Das if getattr(attr, "cgo_context_data", None) and CgoContextInfo in attr.cgo_context_data: 418*9bb1b549SSpandan Das cgo_context_info = attr.cgo_context_data[CgoContextInfo] 419*9bb1b549SSpandan Das if hasattr(attr, "_go_config"): 420*9bb1b549SSpandan Das go_config_info = attr._go_config[GoConfigInfo] 421*9bb1b549SSpandan Das if hasattr(attr, "_stdlib"): 422*9bb1b549SSpandan Das stdlib = _flatten_possibly_transitioned_attr(attr._stdlib)[GoStdLib] 423*9bb1b549SSpandan Das 424*9bb1b549SSpandan Das mode = get_mode(ctx, toolchain, cgo_context_info, go_config_info) 425*9bb1b549SSpandan Das tags = mode.tags 426*9bb1b549SSpandan Das binary = toolchain.sdk.go 427*9bb1b549SSpandan Das 428*9bb1b549SSpandan Das if stdlib: 429*9bb1b549SSpandan Das goroot = stdlib.root_file.dirname 430*9bb1b549SSpandan Das else: 431*9bb1b549SSpandan Das goroot = toolchain.sdk.root_file.dirname 432*9bb1b549SSpandan Das 433*9bb1b549SSpandan Das env = { 434*9bb1b549SSpandan Das "GOARCH": mode.goarch, 435*9bb1b549SSpandan Das "GOOS": mode.goos, 436*9bb1b549SSpandan Das "GOEXPERIMENT": ",".join(toolchain.sdk.experiments), 437*9bb1b549SSpandan Das "GOROOT": goroot, 438*9bb1b549SSpandan Das "GOROOT_FINAL": "GOROOT", 439*9bb1b549SSpandan Das "CGO_ENABLED": "0" if mode.pure else "1", 440*9bb1b549SSpandan Das 441*9bb1b549SSpandan Das # If we use --action_env=GOPATH, or in other cases where environment 442*9bb1b549SSpandan Das # variables are passed through to this builder, the SDK build will try 443*9bb1b549SSpandan Das # to write to that GOPATH (e.g. for x/net/nettest). This will fail if 444*9bb1b549SSpandan Das # the GOPATH is on a read-only mount, and is generally a bad idea. 445*9bb1b549SSpandan Das # Explicitly clear this environment variable to ensure that doesn't 446*9bb1b549SSpandan Das # happen. See #2291 for more information. 447*9bb1b549SSpandan Das "GOPATH": "", 448*9bb1b549SSpandan Das } 449*9bb1b549SSpandan Das 450*9bb1b549SSpandan Das # The level of support is determined by the platform constraints in 451*9bb1b549SSpandan Das # //go/constraints/amd64. 452*9bb1b549SSpandan Das # See https://github.com/golang/go/wiki/MinimumRequirements#amd64 453*9bb1b549SSpandan Das if mode.amd64: 454*9bb1b549SSpandan Das env["GOAMD64"] = mode.amd64 455*9bb1b549SSpandan Das if not cgo_context_info: 456*9bb1b549SSpandan Das crosstool = [] 457*9bb1b549SSpandan Das cgo_tools = None 458*9bb1b549SSpandan Das else: 459*9bb1b549SSpandan Das env.update(cgo_context_info.env) 460*9bb1b549SSpandan Das crosstool = cgo_context_info.crosstool 461*9bb1b549SSpandan Das 462*9bb1b549SSpandan Das # Add C toolchain directories to PATH. 463*9bb1b549SSpandan Das # On ARM, go tool link uses some features of gcc to complete its work, 464*9bb1b549SSpandan Das # so PATH is needed on ARM. 465*9bb1b549SSpandan Das path_set = {} 466*9bb1b549SSpandan Das if "PATH" in env: 467*9bb1b549SSpandan Das for p in env["PATH"].split(ctx.configuration.host_path_separator): 468*9bb1b549SSpandan Das path_set[p] = None 469*9bb1b549SSpandan Das cgo_tools = cgo_context_info.cgo_tools 470*9bb1b549SSpandan Das tool_paths = [ 471*9bb1b549SSpandan Das cgo_tools.c_compiler_path, 472*9bb1b549SSpandan Das cgo_tools.ld_executable_path, 473*9bb1b549SSpandan Das cgo_tools.ld_static_lib_path, 474*9bb1b549SSpandan Das cgo_tools.ld_dynamic_lib_path, 475*9bb1b549SSpandan Das ] 476*9bb1b549SSpandan Das for tool_path in tool_paths: 477*9bb1b549SSpandan Das tool_dir, _, _ = tool_path.rpartition("/") 478*9bb1b549SSpandan Das path_set[tool_dir] = None 479*9bb1b549SSpandan Das paths = sorted(path_set.keys()) 480*9bb1b549SSpandan Das if ctx.configuration.host_path_separator == ":": 481*9bb1b549SSpandan Das # HACK: ":" is a proxy for a UNIX-like host. 482*9bb1b549SSpandan Das # The tools returned above may be bash scripts that reference commands 483*9bb1b549SSpandan Das # in directories we might not otherwise include. For example, 484*9bb1b549SSpandan Das # on macOS, wrapped_ar calls dirname. 485*9bb1b549SSpandan Das if "/bin" not in path_set: 486*9bb1b549SSpandan Das paths.append("/bin") 487*9bb1b549SSpandan Das if "/usr/bin" not in path_set: 488*9bb1b549SSpandan Das paths.append("/usr/bin") 489*9bb1b549SSpandan Das env["PATH"] = ctx.configuration.host_path_separator.join(paths) 490*9bb1b549SSpandan Das 491*9bb1b549SSpandan Das # TODO(jayconrod): remove this. It's way too broad. Everything should 492*9bb1b549SSpandan Das # depend on more specific lists. 493*9bb1b549SSpandan Das sdk_files = ([toolchain.sdk.go] + 494*9bb1b549SSpandan Das toolchain.sdk.srcs + 495*9bb1b549SSpandan Das toolchain.sdk.headers + 496*9bb1b549SSpandan Das toolchain.sdk.libs + 497*9bb1b549SSpandan Das toolchain.sdk.tools) 498*9bb1b549SSpandan Das 499*9bb1b549SSpandan Das _check_importpaths(ctx) 500*9bb1b549SSpandan Das importpath, importmap, pathtype = _infer_importpath(ctx) 501*9bb1b549SSpandan Das importpath_aliases = tuple(getattr(attr, "importpath_aliases", ())) 502*9bb1b549SSpandan Das 503*9bb1b549SSpandan Das return struct( 504*9bb1b549SSpandan Das # Fields 505*9bb1b549SSpandan Das toolchain = toolchain, 506*9bb1b549SSpandan Das sdk = toolchain.sdk, 507*9bb1b549SSpandan Das mode = mode, 508*9bb1b549SSpandan Das root = goroot, 509*9bb1b549SSpandan Das go = binary, 510*9bb1b549SSpandan Das stdlib = stdlib, 511*9bb1b549SSpandan Das sdk_root = toolchain.sdk.root_file, 512*9bb1b549SSpandan Das sdk_files = sdk_files, 513*9bb1b549SSpandan Das sdk_tools = toolchain.sdk.tools, 514*9bb1b549SSpandan Das actions = ctx.actions, 515*9bb1b549SSpandan Das exe_extension = goos_to_extension(mode.goos), 516*9bb1b549SSpandan Das shared_extension = goos_to_shared_extension(mode.goos), 517*9bb1b549SSpandan Das crosstool = crosstool, 518*9bb1b549SSpandan Das package_list = toolchain.sdk.package_list, 519*9bb1b549SSpandan Das importpath = importpath, 520*9bb1b549SSpandan Das importmap = importmap, 521*9bb1b549SSpandan Das importpath_aliases = importpath_aliases, 522*9bb1b549SSpandan Das pathtype = pathtype, 523*9bb1b549SSpandan Das cgo_tools = cgo_tools, 524*9bb1b549SSpandan Das nogo = nogo, 525*9bb1b549SSpandan Das coverdata = coverdata, 526*9bb1b549SSpandan Das coverage_enabled = ctx.configuration.coverage_enabled, 527*9bb1b549SSpandan Das coverage_instrumented = ctx.coverage_instrumented(), 528*9bb1b549SSpandan Das env = env, 529*9bb1b549SSpandan Das tags = tags, 530*9bb1b549SSpandan Das stamp = mode.stamp, 531*9bb1b549SSpandan Das label = ctx.label, 532*9bb1b549SSpandan Das cover_format = mode.cover_format, 533*9bb1b549SSpandan Das # Action generators 534*9bb1b549SSpandan Das archive = toolchain.actions.archive, 535*9bb1b549SSpandan Das binary = toolchain.actions.binary, 536*9bb1b549SSpandan Das link = toolchain.actions.link, 537*9bb1b549SSpandan Das 538*9bb1b549SSpandan Das # Helpers 539*9bb1b549SSpandan Das args = _new_args, # deprecated 540*9bb1b549SSpandan Das builder_args = _builder_args, 541*9bb1b549SSpandan Das tool_args = _tool_args, 542*9bb1b549SSpandan Das new_library = _new_library, 543*9bb1b549SSpandan Das library_to_source = _library_to_source, 544*9bb1b549SSpandan Das declare_file = _declare_file, 545*9bb1b549SSpandan Das declare_directory = _declare_directory, 546*9bb1b549SSpandan Das 547*9bb1b549SSpandan Das # Private 548*9bb1b549SSpandan Das # TODO: All uses of this should be removed 549*9bb1b549SSpandan Das _ctx = ctx, 550*9bb1b549SSpandan Das ) 551*9bb1b549SSpandan Das 552*9bb1b549SSpandan Dasdef _go_context_data_impl(ctx): 553*9bb1b549SSpandan Das if "race" in ctx.features: 554*9bb1b549SSpandan Das print("WARNING: --features=race is no longer supported. Use --@io_bazel_rules_go//go/config:race instead.") 555*9bb1b549SSpandan Das if "msan" in ctx.features: 556*9bb1b549SSpandan Das print("WARNING: --features=msan is no longer supported. Use --@io_bazel_rules_go//go/config:msan instead.") 557*9bb1b549SSpandan Das nogo = ctx.files.nogo[0] if ctx.files.nogo else None 558*9bb1b549SSpandan Das providers = [ 559*9bb1b549SSpandan Das GoContextInfo( 560*9bb1b549SSpandan Das coverdata = ctx.attr.coverdata[GoArchive], 561*9bb1b549SSpandan Das nogo = nogo, 562*9bb1b549SSpandan Das ), 563*9bb1b549SSpandan Das ctx.attr.stdlib[GoStdLib], 564*9bb1b549SSpandan Das ctx.attr.go_config[GoConfigInfo], 565*9bb1b549SSpandan Das ] 566*9bb1b549SSpandan Das if ctx.attr.cgo_context_data and CgoContextInfo in ctx.attr.cgo_context_data: 567*9bb1b549SSpandan Das providers.append(ctx.attr.cgo_context_data[CgoContextInfo]) 568*9bb1b549SSpandan Das return providers 569*9bb1b549SSpandan Das 570*9bb1b549SSpandan Dasgo_context_data = rule( 571*9bb1b549SSpandan Das _go_context_data_impl, 572*9bb1b549SSpandan Das attrs = { 573*9bb1b549SSpandan Das "cgo_context_data": attr.label(), 574*9bb1b549SSpandan Das "coverdata": attr.label( 575*9bb1b549SSpandan Das mandatory = True, 576*9bb1b549SSpandan Das providers = [GoArchive], 577*9bb1b549SSpandan Das ), 578*9bb1b549SSpandan Das "go_config": attr.label( 579*9bb1b549SSpandan Das mandatory = True, 580*9bb1b549SSpandan Das providers = [GoConfigInfo], 581*9bb1b549SSpandan Das ), 582*9bb1b549SSpandan Das "nogo": attr.label( 583*9bb1b549SSpandan Das mandatory = True, 584*9bb1b549SSpandan Das cfg = "exec", 585*9bb1b549SSpandan Das ), 586*9bb1b549SSpandan Das "stdlib": attr.label( 587*9bb1b549SSpandan Das mandatory = True, 588*9bb1b549SSpandan Das providers = [GoStdLib], 589*9bb1b549SSpandan Das ), 590*9bb1b549SSpandan Das "_allowlist_function_transition": attr.label( 591*9bb1b549SSpandan Das default = "@bazel_tools//tools/allowlists/function_transition_allowlist", 592*9bb1b549SSpandan Das ), 593*9bb1b549SSpandan Das }, 594*9bb1b549SSpandan Das doc = """go_context_data gathers information about the build configuration. 595*9bb1b549SSpandan Das It is a common dependency of all Go targets.""", 596*9bb1b549SSpandan Das toolchains = [GO_TOOLCHAIN], 597*9bb1b549SSpandan Das cfg = request_nogo_transition, 598*9bb1b549SSpandan Das) 599*9bb1b549SSpandan Das 600*9bb1b549SSpandan Dasdef _cgo_context_data_impl(ctx): 601*9bb1b549SSpandan Das # TODO(jayconrod): find a way to get a list of files that comprise the 602*9bb1b549SSpandan Das # toolchain (to be inputs into actions that need it). 603*9bb1b549SSpandan Das # ctx.files._cc_toolchain won't work when cc toolchain resolution 604*9bb1b549SSpandan Das # is switched on. 605*9bb1b549SSpandan Das cc_toolchain = find_cpp_toolchain(ctx) 606*9bb1b549SSpandan Das if cc_toolchain.compiler in _UNSUPPORTED_C_COMPILERS: 607*9bb1b549SSpandan Das return [] 608*9bb1b549SSpandan Das 609*9bb1b549SSpandan Das feature_configuration = cc_common.configure_features( 610*9bb1b549SSpandan Das ctx = ctx, 611*9bb1b549SSpandan Das cc_toolchain = cc_toolchain, 612*9bb1b549SSpandan Das requested_features = ctx.features, 613*9bb1b549SSpandan Das unsupported_features = ctx.disabled_features + _UNSUPPORTED_FEATURES, 614*9bb1b549SSpandan Das ) 615*9bb1b549SSpandan Das 616*9bb1b549SSpandan Das # TODO(jayconrod): keep the environment separate for different actions. 617*9bb1b549SSpandan Das env = {} 618*9bb1b549SSpandan Das 619*9bb1b549SSpandan Das c_compile_variables = cc_common.create_compile_variables( 620*9bb1b549SSpandan Das feature_configuration = feature_configuration, 621*9bb1b549SSpandan Das cc_toolchain = cc_toolchain, 622*9bb1b549SSpandan Das ) 623*9bb1b549SSpandan Das c_compiler_path = cc_common.get_tool_for_action( 624*9bb1b549SSpandan Das feature_configuration = feature_configuration, 625*9bb1b549SSpandan Das action_name = C_COMPILE_ACTION_NAME, 626*9bb1b549SSpandan Das ) 627*9bb1b549SSpandan Das c_compile_options = _filter_options( 628*9bb1b549SSpandan Das cc_common.get_memory_inefficient_command_line( 629*9bb1b549SSpandan Das feature_configuration = feature_configuration, 630*9bb1b549SSpandan Das action_name = C_COMPILE_ACTION_NAME, 631*9bb1b549SSpandan Das variables = c_compile_variables, 632*9bb1b549SSpandan Das ) + ctx.fragments.cpp.copts + ctx.fragments.cpp.conlyopts, 633*9bb1b549SSpandan Das _COMPILER_OPTIONS_DENYLIST, 634*9bb1b549SSpandan Das ) 635*9bb1b549SSpandan Das env.update(cc_common.get_environment_variables( 636*9bb1b549SSpandan Das feature_configuration = feature_configuration, 637*9bb1b549SSpandan Das action_name = C_COMPILE_ACTION_NAME, 638*9bb1b549SSpandan Das variables = c_compile_variables, 639*9bb1b549SSpandan Das )) 640*9bb1b549SSpandan Das 641*9bb1b549SSpandan Das cxx_compile_variables = cc_common.create_compile_variables( 642*9bb1b549SSpandan Das feature_configuration = feature_configuration, 643*9bb1b549SSpandan Das cc_toolchain = cc_toolchain, 644*9bb1b549SSpandan Das ) 645*9bb1b549SSpandan Das cxx_compile_options = _filter_options( 646*9bb1b549SSpandan Das cc_common.get_memory_inefficient_command_line( 647*9bb1b549SSpandan Das feature_configuration = feature_configuration, 648*9bb1b549SSpandan Das action_name = CPP_COMPILE_ACTION_NAME, 649*9bb1b549SSpandan Das variables = cxx_compile_variables, 650*9bb1b549SSpandan Das ) + ctx.fragments.cpp.copts + ctx.fragments.cpp.cxxopts, 651*9bb1b549SSpandan Das _COMPILER_OPTIONS_DENYLIST, 652*9bb1b549SSpandan Das ) 653*9bb1b549SSpandan Das env.update(cc_common.get_environment_variables( 654*9bb1b549SSpandan Das feature_configuration = feature_configuration, 655*9bb1b549SSpandan Das action_name = CPP_COMPILE_ACTION_NAME, 656*9bb1b549SSpandan Das variables = cxx_compile_variables, 657*9bb1b549SSpandan Das )) 658*9bb1b549SSpandan Das 659*9bb1b549SSpandan Das objc_compile_variables = cc_common.create_compile_variables( 660*9bb1b549SSpandan Das feature_configuration = feature_configuration, 661*9bb1b549SSpandan Das cc_toolchain = cc_toolchain, 662*9bb1b549SSpandan Das ) 663*9bb1b549SSpandan Das objc_compile_options = _filter_options( 664*9bb1b549SSpandan Das cc_common.get_memory_inefficient_command_line( 665*9bb1b549SSpandan Das feature_configuration = feature_configuration, 666*9bb1b549SSpandan Das action_name = OBJC_COMPILE_ACTION_NAME, 667*9bb1b549SSpandan Das variables = objc_compile_variables, 668*9bb1b549SSpandan Das ), 669*9bb1b549SSpandan Das _COMPILER_OPTIONS_DENYLIST, 670*9bb1b549SSpandan Das ) 671*9bb1b549SSpandan Das env.update(cc_common.get_environment_variables( 672*9bb1b549SSpandan Das feature_configuration = feature_configuration, 673*9bb1b549SSpandan Das action_name = OBJC_COMPILE_ACTION_NAME, 674*9bb1b549SSpandan Das variables = objc_compile_variables, 675*9bb1b549SSpandan Das )) 676*9bb1b549SSpandan Das 677*9bb1b549SSpandan Das objcxx_compile_variables = cc_common.create_compile_variables( 678*9bb1b549SSpandan Das feature_configuration = feature_configuration, 679*9bb1b549SSpandan Das cc_toolchain = cc_toolchain, 680*9bb1b549SSpandan Das ) 681*9bb1b549SSpandan Das objcxx_compile_options = _filter_options( 682*9bb1b549SSpandan Das cc_common.get_memory_inefficient_command_line( 683*9bb1b549SSpandan Das feature_configuration = feature_configuration, 684*9bb1b549SSpandan Das action_name = OBJCPP_COMPILE_ACTION_NAME, 685*9bb1b549SSpandan Das variables = objcxx_compile_variables, 686*9bb1b549SSpandan Das ), 687*9bb1b549SSpandan Das _COMPILER_OPTIONS_DENYLIST, 688*9bb1b549SSpandan Das ) 689*9bb1b549SSpandan Das env.update(cc_common.get_environment_variables( 690*9bb1b549SSpandan Das feature_configuration = feature_configuration, 691*9bb1b549SSpandan Das action_name = OBJCPP_COMPILE_ACTION_NAME, 692*9bb1b549SSpandan Das variables = objcxx_compile_variables, 693*9bb1b549SSpandan Das )) 694*9bb1b549SSpandan Das 695*9bb1b549SSpandan Das ld_executable_variables = cc_common.create_link_variables( 696*9bb1b549SSpandan Das feature_configuration = feature_configuration, 697*9bb1b549SSpandan Das cc_toolchain = cc_toolchain, 698*9bb1b549SSpandan Das is_linking_dynamic_library = False, 699*9bb1b549SSpandan Das ) 700*9bb1b549SSpandan Das ld_executable_path = cc_common.get_tool_for_action( 701*9bb1b549SSpandan Das feature_configuration = feature_configuration, 702*9bb1b549SSpandan Das action_name = CPP_LINK_EXECUTABLE_ACTION_NAME, 703*9bb1b549SSpandan Das ) 704*9bb1b549SSpandan Das ld_executable_options = _filter_options( 705*9bb1b549SSpandan Das cc_common.get_memory_inefficient_command_line( 706*9bb1b549SSpandan Das feature_configuration = feature_configuration, 707*9bb1b549SSpandan Das action_name = CPP_LINK_EXECUTABLE_ACTION_NAME, 708*9bb1b549SSpandan Das variables = ld_executable_variables, 709*9bb1b549SSpandan Das ) + ctx.fragments.cpp.linkopts, 710*9bb1b549SSpandan Das _LINKER_OPTIONS_DENYLIST, 711*9bb1b549SSpandan Das ) 712*9bb1b549SSpandan Das env.update(cc_common.get_environment_variables( 713*9bb1b549SSpandan Das feature_configuration = feature_configuration, 714*9bb1b549SSpandan Das action_name = CPP_LINK_EXECUTABLE_ACTION_NAME, 715*9bb1b549SSpandan Das variables = ld_executable_variables, 716*9bb1b549SSpandan Das )) 717*9bb1b549SSpandan Das 718*9bb1b549SSpandan Das # We don't collect options for static libraries. Go always links with 719*9bb1b549SSpandan Das # "ar" in "c-archive" mode. We can set the ar executable path with 720*9bb1b549SSpandan Das # -extar, but the options are hard-coded to something like -q -c -s. 721*9bb1b549SSpandan Das ld_static_lib_variables = cc_common.create_link_variables( 722*9bb1b549SSpandan Das feature_configuration = feature_configuration, 723*9bb1b549SSpandan Das cc_toolchain = cc_toolchain, 724*9bb1b549SSpandan Das is_linking_dynamic_library = False, 725*9bb1b549SSpandan Das ) 726*9bb1b549SSpandan Das ld_static_lib_path = cc_common.get_tool_for_action( 727*9bb1b549SSpandan Das feature_configuration = feature_configuration, 728*9bb1b549SSpandan Das action_name = CPP_LINK_STATIC_LIBRARY_ACTION_NAME, 729*9bb1b549SSpandan Das ) 730*9bb1b549SSpandan Das env.update(cc_common.get_environment_variables( 731*9bb1b549SSpandan Das feature_configuration = feature_configuration, 732*9bb1b549SSpandan Das action_name = CPP_LINK_STATIC_LIBRARY_ACTION_NAME, 733*9bb1b549SSpandan Das variables = ld_static_lib_variables, 734*9bb1b549SSpandan Das )) 735*9bb1b549SSpandan Das 736*9bb1b549SSpandan Das ld_dynamic_lib_variables = cc_common.create_link_variables( 737*9bb1b549SSpandan Das feature_configuration = feature_configuration, 738*9bb1b549SSpandan Das cc_toolchain = cc_toolchain, 739*9bb1b549SSpandan Das is_linking_dynamic_library = True, 740*9bb1b549SSpandan Das ) 741*9bb1b549SSpandan Das ld_dynamic_lib_path = cc_common.get_tool_for_action( 742*9bb1b549SSpandan Das feature_configuration = feature_configuration, 743*9bb1b549SSpandan Das action_name = CPP_LINK_DYNAMIC_LIBRARY_ACTION_NAME, 744*9bb1b549SSpandan Das ) 745*9bb1b549SSpandan Das ld_dynamic_lib_options = _filter_options( 746*9bb1b549SSpandan Das cc_common.get_memory_inefficient_command_line( 747*9bb1b549SSpandan Das feature_configuration = feature_configuration, 748*9bb1b549SSpandan Das action_name = CPP_LINK_DYNAMIC_LIBRARY_ACTION_NAME, 749*9bb1b549SSpandan Das variables = ld_dynamic_lib_variables, 750*9bb1b549SSpandan Das ) + ctx.fragments.cpp.linkopts, 751*9bb1b549SSpandan Das _LINKER_OPTIONS_DENYLIST, 752*9bb1b549SSpandan Das ) 753*9bb1b549SSpandan Das 754*9bb1b549SSpandan Das env.update(cc_common.get_environment_variables( 755*9bb1b549SSpandan Das feature_configuration = feature_configuration, 756*9bb1b549SSpandan Das action_name = CPP_LINK_DYNAMIC_LIBRARY_ACTION_NAME, 757*9bb1b549SSpandan Das variables = ld_dynamic_lib_variables, 758*9bb1b549SSpandan Das )) 759*9bb1b549SSpandan Das 760*9bb1b549SSpandan Das tags = [] 761*9bb1b549SSpandan Das if "gotags" in ctx.var: 762*9bb1b549SSpandan Das tags = ctx.var["gotags"].split(",") 763*9bb1b549SSpandan Das apple_ensure_options( 764*9bb1b549SSpandan Das ctx, 765*9bb1b549SSpandan Das env, 766*9bb1b549SSpandan Das tags, 767*9bb1b549SSpandan Das (c_compile_options, cxx_compile_options, objc_compile_options, objcxx_compile_options), 768*9bb1b549SSpandan Das (ld_executable_options, ld_dynamic_lib_options), 769*9bb1b549SSpandan Das cc_toolchain.target_gnu_system_name, 770*9bb1b549SSpandan Das ) 771*9bb1b549SSpandan Das 772*9bb1b549SSpandan Das return [CgoContextInfo( 773*9bb1b549SSpandan Das crosstool = cc_toolchain.all_files.to_list(), 774*9bb1b549SSpandan Das tags = tags, 775*9bb1b549SSpandan Das env = env, 776*9bb1b549SSpandan Das cgo_tools = struct( 777*9bb1b549SSpandan Das cc_toolchain = cc_toolchain, 778*9bb1b549SSpandan Das feature_configuration = feature_configuration, 779*9bb1b549SSpandan Das c_compiler_path = c_compiler_path, 780*9bb1b549SSpandan Das c_compile_options = c_compile_options, 781*9bb1b549SSpandan Das cxx_compile_options = cxx_compile_options, 782*9bb1b549SSpandan Das objc_compile_options = objc_compile_options, 783*9bb1b549SSpandan Das objcxx_compile_options = objcxx_compile_options, 784*9bb1b549SSpandan Das ld_executable_path = ld_executable_path, 785*9bb1b549SSpandan Das ld_executable_options = ld_executable_options, 786*9bb1b549SSpandan Das ld_static_lib_path = ld_static_lib_path, 787*9bb1b549SSpandan Das ld_dynamic_lib_path = ld_dynamic_lib_path, 788*9bb1b549SSpandan Das ld_dynamic_lib_options = ld_dynamic_lib_options, 789*9bb1b549SSpandan Das ), 790*9bb1b549SSpandan Das )] 791*9bb1b549SSpandan Das 792*9bb1b549SSpandan Dascgo_context_data = rule( 793*9bb1b549SSpandan Das implementation = _cgo_context_data_impl, 794*9bb1b549SSpandan Das attrs = { 795*9bb1b549SSpandan Das "_cc_toolchain": attr.label(default = "@bazel_tools//tools/cpp:current_cc_toolchain"), 796*9bb1b549SSpandan Das "_xcode_config": attr.label( 797*9bb1b549SSpandan Das default = "@bazel_tools//tools/osx:current_xcode_config", 798*9bb1b549SSpandan Das ), 799*9bb1b549SSpandan Das }, 800*9bb1b549SSpandan Das toolchains = ["@bazel_tools//tools/cpp:toolchain_type"], 801*9bb1b549SSpandan Das fragments = ["apple", "cpp"], 802*9bb1b549SSpandan Das doc = """Collects information about the C/C++ toolchain. The C/C++ toolchain 803*9bb1b549SSpandan Das is needed to build cgo code, but is generally optional. Rules can't have 804*9bb1b549SSpandan Das optional toolchains, so instead, we have an optional dependency on this 805*9bb1b549SSpandan Das rule.""", 806*9bb1b549SSpandan Das) 807*9bb1b549SSpandan Das 808*9bb1b549SSpandan Dasdef _cgo_context_data_proxy_impl(ctx): 809*9bb1b549SSpandan Das if ctx.attr.actual and CgoContextInfo in ctx.attr.actual: 810*9bb1b549SSpandan Das return [ctx.attr.actual[CgoContextInfo]] 811*9bb1b549SSpandan Das return [] 812*9bb1b549SSpandan Das 813*9bb1b549SSpandan Dascgo_context_data_proxy = rule( 814*9bb1b549SSpandan Das implementation = _cgo_context_data_proxy_impl, 815*9bb1b549SSpandan Das attrs = { 816*9bb1b549SSpandan Das "actual": attr.label(), 817*9bb1b549SSpandan Das }, 818*9bb1b549SSpandan Das doc = """Conditionally depends on cgo_context_data and forwards it provider. 819*9bb1b549SSpandan Das 820*9bb1b549SSpandan Das Useful in situations where select cannot be used, like attribute defaults. 821*9bb1b549SSpandan Das """, 822*9bb1b549SSpandan Das) 823*9bb1b549SSpandan Das 824*9bb1b549SSpandan Dasdef _go_config_impl(ctx): 825*9bb1b549SSpandan Das return [GoConfigInfo( 826*9bb1b549SSpandan Das static = ctx.attr.static[BuildSettingInfo].value, 827*9bb1b549SSpandan Das race = ctx.attr.race[BuildSettingInfo].value, 828*9bb1b549SSpandan Das msan = ctx.attr.msan[BuildSettingInfo].value, 829*9bb1b549SSpandan Das pure = ctx.attr.pure[BuildSettingInfo].value, 830*9bb1b549SSpandan Das strip = ctx.attr.strip, 831*9bb1b549SSpandan Das debug = ctx.attr.debug[BuildSettingInfo].value, 832*9bb1b549SSpandan Das linkmode = ctx.attr.linkmode[BuildSettingInfo].value, 833*9bb1b549SSpandan Das gc_linkopts = ctx.attr.gc_linkopts[BuildSettingInfo].value, 834*9bb1b549SSpandan Das tags = ctx.attr.gotags[BuildSettingInfo].value, 835*9bb1b549SSpandan Das stamp = ctx.attr.stamp, 836*9bb1b549SSpandan Das cover_format = ctx.attr.cover_format[BuildSettingInfo].value, 837*9bb1b549SSpandan Das gc_goopts = ctx.attr.gc_goopts[BuildSettingInfo].value, 838*9bb1b549SSpandan Das amd64 = ctx.attr.amd64, 839*9bb1b549SSpandan Das )] 840*9bb1b549SSpandan Das 841*9bb1b549SSpandan Dasgo_config = rule( 842*9bb1b549SSpandan Das implementation = _go_config_impl, 843*9bb1b549SSpandan Das attrs = { 844*9bb1b549SSpandan Das "static": attr.label( 845*9bb1b549SSpandan Das mandatory = True, 846*9bb1b549SSpandan Das providers = [BuildSettingInfo], 847*9bb1b549SSpandan Das ), 848*9bb1b549SSpandan Das "race": attr.label( 849*9bb1b549SSpandan Das mandatory = True, 850*9bb1b549SSpandan Das providers = [BuildSettingInfo], 851*9bb1b549SSpandan Das ), 852*9bb1b549SSpandan Das "msan": attr.label( 853*9bb1b549SSpandan Das mandatory = True, 854*9bb1b549SSpandan Das providers = [BuildSettingInfo], 855*9bb1b549SSpandan Das ), 856*9bb1b549SSpandan Das "pure": attr.label( 857*9bb1b549SSpandan Das mandatory = True, 858*9bb1b549SSpandan Das providers = [BuildSettingInfo], 859*9bb1b549SSpandan Das ), 860*9bb1b549SSpandan Das "strip": attr.bool(mandatory = True), 861*9bb1b549SSpandan Das "debug": attr.label( 862*9bb1b549SSpandan Das mandatory = True, 863*9bb1b549SSpandan Das providers = [BuildSettingInfo], 864*9bb1b549SSpandan Das ), 865*9bb1b549SSpandan Das "linkmode": attr.label( 866*9bb1b549SSpandan Das mandatory = True, 867*9bb1b549SSpandan Das providers = [BuildSettingInfo], 868*9bb1b549SSpandan Das ), 869*9bb1b549SSpandan Das "gc_linkopts": attr.label( 870*9bb1b549SSpandan Das mandatory = True, 871*9bb1b549SSpandan Das providers = [BuildSettingInfo], 872*9bb1b549SSpandan Das ), 873*9bb1b549SSpandan Das "gotags": attr.label( 874*9bb1b549SSpandan Das mandatory = True, 875*9bb1b549SSpandan Das providers = [BuildSettingInfo], 876*9bb1b549SSpandan Das ), 877*9bb1b549SSpandan Das "stamp": attr.bool(mandatory = True), 878*9bb1b549SSpandan Das "cover_format": attr.label( 879*9bb1b549SSpandan Das mandatory = True, 880*9bb1b549SSpandan Das providers = [BuildSettingInfo], 881*9bb1b549SSpandan Das ), 882*9bb1b549SSpandan Das "gc_goopts": attr.label( 883*9bb1b549SSpandan Das mandatory = True, 884*9bb1b549SSpandan Das providers = [BuildSettingInfo], 885*9bb1b549SSpandan Das ), 886*9bb1b549SSpandan Das "amd64": attr.string(), 887*9bb1b549SSpandan Das }, 888*9bb1b549SSpandan Das provides = [GoConfigInfo], 889*9bb1b549SSpandan Das doc = """Collects information about build settings in the current 890*9bb1b549SSpandan Das configuration. Rules may depend on this instead of depending on all 891*9bb1b549SSpandan Das the build settings directly.""", 892*9bb1b549SSpandan Das) 893*9bb1b549SSpandan Das 894*9bb1b549SSpandan Dasdef _expand_opts(go, attribute_name, opts): 895*9bb1b549SSpandan Das return [go._ctx.expand_make_variables(attribute_name, opt, {}) for opt in opts] 896*9bb1b549SSpandan Das 897*9bb1b549SSpandan Dasdef _expand_location(go, attr, s): 898*9bb1b549SSpandan Das return go._ctx.expand_location(s, getattr(attr, "data", [])) 899*9bb1b549SSpandan Das 900*9bb1b549SSpandan Das_LIST_TYPE = type([]) 901*9bb1b549SSpandan Das 902*9bb1b549SSpandan Das# Used to get attribute values which may have been transitioned. 903*9bb1b549SSpandan Das# Transitioned attributes end up as lists. 904*9bb1b549SSpandan Das# We never use split-transitions, so we always expect exactly one element in those lists. 905*9bb1b549SSpandan Das# But if the attribute wasn't transitioned, it won't be a list. 906*9bb1b549SSpandan Dasdef _flatten_possibly_transitioned_attr(maybe_list): 907*9bb1b549SSpandan Das if type(maybe_list) == _LIST_TYPE: 908*9bb1b549SSpandan Das if len(maybe_list) == 1: 909*9bb1b549SSpandan Das return maybe_list[0] 910*9bb1b549SSpandan Das else: 911*9bb1b549SSpandan Das fail("Expected exactly one element in list but got {}".format(maybe_list)) 912*9bb1b549SSpandan Das return maybe_list 913