xref: /aosp_15_r20/external/bazelbuild-rules_go/go/private/mode.bzl (revision 9bb1b549b6a84214c53be0924760be030e66b93a)
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 Das# Modes are documented in go/modes.rst#compilation-modes
16*9bb1b549SSpandan Das
17*9bb1b549SSpandan DasLINKMODE_NORMAL = "normal"
18*9bb1b549SSpandan Das
19*9bb1b549SSpandan DasLINKMODE_SHARED = "shared"
20*9bb1b549SSpandan Das
21*9bb1b549SSpandan DasLINKMODE_PIE = "pie"
22*9bb1b549SSpandan Das
23*9bb1b549SSpandan DasLINKMODE_PLUGIN = "plugin"
24*9bb1b549SSpandan Das
25*9bb1b549SSpandan DasLINKMODE_C_SHARED = "c-shared"
26*9bb1b549SSpandan Das
27*9bb1b549SSpandan DasLINKMODE_C_ARCHIVE = "c-archive"
28*9bb1b549SSpandan Das
29*9bb1b549SSpandan DasLINKMODES = [LINKMODE_NORMAL, LINKMODE_PLUGIN, LINKMODE_C_SHARED, LINKMODE_C_ARCHIVE, LINKMODE_PIE]
30*9bb1b549SSpandan Das
31*9bb1b549SSpandan Das# All link modes that produce executables to be run with bazel run.
32*9bb1b549SSpandan DasLINKMODES_EXECUTABLE = [LINKMODE_NORMAL, LINKMODE_PIE]
33*9bb1b549SSpandan Das
34*9bb1b549SSpandan Das# All link modes that require external linking and thus a cgo context.
35*9bb1b549SSpandan DasLINKMODES_REQUIRING_EXTERNAL_LINKING = [
36*9bb1b549SSpandan Das    LINKMODE_PLUGIN,
37*9bb1b549SSpandan Das    LINKMODE_C_ARCHIVE,
38*9bb1b549SSpandan Das    LINKMODE_C_SHARED,
39*9bb1b549SSpandan Das]
40*9bb1b549SSpandan Das
41*9bb1b549SSpandan Dasdef mode_string(mode):
42*9bb1b549SSpandan Das    result = [mode.goos, mode.goarch]
43*9bb1b549SSpandan Das    if mode.static:
44*9bb1b549SSpandan Das        result.append("static")
45*9bb1b549SSpandan Das    if mode.race:
46*9bb1b549SSpandan Das        result.append("race")
47*9bb1b549SSpandan Das    if mode.msan:
48*9bb1b549SSpandan Das        result.append("msan")
49*9bb1b549SSpandan Das    if mode.pure:
50*9bb1b549SSpandan Das        result.append("pure")
51*9bb1b549SSpandan Das    if mode.debug:
52*9bb1b549SSpandan Das        result.append("debug")
53*9bb1b549SSpandan Das    if mode.strip:
54*9bb1b549SSpandan Das        result.append("stripped")
55*9bb1b549SSpandan Das    if not result or not mode.link == LINKMODE_NORMAL:
56*9bb1b549SSpandan Das        result.append(mode.link)
57*9bb1b549SSpandan Das    if mode.gc_goopts:
58*9bb1b549SSpandan Das        result.extend(mode.gc_goopts)
59*9bb1b549SSpandan Das    return "_".join(result)
60*9bb1b549SSpandan Das
61*9bb1b549SSpandan Dasdef _ternary(*values):
62*9bb1b549SSpandan Das    for v in values:
63*9bb1b549SSpandan Das        if v == None:
64*9bb1b549SSpandan Das            continue
65*9bb1b549SSpandan Das        if type(v) == "bool":
66*9bb1b549SSpandan Das            return v
67*9bb1b549SSpandan Das        if type(v) != "string":
68*9bb1b549SSpandan Das            fail("Invalid value type {}".format(type(v)))
69*9bb1b549SSpandan Das        v = v.lower()
70*9bb1b549SSpandan Das        if v == "on":
71*9bb1b549SSpandan Das            return True
72*9bb1b549SSpandan Das        if v == "off":
73*9bb1b549SSpandan Das            return False
74*9bb1b549SSpandan Das        if v == "auto":
75*9bb1b549SSpandan Das            continue
76*9bb1b549SSpandan Das        fail("Invalid value {}".format(v))
77*9bb1b549SSpandan Das    fail("_ternary failed to produce a final result from {}".format(values))
78*9bb1b549SSpandan Das
79*9bb1b549SSpandan Dasdef get_mode(ctx, go_toolchain, cgo_context_info, go_config_info):
80*9bb1b549SSpandan Das    static = _ternary(go_config_info.static if go_config_info else "off")
81*9bb1b549SSpandan Das    pure = _ternary(
82*9bb1b549SSpandan Das        "on" if not cgo_context_info else "auto",
83*9bb1b549SSpandan Das        go_config_info.pure if go_config_info else "off",
84*9bb1b549SSpandan Das    )
85*9bb1b549SSpandan Das    race = _ternary(go_config_info.race if go_config_info else "off")
86*9bb1b549SSpandan Das    msan = _ternary(go_config_info.msan if go_config_info else "off")
87*9bb1b549SSpandan Das    strip = go_config_info.strip if go_config_info else False
88*9bb1b549SSpandan Das    stamp = go_config_info.stamp if go_config_info else False
89*9bb1b549SSpandan Das    debug = go_config_info.debug if go_config_info else False
90*9bb1b549SSpandan Das    linkmode = go_config_info.linkmode if go_config_info else LINKMODE_NORMAL
91*9bb1b549SSpandan Das    cover_format = go_config_info and go_config_info.cover_format
92*9bb1b549SSpandan Das    amd64 = go_config_info.amd64 if go_config_info else None
93*9bb1b549SSpandan Das    goos = go_toolchain.default_goos if getattr(ctx.attr, "goos", "auto") == "auto" else ctx.attr.goos
94*9bb1b549SSpandan Das    goarch = go_toolchain.default_goarch if getattr(ctx.attr, "goarch", "auto") == "auto" else ctx.attr.goarch
95*9bb1b549SSpandan Das    gc_goopts = go_config_info.gc_goopts if go_config_info else []
96*9bb1b549SSpandan Das
97*9bb1b549SSpandan Das    # TODO(jayconrod): check for more invalid and contradictory settings.
98*9bb1b549SSpandan Das    if pure and race:
99*9bb1b549SSpandan Das        fail("race instrumentation can't be enabled when cgo is disabled. Check that pure is not set to \"off\" and a C/C++ toolchain is configured.")
100*9bb1b549SSpandan Das    if pure and msan:
101*9bb1b549SSpandan Das        fail("msan instrumentation can't be enabled when cgo is disabled. Check that pure is not set to \"off\" and a C/C++ toolchain is configured.")
102*9bb1b549SSpandan Das    if pure and linkmode in LINKMODES_REQUIRING_EXTERNAL_LINKING:
103*9bb1b549SSpandan Das        fail(("linkmode '{}' can't be used when cgo is disabled. Check that pure is not set to \"off\" and that a C/C++ toolchain is configured for " +
104*9bb1b549SSpandan Das              "your current platform. If you defined a custom platform, make sure that it has the @io_bazel_rules_go//go/toolchain:cgo_on constraint value.").format(linkmode))
105*9bb1b549SSpandan Das
106*9bb1b549SSpandan Das    gc_linkopts = list(go_config_info.gc_linkopts) if go_config_info else []
107*9bb1b549SSpandan Das    tags = list(go_config_info.tags) if go_config_info else []
108*9bb1b549SSpandan Das    if "gotags" in ctx.var:
109*9bb1b549SSpandan Das        tags.extend(ctx.var["gotags"].split(","))
110*9bb1b549SSpandan Das    if cgo_context_info:
111*9bb1b549SSpandan Das        tags.extend(cgo_context_info.tags)
112*9bb1b549SSpandan Das    if race:
113*9bb1b549SSpandan Das        tags.append("race")
114*9bb1b549SSpandan Das    if msan:
115*9bb1b549SSpandan Das        tags.append("msan")
116*9bb1b549SSpandan Das
117*9bb1b549SSpandan Das    return struct(
118*9bb1b549SSpandan Das        static = static,
119*9bb1b549SSpandan Das        race = race,
120*9bb1b549SSpandan Das        msan = msan,
121*9bb1b549SSpandan Das        pure = pure,
122*9bb1b549SSpandan Das        link = linkmode,
123*9bb1b549SSpandan Das        gc_linkopts = gc_linkopts,
124*9bb1b549SSpandan Das        strip = strip,
125*9bb1b549SSpandan Das        stamp = stamp,
126*9bb1b549SSpandan Das        debug = debug,
127*9bb1b549SSpandan Das        goos = goos,
128*9bb1b549SSpandan Das        goarch = goarch,
129*9bb1b549SSpandan Das        tags = tags,
130*9bb1b549SSpandan Das        cover_format = cover_format,
131*9bb1b549SSpandan Das        amd64 = amd64,
132*9bb1b549SSpandan Das        gc_goopts = gc_goopts,
133*9bb1b549SSpandan Das    )
134*9bb1b549SSpandan Das
135*9bb1b549SSpandan Dasdef installsuffix(mode):
136*9bb1b549SSpandan Das    s = mode.goos + "_" + mode.goarch
137*9bb1b549SSpandan Das    if mode.race:
138*9bb1b549SSpandan Das        s += "_race"
139*9bb1b549SSpandan Das    elif mode.msan:
140*9bb1b549SSpandan Das        s += "_msan"
141*9bb1b549SSpandan Das    return s
142*9bb1b549SSpandan Das
143*9bb1b549SSpandan Dasdef mode_tags_equivalent(l, r):
144*9bb1b549SSpandan Das    # Returns whether two modes are equivalent for Go build tags. For example,
145*9bb1b549SSpandan Das    # goos and goarch must match, but static doesn't matter.
146*9bb1b549SSpandan Das    return (l.goos == r.goos and
147*9bb1b549SSpandan Das            l.goarch == r.goarch and
148*9bb1b549SSpandan Das            l.race == r.race and
149*9bb1b549SSpandan Das            l.msan == r.msan)
150*9bb1b549SSpandan Das
151*9bb1b549SSpandan Das# Ported from https://github.com/golang/go/blob/master/src/cmd/go/internal/work/init.go#L76
152*9bb1b549SSpandan Das_LINK_C_ARCHIVE_PLATFORMS = {
153*9bb1b549SSpandan Das    "darwin/arm64": None,
154*9bb1b549SSpandan Das    "ios/arm64": None,
155*9bb1b549SSpandan Das}
156*9bb1b549SSpandan Das
157*9bb1b549SSpandan Das_LINK_C_ARCHIVE_GOOS = {
158*9bb1b549SSpandan Das    "dragonfly": None,
159*9bb1b549SSpandan Das    "freebsd": None,
160*9bb1b549SSpandan Das    "linux": None,
161*9bb1b549SSpandan Das    "netbsd": None,
162*9bb1b549SSpandan Das    "openbsd": None,
163*9bb1b549SSpandan Das    "solaris": None,
164*9bb1b549SSpandan Das}
165*9bb1b549SSpandan Das
166*9bb1b549SSpandan Das_LINK_C_SHARED_GOOS = [
167*9bb1b549SSpandan Das    "android",
168*9bb1b549SSpandan Das    "freebsd",
169*9bb1b549SSpandan Das    "linux",
170*9bb1b549SSpandan Das]
171*9bb1b549SSpandan Das
172*9bb1b549SSpandan Das_LINK_PLUGIN_PLATFORMS = {
173*9bb1b549SSpandan Das    "linux/amd64": None,
174*9bb1b549SSpandan Das    "linux/arm": None,
175*9bb1b549SSpandan Das    "linux/arm64": None,
176*9bb1b549SSpandan Das    "linux/386": None,
177*9bb1b549SSpandan Das    "linux/s390x": None,
178*9bb1b549SSpandan Das    "linux/ppc64le": None,
179*9bb1b549SSpandan Das    "android/amd64": None,
180*9bb1b549SSpandan Das    "android/arm": None,
181*9bb1b549SSpandan Das    "android/arm64": None,
182*9bb1b549SSpandan Das    "android/386": None,
183*9bb1b549SSpandan Das    "darwin/amd64": None,
184*9bb1b549SSpandan Das    "darwin/arm64": None,
185*9bb1b549SSpandan Das    "ios/arm": None,
186*9bb1b549SSpandan Das    "ios/arm64": None,
187*9bb1b549SSpandan Das}
188*9bb1b549SSpandan Das
189*9bb1b549SSpandan Das_LINK_PIE_PLATFORMS = {
190*9bb1b549SSpandan Das    "linux/amd64": None,
191*9bb1b549SSpandan Das    "linux/arm": None,
192*9bb1b549SSpandan Das    "linux/arm64": None,
193*9bb1b549SSpandan Das    "linux/386": None,
194*9bb1b549SSpandan Das    "linux/s390x": None,
195*9bb1b549SSpandan Das    "linux/ppc64le": None,
196*9bb1b549SSpandan Das    "android/amd64": None,
197*9bb1b549SSpandan Das    "android/arm": None,
198*9bb1b549SSpandan Das    "android/arm64": None,
199*9bb1b549SSpandan Das    "android/386": None,
200*9bb1b549SSpandan Das    "freebsd/amd64": None,
201*9bb1b549SSpandan Das}
202*9bb1b549SSpandan Das
203*9bb1b549SSpandan Dasdef link_mode_args(mode):
204*9bb1b549SSpandan Das    # based on buildModeInit in cmd/go/internal/work/init.go
205*9bb1b549SSpandan Das    platform = mode.goos + "/" + mode.goarch
206*9bb1b549SSpandan Das    args = []
207*9bb1b549SSpandan Das    if mode.link == LINKMODE_C_ARCHIVE:
208*9bb1b549SSpandan Das        if (platform in _LINK_C_ARCHIVE_PLATFORMS or
209*9bb1b549SSpandan Das            mode.goos in _LINK_C_ARCHIVE_GOOS and platform != "linux/ppc64"):
210*9bb1b549SSpandan Das            args.append("-shared")
211*9bb1b549SSpandan Das    elif mode.link == LINKMODE_C_SHARED:
212*9bb1b549SSpandan Das        if mode.goos in _LINK_C_SHARED_GOOS:
213*9bb1b549SSpandan Das            args.append("-shared")
214*9bb1b549SSpandan Das    elif mode.link == LINKMODE_PLUGIN:
215*9bb1b549SSpandan Das        if platform in _LINK_PLUGIN_PLATFORMS:
216*9bb1b549SSpandan Das            args.append("-dynlink")
217*9bb1b549SSpandan Das    elif mode.link == LINKMODE_PIE:
218*9bb1b549SSpandan Das        if platform in _LINK_PIE_PLATFORMS:
219*9bb1b549SSpandan Das            args.append("-shared")
220*9bb1b549SSpandan Das    return args
221*9bb1b549SSpandan Das
222*9bb1b549SSpandan Dasdef extldflags_from_cc_toolchain(go):
223*9bb1b549SSpandan Das    if not go.cgo_tools:
224*9bb1b549SSpandan Das        return []
225*9bb1b549SSpandan Das    elif go.mode.link in (LINKMODE_SHARED, LINKMODE_PLUGIN, LINKMODE_C_SHARED):
226*9bb1b549SSpandan Das        return go.cgo_tools.ld_dynamic_lib_options
227*9bb1b549SSpandan Das    else:
228*9bb1b549SSpandan Das        # NOTE: in c-archive mode, -extldflags are ignored by the linker.
229*9bb1b549SSpandan Das        # However, we still need to set them for cgo, which links a binary
230*9bb1b549SSpandan Das        # in each package. We use the executable options for this.
231*9bb1b549SSpandan Das        return go.cgo_tools.ld_executable_options
232*9bb1b549SSpandan Das
233*9bb1b549SSpandan Dasdef extld_from_cc_toolchain(go):
234*9bb1b549SSpandan Das    if not go.cgo_tools:
235*9bb1b549SSpandan Das        return []
236*9bb1b549SSpandan Das    elif go.mode.link in (LINKMODE_SHARED, LINKMODE_PLUGIN, LINKMODE_C_SHARED, LINKMODE_PIE):
237*9bb1b549SSpandan Das        return ["-extld", go.cgo_tools.ld_dynamic_lib_path]
238*9bb1b549SSpandan Das    elif go.mode.link == LINKMODE_C_ARCHIVE:
239*9bb1b549SSpandan Das        if go.mode.goos in ["darwin", "ios"]:
240*9bb1b549SSpandan Das            # TODO(jayconrod): on macOS, set -extar. At this time, wrapped_ar is
241*9bb1b549SSpandan Das            # a bash script without a shebang line, so we can't execute it. We
242*9bb1b549SSpandan Das            # use /usr/bin/ar (the default) instead.
243*9bb1b549SSpandan Das            return []
244*9bb1b549SSpandan Das        else:
245*9bb1b549SSpandan Das            return ["-extar", go.cgo_tools.ld_static_lib_path]
246*9bb1b549SSpandan Das    else:
247*9bb1b549SSpandan Das        # NOTE: In c-archive mode, we should probably set -extar. However,
248*9bb1b549SSpandan Das        # on macOS, Bazel returns wrapped_ar, which is not executable.
249*9bb1b549SSpandan Das        # /usr/bin/ar (the default) should be visible though, and we have a
250*9bb1b549SSpandan Das        # hack in link.go to strip out non-reproducible stuff.
251*9bb1b549SSpandan Das        return ["-extld", go.cgo_tools.ld_executable_path]
252