xref: /aosp_15_r20/external/bazelbuild-rules_go/go/private/go_toolchain.bzl (revision 9bb1b549b6a84214c53be0924760be030e66b93a)
1# Copyright 2016 The Bazel Go Rules Authors. All rights reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#    http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14"""
15Toolchain rules used by go.
16"""
17
18load("//go/private:platforms.bzl", "PLATFORMS")
19load("//go/private:providers.bzl", "GoSDK")
20load("//go/private/actions:archive.bzl", "emit_archive")
21load("//go/private/actions:binary.bzl", "emit_binary")
22load("//go/private/actions:link.bzl", "emit_link")
23load("//go/private/actions:stdlib.bzl", "emit_stdlib")
24load("@bazel_skylib//lib:selects.bzl", "selects")
25
26GO_TOOLCHAIN = "@io_bazel_rules_go//go:toolchain"
27
28def _go_toolchain_impl(ctx):
29    sdk = ctx.attr.sdk[GoSDK]
30    cross_compile = ctx.attr.goos != sdk.goos or ctx.attr.goarch != sdk.goarch
31    return [platform_common.ToolchainInfo(
32        # Public fields
33        name = ctx.label.name,
34        cross_compile = cross_compile,
35        default_goos = ctx.attr.goos,
36        default_goarch = ctx.attr.goarch,
37        actions = struct(
38            archive = emit_archive,
39            binary = emit_binary,
40            link = emit_link,
41            stdlib = emit_stdlib,
42        ),
43        flags = struct(
44            compile = (),
45            link = ctx.attr.link_flags,
46            link_cgo = ctx.attr.cgo_link_flags,
47        ),
48        sdk = sdk,
49
50        # Internal fields -- may be read by emit functions.
51        _builder = ctx.executable.builder,
52    )]
53
54go_toolchain = rule(
55    _go_toolchain_impl,
56    attrs = {
57        # Minimum requirements to specify a toolchain
58        "builder": attr.label(
59            mandatory = True,
60            cfg = "exec",
61            executable = True,
62            doc = "Tool used to execute most Go actions",
63        ),
64        "goos": attr.string(
65            mandatory = True,
66            doc = "Default target OS",
67        ),
68        "goarch": attr.string(
69            mandatory = True,
70            doc = "Default target architecture",
71        ),
72        "sdk": attr.label(
73            mandatory = True,
74            providers = [GoSDK],
75            cfg = "exec",
76            doc = "The SDK this toolchain is based on",
77        ),
78        # Optional extras to a toolchain
79        "link_flags": attr.string_list(
80            doc = "Flags passed to the Go internal linker",
81        ),
82        "cgo_link_flags": attr.string_list(
83            doc = "Flags passed to the external linker (if it is used)",
84        ),
85    },
86    doc = "Defines a Go toolchain based on an SDK",
87    provides = [platform_common.ToolchainInfo],
88)
89
90def declare_go_toolchains(host_goos, sdk, builder):
91    """Declares go_toolchain targets for each platform."""
92    for p in PLATFORMS:
93        if p.cgo:
94            # Don't declare separate toolchains for cgo_on / cgo_off.
95            # This is controlled by the cgo_context_data dependency of
96            # go_context_data, which is configured using constraint_values.
97            continue
98
99        link_flags = []
100        cgo_link_flags = []
101        if host_goos == "darwin":
102            cgo_link_flags.extend(["-shared", "-Wl,-all_load"])
103        if host_goos == "linux":
104            cgo_link_flags.append("-Wl,-whole-archive")
105
106        go_toolchain(
107            name = "go_" + p.name + "-impl",
108            goos = p.goos,
109            goarch = p.goarch,
110            sdk = sdk,
111            builder = builder,
112            link_flags = link_flags,
113            cgo_link_flags = cgo_link_flags,
114            tags = ["manual"],
115            visibility = ["//visibility:public"],
116        )
117
118def declare_bazel_toolchains(
119        *,
120        go_toolchain_repo,
121        host_goarch,
122        host_goos,
123        major,
124        minor,
125        patch,
126        prerelease,
127        sdk_type,
128        prefix = ""):
129    """Declares toolchain targets for each platform."""
130
131    sdk_version_label = Label("//go/toolchain:sdk_version")
132
133    native.config_setting(
134        name = prefix + "match_all_versions",
135        flag_values = {
136            sdk_version_label: "",
137        },
138        visibility = ["//visibility:private"],
139    )
140
141    native.config_setting(
142        name = prefix + "match_major_version",
143        flag_values = {
144            sdk_version_label: major,
145        },
146        visibility = ["//visibility:private"],
147    )
148
149    native.config_setting(
150        name = prefix + "match_major_minor_version",
151        flag_values = {
152            sdk_version_label: major + "." + minor,
153        },
154        visibility = ["//visibility:private"],
155    )
156
157    native.config_setting(
158        name = prefix + "match_patch_version",
159        flag_values = {
160            sdk_version_label: major + "." + minor + "." + patch,
161        },
162        visibility = ["//visibility:private"],
163    )
164
165    # If prerelease version is "", this will be the same as ":match_patch_version", but that's fine since we use match_any in config_setting_group.
166    native.config_setting(
167        name = prefix + "match_prerelease_version",
168        flag_values = {
169            sdk_version_label: major + "." + minor + "." + patch + prerelease,
170        },
171        visibility = ["//visibility:private"],
172    )
173
174    native.config_setting(
175        name = prefix + "match_sdk_type",
176        flag_values = {
177            sdk_version_label: sdk_type,
178        },
179        visibility = ["//visibility:private"],
180    )
181
182    selects.config_setting_group(
183        name = prefix + "sdk_version_setting",
184        match_any = [
185            ":" + prefix + "match_all_versions",
186            ":" + prefix + "match_major_version",
187            ":" + prefix + "match_major_minor_version",
188            ":" + prefix + "match_patch_version",
189            ":" + prefix + "match_prerelease_version",
190            ":" + prefix + "match_sdk_type",
191        ],
192        visibility = ["//visibility:private"],
193    )
194
195    for p in PLATFORMS:
196        if p.cgo:
197            # Don't declare separate toolchains for cgo_on / cgo_off.
198            # This is controlled by the cgo_context_data dependency of
199            # go_context_data, which is configured using constraint_values.
200            continue
201
202        cgo_constraints = (
203            "@io_bazel_rules_go//go/toolchain:cgo_off",
204            "@io_bazel_rules_go//go/toolchain:cgo_on",
205        )
206        constraints = [c for c in p.constraints if c not in cgo_constraints]
207
208        native.toolchain(
209            # keep in sync with generate_toolchain_names
210            name = prefix + "go_" + p.name,
211            toolchain_type = GO_TOOLCHAIN,
212            exec_compatible_with = [
213                "@io_bazel_rules_go//go/toolchain:" + host_goos,
214                "@io_bazel_rules_go//go/toolchain:" + host_goarch,
215            ],
216            target_compatible_with = constraints,
217            target_settings = [":" + prefix + "sdk_version_setting"],
218            toolchain = go_toolchain_repo + "//:go_" + p.name + "-impl",
219        )
220