1*7594170eSAndroid Build Coastguard Worker# Copyright (C) 2021 The Android Open Source Project 2*7594170eSAndroid Build Coastguard Worker# 3*7594170eSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 4*7594170eSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 5*7594170eSAndroid Build Coastguard Worker# You may obtain a copy of the License at 6*7594170eSAndroid Build Coastguard Worker# 7*7594170eSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 8*7594170eSAndroid Build Coastguard Worker# 9*7594170eSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 10*7594170eSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 11*7594170eSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*7594170eSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 13*7594170eSAndroid Build Coastguard Worker# limitations under the License. 14*7594170eSAndroid Build Coastguard Worker 15*7594170eSAndroid Build Coastguard Workerload("@bazel_skylib//lib:paths.bzl", "paths") 16*7594170eSAndroid Build Coastguard Workerload("@bazel_skylib//lib:sets.bzl", "sets") 17*7594170eSAndroid Build Coastguard Worker 18*7594170eSAndroid Build Coastguard Workerdef _generate_and_declare_output_files( 19*7594170eSAndroid Build Coastguard Worker ctx, 20*7594170eSAndroid Build Coastguard Worker proto_rel_paths, 21*7594170eSAndroid Build Coastguard Worker type_dictionary): 22*7594170eSAndroid Build Coastguard Worker ret = {} 23*7594170eSAndroid Build Coastguard Worker for typ in type_dictionary: 24*7594170eSAndroid Build Coastguard Worker ret[typ] = [] 25*7594170eSAndroid Build Coastguard Worker 26*7594170eSAndroid Build Coastguard Worker for proto_rel_path in proto_rel_paths: 27*7594170eSAndroid Build Coastguard Worker for typ, ext in type_dictionary.items(): 28*7594170eSAndroid Build Coastguard Worker # prefix with label.name to prevent collisions between targets 29*7594170eSAndroid Build Coastguard Worker # if proto compliation becomes an aspect, can prefix with output 30*7594170eSAndroid Build Coastguard Worker # information instead to allow reuse, e.g. multiple cc `lite` 31*7594170eSAndroid Build Coastguard Worker # libraries containing the same proto file 32*7594170eSAndroid Build Coastguard Worker out_name = paths.join(ctx.label.name, paths.replace_extension(proto_rel_path, ext)) 33*7594170eSAndroid Build Coastguard Worker declared = ctx.actions.declare_file(out_name) 34*7594170eSAndroid Build Coastguard Worker ret[typ].append(declared) 35*7594170eSAndroid Build Coastguard Worker 36*7594170eSAndroid Build Coastguard Worker return ret 37*7594170eSAndroid Build Coastguard Worker 38*7594170eSAndroid Build Coastguard Workerdef _generate_jar_proto_action( 39*7594170eSAndroid Build Coastguard Worker proto_infos, 40*7594170eSAndroid Build Coastguard Worker protoc, 41*7594170eSAndroid Build Coastguard Worker ctx, 42*7594170eSAndroid Build Coastguard Worker out_flags = [], 43*7594170eSAndroid Build Coastguard Worker plugin_executable = None, 44*7594170eSAndroid Build Coastguard Worker out_arg = None, 45*7594170eSAndroid Build Coastguard Worker mnemonic = "ProtoGen", 46*7594170eSAndroid Build Coastguard Worker transitive_proto_infos = []): 47*7594170eSAndroid Build Coastguard Worker jar_basename = ctx.label.name + "-proto_gen" 48*7594170eSAndroid Build Coastguard Worker jar_name = jar_basename + "-src.jar" 49*7594170eSAndroid Build Coastguard Worker jar_file = ctx.actions.declare_file(jar_name) 50*7594170eSAndroid Build Coastguard Worker 51*7594170eSAndroid Build Coastguard Worker _generate_proto_action( 52*7594170eSAndroid Build Coastguard Worker proto_infos = proto_infos, 53*7594170eSAndroid Build Coastguard Worker protoc = protoc, 54*7594170eSAndroid Build Coastguard Worker ctx = ctx, 55*7594170eSAndroid Build Coastguard Worker out_flags = out_flags, 56*7594170eSAndroid Build Coastguard Worker plugin_executable = plugin_executable, 57*7594170eSAndroid Build Coastguard Worker out_arg = out_arg, 58*7594170eSAndroid Build Coastguard Worker mnemonic = mnemonic, 59*7594170eSAndroid Build Coastguard Worker output_file = jar_file, 60*7594170eSAndroid Build Coastguard Worker transitive_proto_infos = transitive_proto_infos, 61*7594170eSAndroid Build Coastguard Worker ) 62*7594170eSAndroid Build Coastguard Worker 63*7594170eSAndroid Build Coastguard Worker srcjar_name = jar_basename + ".srcjar" 64*7594170eSAndroid Build Coastguard Worker srcjar_file = ctx.actions.declare_file(srcjar_name) 65*7594170eSAndroid Build Coastguard Worker ctx.actions.symlink( 66*7594170eSAndroid Build Coastguard Worker output = srcjar_file, 67*7594170eSAndroid Build Coastguard Worker target_file = jar_file, 68*7594170eSAndroid Build Coastguard Worker ) 69*7594170eSAndroid Build Coastguard Worker 70*7594170eSAndroid Build Coastguard Worker return srcjar_file 71*7594170eSAndroid Build Coastguard Worker 72*7594170eSAndroid Build Coastguard Workerdef _generate_proto_action( 73*7594170eSAndroid Build Coastguard Worker proto_infos, 74*7594170eSAndroid Build Coastguard Worker protoc, 75*7594170eSAndroid Build Coastguard Worker ctx, 76*7594170eSAndroid Build Coastguard Worker type_dictionary = None, 77*7594170eSAndroid Build Coastguard Worker out_flags = [], 78*7594170eSAndroid Build Coastguard Worker plugin_executable = None, 79*7594170eSAndroid Build Coastguard Worker out_arg = None, 80*7594170eSAndroid Build Coastguard Worker mnemonic = "ProtoGen", 81*7594170eSAndroid Build Coastguard Worker output_file = None, 82*7594170eSAndroid Build Coastguard Worker transitive_proto_infos = []): 83*7594170eSAndroid Build Coastguard Worker """ Utility function for creating proto_compiler action. 84*7594170eSAndroid Build Coastguard Worker 85*7594170eSAndroid Build Coastguard Worker Args: 86*7594170eSAndroid Build Coastguard Worker proto_infos: A list of ProtoInfo. 87*7594170eSAndroid Build Coastguard Worker protoc: proto compiler executable. 88*7594170eSAndroid Build Coastguard Worker ctx: context, used for declaring new files only. 89*7594170eSAndroid Build Coastguard Worker type_dictionary: a dictionary of types to output extensions 90*7594170eSAndroid Build Coastguard Worker out_flags: protoc output flags 91*7594170eSAndroid Build Coastguard Worker plugin_executable: plugin executable file 92*7594170eSAndroid Build Coastguard Worker out_arg: as appropriate, if plugin_executable and out_arg are both supplied, plugin_executable is preferred 93*7594170eSAndroid Build Coastguard Worker mnemonic: (optional) a string to describe the proto compilation action 94*7594170eSAndroid Build Coastguard Worker output_file: (optional) File, used to specify a specific file for protoc output (typically a JAR file) 95*7594170eSAndroid Build Coastguard Worker 96*7594170eSAndroid Build Coastguard Worker Returns: 97*7594170eSAndroid Build Coastguard Worker Dictionary with declared files grouped by type from the type_dictionary. 98*7594170eSAndroid Build Coastguard Worker """ 99*7594170eSAndroid Build Coastguard Worker 100*7594170eSAndroid Build Coastguard Worker # TODO(B/245629074): Don't build external/protobuf if it is provided in 101*7594170eSAndroid Build Coastguard Worker # toolchain already. 102*7594170eSAndroid Build Coastguard Worker proto_srcs = [] 103*7594170eSAndroid Build Coastguard Worker proto_rel_srcs = [] 104*7594170eSAndroid Build Coastguard Worker proto_source_root_list = sets.make() 105*7594170eSAndroid Build Coastguard Worker transitive_proto_srcs_list = [] 106*7594170eSAndroid Build Coastguard Worker transitive_proto_path_list = sets.make() 107*7594170eSAndroid Build Coastguard Worker 108*7594170eSAndroid Build Coastguard Worker for proto_info in proto_infos: 109*7594170eSAndroid Build Coastguard Worker sets.insert(proto_source_root_list, proto_info.proto_source_root) 110*7594170eSAndroid Build Coastguard Worker proto_srcs.extend(proto_info.direct_sources) 111*7594170eSAndroid Build Coastguard Worker proto_rel_srcs.extend([paths.relativize(p.path, proto_info.proto_source_root) for p in proto_info.direct_sources]) 112*7594170eSAndroid Build Coastguard Worker transitive_proto_srcs_list.append(proto_info.transitive_imports) 113*7594170eSAndroid Build Coastguard Worker for p in proto_info.transitive_proto_path.to_list(): 114*7594170eSAndroid Build Coastguard Worker sets.insert(transitive_proto_path_list, p) 115*7594170eSAndroid Build Coastguard Worker 116*7594170eSAndroid Build Coastguard Worker for transitive_proto_info in transitive_proto_infos: 117*7594170eSAndroid Build Coastguard Worker sets.insert(transitive_proto_path_list, transitive_proto_info.proto_source_root) 118*7594170eSAndroid Build Coastguard Worker transitive_proto_srcs_list.append(depset(transitive_proto_info.direct_sources)) 119*7594170eSAndroid Build Coastguard Worker 120*7594170eSAndroid Build Coastguard Worker protoc_out_name = paths.join(ctx.bin_dir.path, ctx.label.package) 121*7594170eSAndroid Build Coastguard Worker 122*7594170eSAndroid Build Coastguard Worker if output_file: 123*7594170eSAndroid Build Coastguard Worker protoc_out_name = paths.join(protoc_out_name, output_file.basename) 124*7594170eSAndroid Build Coastguard Worker out_files = { 125*7594170eSAndroid Build Coastguard Worker "out": [output_file], 126*7594170eSAndroid Build Coastguard Worker } 127*7594170eSAndroid Build Coastguard Worker else: 128*7594170eSAndroid Build Coastguard Worker protoc_out_name = paths.join(protoc_out_name, ctx.label.name) 129*7594170eSAndroid Build Coastguard Worker out_files = _generate_and_declare_output_files( 130*7594170eSAndroid Build Coastguard Worker ctx, 131*7594170eSAndroid Build Coastguard Worker proto_rel_srcs, 132*7594170eSAndroid Build Coastguard Worker type_dictionary, 133*7594170eSAndroid Build Coastguard Worker ) 134*7594170eSAndroid Build Coastguard Worker 135*7594170eSAndroid Build Coastguard Worker tools = [] 136*7594170eSAndroid Build Coastguard Worker args = ctx.actions.args() 137*7594170eSAndroid Build Coastguard Worker if plugin_executable: 138*7594170eSAndroid Build Coastguard Worker tools.append(plugin_executable) 139*7594170eSAndroid Build Coastguard Worker args.add("--plugin=protoc-gen-PLUGIN=" + plugin_executable.path) 140*7594170eSAndroid Build Coastguard Worker args.add("--PLUGIN_out=" + ",".join(out_flags) + ":" + protoc_out_name) 141*7594170eSAndroid Build Coastguard Worker else: 142*7594170eSAndroid Build Coastguard Worker args.add("{}={}:{}".format(out_arg, ",".join(out_flags), protoc_out_name)) 143*7594170eSAndroid Build Coastguard Worker 144*7594170eSAndroid Build Coastguard Worker # the order matters so we add the source roots first 145*7594170eSAndroid Build Coastguard Worker args.add_all(["-I" + p for p in sets.to_list(proto_source_root_list)]) 146*7594170eSAndroid Build Coastguard Worker args.add_all(["-I" + p for p in sets.to_list(transitive_proto_path_list)]) 147*7594170eSAndroid Build Coastguard Worker args.add_all(["-I{0}={1}".format(f.short_path, f.path) for t in transitive_proto_srcs_list for f in t.to_list()]) 148*7594170eSAndroid Build Coastguard Worker 149*7594170eSAndroid Build Coastguard Worker args.add_all([f.path for f in proto_srcs]) 150*7594170eSAndroid Build Coastguard Worker 151*7594170eSAndroid Build Coastguard Worker inputs = depset( 152*7594170eSAndroid Build Coastguard Worker direct = proto_srcs, 153*7594170eSAndroid Build Coastguard Worker transitive = transitive_proto_srcs_list, 154*7594170eSAndroid Build Coastguard Worker ) 155*7594170eSAndroid Build Coastguard Worker 156*7594170eSAndroid Build Coastguard Worker outputs = [] 157*7594170eSAndroid Build Coastguard Worker for outs in out_files.values(): 158*7594170eSAndroid Build Coastguard Worker outputs.extend(outs) 159*7594170eSAndroid Build Coastguard Worker 160*7594170eSAndroid Build Coastguard Worker ctx.actions.run( 161*7594170eSAndroid Build Coastguard Worker inputs = inputs, 162*7594170eSAndroid Build Coastguard Worker executable = protoc, 163*7594170eSAndroid Build Coastguard Worker tools = tools, 164*7594170eSAndroid Build Coastguard Worker outputs = outputs, 165*7594170eSAndroid Build Coastguard Worker arguments = [args], 166*7594170eSAndroid Build Coastguard Worker mnemonic = mnemonic, 167*7594170eSAndroid Build Coastguard Worker ) 168*7594170eSAndroid Build Coastguard Worker return out_files 169*7594170eSAndroid Build Coastguard Worker 170*7594170eSAndroid Build Coastguard Workerproto_file_utils = struct( 171*7594170eSAndroid Build Coastguard Worker generate_proto_action = _generate_proto_action, 172*7594170eSAndroid Build Coastguard Worker generate_jar_proto_action = _generate_jar_proto_action, 173*7594170eSAndroid Build Coastguard Worker) 174