| # Copyright 2014 The Bazel Authors. All rights reserved. |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo") |
| load("@rules_cc//cc/common:cc_common.bzl", "cc_common") |
| load("@rules_cc//cc/common:cc_info.bzl", "CcInfo") |
| load( |
| "//go/private:common.bzl", |
| "GO_TOOLCHAIN", |
| "SUPPORTS_PATH_MAPPING_REQUIREMENT", |
| "asm_exts", |
| "cgo_exts", |
| "go_exts", |
| "syso_exts", |
| ) |
| load( |
| "//go/private:context.bzl", |
| "CGO_ATTRS", |
| "CGO_FRAGMENTS", |
| "CGO_TOOLCHAINS", |
| "go_context", |
| "maybe_needs_cc_toolchain", |
| "new_go_info", |
| ) |
| load( |
| "//go/private:mode.bzl", |
| "LINKMODES", |
| "LINKMODES_EXECUTABLE", |
| "LINKMODE_C_ARCHIVE", |
| "LINKMODE_C_SHARED", |
| "LINKMODE_PLUGIN", |
| "LINKMODE_SHARED", |
| ) |
| load( |
| "//go/private:providers.bzl", |
| "GoArchive", |
| "GoInfo", |
| "GoSDK", |
| ) |
| load( |
| "//go/private/rules:transition.bzl", |
| "go_transition", |
| "non_go_transition", |
| ) |
| |
| _EMPTY_DEPSET = depset([]) |
| |
| def _include_path(hdr): |
| if not hdr.root.path: |
| fail("Expected hdr to be a generated file, got source file: " + hdr.path) |
| |
| root_relative_path = hdr.path[len(hdr.root.path + "/"):] |
| if not root_relative_path.startswith("external/"): |
| return hdr.root.path |
| |
| # All headers should be includeable via a path relative to their repository |
| # root, regardless of whether the repository is external or not. If it is, |
| # we thus need to append "external/<external repo name>" to the path. |
| return "/".join([hdr.root.path] + root_relative_path.split("/")[0:2]) |
| |
| def new_cc_import( |
| go, |
| hdrs = _EMPTY_DEPSET, |
| defines = _EMPTY_DEPSET, |
| local_defines = _EMPTY_DEPSET, |
| dynamic_library = None, |
| static_library = None, |
| alwayslink = False, |
| linkopts = []): |
| return CcInfo( |
| compilation_context = cc_common.create_compilation_context( |
| defines = defines, |
| local_defines = local_defines, |
| headers = hdrs, |
| includes = depset([_include_path(hdr) for hdr in hdrs.to_list()]), |
| ), |
| linking_context = cc_common.create_linking_context( |
| linker_inputs = depset([ |
| cc_common.create_linker_input( |
| owner = go.label, |
| libraries = depset([ |
| cc_common.create_library_to_link( |
| actions = go.actions, |
| cc_toolchain = go.cgo_tools.cc_toolchain, |
| feature_configuration = go.cgo_tools.feature_configuration, |
| dynamic_library = dynamic_library, |
| static_library = static_library, |
| alwayslink = alwayslink, |
| ), |
| ]), |
| user_link_flags = depset(linkopts), |
| ), |
| ]), |
| ), |
| ) |
| |
| def _go_cc_aspect_impl(target, ctx): |
| if GoInfo not in target: |
| return [] |
| |
| deps = ( |
| getattr(ctx.rule.attr, "cdeps", []) + |
| getattr(ctx.rule.attr, "deps", []) + |
| getattr(ctx.rule.attr, "embed", []) |
| ) |
| return [ |
| cc_common.merge_cc_infos(cc_infos = [dep[CcInfo] for dep in deps]), |
| ] |
| |
| _go_cc_aspect = aspect( |
| implementation = _go_cc_aspect_impl, |
| attr_aspects = ["deps", "embed"], |
| ) |
| |
| def _go_binary_impl(ctx): |
| """go_binary_impl emits actions for compiling and linking a go executable.""" |
| go = go_context( |
| ctx, |
| importpath = ctx.attr.importpath, |
| embed = ctx.attr.embed, |
| go_context_data = ctx.attr._go_context_data, |
| maybe_needs_cc_toolchain = maybe_needs_cc_toolchain(ctx.attr, go_infos = ctx.attr.deps), |
| goos = ctx.attr.goos, |
| goarch = ctx.attr.goarch, |
| ) |
| |
| generated_srcs = [] |
| deps = ctx.attr.deps |
| |
| if go.coverage_enabled: |
| coverage_shim = ctx.actions.declare_file(ctx.attr.name + "_coverage_shim.go") |
| ctx.actions.symlink( |
| output = coverage_shim, |
| target_file = ctx.file._coverage_shim, |
| ) |
| generated_srcs.append(coverage_shim) |
| deps = list(deps) + [ctx.attr._bincov] |
| |
| is_main = go.mode.linkmode not in (LINKMODE_SHARED, LINKMODE_PLUGIN) |
| go_info = new_go_info( |
| go, |
| ctx.attr, |
| generated_srcs = generated_srcs, |
| deps = [dep[GoArchive] for dep in deps], |
| importable = False, |
| is_main = is_main, |
| ) |
| name = ctx.attr.basename |
| if not name: |
| name = ctx.label.name |
| executable = None |
| if ctx.attr.out: |
| # Use declare_file instead of attr.output(). When users set output files |
| # directly, Bazel warns them not to use the same name as the rule, which is |
| # the common case with go_binary. |
| executable = ctx.actions.declare_file(ctx.attr.out) |
| archive, executable, runfiles = go.binary( |
| go, |
| name = name, |
| source = go_info, |
| gc_linkopts = gc_linkopts(ctx), |
| version_file = ctx.version_file, |
| info_file = ctx.info_file, |
| executable = executable, |
| ) |
| validation_output = archive.data._validation_output |
| nogo_diagnostics = archive.data._nogo_diagnostics |
| |
| providers = [ |
| archive, |
| OutputGroupInfo( |
| cgo_exports = archive.cgo_exports, |
| compilation_outputs = [archive.data.file], |
| nogo_fix = [nogo_diagnostics] if nogo_diagnostics else [], |
| _validation = [validation_output] if validation_output else [], |
| ), |
| ] |
| |
| if go.mode.linkmode in LINKMODES_EXECUTABLE: |
| env = {} |
| for k, v in ctx.attr.env.items(): |
| env[k] = ctx.expand_location(v, ctx.attr.data) if "$" in v else v |
| providers.append(RunEnvironmentInfo(environment = env)) |
| |
| # The executable is automatically added to the runfiles. |
| providers.append(DefaultInfo( |
| files = depset([executable]), |
| runfiles = runfiles, |
| executable = executable, |
| )) |
| else: |
| # Workaround for https://github.com/bazelbuild/bazel/issues/15043 |
| # As of Bazel 5.1.1, native rules do not pick up the "files" of a data |
| # dependency's DefaultInfo, only the "data_runfiles". Since transitive |
| # non-data dependents should not pick up the executable as a runfile |
| # implicitly, the deprecated "default_runfiles" and "data_runfiles" |
| # constructor parameters have to be used. |
| providers.append(DefaultInfo( |
| files = depset([executable]), |
| default_runfiles = runfiles, |
| data_runfiles = runfiles.merge(ctx.runfiles([executable])), |
| )) |
| |
| # If the binary's linkmode is c-archive or c-shared, expose CcInfo |
| if go.cgo_tools and go.mode.linkmode in (LINKMODE_C_ARCHIVE, LINKMODE_C_SHARED): |
| cc_import_kwargs = { |
| "linkopts": { |
| "darwin": [], |
| "ios": [], |
| "windows": ["-mthreads"], |
| }.get(go.mode.goos, ["-pthread"]), |
| } |
| cgo_exports = archive.cgo_exports.to_list() |
| if cgo_exports: |
| header = ctx.actions.declare_file("{}.h".format(name)) |
| ctx.actions.symlink( |
| output = header, |
| target_file = cgo_exports[0], |
| ) |
| cc_import_kwargs["hdrs"] = depset([header]) |
| if go.mode.linkmode == LINKMODE_C_SHARED: |
| cc_import_kwargs["dynamic_library"] = executable |
| elif go.mode.linkmode == LINKMODE_C_ARCHIVE: |
| cc_import_kwargs["static_library"] = executable |
| cc_import_kwargs["alwayslink"] = True |
| |
| cc_infos = [new_cc_import(go, **cc_import_kwargs)] |
| cc_infos.extend([dep[CcInfo] for dep in ctx.attr.cdeps + ctx.attr.deps + ctx.attr.embed if CcInfo in dep]) |
| |
| ccinfo = cc_common.merge_cc_infos(cc_infos = cc_infos) |
| providers.append(ccinfo) |
| |
| providers.append( |
| coverage_common.instrumented_files_info( |
| ctx, |
| source_attributes = ["srcs"], |
| dependency_attributes = ["data", "deps", "embed", "embedsrcs"], |
| extensions = ["go"], |
| ), |
| ) |
| |
| return providers |
| |
| def _go_binary_kwargs(go_cc_aspects = []): |
| return { |
| "cfg": go_transition, |
| "implementation": _go_binary_impl, |
| "attrs": { |
| "srcs": attr.label_list( |
| allow_files = go_exts + asm_exts + cgo_exts + syso_exts, |
| cfg = non_go_transition, |
| doc = """The list of Go source files that are compiled to create the package. |
| Only `.go`, `.s`, and `.syso` files are permitted, unless the `cgo` |
| attribute is set, in which case, |
| `.c .cc .cpp .cxx .h .hh .hpp .hxx .inc .m .mm` |
| files are also permitted. Files may be filtered at build time |
| using Go [build constraints]. |
| """, |
| ), |
| "data": attr.label_list( |
| allow_files = True, |
| cfg = non_go_transition, |
| doc = """List of files needed by this rule at run-time. This may include data files |
| needed or other programs that may be executed. The [bazel] package may be |
| used to locate run files; they may appear in different places depending on the |
| operating system and environment. See [data dependencies] for more |
| information on data files. |
| """, |
| ), |
| "deps": attr.label_list( |
| providers = [GoInfo], |
| aspects = go_cc_aspects, |
| doc = """List of Go libraries this package imports directly. |
| These may be `go_library` rules or compatible rules with the [GoInfo] provider. |
| """, |
| ), |
| "embed": attr.label_list( |
| providers = [GoInfo], |
| aspects = go_cc_aspects, |
| doc = """List of Go libraries whose sources should be compiled together with this |
| binary's sources. Labels listed here must name `go_library`, |
| `go_proto_library`, or other compatible targets with the [GoInfo] provider. |
| Embedded libraries must all have the same `importpath`, |
| which must match the `importpath` for this `go_binary` if one is |
| specified. At most one embedded library may have `cgo = True`, and the |
| embedding binary may not also have `cgo = True`. See [Embedding] for |
| more information. |
| """, |
| ), |
| "embedsrcs": attr.label_list( |
| allow_files = True, |
| cfg = non_go_transition, |
| doc = """The list of files that may be embedded into the compiled package using |
| `//go:embed` directives. All files must be in the same logical directory |
| or a subdirectory as source files. All source files containing `//go:embed` |
| directives must be in the same logical directory. It's okay to mix static and |
| generated source files and static and generated embeddable files. |
| """, |
| ), |
| "env": attr.string_dict( |
| doc = """Environment variables to set when the binary is executed with bazel run. |
| The values (but not keys) are subject to |
| [location expansion](https://docs.bazel.build/versions/main/skylark/macros.html) but not full |
| [make variable expansion](https://docs.bazel.build/versions/main/be/make-variables.html). |
| """, |
| ), |
| "importpath": attr.string( |
| doc = """The import path of this binary. Binaries can't actually be imported, but this |
| may be used by [go_path] and other tools to report the location of source |
| files. This may be inferred from embedded libraries. |
| """, |
| ), |
| "gc_goopts": attr.string_list( |
| doc = """List of flags to add to the Go compilation command when using the gc compiler. |
| Subject to ["Make variable"] substitution and [Bourne shell tokenization]. |
| """, |
| ), |
| "gc_linkopts": attr.string_list( |
| doc = """List of flags to add to the Go link command when using the gc compiler. |
| Subject to ["Make variable"] substitution and [Bourne shell tokenization]. |
| """, |
| ), |
| "x_defs": attr.string_dict( |
| doc = """Map of defines to add to the go link command. |
| See [Defines and stamping] for examples of how to use these. |
| """, |
| ), |
| "basename": attr.string( |
| doc = """The basename of this binary. The binary |
| basename may also be platform-dependent: on Windows, we add an .exe extension. |
| """, |
| ), |
| "out": attr.string( |
| doc = """Sets the output filename for the generated executable. When set, `go_binary` |
| will write this file without mode-specific directory prefixes, without |
| linkmode-specific prefixes like "lib", and without platform-specific suffixes |
| like ".exe". Note that without a mode-specific directory prefix, the |
| output file (but not its dependencies) will be invalidated in Bazel's cache |
| when changing configurations. |
| """, |
| ), |
| "cgo": attr.bool( |
| doc = """If `True`, the package may contain [cgo] code, and `srcs` may contain |
| C, C++, Objective-C, and Objective-C++ files and non-Go assembly files. |
| When cgo is enabled, these files will be compiled with the C/C++ toolchain |
| and included in the package. Note that this attribute does not force cgo |
| to be enabled. Cgo is enabled for non-cross-compiling builds when a C/C++ |
| toolchain is configured. |
| """, |
| ), |
| "cdeps": attr.label_list( |
| cfg = non_go_transition, |
| doc = """The list of other libraries that the c code depends on. |
| This can be anything that would be allowed in [cc_library deps] |
| Only valid if `cgo` = `True`. |
| """, |
| ), |
| "cppopts": attr.string_list( |
| doc = """List of flags to add to the C/C++ preprocessor command. |
| Subject to ["Make variable"] substitution and [Bourne shell tokenization]. |
| Only valid if `cgo` = `True`. |
| """, |
| ), |
| "copts": attr.string_list( |
| doc = """List of flags to add to the C compilation command. |
| Subject to ["Make variable"] substitution and [Bourne shell tokenization]. |
| Only valid if `cgo` = `True`. |
| """, |
| ), |
| "cxxopts": attr.string_list( |
| doc = """List of flags to add to the C++ compilation command. |
| Subject to ["Make variable"] substitution and [Bourne shell tokenization]. |
| Only valid if `cgo` = `True`. |
| """, |
| ), |
| "clinkopts": attr.string_list( |
| doc = """List of flags to add to the C link command. |
| Subject to ["Make variable"] substitution and [Bourne shell tokenization]. |
| Only valid if `cgo` = `True`. |
| """, |
| ), |
| "pure": attr.string( |
| default = "auto", |
| doc = """Controls whether cgo source code and dependencies are compiled and linked, |
| similar to setting `CGO_ENABLED`. May be one of `on`, `off`, |
| or `auto`. If `auto`, pure mode is enabled when no C/C++ |
| toolchain is configured or when cross-compiling. It's usually better to |
| control this on the command line with |
| `--@io_bazel_rules_go//go/config:pure`. See [mode attributes], specifically |
| [pure]. |
| """, |
| ), |
| "static": attr.string( |
| default = "auto", |
| doc = """Controls whether a binary is statically linked. May be one of `on`, |
| `off`, or `auto`. Not available on all platforms or in all |
| modes. It's usually better to control this on the command line with |
| `--@io_bazel_rules_go//go/config:static`. See [mode attributes], |
| specifically [static]. |
| """, |
| ), |
| "race": attr.string( |
| default = "auto", |
| doc = """Controls whether code is instrumented for race detection. May be one of |
| `on`, `off`, or `auto`. Not available when cgo is |
| disabled. In most cases, it's better to control this on the command line with |
| `--@io_bazel_rules_go//go/config:race`. See [mode attributes], specifically |
| [race]. |
| """, |
| ), |
| "msan": attr.string( |
| default = "auto", |
| doc = """Controls whether code is instrumented for memory sanitization. May be one of |
| `on`, `off`, or `auto`. Not available when cgo is |
| disabled. In most cases, it's better to control this on the command line with |
| `--@io_bazel_rules_go//go/config:msan`. See [mode attributes], specifically |
| [msan]. |
| """, |
| ), |
| "gotags": attr.string_list( |
| doc = """Enables a list of build tags when evaluating [build constraints]. Useful for |
| conditional compilation. |
| """, |
| ), |
| "goos": attr.string( |
| default = "auto", |
| doc = """Forces a binary to be cross-compiled for a specific operating system. It's |
| usually better to control this on the command line with `--platforms`. |
| |
| This disables cgo by default, since a cross-compiling C/C++ toolchain is |
| rarely available. To force cgo, set `pure` = `off`. |
| |
| See [Cross compilation] for more information. |
| """, |
| ), |
| "goarch": attr.string( |
| default = "auto", |
| doc = """Forces a binary to be cross-compiled for a specific architecture. It's usually |
| better to control this on the command line with `--platforms`. |
| |
| This disables cgo by default, since a cross-compiling C/C++ toolchain is |
| rarely available. To force cgo, set `pure` = `off`. |
| |
| See [Cross compilation] for more information. |
| """, |
| ), |
| "linkmode": attr.string( |
| default = "auto", |
| values = ["auto"] + LINKMODES, |
| doc = """Determines how the binary should be built and linked. This accepts some of |
| the same values as `go build -buildmode` and works the same way. |
| |
| <ul> |
| <li>`auto` (default): Controlled by `//go/config:linkmode`, which defaults to `pie` on supported platforms and `normal` elsewhere.</li> |
| <li>`normal`: Builds a normal executable with position-dependent code.</li> |
| <li>`pie`: Builds a position-independent executable.</li> |
| <li>`plugin`: Builds a shared library that can be loaded as a Go plugin. Only supported on platforms that support plugins.</li> |
| <li>`c-shared`: Builds a shared library that can be linked into a C program.</li> |
| <li>`c-archive`: Builds an archive that can be linked into a C program.</li> |
| </ul> |
| """, |
| ), |
| "pgoprofile": attr.label( |
| allow_files = True, |
| doc = """Provides a pprof file to be used for profile guided optimization when compiling go targets. |
| A pprof file can also be provided via `--@io_bazel_rules_go//go/config:pgoprofile=<label of a pprof file>`. |
| Profile guided optimization is only supported on go 1.20+. |
| See https://go.dev/doc/pgo for more information. |
| """, |
| default = "//go/config:empty", |
| ), |
| "_go_context_data": attr.label(default = "//:go_context_data"), |
| "_allowlist_function_transition": attr.label( |
| default = "@bazel_tools//tools/allowlists/function_transition_allowlist", |
| ), |
| "_coverage_shim": attr.label( |
| default = "//go/private:coverage_shim.go", |
| allow_single_file = True, |
| ), |
| "_bincov": attr.label( |
| default = "//go/tools/bzltestutil/bincov", |
| ), |
| } | CGO_ATTRS, |
| "fragments": CGO_FRAGMENTS, |
| "toolchains": [GO_TOOLCHAIN] + CGO_TOOLCHAINS, |
| "doc": """This builds an executable from a set of source files, |
| which must all be in the `main` package. You can run the binary with |
| `bazel run`, or you can build it with `bazel build` and run it directly. |
| |
| ***Note:*** `name` should be the same as the desired name of the generated binary. |
| |
| **Providers:** |
| - [GoArchive] |
| """, |
| } |
| |
| go_binary = rule(executable = True, **_go_binary_kwargs()) |
| go_non_executable_binary = rule(executable = False, **_go_binary_kwargs( |
| go_cc_aspects = [_go_cc_aspect], |
| )) |
| |
| def _go_tool_binary_impl(ctx): |
| # Keep in mind that the actions registered by this rule may not be |
| # sandboxed, so care must be taken to make them hermetic, for example by |
| # preventing `go build` from searching for go.mod or downloading a |
| # different toolchain version. |
| # |
| # A side effect of the usage of GO111MODULE below is that the absolute |
| # path to the sources is included in the buildid, which would make the |
| # resulting binary non-reproducible. We thus need to blank it out. |
| # https://github.com/golang/go/blob/583d750fa119d504686c737be6a898994b674b69/src/cmd/go/internal/load/pkg.go#L1764-L1766 |
| # https://github.com/golang/go/blob/583d750fa119d504686c737be6a898994b674b69/src/cmd/go/internal/work/exec.go#L284 |
| |
| sdk = ctx.attr.sdk[GoSDK] |
| name = ctx.label.name |
| if sdk.goos == "windows": |
| name += ".exe" |
| |
| out = ctx.actions.declare_file(name) |
| if sdk.goos == "windows": |
| # Using pre-declared directory for temporary output as there is no safe |
| # way under Windows to create unique temporary dir. |
| gotmp = ctx.actions.declare_directory("gotmp") |
| cmd = """@echo off |
| set GOMAXPROCS=1 |
| set GOCACHE=%cd%\\{gotmp}\\gocache |
| set GOPATH=%cd%"\\{gotmp}\\gopath |
| set GOTOOLCHAIN=local |
| set GO111MODULE=off |
| set GOTELEMETRY=off |
| set GOENV=off |
| {go} build -trimpath -ldflags \"-buildid='' {ldflags}\" -o {out_pack} cmd/pack |
| if %ERRORLEVEL% EQU 0 ( |
| {go} build -trimpath -ldflags \"-buildid='' {ldflags}\" -o {out} {srcs} |
| ) |
| set GO_EXIT_CODE=%ERRORLEVEL% |
| RMDIR /S /Q "{gotmp}" |
| MKDIR "{gotmp}" |
| exit /b %GO_EXIT_CODE% |
| """.format( |
| gotmp = gotmp.path.replace("/", "\\"), |
| go = sdk.go.path.replace("/", "\\"), |
| out = out.path, |
| out_pack = ctx.outputs.out_pack.path, |
| srcs = " ".join([f.path for f in ctx.files.srcs]), |
| ldflags = ctx.attr.ldflags, |
| ) |
| bat = ctx.actions.declare_file(name + ".bat") |
| ctx.actions.write( |
| output = bat, |
| content = cmd, |
| ) |
| ctx.actions.run( |
| executable = bat, |
| tools = depset( |
| ctx.files.srcs + [sdk.go], |
| transitive = [sdk.headers, sdk.srcs, sdk.tools], |
| ), |
| toolchain = None, |
| outputs = [out, ctx.outputs.out_pack, gotmp], |
| mnemonic = "GoToolchainBinaryBuild", |
| ) |
| else: |
| # Pass (potentially) generated files in via args to support path mapping. |
| args = ctx.actions.args() |
| args.add(ctx.outputs.out_pack) |
| args.add(out) |
| args.add_all(ctx.files.srcs) |
| |
| setting = ctx.attr._use_sh_toolchain_for_bootstrap_process_wrapper[BuildSettingInfo].value |
| sh_toolchain = ctx.toolchains["@bazel_tools//tools/sh:toolchain_type"] |
| binary_wrapper = ctx.file._binary_wrapper |
| if setting and sh_toolchain: |
| binary_wrapper = ctx.actions.declare_file(name + "_binary_wrapper.sh") |
| ctx.actions.expand_template( |
| template = ctx.file._binary_wrapper, |
| output = binary_wrapper, |
| is_executable = True, |
| substitutions = { |
| "#!/usr/bin/env bash": "#!{}".format(sh_toolchain.path), |
| }, |
| ) |
| |
| ctx.actions.run( |
| executable = binary_wrapper, |
| arguments = [args], |
| tools = [sdk.go], |
| env = { |
| "GOMAXPROCS": "1", |
| "GOTOOLCHAIN": "local", |
| "GO111MODULE": "off", |
| "GOTELEMETRY": "off", |
| "GOENV": "off", |
| "GO_BINARY": sdk.go.path, |
| "LD_FLAGS": ctx.attr.ldflags, |
| }, |
| inputs = depset( |
| ctx.files.srcs, |
| transitive = [sdk.headers, sdk.srcs, sdk.libs, sdk.tools], |
| ), |
| toolchain = None, |
| outputs = [out, ctx.outputs.out_pack], |
| execution_requirements = SUPPORTS_PATH_MAPPING_REQUIREMENT, |
| mnemonic = "GoToolchainBinaryBuild", |
| ) |
| |
| return [DefaultInfo( |
| files = depset([out]), |
| executable = out, |
| )] |
| |
| go_tool_binary = rule( |
| implementation = _go_tool_binary_impl, |
| attrs = { |
| "srcs": attr.label_list( |
| allow_files = True, |
| doc = "Source files for the binary. Must be in 'package main'.", |
| ), |
| "sdk": attr.label( |
| mandatory = True, |
| providers = [GoSDK], |
| doc = "The SDK containing tools and libraries to build this binary", |
| ), |
| "ldflags": attr.string( |
| doc = "Raw value to pass to go build via -ldflags without tokenization", |
| ), |
| "out_pack": attr.output(), |
| "_binary_wrapper": attr.label( |
| allow_single_file = True, |
| default = "//go/private/rules:binary_wrapper.sh", |
| ), |
| "_use_sh_toolchain_for_bootstrap_process_wrapper": attr.label( |
| default = Label("//go/config:experimental_use_sh_toolchain"), |
| ), |
| }, |
| executable = True, |
| doc = """Used instead of go_binary for executables used in the toolchain. |
| |
| go_tool_binary depends on tools and libraries that are part of the Go SDK. |
| It does not depend on other toolchains. It can only compile binaries that |
| just have a main package and only depend on the standard library and don't |
| require build constraints. |
| |
| It is currently only used to build the `builder` tool maintained as part of |
| rules_go as well as the `pack` tool provided by the Go SDK in source form |
| only as of Go 1.25. Combining both builds into a single action drastically |
| reduces the overall build time due to Go's own caching mechanism. |
| """, |
| toolchains = [config_common.toolchain_type("@bazel_tools//tools/sh:toolchain_type", mandatory = False)], |
| ) |
| |
| def gc_linkopts(ctx): |
| gc_linkopts = [ |
| ctx.expand_make_variables("gc_linkopts", f, {}) |
| for f in ctx.attr.gc_linkopts |
| ] |
| return gc_linkopts |