xref: /aosp_15_r20/external/bazelbuild-rules_go/go/private/rules/nogo.bzl (revision 9bb1b549b6a84214c53be0924760be030e66b93a)
1*9bb1b549SSpandan Das# Copyright 2018 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:go_toolchain.bzl",
21*9bb1b549SSpandan Das    "GO_TOOLCHAIN",
22*9bb1b549SSpandan Das)
23*9bb1b549SSpandan Dasload(
24*9bb1b549SSpandan Das    "//go/private:providers.bzl",
25*9bb1b549SSpandan Das    "EXPORT_PATH",
26*9bb1b549SSpandan Das    "GoArchive",
27*9bb1b549SSpandan Das    "GoLibrary",
28*9bb1b549SSpandan Das    "get_archive",
29*9bb1b549SSpandan Das)
30*9bb1b549SSpandan Dasload(
31*9bb1b549SSpandan Das    "//go/private/rules:transition.bzl",
32*9bb1b549SSpandan Das    "go_tool_transition",
33*9bb1b549SSpandan Das)
34*9bb1b549SSpandan Das
35*9bb1b549SSpandan Dasdef _nogo_impl(ctx):
36*9bb1b549SSpandan Das    if not ctx.attr.deps:
37*9bb1b549SSpandan Das        # If there aren't any analyzers to run, don't generate a binary.
38*9bb1b549SSpandan Das        # go_context will check for this condition.
39*9bb1b549SSpandan Das        return None
40*9bb1b549SSpandan Das
41*9bb1b549SSpandan Das    # Generate the source for the nogo binary.
42*9bb1b549SSpandan Das    go = go_context(ctx)
43*9bb1b549SSpandan Das    nogo_main = go.declare_file(go, path = "nogo_main.go")
44*9bb1b549SSpandan Das    nogo_args = ctx.actions.args()
45*9bb1b549SSpandan Das    nogo_args.add("gennogomain")
46*9bb1b549SSpandan Das    nogo_args.add("-output", nogo_main)
47*9bb1b549SSpandan Das    nogo_inputs = []
48*9bb1b549SSpandan Das    analyzer_archives = [get_archive(dep) for dep in ctx.attr.deps]
49*9bb1b549SSpandan Das    analyzer_importpaths = [archive.data.importpath for archive in analyzer_archives]
50*9bb1b549SSpandan Das    nogo_args.add_all(analyzer_importpaths, before_each = "-analyzer_importpath")
51*9bb1b549SSpandan Das    if ctx.file.config:
52*9bb1b549SSpandan Das        nogo_args.add("-config", ctx.file.config)
53*9bb1b549SSpandan Das        nogo_inputs.append(ctx.file.config)
54*9bb1b549SSpandan Das    ctx.actions.run(
55*9bb1b549SSpandan Das        inputs = nogo_inputs,
56*9bb1b549SSpandan Das        outputs = [nogo_main],
57*9bb1b549SSpandan Das        mnemonic = "GoGenNogo",
58*9bb1b549SSpandan Das        executable = go.toolchain._builder,
59*9bb1b549SSpandan Das        arguments = [nogo_args],
60*9bb1b549SSpandan Das    )
61*9bb1b549SSpandan Das
62*9bb1b549SSpandan Das    # Compile the nogo binary itself.
63*9bb1b549SSpandan Das    nogo_library = GoLibrary(
64*9bb1b549SSpandan Das        name = go.label.name + "~nogo",
65*9bb1b549SSpandan Das        label = go.label,
66*9bb1b549SSpandan Das        importpath = "nogomain",
67*9bb1b549SSpandan Das        importmap = "nogomain",
68*9bb1b549SSpandan Das        importpath_aliases = (),
69*9bb1b549SSpandan Das        pathtype = EXPORT_PATH,
70*9bb1b549SSpandan Das        is_main = True,
71*9bb1b549SSpandan Das        resolve = None,
72*9bb1b549SSpandan Das    )
73*9bb1b549SSpandan Das
74*9bb1b549SSpandan Das    nogo_source = go.library_to_source(go, struct(
75*9bb1b549SSpandan Das        srcs = [struct(files = [nogo_main])],
76*9bb1b549SSpandan Das        embed = [ctx.attr._nogo_srcs],
77*9bb1b549SSpandan Das        deps = analyzer_archives,
78*9bb1b549SSpandan Das    ), nogo_library, False)
79*9bb1b549SSpandan Das    _, executable, runfiles = go.binary(
80*9bb1b549SSpandan Das        go,
81*9bb1b549SSpandan Das        name = ctx.label.name,
82*9bb1b549SSpandan Das        source = nogo_source,
83*9bb1b549SSpandan Das    )
84*9bb1b549SSpandan Das    return [DefaultInfo(
85*9bb1b549SSpandan Das        files = depset([executable]),
86*9bb1b549SSpandan Das        runfiles = runfiles,
87*9bb1b549SSpandan Das        executable = executable,
88*9bb1b549SSpandan Das    )]
89*9bb1b549SSpandan Das
90*9bb1b549SSpandan Das_nogo = rule(
91*9bb1b549SSpandan Das    implementation = _nogo_impl,
92*9bb1b549SSpandan Das    attrs = {
93*9bb1b549SSpandan Das        "deps": attr.label_list(
94*9bb1b549SSpandan Das            providers = [GoArchive],
95*9bb1b549SSpandan Das        ),
96*9bb1b549SSpandan Das        "config": attr.label(
97*9bb1b549SSpandan Das            allow_single_file = True,
98*9bb1b549SSpandan Das        ),
99*9bb1b549SSpandan Das        "_nogo_srcs": attr.label(
100*9bb1b549SSpandan Das            default = "//go/tools/builders:nogo_srcs",
101*9bb1b549SSpandan Das        ),
102*9bb1b549SSpandan Das        "_cgo_context_data": attr.label(default = "//:cgo_context_data_proxy"),
103*9bb1b549SSpandan Das        "_go_config": attr.label(default = "//:go_config"),
104*9bb1b549SSpandan Das        "_stdlib": attr.label(default = "//:stdlib"),
105*9bb1b549SSpandan Das        "_allowlist_function_transition": attr.label(
106*9bb1b549SSpandan Das            default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
107*9bb1b549SSpandan Das        ),
108*9bb1b549SSpandan Das    },
109*9bb1b549SSpandan Das    toolchains = [GO_TOOLCHAIN],
110*9bb1b549SSpandan Das    cfg = go_tool_transition,
111*9bb1b549SSpandan Das)
112*9bb1b549SSpandan Das
113*9bb1b549SSpandan Dasdef nogo(name, visibility = None, **kwargs):
114*9bb1b549SSpandan Das    actual_name = "%s_actual" % name
115*9bb1b549SSpandan Das    native.alias(
116*9bb1b549SSpandan Das        name = name,
117*9bb1b549SSpandan Das        actual = select({
118*9bb1b549SSpandan Das            "@io_bazel_rules_go//go/private:nogo_active": actual_name,
119*9bb1b549SSpandan Das            "//conditions:default": Label("//:default_nogo"),
120*9bb1b549SSpandan Das        }),
121*9bb1b549SSpandan Das        visibility = visibility,
122*9bb1b549SSpandan Das    )
123*9bb1b549SSpandan Das
124*9bb1b549SSpandan Das    # With --use_top_level_targets_for_symlinks, which is enabled by default in
125*9bb1b549SSpandan Das    # Bazel 6.0.0, self-transitioning top-level targets prevent the bazel-bin
126*9bb1b549SSpandan Das    # convenience symlink from being created. Since nogo targets are of this
127*9bb1b549SSpandan Das    # type, their presence would trigger this behavior. Work around this by
128*9bb1b549SSpandan Das    # excluding them from wildcards - they are still transitively built as a
129*9bb1b549SSpandan Das    # tool dependency of every Go target.
130*9bb1b549SSpandan Das    kwargs.setdefault("tags", [])
131*9bb1b549SSpandan Das    if "manual" not in kwargs["tags"]:
132*9bb1b549SSpandan Das        kwargs["tags"].append("manual")
133*9bb1b549SSpandan Das
134*9bb1b549SSpandan Das    _nogo(
135*9bb1b549SSpandan Das        name = actual_name,
136*9bb1b549SSpandan Das        visibility = visibility,
137*9bb1b549SSpandan Das        **kwargs
138*9bb1b549SSpandan Das    )
139*9bb1b549SSpandan Das
140*9bb1b549SSpandan Dasdef nogo_wrapper(**kwargs):
141*9bb1b549SSpandan Das    if kwargs.get("vet"):
142*9bb1b549SSpandan Das        kwargs["deps"] = kwargs.get("deps", []) + [
143*9bb1b549SSpandan Das            "@org_golang_x_tools//go/analysis/passes/atomic:go_default_library",
144*9bb1b549SSpandan Das            "@org_golang_x_tools//go/analysis/passes/bools:go_default_library",
145*9bb1b549SSpandan Das            "@org_golang_x_tools//go/analysis/passes/buildtag:go_default_library",
146*9bb1b549SSpandan Das            "@org_golang_x_tools//go/analysis/passes/nilfunc:go_default_library",
147*9bb1b549SSpandan Das            "@org_golang_x_tools//go/analysis/passes/printf:go_default_library",
148*9bb1b549SSpandan Das        ]
149*9bb1b549SSpandan Das        kwargs = {k: v for k, v in kwargs.items() if k != "vet"}
150*9bb1b549SSpandan Das    nogo(**kwargs)
151