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 15 package java 16 17 import ( 18 "path/filepath" 19 "strconv" 20 21 "android/soong/android" 22 "android/soong/bazel" 23 24 "github.com/google/blueprint/proptools" 25 ) 26 27 const ( 28 protoTypeDefault = "lite" 29 ) 30 31 func 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 82 func 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() || ctx.BazelConversionMode() { 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 106 func 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 145 type protoAttributes struct { 146 Deps bazel.LabelListAttribute 147 } 148 149 func bp2buildProto(ctx android.Bp2buildMutatorContext, m *Module, protoSrcs bazel.LabelListAttribute) *bazel.Label { 150 protoInfo, ok := android.Bp2buildProtoProperties(ctx, &m.ModuleBase, protoSrcs) 151 if !ok { 152 return nil 153 } 154 155 typ := proptools.StringDefault(protoInfo.Type, protoTypeDefault) 156 var rule_class string 157 suffix := "_java_proto" 158 switch typ { 159 case "nano": 160 suffix += "_nano" 161 rule_class = "java_nano_proto_library" 162 case "micro": 163 suffix += "_micro" 164 rule_class = "java_micro_proto_library" 165 case "lite": 166 suffix += "_lite" 167 rule_class = "java_lite_proto_library" 168 case "stream": 169 suffix += "_stream" 170 rule_class = "java_stream_proto_library" 171 case "full": 172 rule_class = "java_proto_library" 173 default: 174 ctx.PropertyErrorf("proto.type", "cannot handle conversion at this time: %q", typ) 175 } 176 177 protoLabel := bazel.Label{Label: ":" + m.Name() + "_proto"} 178 var protoAttrs protoAttributes 179 protoAttrs.Deps.SetValue(bazel.LabelList{Includes: []bazel.Label{protoLabel}}) 180 181 name := m.Name() + suffix 182 183 ctx.CreateBazelTargetModule( 184 bazel.BazelTargetModuleProperties{ 185 Rule_class: rule_class, 186 Bzl_load_location: "//build/bazel/rules/java:proto.bzl", 187 }, 188 android.CommonAttributes{Name: name}, 189 &protoAttrs) 190 191 return &bazel.Label{Label: ":" + name} 192 } 193