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