1*9bb1b549SSpandan Das# Copyright 2014 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 "//go/private:context.bzl", 17*9bb1b549SSpandan Das "go_context", 18*9bb1b549SSpandan Das) 19*9bb1b549SSpandan Dasload( 20*9bb1b549SSpandan Das "//go/private:common.bzl", 21*9bb1b549SSpandan Das "asm_exts", 22*9bb1b549SSpandan Das "cgo_exts", 23*9bb1b549SSpandan Das "go_exts", 24*9bb1b549SSpandan Das) 25*9bb1b549SSpandan Dasload( 26*9bb1b549SSpandan Das "//go/private:go_toolchain.bzl", 27*9bb1b549SSpandan Das "GO_TOOLCHAIN", 28*9bb1b549SSpandan Das) 29*9bb1b549SSpandan Dasload( 30*9bb1b549SSpandan Das "//go/private:providers.bzl", 31*9bb1b549SSpandan Das "GoLibrary", 32*9bb1b549SSpandan Das "GoSDK", 33*9bb1b549SSpandan Das) 34*9bb1b549SSpandan Dasload( 35*9bb1b549SSpandan Das "//go/private/rules:transition.bzl", 36*9bb1b549SSpandan Das "go_transition", 37*9bb1b549SSpandan Das) 38*9bb1b549SSpandan Dasload( 39*9bb1b549SSpandan Das "//go/private:mode.bzl", 40*9bb1b549SSpandan Das "LINKMODES_EXECUTABLE", 41*9bb1b549SSpandan Das "LINKMODE_C_ARCHIVE", 42*9bb1b549SSpandan Das "LINKMODE_C_SHARED", 43*9bb1b549SSpandan Das "LINKMODE_NORMAL", 44*9bb1b549SSpandan Das "LINKMODE_PLUGIN", 45*9bb1b549SSpandan Das "LINKMODE_SHARED", 46*9bb1b549SSpandan Das) 47*9bb1b549SSpandan Das 48*9bb1b549SSpandan Das_EMPTY_DEPSET = depset([]) 49*9bb1b549SSpandan Das 50*9bb1b549SSpandan Dasdef _include_path(hdr): 51*9bb1b549SSpandan Das if not hdr.root.path: 52*9bb1b549SSpandan Das fail("Expected hdr to be a generated file, got source file: " + hdr.path) 53*9bb1b549SSpandan Das 54*9bb1b549SSpandan Das root_relative_path = hdr.path[len(hdr.root.path + "/"):] 55*9bb1b549SSpandan Das if not root_relative_path.startswith("external/"): 56*9bb1b549SSpandan Das return hdr.root.path 57*9bb1b549SSpandan Das 58*9bb1b549SSpandan Das # All headers should be includeable via a path relative to their repository 59*9bb1b549SSpandan Das # root, regardless of whether the repository is external or not. If it is, 60*9bb1b549SSpandan Das # we thus need to append "external/<external repo name>" to the path. 61*9bb1b549SSpandan Das return "/".join([hdr.root.path] + root_relative_path.split("/")[0:2]) 62*9bb1b549SSpandan Das 63*9bb1b549SSpandan Dasdef new_cc_import( 64*9bb1b549SSpandan Das go, 65*9bb1b549SSpandan Das hdrs = _EMPTY_DEPSET, 66*9bb1b549SSpandan Das defines = _EMPTY_DEPSET, 67*9bb1b549SSpandan Das local_defines = _EMPTY_DEPSET, 68*9bb1b549SSpandan Das dynamic_library = None, 69*9bb1b549SSpandan Das static_library = None, 70*9bb1b549SSpandan Das alwayslink = False, 71*9bb1b549SSpandan Das linkopts = []): 72*9bb1b549SSpandan Das return CcInfo( 73*9bb1b549SSpandan Das compilation_context = cc_common.create_compilation_context( 74*9bb1b549SSpandan Das defines = defines, 75*9bb1b549SSpandan Das local_defines = local_defines, 76*9bb1b549SSpandan Das headers = hdrs, 77*9bb1b549SSpandan Das includes = depset([_include_path(hdr) for hdr in hdrs.to_list()]), 78*9bb1b549SSpandan Das ), 79*9bb1b549SSpandan Das linking_context = cc_common.create_linking_context( 80*9bb1b549SSpandan Das linker_inputs = depset([ 81*9bb1b549SSpandan Das cc_common.create_linker_input( 82*9bb1b549SSpandan Das owner = go.label, 83*9bb1b549SSpandan Das libraries = depset([ 84*9bb1b549SSpandan Das cc_common.create_library_to_link( 85*9bb1b549SSpandan Das actions = go.actions, 86*9bb1b549SSpandan Das cc_toolchain = go.cgo_tools.cc_toolchain, 87*9bb1b549SSpandan Das feature_configuration = go.cgo_tools.feature_configuration, 88*9bb1b549SSpandan Das dynamic_library = dynamic_library, 89*9bb1b549SSpandan Das static_library = static_library, 90*9bb1b549SSpandan Das alwayslink = alwayslink, 91*9bb1b549SSpandan Das ), 92*9bb1b549SSpandan Das ]), 93*9bb1b549SSpandan Das user_link_flags = depset(linkopts), 94*9bb1b549SSpandan Das ), 95*9bb1b549SSpandan Das ]), 96*9bb1b549SSpandan Das ), 97*9bb1b549SSpandan Das ) 98*9bb1b549SSpandan Das 99*9bb1b549SSpandan Dasdef _go_binary_impl(ctx): 100*9bb1b549SSpandan Das """go_binary_impl emits actions for compiling and linking a go executable.""" 101*9bb1b549SSpandan Das go = go_context(ctx) 102*9bb1b549SSpandan Das 103*9bb1b549SSpandan Das is_main = go.mode.link not in (LINKMODE_SHARED, LINKMODE_PLUGIN) 104*9bb1b549SSpandan Das library = go.new_library(go, importable = False, is_main = is_main) 105*9bb1b549SSpandan Das source = go.library_to_source(go, ctx.attr, library, ctx.coverage_instrumented()) 106*9bb1b549SSpandan Das name = ctx.attr.basename 107*9bb1b549SSpandan Das if not name: 108*9bb1b549SSpandan Das name = ctx.label.name 109*9bb1b549SSpandan Das executable = None 110*9bb1b549SSpandan Das if ctx.attr.out: 111*9bb1b549SSpandan Das # Use declare_file instead of attr.output(). When users set output files 112*9bb1b549SSpandan Das # directly, Bazel warns them not to use the same name as the rule, which is 113*9bb1b549SSpandan Das # the common case with go_binary. 114*9bb1b549SSpandan Das executable = ctx.actions.declare_file(ctx.attr.out) 115*9bb1b549SSpandan Das archive, executable, runfiles = go.binary( 116*9bb1b549SSpandan Das go, 117*9bb1b549SSpandan Das name = name, 118*9bb1b549SSpandan Das source = source, 119*9bb1b549SSpandan Das gc_linkopts = gc_linkopts(ctx), 120*9bb1b549SSpandan Das version_file = ctx.version_file, 121*9bb1b549SSpandan Das info_file = ctx.info_file, 122*9bb1b549SSpandan Das executable = executable, 123*9bb1b549SSpandan Das ) 124*9bb1b549SSpandan Das 125*9bb1b549SSpandan Das providers = [ 126*9bb1b549SSpandan Das library, 127*9bb1b549SSpandan Das source, 128*9bb1b549SSpandan Das archive, 129*9bb1b549SSpandan Das OutputGroupInfo( 130*9bb1b549SSpandan Das cgo_exports = archive.cgo_exports, 131*9bb1b549SSpandan Das compilation_outputs = [archive.data.file], 132*9bb1b549SSpandan Das ), 133*9bb1b549SSpandan Das ] 134*9bb1b549SSpandan Das 135*9bb1b549SSpandan Das if go.mode.link in LINKMODES_EXECUTABLE: 136*9bb1b549SSpandan Das env = {} 137*9bb1b549SSpandan Das for k, v in ctx.attr.env.items(): 138*9bb1b549SSpandan Das env[k] = ctx.expand_location(v, ctx.attr.data) 139*9bb1b549SSpandan Das providers.append(RunEnvironmentInfo(environment = env)) 140*9bb1b549SSpandan Das 141*9bb1b549SSpandan Das # The executable is automatically added to the runfiles. 142*9bb1b549SSpandan Das providers.append(DefaultInfo( 143*9bb1b549SSpandan Das files = depset([executable]), 144*9bb1b549SSpandan Das runfiles = runfiles, 145*9bb1b549SSpandan Das executable = executable, 146*9bb1b549SSpandan Das )) 147*9bb1b549SSpandan Das else: 148*9bb1b549SSpandan Das # Workaround for https://github.com/bazelbuild/bazel/issues/15043 149*9bb1b549SSpandan Das # As of Bazel 5.1.1, native rules do not pick up the "files" of a data 150*9bb1b549SSpandan Das # dependency's DefaultInfo, only the "data_runfiles". Since transitive 151*9bb1b549SSpandan Das # non-data dependents should not pick up the executable as a runfile 152*9bb1b549SSpandan Das # implicitly, the deprecated "default_runfiles" and "data_runfiles" 153*9bb1b549SSpandan Das # constructor parameters have to be used. 154*9bb1b549SSpandan Das providers.append(DefaultInfo( 155*9bb1b549SSpandan Das files = depset([executable]), 156*9bb1b549SSpandan Das default_runfiles = runfiles, 157*9bb1b549SSpandan Das data_runfiles = runfiles.merge(ctx.runfiles([executable])), 158*9bb1b549SSpandan Das )) 159*9bb1b549SSpandan Das 160*9bb1b549SSpandan Das # If the binary's linkmode is c-archive or c-shared, expose CcInfo 161*9bb1b549SSpandan Das if go.cgo_tools and go.mode.link in (LINKMODE_C_ARCHIVE, LINKMODE_C_SHARED): 162*9bb1b549SSpandan Das cc_import_kwargs = { 163*9bb1b549SSpandan Das "linkopts": { 164*9bb1b549SSpandan Das "darwin": [], 165*9bb1b549SSpandan Das "ios": [], 166*9bb1b549SSpandan Das "windows": ["-mthreads"], 167*9bb1b549SSpandan Das }.get(go.mode.goos, ["-pthread"]), 168*9bb1b549SSpandan Das } 169*9bb1b549SSpandan Das cgo_exports = archive.cgo_exports.to_list() 170*9bb1b549SSpandan Das if cgo_exports: 171*9bb1b549SSpandan Das header = ctx.actions.declare_file("{}.h".format(name)) 172*9bb1b549SSpandan Das ctx.actions.symlink( 173*9bb1b549SSpandan Das output = header, 174*9bb1b549SSpandan Das target_file = cgo_exports[0], 175*9bb1b549SSpandan Das ) 176*9bb1b549SSpandan Das cc_import_kwargs["hdrs"] = depset([header]) 177*9bb1b549SSpandan Das if go.mode.link == LINKMODE_C_SHARED: 178*9bb1b549SSpandan Das cc_import_kwargs["dynamic_library"] = executable 179*9bb1b549SSpandan Das elif go.mode.link == LINKMODE_C_ARCHIVE: 180*9bb1b549SSpandan Das cc_import_kwargs["static_library"] = executable 181*9bb1b549SSpandan Das cc_import_kwargs["alwayslink"] = True 182*9bb1b549SSpandan Das ccinfo = new_cc_import(go, **cc_import_kwargs) 183*9bb1b549SSpandan Das ccinfo = cc_common.merge_cc_infos( 184*9bb1b549SSpandan Das cc_infos = [ccinfo, source.cc_info], 185*9bb1b549SSpandan Das ) 186*9bb1b549SSpandan Das providers.append(ccinfo) 187*9bb1b549SSpandan Das 188*9bb1b549SSpandan Das return providers 189*9bb1b549SSpandan Das 190*9bb1b549SSpandan Das_go_binary_kwargs = { 191*9bb1b549SSpandan Das "implementation": _go_binary_impl, 192*9bb1b549SSpandan Das "attrs": { 193*9bb1b549SSpandan Das "srcs": attr.label_list( 194*9bb1b549SSpandan Das allow_files = go_exts + asm_exts + cgo_exts, 195*9bb1b549SSpandan Das doc = """The list of Go source files that are compiled to create the package. 196*9bb1b549SSpandan Das Only `.go` and `.s` files are permitted, unless the `cgo` 197*9bb1b549SSpandan Das attribute is set, in which case, 198*9bb1b549SSpandan Das `.c .cc .cpp .cxx .h .hh .hpp .hxx .inc .m .mm` 199*9bb1b549SSpandan Das files are also permitted. Files may be filtered at build time 200*9bb1b549SSpandan Das using Go [build constraints]. 201*9bb1b549SSpandan Das """, 202*9bb1b549SSpandan Das ), 203*9bb1b549SSpandan Das "data": attr.label_list( 204*9bb1b549SSpandan Das allow_files = True, 205*9bb1b549SSpandan Das doc = """List of files needed by this rule at run-time. This may include data files 206*9bb1b549SSpandan Das needed or other programs that may be executed. The [bazel] package may be 207*9bb1b549SSpandan Das used to locate run files; they may appear in different places depending on the 208*9bb1b549SSpandan Das operating system and environment. See [data dependencies] for more 209*9bb1b549SSpandan Das information on data files. 210*9bb1b549SSpandan Das """, 211*9bb1b549SSpandan Das ), 212*9bb1b549SSpandan Das "deps": attr.label_list( 213*9bb1b549SSpandan Das providers = [GoLibrary], 214*9bb1b549SSpandan Das doc = """List of Go libraries this package imports directly. 215*9bb1b549SSpandan Das These may be `go_library` rules or compatible rules with the [GoLibrary] provider. 216*9bb1b549SSpandan Das """, 217*9bb1b549SSpandan Das cfg = go_transition, 218*9bb1b549SSpandan Das ), 219*9bb1b549SSpandan Das "embed": attr.label_list( 220*9bb1b549SSpandan Das providers = [GoLibrary], 221*9bb1b549SSpandan Das doc = """List of Go libraries whose sources should be compiled together with this 222*9bb1b549SSpandan Das binary's sources. Labels listed here must name `go_library`, 223*9bb1b549SSpandan Das `go_proto_library`, or other compatible targets with the [GoLibrary] and 224*9bb1b549SSpandan Das [GoSource] providers. Embedded libraries must all have the same `importpath`, 225*9bb1b549SSpandan Das which must match the `importpath` for this `go_binary` if one is 226*9bb1b549SSpandan Das specified. At most one embedded library may have `cgo = True`, and the 227*9bb1b549SSpandan Das embedding binary may not also have `cgo = True`. See [Embedding] for 228*9bb1b549SSpandan Das more information. 229*9bb1b549SSpandan Das """, 230*9bb1b549SSpandan Das cfg = go_transition, 231*9bb1b549SSpandan Das ), 232*9bb1b549SSpandan Das "embedsrcs": attr.label_list( 233*9bb1b549SSpandan Das allow_files = True, 234*9bb1b549SSpandan Das doc = """The list of files that may be embedded into the compiled package using 235*9bb1b549SSpandan Das `//go:embed` directives. All files must be in the same logical directory 236*9bb1b549SSpandan Das or a subdirectory as source files. All source files containing `//go:embed` 237*9bb1b549SSpandan Das directives must be in the same logical directory. It's okay to mix static and 238*9bb1b549SSpandan Das generated source files and static and generated embeddable files. 239*9bb1b549SSpandan Das """, 240*9bb1b549SSpandan Das ), 241*9bb1b549SSpandan Das "env": attr.string_dict( 242*9bb1b549SSpandan Das doc = """Environment variables to set when the binary is executed with bazel run. 243*9bb1b549SSpandan Das The values (but not keys) are subject to 244*9bb1b549SSpandan Das [location expansion](https://docs.bazel.build/versions/main/skylark/macros.html) but not full 245*9bb1b549SSpandan Das [make variable expansion](https://docs.bazel.build/versions/main/be/make-variables.html). 246*9bb1b549SSpandan Das """, 247*9bb1b549SSpandan Das ), 248*9bb1b549SSpandan Das "importpath": attr.string( 249*9bb1b549SSpandan Das doc = """The import path of this binary. Binaries can't actually be imported, but this 250*9bb1b549SSpandan Das may be used by [go_path] and other tools to report the location of source 251*9bb1b549SSpandan Das files. This may be inferred from embedded libraries. 252*9bb1b549SSpandan Das """, 253*9bb1b549SSpandan Das ), 254*9bb1b549SSpandan Das "gc_goopts": attr.string_list( 255*9bb1b549SSpandan Das doc = """List of flags to add to the Go compilation command when using the gc compiler. 256*9bb1b549SSpandan Das Subject to ["Make variable"] substitution and [Bourne shell tokenization]. 257*9bb1b549SSpandan Das """, 258*9bb1b549SSpandan Das ), 259*9bb1b549SSpandan Das "gc_linkopts": attr.string_list( 260*9bb1b549SSpandan Das doc = """List of flags to add to the Go link command when using the gc compiler. 261*9bb1b549SSpandan Das Subject to ["Make variable"] substitution and [Bourne shell tokenization]. 262*9bb1b549SSpandan Das """, 263*9bb1b549SSpandan Das ), 264*9bb1b549SSpandan Das "x_defs": attr.string_dict( 265*9bb1b549SSpandan Das doc = """Map of defines to add to the go link command. 266*9bb1b549SSpandan Das See [Defines and stamping] for examples of how to use these. 267*9bb1b549SSpandan Das """, 268*9bb1b549SSpandan Das ), 269*9bb1b549SSpandan Das "basename": attr.string( 270*9bb1b549SSpandan Das doc = """The basename of this binary. The binary 271*9bb1b549SSpandan Das basename may also be platform-dependent: on Windows, we add an .exe extension. 272*9bb1b549SSpandan Das """, 273*9bb1b549SSpandan Das ), 274*9bb1b549SSpandan Das "out": attr.string( 275*9bb1b549SSpandan Das doc = """Sets the output filename for the generated executable. When set, `go_binary` 276*9bb1b549SSpandan Das will write this file without mode-specific directory prefixes, without 277*9bb1b549SSpandan Das linkmode-specific prefixes like "lib", and without platform-specific suffixes 278*9bb1b549SSpandan Das like ".exe". Note that without a mode-specific directory prefix, the 279*9bb1b549SSpandan Das output file (but not its dependencies) will be invalidated in Bazel's cache 280*9bb1b549SSpandan Das when changing configurations. 281*9bb1b549SSpandan Das """, 282*9bb1b549SSpandan Das ), 283*9bb1b549SSpandan Das "cgo": attr.bool( 284*9bb1b549SSpandan Das doc = """If `True`, the package may contain [cgo] code, and `srcs` may contain 285*9bb1b549SSpandan Das C, C++, Objective-C, and Objective-C++ files and non-Go assembly files. 286*9bb1b549SSpandan Das When cgo is enabled, these files will be compiled with the C/C++ toolchain 287*9bb1b549SSpandan Das and included in the package. Note that this attribute does not force cgo 288*9bb1b549SSpandan Das to be enabled. Cgo is enabled for non-cross-compiling builds when a C/C++ 289*9bb1b549SSpandan Das toolchain is configured. 290*9bb1b549SSpandan Das """, 291*9bb1b549SSpandan Das ), 292*9bb1b549SSpandan Das "cdeps": attr.label_list( 293*9bb1b549SSpandan Das doc = """The list of other libraries that the c code depends on. 294*9bb1b549SSpandan Das This can be anything that would be allowed in [cc_library deps] 295*9bb1b549SSpandan Das Only valid if `cgo` = `True`. 296*9bb1b549SSpandan Das """, 297*9bb1b549SSpandan Das ), 298*9bb1b549SSpandan Das "cppopts": attr.string_list( 299*9bb1b549SSpandan Das doc = """List of flags to add to the C/C++ preprocessor command. 300*9bb1b549SSpandan Das Subject to ["Make variable"] substitution and [Bourne shell tokenization]. 301*9bb1b549SSpandan Das Only valid if `cgo` = `True`. 302*9bb1b549SSpandan Das """, 303*9bb1b549SSpandan Das ), 304*9bb1b549SSpandan Das "copts": attr.string_list( 305*9bb1b549SSpandan Das doc = """List of flags to add to the C compilation command. 306*9bb1b549SSpandan Das Subject to ["Make variable"] substitution and [Bourne shell tokenization]. 307*9bb1b549SSpandan Das Only valid if `cgo` = `True`. 308*9bb1b549SSpandan Das """, 309*9bb1b549SSpandan Das ), 310*9bb1b549SSpandan Das "cxxopts": attr.string_list( 311*9bb1b549SSpandan Das doc = """List of flags to add to the C++ compilation command. 312*9bb1b549SSpandan Das Subject to ["Make variable"] substitution and [Bourne shell tokenization]. 313*9bb1b549SSpandan Das Only valid if `cgo` = `True`. 314*9bb1b549SSpandan Das """, 315*9bb1b549SSpandan Das ), 316*9bb1b549SSpandan Das "clinkopts": attr.string_list( 317*9bb1b549SSpandan Das doc = """List of flags to add to the C link command. 318*9bb1b549SSpandan Das Subject to ["Make variable"] substitution and [Bourne shell tokenization]. 319*9bb1b549SSpandan Das Only valid if `cgo` = `True`. 320*9bb1b549SSpandan Das """, 321*9bb1b549SSpandan Das ), 322*9bb1b549SSpandan Das "pure": attr.string( 323*9bb1b549SSpandan Das default = "auto", 324*9bb1b549SSpandan Das doc = """Controls whether cgo source code and dependencies are compiled and linked, 325*9bb1b549SSpandan Das similar to setting `CGO_ENABLED`. May be one of `on`, `off`, 326*9bb1b549SSpandan Das or `auto`. If `auto`, pure mode is enabled when no C/C++ 327*9bb1b549SSpandan Das toolchain is configured or when cross-compiling. It's usually better to 328*9bb1b549SSpandan Das control this on the command line with 329*9bb1b549SSpandan Das `--@io_bazel_rules_go//go/config:pure`. See [mode attributes], specifically 330*9bb1b549SSpandan Das [pure]. 331*9bb1b549SSpandan Das """, 332*9bb1b549SSpandan Das ), 333*9bb1b549SSpandan Das "static": attr.string( 334*9bb1b549SSpandan Das default = "auto", 335*9bb1b549SSpandan Das doc = """Controls whether a binary is statically linked. May be one of `on`, 336*9bb1b549SSpandan Das `off`, or `auto`. Not available on all platforms or in all 337*9bb1b549SSpandan Das modes. It's usually better to control this on the command line with 338*9bb1b549SSpandan Das `--@io_bazel_rules_go//go/config:static`. See [mode attributes], 339*9bb1b549SSpandan Das specifically [static]. 340*9bb1b549SSpandan Das """, 341*9bb1b549SSpandan Das ), 342*9bb1b549SSpandan Das "race": attr.string( 343*9bb1b549SSpandan Das default = "auto", 344*9bb1b549SSpandan Das doc = """Controls whether code is instrumented for race detection. May be one of 345*9bb1b549SSpandan Das `on`, `off`, or `auto`. Not available when cgo is 346*9bb1b549SSpandan Das disabled. In most cases, it's better to control this on the command line with 347*9bb1b549SSpandan Das `--@io_bazel_rules_go//go/config:race`. See [mode attributes], specifically 348*9bb1b549SSpandan Das [race]. 349*9bb1b549SSpandan Das """, 350*9bb1b549SSpandan Das ), 351*9bb1b549SSpandan Das "msan": attr.string( 352*9bb1b549SSpandan Das default = "auto", 353*9bb1b549SSpandan Das doc = """Controls whether code is instrumented for memory sanitization. May be one of 354*9bb1b549SSpandan Das `on`, `off`, or `auto`. Not available when cgo is 355*9bb1b549SSpandan Das disabled. In most cases, it's better to control this on the command line with 356*9bb1b549SSpandan Das `--@io_bazel_rules_go//go/config:msan`. See [mode attributes], specifically 357*9bb1b549SSpandan Das [msan]. 358*9bb1b549SSpandan Das """, 359*9bb1b549SSpandan Das ), 360*9bb1b549SSpandan Das "gotags": attr.string_list( 361*9bb1b549SSpandan Das doc = """Enables a list of build tags when evaluating [build constraints]. Useful for 362*9bb1b549SSpandan Das conditional compilation. 363*9bb1b549SSpandan Das """, 364*9bb1b549SSpandan Das ), 365*9bb1b549SSpandan Das "goos": attr.string( 366*9bb1b549SSpandan Das default = "auto", 367*9bb1b549SSpandan Das doc = """Forces a binary to be cross-compiled for a specific operating system. It's 368*9bb1b549SSpandan Das usually better to control this on the command line with `--platforms`. 369*9bb1b549SSpandan Das 370*9bb1b549SSpandan Das This disables cgo by default, since a cross-compiling C/C++ toolchain is 371*9bb1b549SSpandan Das rarely available. To force cgo, set `pure` = `off`. 372*9bb1b549SSpandan Das 373*9bb1b549SSpandan Das See [Cross compilation] for more information. 374*9bb1b549SSpandan Das """, 375*9bb1b549SSpandan Das ), 376*9bb1b549SSpandan Das "goarch": attr.string( 377*9bb1b549SSpandan Das default = "auto", 378*9bb1b549SSpandan Das doc = """Forces a binary to be cross-compiled for a specific architecture. It's usually 379*9bb1b549SSpandan Das better to control this on the command line with `--platforms`. 380*9bb1b549SSpandan Das 381*9bb1b549SSpandan Das This disables cgo by default, since a cross-compiling C/C++ toolchain is 382*9bb1b549SSpandan Das rarely available. To force cgo, set `pure` = `off`. 383*9bb1b549SSpandan Das 384*9bb1b549SSpandan Das See [Cross compilation] for more information. 385*9bb1b549SSpandan Das """, 386*9bb1b549SSpandan Das ), 387*9bb1b549SSpandan Das "linkmode": attr.string( 388*9bb1b549SSpandan Das default = LINKMODE_NORMAL, 389*9bb1b549SSpandan Das doc = """Determines how the binary should be built and linked. This accepts some of 390*9bb1b549SSpandan Das the same values as `go build -buildmode` and works the same way. 391*9bb1b549SSpandan Das <br><br> 392*9bb1b549SSpandan Das <ul> 393*9bb1b549SSpandan Das <li>`normal`: Builds a normal executable with position-dependent code.</li> 394*9bb1b549SSpandan Das <li>`pie`: Builds a position-independent executable.</li> 395*9bb1b549SSpandan Das <li>`plugin`: Builds a shared library that can be loaded as a Go plugin. Only supported on platforms that support plugins.</li> 396*9bb1b549SSpandan Das <li>`c-shared`: Builds a shared library that can be linked into a C program.</li> 397*9bb1b549SSpandan Das <li>`c-archive`: Builds an archive that can be linked into a C program.</li> 398*9bb1b549SSpandan Das </ul> 399*9bb1b549SSpandan Das """, 400*9bb1b549SSpandan Das ), 401*9bb1b549SSpandan Das "_go_context_data": attr.label(default = "//:go_context_data", cfg = go_transition), 402*9bb1b549SSpandan Das "_allowlist_function_transition": attr.label( 403*9bb1b549SSpandan Das default = "@bazel_tools//tools/allowlists/function_transition_allowlist", 404*9bb1b549SSpandan Das ), 405*9bb1b549SSpandan Das }, 406*9bb1b549SSpandan Das "toolchains": [GO_TOOLCHAIN], 407*9bb1b549SSpandan Das "doc": """This builds an executable from a set of source files, 408*9bb1b549SSpandan Das which must all be in the `main` package. You can run the binary with 409*9bb1b549SSpandan Das `bazel run`, or you can build it with `bazel build` and run it directly.<br><br> 410*9bb1b549SSpandan Das ***Note:*** `name` should be the same as the desired name of the generated binary.<br><br> 411*9bb1b549SSpandan Das **Providers:** 412*9bb1b549SSpandan Das <ul> 413*9bb1b549SSpandan Das <li>[GoLibrary]</li> 414*9bb1b549SSpandan Das <li>[GoSource]</li> 415*9bb1b549SSpandan Das <li>[GoArchive]</li> 416*9bb1b549SSpandan Das </ul> 417*9bb1b549SSpandan Das """, 418*9bb1b549SSpandan Das} 419*9bb1b549SSpandan Das 420*9bb1b549SSpandan Dasgo_binary = rule(executable = True, **_go_binary_kwargs) 421*9bb1b549SSpandan Dasgo_non_executable_binary = rule(executable = False, **_go_binary_kwargs) 422*9bb1b549SSpandan Das 423*9bb1b549SSpandan Dasdef _go_tool_binary_impl(ctx): 424*9bb1b549SSpandan Das sdk = ctx.attr.sdk[GoSDK] 425*9bb1b549SSpandan Das name = ctx.label.name 426*9bb1b549SSpandan Das if sdk.goos == "windows": 427*9bb1b549SSpandan Das name += ".exe" 428*9bb1b549SSpandan Das 429*9bb1b549SSpandan Das out = ctx.actions.declare_file(name) 430*9bb1b549SSpandan Das if sdk.goos == "windows": 431*9bb1b549SSpandan Das gopath = ctx.actions.declare_directory("gopath") 432*9bb1b549SSpandan Das gocache = ctx.actions.declare_directory("gocache") 433*9bb1b549SSpandan Das cmd = "@echo off\nset GOMAXPROCS=1\nset GOCACHE=%cd%\\{gocache}\nset GOPATH=%cd%\\{gopath}\n{go} build -o {out} -trimpath {srcs}".format( 434*9bb1b549SSpandan Das gopath = gopath.path, 435*9bb1b549SSpandan Das gocache = gocache.path, 436*9bb1b549SSpandan Das go = sdk.go.path.replace("/", "\\"), 437*9bb1b549SSpandan Das out = out.path, 438*9bb1b549SSpandan Das srcs = " ".join([f.path for f in ctx.files.srcs]), 439*9bb1b549SSpandan Das ) 440*9bb1b549SSpandan Das bat = ctx.actions.declare_file(name + ".bat") 441*9bb1b549SSpandan Das ctx.actions.write( 442*9bb1b549SSpandan Das output = bat, 443*9bb1b549SSpandan Das content = cmd, 444*9bb1b549SSpandan Das ) 445*9bb1b549SSpandan Das ctx.actions.run( 446*9bb1b549SSpandan Das executable = bat, 447*9bb1b549SSpandan Das inputs = sdk.headers + sdk.tools + sdk.srcs + ctx.files.srcs + [sdk.go], 448*9bb1b549SSpandan Das outputs = [out, gopath, gocache], 449*9bb1b549SSpandan Das mnemonic = "GoToolchainBinaryBuild", 450*9bb1b549SSpandan Das ) 451*9bb1b549SSpandan Das else: 452*9bb1b549SSpandan Das # Note: GOPATH is needed for Go 1.16. 453*9bb1b549SSpandan Das cmd = "GOMAXPROCS=1 GOCACHE=$(mktemp -d) GOPATH=$(mktemp -d) {go} build -o {out} -trimpath {srcs}".format( 454*9bb1b549SSpandan Das go = sdk.go.path, 455*9bb1b549SSpandan Das out = out.path, 456*9bb1b549SSpandan Das srcs = " ".join([f.path for f in ctx.files.srcs]), 457*9bb1b549SSpandan Das ) 458*9bb1b549SSpandan Das ctx.actions.run_shell( 459*9bb1b549SSpandan Das command = cmd, 460*9bb1b549SSpandan Das inputs = sdk.headers + sdk.tools + sdk.srcs + sdk.libs + ctx.files.srcs + [sdk.go], 461*9bb1b549SSpandan Das outputs = [out], 462*9bb1b549SSpandan Das mnemonic = "GoToolchainBinaryBuild", 463*9bb1b549SSpandan Das ) 464*9bb1b549SSpandan Das 465*9bb1b549SSpandan Das return [DefaultInfo( 466*9bb1b549SSpandan Das files = depset([out]), 467*9bb1b549SSpandan Das executable = out, 468*9bb1b549SSpandan Das )] 469*9bb1b549SSpandan Das 470*9bb1b549SSpandan Dasgo_tool_binary = rule( 471*9bb1b549SSpandan Das implementation = _go_tool_binary_impl, 472*9bb1b549SSpandan Das attrs = { 473*9bb1b549SSpandan Das "srcs": attr.label_list( 474*9bb1b549SSpandan Das allow_files = True, 475*9bb1b549SSpandan Das doc = "Source files for the binary. Must be in 'package main'.", 476*9bb1b549SSpandan Das ), 477*9bb1b549SSpandan Das "sdk": attr.label( 478*9bb1b549SSpandan Das mandatory = True, 479*9bb1b549SSpandan Das providers = [GoSDK], 480*9bb1b549SSpandan Das doc = "The SDK containing tools and libraries to build this binary", 481*9bb1b549SSpandan Das ), 482*9bb1b549SSpandan Das }, 483*9bb1b549SSpandan Das executable = True, 484*9bb1b549SSpandan Das doc = """Used instead of go_binary for executables used in the toolchain. 485*9bb1b549SSpandan Das 486*9bb1b549SSpandan Dasgo_tool_binary depends on tools and libraries that are part of the Go SDK. 487*9bb1b549SSpandan DasIt does not depend on other toolchains. It can only compile binaries that 488*9bb1b549SSpandan Dasjust have a main package and only depend on the standard library and don't 489*9bb1b549SSpandan Dasrequire build constraints. 490*9bb1b549SSpandan Das""", 491*9bb1b549SSpandan Das) 492*9bb1b549SSpandan Das 493*9bb1b549SSpandan Dasdef gc_linkopts(ctx): 494*9bb1b549SSpandan Das gc_linkopts = [ 495*9bb1b549SSpandan Das ctx.expand_make_variables("gc_linkopts", f, {}) 496*9bb1b549SSpandan Das for f in ctx.attr.gc_linkopts 497*9bb1b549SSpandan Das ] 498*9bb1b549SSpandan Das return gc_linkopts 499