// Copyright 2017 Google Inc. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package java import ( "path/filepath" "strconv" "android/soong/android" "android/soong/bazel" "github.com/google/blueprint/proptools" ) const ( protoTypeDefault = "lite" ) func genProto(ctx android.ModuleContext, protoFiles android.Paths, flags android.ProtoFlags) android.Paths { // Shard proto files into groups of 100 to avoid having to recompile all of them if one changes and to avoid // hitting command line length limits. shards := android.ShardPaths(protoFiles, 50) srcJarFiles := make(android.Paths, 0, len(shards)) for i, shard := range shards { srcJarFile := android.PathForModuleGen(ctx, "proto", "proto"+strconv.Itoa(i)+".srcjar") srcJarFiles = append(srcJarFiles, srcJarFile) outDir := srcJarFile.ReplaceExtension(ctx, "tmp") rule := android.NewRuleBuilder(pctx, ctx) rule.Command().Text("rm -rf").Flag(outDir.String()) rule.Command().Text("mkdir -p").Flag(outDir.String()) for _, protoFile := range shard { depFile := srcJarFile.InSameDir(ctx, protoFile.String()+".d") rule.Command().Text("mkdir -p").Flag(filepath.Dir(depFile.String())) android.ProtoRule(rule, protoFile, flags, flags.Deps, outDir, depFile, nil) } // Proto generated java files have an unknown package name in the path, so package the entire output directory // into a srcjar. rule.Command(). BuiltTool("soong_zip"). Flag("-srcjar"). Flag("-write_if_changed"). FlagWithOutput("-o ", srcJarFile). FlagWithArg("-C ", outDir.String()). FlagWithArg("-D ", outDir.String()) rule.Command().Text("rm -rf").Flag(outDir.String()) rule.Restat() ruleName := "protoc" ruleDesc := "protoc" if len(shards) > 1 { ruleName += "_" + strconv.Itoa(i) ruleDesc += " " + strconv.Itoa(i) } rule.Build(ruleName, ruleDesc) } return srcJarFiles } func protoDeps(ctx android.BottomUpMutatorContext, p *android.ProtoProperties) { const unspecifiedProtobufPluginType = "" if String(p.Proto.Plugin) == "" { switch String(p.Proto.Type) { case "stream": // does not require additional dependencies case "micro": ctx.AddVariationDependencies(nil, staticLibTag, "libprotobuf-java-micro") case "nano": ctx.AddVariationDependencies(nil, staticLibTag, "libprotobuf-java-nano") case "lite", unspecifiedProtobufPluginType: ctx.AddVariationDependencies(nil, staticLibTag, "libprotobuf-java-lite") case "full": if ctx.Host() { ctx.AddVariationDependencies(nil, staticLibTag, "libprotobuf-java-full") } else { ctx.PropertyErrorf("proto.type", "full java protos only supported on the host") } default: ctx.PropertyErrorf("proto.type", "unknown proto type %q", String(p.Proto.Type)) } } } func protoFlags(ctx android.ModuleContext, j *CommonProperties, p *android.ProtoProperties, flags javaBuilderFlags) javaBuilderFlags { flags.proto = android.GetProtoFlags(ctx, p) if String(p.Proto.Plugin) == "" { var typeToPlugin string switch String(p.Proto.Type) { case "stream": flags.proto.OutTypeFlag = "--javastream_out" typeToPlugin = "javastream" case "micro": flags.proto.OutTypeFlag = "--javamicro_out" typeToPlugin = "javamicro" case "nano": flags.proto.OutTypeFlag = "--javanano_out" typeToPlugin = "javanano" case "lite", "": flags.proto.OutTypeFlag = "--java_out" flags.proto.OutParams = append(flags.proto.OutParams, "lite") case "full": flags.proto.OutTypeFlag = "--java_out" default: ctx.PropertyErrorf("proto.type", "unknown proto type %q", String(p.Proto.Type)) } if typeToPlugin != "" { hostTool := ctx.Config().HostToolPath(ctx, "protoc-gen-"+typeToPlugin) flags.proto.Deps = append(flags.proto.Deps, hostTool) flags.proto.Flags = append(flags.proto.Flags, "--plugin=protoc-gen-"+typeToPlugin+"="+hostTool.String()) } } flags.proto.OutParams = append(flags.proto.OutParams, j.Proto.Output_params...) return flags } type protoAttributes struct { Deps bazel.LabelListAttribute // A list of proto_library targets that the proto_library in `deps` depends on // This list is overestimation. // Overestimation is necessary since Soong includes other protos via proto.include_dirs and not // a specific .proto file module explicitly. Transitive_deps bazel.LabelListAttribute // This is the libs and the static_libs of the original java_library module. // On the bazel side, after proto sources are generated in java_*_proto_library, a java_library // will compile them. The libs and static_libs from the original java_library module need // to be linked because they are necessary in compile-time classpath. Additional_proto_deps bazel.LabelListAttribute Sdk_version bazel.StringAttribute Java_version bazel.StringAttribute Plugin bazel.LabelAttribute } func bp2buildProto(ctx android.Bp2buildMutatorContext, m *Module, protoSrcs bazel.LabelListAttribute, AdditionalProtoDeps bazel.LabelListAttribute) *bazel.Label { protoInfo, ok := android.Bp2buildProtoProperties(ctx, &m.ModuleBase, protoSrcs) if !ok { return nil } typ := proptools.StringDefault(protoInfo.Type, protoTypeDefault) var rule_class string suffix := "_java_proto" switch typ { case "nano": suffix += "_nano" rule_class = "java_nano_proto_library" case "micro": suffix += "_micro" rule_class = "java_micro_proto_library" case "lite": suffix += "_lite" rule_class = "java_lite_proto_library" case "stream": suffix += "_stream" rule_class = "java_stream_proto_library" case "full": rule_class = "java_proto_library" default: ctx.PropertyErrorf("proto.type", "cannot handle conversion at this time: %q", typ) } plugin := bazel.LabelAttribute{} if m.protoProperties.Proto.Plugin != nil { plugin.SetValue(android.BazelLabelForModuleDepSingle(ctx, "protoc-gen-"+*m.protoProperties.Proto.Plugin)) } protoAttrs := &protoAttributes{ Deps: bazel.MakeLabelListAttribute(protoInfo.Proto_libs), Transitive_deps: bazel.MakeLabelListAttribute(protoInfo.Transitive_proto_libs), Additional_proto_deps: AdditionalProtoDeps, Java_version: bazel.StringAttribute{Value: m.properties.Java_version}, Sdk_version: bazel.StringAttribute{Value: m.deviceProperties.Sdk_version}, Plugin: plugin, } name := m.Name() + suffix ctx.CreateBazelTargetModule( bazel.BazelTargetModuleProperties{ Rule_class: rule_class, Bzl_load_location: "//build/bazel/rules/java:proto.bzl", }, android.CommonAttributes{Name: name}, protoAttrs) return &bazel.Label{Label: ":" + name} }