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 Dasload( 16*9bb1b549SSpandan Das "//go:def.bzl", 17*9bb1b549SSpandan Das "GoLibrary", 18*9bb1b549SSpandan Das "GoSource", 19*9bb1b549SSpandan Das "go_context", 20*9bb1b549SSpandan Das) 21*9bb1b549SSpandan Dasload( 22*9bb1b549SSpandan Das "@bazel_skylib//lib:types.bzl", 23*9bb1b549SSpandan Das "types", 24*9bb1b549SSpandan Das) 25*9bb1b549SSpandan Dasload( 26*9bb1b549SSpandan Das "//proto:compiler.bzl", 27*9bb1b549SSpandan Das "GoProtoCompiler", 28*9bb1b549SSpandan Das "proto_path", 29*9bb1b549SSpandan Das) 30*9bb1b549SSpandan Dasload( 31*9bb1b549SSpandan Das "//go/private:go_toolchain.bzl", 32*9bb1b549SSpandan Das "GO_TOOLCHAIN", 33*9bb1b549SSpandan Das) 34*9bb1b549SSpandan Dasload( 35*9bb1b549SSpandan Das "//go/private:providers.bzl", 36*9bb1b549SSpandan Das "INFERRED_PATH", 37*9bb1b549SSpandan Das) 38*9bb1b549SSpandan Dasload( 39*9bb1b549SSpandan Das "//go/private/rules:transition.bzl", 40*9bb1b549SSpandan Das "non_go_tool_transition", 41*9bb1b549SSpandan Das) 42*9bb1b549SSpandan Dasload( 43*9bb1b549SSpandan Das "@rules_proto//proto:defs.bzl", 44*9bb1b549SSpandan Das "ProtoInfo", 45*9bb1b549SSpandan Das) 46*9bb1b549SSpandan Das 47*9bb1b549SSpandan DasGoProtoImports = provider() 48*9bb1b549SSpandan Das 49*9bb1b549SSpandan Dasdef get_imports(attr): 50*9bb1b549SSpandan Das proto_deps = [] 51*9bb1b549SSpandan Das 52*9bb1b549SSpandan Das # ctx.attr.proto is a one-element array since there is a Starlark transition attached to it. 53*9bb1b549SSpandan Das if hasattr(attr, "proto") and attr.proto and types.is_list(attr.proto) and ProtoInfo in attr.proto[0]: 54*9bb1b549SSpandan Das proto_deps = [attr.proto[0]] 55*9bb1b549SSpandan Das elif hasattr(attr, "protos"): 56*9bb1b549SSpandan Das proto_deps = [d for d in attr.protos if ProtoInfo in d] 57*9bb1b549SSpandan Das else: 58*9bb1b549SSpandan Das proto_deps = [] 59*9bb1b549SSpandan Das 60*9bb1b549SSpandan Das direct = dict() 61*9bb1b549SSpandan Das for dep in proto_deps: 62*9bb1b549SSpandan Das for src in dep[ProtoInfo].check_deps_sources.to_list(): 63*9bb1b549SSpandan Das direct["{}={}".format(proto_path(src, dep[ProtoInfo]), attr.importpath)] = True 64*9bb1b549SSpandan Das 65*9bb1b549SSpandan Das deps = getattr(attr, "deps", []) + getattr(attr, "embed", []) 66*9bb1b549SSpandan Das transitive = [ 67*9bb1b549SSpandan Das dep[GoProtoImports].imports 68*9bb1b549SSpandan Das for dep in deps 69*9bb1b549SSpandan Das if GoProtoImports in dep 70*9bb1b549SSpandan Das ] 71*9bb1b549SSpandan Das return depset(direct = direct.keys(), transitive = transitive) 72*9bb1b549SSpandan Das 73*9bb1b549SSpandan Dasdef _go_proto_aspect_impl(_target, ctx): 74*9bb1b549SSpandan Das imports = get_imports(ctx.rule.attr) 75*9bb1b549SSpandan Das return [GoProtoImports(imports = imports)] 76*9bb1b549SSpandan Das 77*9bb1b549SSpandan Das_go_proto_aspect = aspect( 78*9bb1b549SSpandan Das _go_proto_aspect_impl, 79*9bb1b549SSpandan Das attr_aspects = [ 80*9bb1b549SSpandan Das "deps", 81*9bb1b549SSpandan Das "embed", 82*9bb1b549SSpandan Das ], 83*9bb1b549SSpandan Das) 84*9bb1b549SSpandan Das 85*9bb1b549SSpandan Dasdef _proto_library_to_source(_go, attr, source, merge): 86*9bb1b549SSpandan Das if attr.compiler: 87*9bb1b549SSpandan Das compilers = [attr.compiler] 88*9bb1b549SSpandan Das else: 89*9bb1b549SSpandan Das compilers = attr.compilers 90*9bb1b549SSpandan Das for compiler in compilers: 91*9bb1b549SSpandan Das if GoSource in compiler: 92*9bb1b549SSpandan Das merge(source, compiler[GoSource]) 93*9bb1b549SSpandan Das 94*9bb1b549SSpandan Dasdef _go_proto_library_impl(ctx): 95*9bb1b549SSpandan Das go = go_context(ctx) 96*9bb1b549SSpandan Das if go.pathtype == INFERRED_PATH: 97*9bb1b549SSpandan Das fail("importpath must be specified in this library or one of its embedded libraries") 98*9bb1b549SSpandan Das if ctx.attr.compiler: 99*9bb1b549SSpandan Das #TODO: print("DEPRECATED: compiler attribute on {}, use compilers instead".format(ctx.label)) 100*9bb1b549SSpandan Das compilers = [ctx.attr.compiler] 101*9bb1b549SSpandan Das else: 102*9bb1b549SSpandan Das compilers = ctx.attr.compilers 103*9bb1b549SSpandan Das 104*9bb1b549SSpandan Das if ctx.attr.proto: 105*9bb1b549SSpandan Das #TODO: print("DEPRECATED: proto attribute on {}, use protos instead".format(ctx.label)) 106*9bb1b549SSpandan Das if ctx.attr.protos: 107*9bb1b549SSpandan Das fail("Either proto or protos (non-empty) argument must be specified, but not both") 108*9bb1b549SSpandan Das 109*9bb1b549SSpandan Das # ctx.attr.proto is a one-element array since there is a Starlark transition attached to it. 110*9bb1b549SSpandan Das proto_deps = [ctx.attr.proto[0]] 111*9bb1b549SSpandan Das else: 112*9bb1b549SSpandan Das if not ctx.attr.protos: 113*9bb1b549SSpandan Das fail("Either proto or protos (non-empty) argument must be specified") 114*9bb1b549SSpandan Das proto_deps = ctx.attr.protos 115*9bb1b549SSpandan Das 116*9bb1b549SSpandan Das go_srcs = [] 117*9bb1b549SSpandan Das valid_archive = False 118*9bb1b549SSpandan Das 119*9bb1b549SSpandan Das for c in compilers: 120*9bb1b549SSpandan Das compiler = c[GoProtoCompiler] 121*9bb1b549SSpandan Das if compiler.valid_archive: 122*9bb1b549SSpandan Das valid_archive = True 123*9bb1b549SSpandan Das go_srcs.extend(compiler.compile( 124*9bb1b549SSpandan Das go, 125*9bb1b549SSpandan Das compiler = compiler, 126*9bb1b549SSpandan Das protos = [d[ProtoInfo] for d in proto_deps], 127*9bb1b549SSpandan Das imports = get_imports(ctx.attr), 128*9bb1b549SSpandan Das importpath = go.importpath, 129*9bb1b549SSpandan Das )) 130*9bb1b549SSpandan Das library = go.new_library( 131*9bb1b549SSpandan Das go, 132*9bb1b549SSpandan Das resolver = _proto_library_to_source, 133*9bb1b549SSpandan Das srcs = go_srcs, 134*9bb1b549SSpandan Das ) 135*9bb1b549SSpandan Das source = go.library_to_source(go, ctx.attr, library, False) 136*9bb1b549SSpandan Das providers = [library, source] 137*9bb1b549SSpandan Das output_groups = { 138*9bb1b549SSpandan Das "go_generated_srcs": go_srcs, 139*9bb1b549SSpandan Das } 140*9bb1b549SSpandan Das if valid_archive: 141*9bb1b549SSpandan Das archive = go.archive(go, source) 142*9bb1b549SSpandan Das output_groups["compilation_outputs"] = [archive.data.file] 143*9bb1b549SSpandan Das providers.extend([ 144*9bb1b549SSpandan Das archive, 145*9bb1b549SSpandan Das DefaultInfo( 146*9bb1b549SSpandan Das files = depset([archive.data.file]), 147*9bb1b549SSpandan Das runfiles = archive.runfiles, 148*9bb1b549SSpandan Das ), 149*9bb1b549SSpandan Das ]) 150*9bb1b549SSpandan Das return providers + [OutputGroupInfo(**output_groups)] 151*9bb1b549SSpandan Das 152*9bb1b549SSpandan Dasgo_proto_library = rule( 153*9bb1b549SSpandan Das implementation = _go_proto_library_impl, 154*9bb1b549SSpandan Das attrs = { 155*9bb1b549SSpandan Das "proto": attr.label( 156*9bb1b549SSpandan Das cfg = non_go_tool_transition, 157*9bb1b549SSpandan Das providers = [ProtoInfo], 158*9bb1b549SSpandan Das ), 159*9bb1b549SSpandan Das "protos": attr.label_list( 160*9bb1b549SSpandan Das cfg = non_go_tool_transition, 161*9bb1b549SSpandan Das providers = [ProtoInfo], 162*9bb1b549SSpandan Das default = [], 163*9bb1b549SSpandan Das ), 164*9bb1b549SSpandan Das "deps": attr.label_list( 165*9bb1b549SSpandan Das providers = [GoLibrary], 166*9bb1b549SSpandan Das aspects = [_go_proto_aspect], 167*9bb1b549SSpandan Das ), 168*9bb1b549SSpandan Das "importpath": attr.string(), 169*9bb1b549SSpandan Das "importmap": attr.string(), 170*9bb1b549SSpandan Das "importpath_aliases": attr.string_list(), # experimental, undocumented 171*9bb1b549SSpandan Das "embed": attr.label_list(providers = [GoLibrary]), 172*9bb1b549SSpandan Das "gc_goopts": attr.string_list(), 173*9bb1b549SSpandan Das "compiler": attr.label(providers = [GoProtoCompiler]), 174*9bb1b549SSpandan Das "compilers": attr.label_list( 175*9bb1b549SSpandan Das providers = [GoProtoCompiler], 176*9bb1b549SSpandan Das default = ["//proto:go_proto"], 177*9bb1b549SSpandan Das ), 178*9bb1b549SSpandan Das "_go_context_data": attr.label( 179*9bb1b549SSpandan Das default = "//:go_context_data", 180*9bb1b549SSpandan Das ), 181*9bb1b549SSpandan Das "_allowlist_function_transition": attr.label( 182*9bb1b549SSpandan Das default = "@bazel_tools//tools/allowlists/function_transition_allowlist", 183*9bb1b549SSpandan Das ), 184*9bb1b549SSpandan Das }, 185*9bb1b549SSpandan Das toolchains = [GO_TOOLCHAIN], 186*9bb1b549SSpandan Das) 187*9bb1b549SSpandan Das# go_proto_library is a rule that takes a proto_library (in the proto 188*9bb1b549SSpandan Das# attribute) and produces a go library for it. 189*9bb1b549SSpandan Das 190*9bb1b549SSpandan Dasdef go_grpc_library(**kwargs): 191*9bb1b549SSpandan Das # TODO: Deprecate once gazelle generates just go_proto_library 192*9bb1b549SSpandan Das go_proto_library(compilers = [Label("//proto:go_grpc")], **kwargs) 193*9bb1b549SSpandan Das 194*9bb1b549SSpandan Dasdef proto_register_toolchains(): 195*9bb1b549SSpandan Das print("You no longer need to call proto_register_toolchains(), it does nothing") 196