1// Copyright 2016 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 cc 16 17import ( 18 "github.com/google/blueprint/pathtools" 19 20 "android/soong/android" 21) 22 23// genProto creates a rule to convert a .proto file to generated .pb.cc and .pb.h files and returns 24// the paths to the generated files. 25func genProto(ctx android.ModuleContext, protoFile android.Path, flags builderFlags) (cc, header android.WritablePath) { 26 var ccFile, headerFile android.ModuleGenPath 27 28 srcSuffix := ".cc" 29 if flags.protoC { 30 srcSuffix = ".c" 31 } 32 33 if flags.proto.CanonicalPathFromRoot { 34 ccFile = android.GenPathWithExt(ctx, "proto", protoFile, "pb"+srcSuffix) 35 headerFile = android.GenPathWithExt(ctx, "proto", protoFile, "pb.h") 36 } else { 37 rel := protoFile.Rel() 38 ccFile = android.PathForModuleGen(ctx, "proto", pathtools.ReplaceExtension(rel, "pb"+srcSuffix)) 39 headerFile = android.PathForModuleGen(ctx, "proto", pathtools.ReplaceExtension(rel, "pb.h")) 40 } 41 42 protoDeps := flags.proto.Deps 43 if flags.protoOptionsFile { 44 optionsFile := pathtools.ReplaceExtension(protoFile.String(), "options") 45 optionsPath := android.PathForSource(ctx, optionsFile) 46 protoDeps = append(android.Paths{optionsPath}, protoDeps...) 47 } 48 49 outDir := flags.proto.Dir 50 depFile := ccFile.ReplaceExtension(ctx, "d") 51 outputs := android.WritablePaths{ccFile, headerFile} 52 53 rule := android.NewRuleBuilder(pctx, ctx) 54 55 android.ProtoRule(rule, protoFile, flags.proto, protoDeps, outDir, depFile, outputs) 56 57 rule.Build("protoc_"+protoFile.Rel(), "protoc "+protoFile.Rel()) 58 59 return ccFile, headerFile 60} 61 62func protoDeps(ctx DepsContext, deps Deps, p *android.ProtoProperties, static bool) Deps { 63 var lib string 64 65 if String(p.Proto.Plugin) == "" { 66 switch String(p.Proto.Type) { 67 case "full": 68 if ctx.useSdk() { 69 lib = "libprotobuf-cpp-full-ndk" 70 static = true 71 } else { 72 lib = "libprotobuf-cpp-full" 73 } 74 case "lite", "": 75 if ctx.useSdk() { 76 lib = "libprotobuf-cpp-lite-ndk" 77 static = true 78 } else { 79 lib = "libprotobuf-cpp-lite" 80 } 81 case "nanopb-c": 82 lib = "libprotobuf-c-nano" 83 static = true 84 case "nanopb-c-enable_malloc": 85 lib = "libprotobuf-c-nano-enable_malloc" 86 static = true 87 case "nanopb-c-16bit": 88 lib = "libprotobuf-c-nano-16bit" 89 static = true 90 case "nanopb-c-enable_malloc-16bit": 91 lib = "libprotobuf-c-nano-enable_malloc-16bit" 92 static = true 93 case "nanopb-c-32bit": 94 lib = "libprotobuf-c-nano-32bit" 95 static = true 96 case "nanopb-c-enable_malloc-32bit": 97 lib = "libprotobuf-c-nano-enable_malloc-32bit" 98 static = true 99 default: 100 ctx.PropertyErrorf("proto.type", "unknown proto type %q", 101 String(p.Proto.Type)) 102 } 103 104 if static { 105 deps.StaticLibs = append(deps.StaticLibs, lib) 106 deps.ReexportStaticLibHeaders = append(deps.ReexportStaticLibHeaders, lib) 107 } else { 108 deps.SharedLibs = append(deps.SharedLibs, lib) 109 deps.ReexportSharedLibHeaders = append(deps.ReexportSharedLibHeaders, lib) 110 } 111 } 112 113 return deps 114} 115 116func protoFlags(ctx ModuleContext, flags Flags, p *android.ProtoProperties) Flags { 117 flags.Local.CFlags = append(flags.Local.CFlags, "-DGOOGLE_PROTOBUF_NO_RTTI") 118 119 flags.proto = android.GetProtoFlags(ctx, p) 120 if flags.proto.CanonicalPathFromRoot { 121 flags.Local.CommonFlags = append(flags.Local.CommonFlags, "-I"+flags.proto.SubDir.String()) 122 } 123 flags.Local.CommonFlags = append(flags.Local.CommonFlags, "-I"+flags.proto.Dir.String()) 124 125 if String(p.Proto.Plugin) == "" { 126 var plugin string 127 128 switch String(p.Proto.Type) { 129 case "nanopb-c", "nanopb-c-enable_malloc", "nanopb-c-16bit", "nanopb-c-enable_malloc-16bit", "nanopb-c-32bit", "nanopb-c-enable_malloc-32bit": 130 flags.protoC = true 131 flags.protoOptionsFile = true 132 flags.proto.OutTypeFlag = "--nanopb_out" 133 // Disable nanopb timestamps to support remote caching. 134 flags.proto.OutParams = append(flags.proto.OutParams, "-T") 135 plugin = "protoc-gen-nanopb" 136 case "full": 137 flags.proto.OutTypeFlag = "--cpp_out" 138 case "lite": 139 flags.proto.OutTypeFlag = "--cpp_out" 140 flags.proto.OutParams = append(flags.proto.OutParams, "lite") 141 case "": 142 // TODO(b/119714316): this should be equivalent to "lite" in 143 // order to match protoDeps, but some modules are depending on 144 // this behavior 145 flags.proto.OutTypeFlag = "--cpp_out" 146 default: 147 ctx.PropertyErrorf("proto.type", "unknown proto type %q", 148 String(p.Proto.Type)) 149 } 150 151 if plugin != "" { 152 path := ctx.Config().HostToolPath(ctx, plugin) 153 flags.proto.Deps = append(flags.proto.Deps, path) 154 flags.proto.Flags = append(flags.proto.Flags, "--plugin="+path.String()) 155 } 156 } 157 158 return flags 159} 160