1// Copyright 2017 Google Inc. All rights reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package java 16 17import ( 18 "path/filepath" 19 "strconv" 20 21 "android/soong/android" 22 "android/soong/bazel" 23 24 "github.com/google/blueprint/proptools" 25) 26 27const ( 28 protoTypeDefault = "lite" 29) 30 31func genProto(ctx android.ModuleContext, protoFiles android.Paths, flags android.ProtoFlags) android.Paths { 32 // Shard proto files into groups of 100 to avoid having to recompile all of them if one changes and to avoid 33 // hitting command line length limits. 34 shards := android.ShardPaths(protoFiles, 50) 35 36 srcJarFiles := make(android.Paths, 0, len(shards)) 37 38 for i, shard := range shards { 39 srcJarFile := android.PathForModuleGen(ctx, "proto", "proto"+strconv.Itoa(i)+".srcjar") 40 srcJarFiles = append(srcJarFiles, srcJarFile) 41 42 outDir := srcJarFile.ReplaceExtension(ctx, "tmp") 43 44 rule := android.NewRuleBuilder(pctx, ctx) 45 46 rule.Command().Text("rm -rf").Flag(outDir.String()) 47 rule.Command().Text("mkdir -p").Flag(outDir.String()) 48 49 for _, protoFile := range shard { 50 depFile := srcJarFile.InSameDir(ctx, protoFile.String()+".d") 51 rule.Command().Text("mkdir -p").Flag(filepath.Dir(depFile.String())) 52 android.ProtoRule(rule, protoFile, flags, flags.Deps, outDir, depFile, nil) 53 } 54 55 // Proto generated java files have an unknown package name in the path, so package the entire output directory 56 // into a srcjar. 57 rule.Command(). 58 BuiltTool("soong_zip"). 59 Flag("-srcjar"). 60 Flag("-write_if_changed"). 61 FlagWithOutput("-o ", srcJarFile). 62 FlagWithArg("-C ", outDir.String()). 63 FlagWithArg("-D ", outDir.String()) 64 65 rule.Command().Text("rm -rf").Flag(outDir.String()) 66 67 rule.Restat() 68 69 ruleName := "protoc" 70 ruleDesc := "protoc" 71 if len(shards) > 1 { 72 ruleName += "_" + strconv.Itoa(i) 73 ruleDesc += " " + strconv.Itoa(i) 74 } 75 76 rule.Build(ruleName, ruleDesc) 77 } 78 79 return srcJarFiles 80} 81 82func protoDeps(ctx android.BottomUpMutatorContext, p *android.ProtoProperties) { 83 const unspecifiedProtobufPluginType = "" 84 if String(p.Proto.Plugin) == "" { 85 switch String(p.Proto.Type) { 86 case "stream": // does not require additional dependencies 87 case "micro": 88 ctx.AddVariationDependencies(nil, staticLibTag, "libprotobuf-java-micro") 89 case "nano": 90 ctx.AddVariationDependencies(nil, staticLibTag, "libprotobuf-java-nano") 91 case "lite", unspecifiedProtobufPluginType: 92 ctx.AddVariationDependencies(nil, staticLibTag, "libprotobuf-java-lite") 93 case "full": 94 if ctx.Host() { 95 ctx.AddVariationDependencies(nil, staticLibTag, "libprotobuf-java-full") 96 } else { 97 ctx.PropertyErrorf("proto.type", "full java protos only supported on the host") 98 } 99 default: 100 ctx.PropertyErrorf("proto.type", "unknown proto type %q", 101 String(p.Proto.Type)) 102 } 103 } 104} 105 106func protoFlags(ctx android.ModuleContext, j *CommonProperties, p *android.ProtoProperties, 107 flags javaBuilderFlags) javaBuilderFlags { 108 109 flags.proto = android.GetProtoFlags(ctx, p) 110 111 if String(p.Proto.Plugin) == "" { 112 var typeToPlugin string 113 switch String(p.Proto.Type) { 114 case "stream": 115 flags.proto.OutTypeFlag = "--javastream_out" 116 typeToPlugin = "javastream" 117 case "micro": 118 flags.proto.OutTypeFlag = "--javamicro_out" 119 typeToPlugin = "javamicro" 120 case "nano": 121 flags.proto.OutTypeFlag = "--javanano_out" 122 typeToPlugin = "javanano" 123 case "lite", "": 124 flags.proto.OutTypeFlag = "--java_out" 125 flags.proto.OutParams = append(flags.proto.OutParams, "lite") 126 case "full": 127 flags.proto.OutTypeFlag = "--java_out" 128 default: 129 ctx.PropertyErrorf("proto.type", "unknown proto type %q", 130 String(p.Proto.Type)) 131 } 132 133 if typeToPlugin != "" { 134 hostTool := ctx.Config().HostToolPath(ctx, "protoc-gen-"+typeToPlugin) 135 flags.proto.Deps = append(flags.proto.Deps, hostTool) 136 flags.proto.Flags = append(flags.proto.Flags, "--plugin=protoc-gen-"+typeToPlugin+"="+hostTool.String()) 137 } 138 } 139 140 flags.proto.OutParams = append(flags.proto.OutParams, j.Proto.Output_params...) 141 142 return flags 143} 144 145type protoAttributes struct { 146 Deps bazel.LabelListAttribute 147 Sdk_version bazel.StringAttribute 148 Java_version bazel.StringAttribute 149} 150 151func bp2buildProto(ctx android.Bp2buildMutatorContext, m *Module, protoSrcs bazel.LabelListAttribute) *bazel.Label { 152 protoInfo, ok := android.Bp2buildProtoProperties(ctx, &m.ModuleBase, protoSrcs) 153 if !ok { 154 return nil 155 } 156 157 typ := proptools.StringDefault(protoInfo.Type, protoTypeDefault) 158 var rule_class string 159 suffix := "_java_proto" 160 switch typ { 161 case "nano": 162 suffix += "_nano" 163 rule_class = "java_nano_proto_library" 164 case "micro": 165 suffix += "_micro" 166 rule_class = "java_micro_proto_library" 167 case "lite": 168 suffix += "_lite" 169 rule_class = "java_lite_proto_library" 170 case "stream": 171 suffix += "_stream" 172 rule_class = "java_stream_proto_library" 173 case "full": 174 rule_class = "java_proto_library" 175 default: 176 ctx.PropertyErrorf("proto.type", "cannot handle conversion at this time: %q", typ) 177 } 178 179 protoLabel := bazel.Label{Label: ":" + m.Name() + "_proto"} 180 protoAttrs := &protoAttributes{ 181 Deps: bazel.MakeSingleLabelListAttribute(protoLabel), 182 Java_version: bazel.StringAttribute{Value: m.properties.Java_version}, 183 Sdk_version: bazel.StringAttribute{Value: m.deviceProperties.Sdk_version}, 184 } 185 186 name := m.Name() + suffix 187 188 ctx.CreateBazelTargetModule( 189 bazel.BazelTargetModuleProperties{ 190 Rule_class: rule_class, 191 Bzl_load_location: "//build/bazel/rules/java:proto.bzl", 192 }, 193 android.CommonAttributes{Name: name}, 194 protoAttrs) 195 196 return &bazel.Label{Label: ":" + name} 197} 198