1*333d2b36SAndroid Build Coastguard Worker// Copyright 2017 Google Inc. All rights reserved. 2*333d2b36SAndroid Build Coastguard Worker// 3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); 4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License. 5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at 6*333d2b36SAndroid Build Coastguard Worker// 7*333d2b36SAndroid Build Coastguard Worker// http://www.apache.org/licenses/LICENSE-2.0 8*333d2b36SAndroid Build Coastguard Worker// 9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, 11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and 13*333d2b36SAndroid Build Coastguard Worker// limitations under the License. 14*333d2b36SAndroid Build Coastguard Worker 15*333d2b36SAndroid Build Coastguard Workerpackage android 16*333d2b36SAndroid Build Coastguard Worker 17*333d2b36SAndroid Build Coastguard Workerimport ( 18*333d2b36SAndroid Build Coastguard Worker "strings" 19*333d2b36SAndroid Build Coastguard Worker 20*333d2b36SAndroid Build Coastguard Worker "github.com/google/blueprint" 21*333d2b36SAndroid Build Coastguard Worker "github.com/google/blueprint/proptools" 22*333d2b36SAndroid Build Coastguard Worker) 23*333d2b36SAndroid Build Coastguard Worker 24*333d2b36SAndroid Build Coastguard Workerconst ( 25*333d2b36SAndroid Build Coastguard Worker canonicalPathFromRootDefault = true 26*333d2b36SAndroid Build Coastguard Worker) 27*333d2b36SAndroid Build Coastguard Worker 28*333d2b36SAndroid Build Coastguard Worker// TODO(ccross): protos are often used to communicate between multiple modules. If the only 29*333d2b36SAndroid Build Coastguard Worker// way to convert a proto to source is to reference it as a source file, and external modules cannot 30*333d2b36SAndroid Build Coastguard Worker// reference source files in other modules, then every module that owns a proto file will need to 31*333d2b36SAndroid Build Coastguard Worker// export a library for every type of external user (lite vs. full, c vs. c++ vs. java). It would 32*333d2b36SAndroid Build Coastguard Worker// be better to support a proto module type that exported a proto file along with some include dirs, 33*333d2b36SAndroid Build Coastguard Worker// and then external modules could depend on the proto module but use their own settings to 34*333d2b36SAndroid Build Coastguard Worker// generate the source. 35*333d2b36SAndroid Build Coastguard Worker 36*333d2b36SAndroid Build Coastguard Workertype ProtoFlags struct { 37*333d2b36SAndroid Build Coastguard Worker Flags []string 38*333d2b36SAndroid Build Coastguard Worker CanonicalPathFromRoot bool 39*333d2b36SAndroid Build Coastguard Worker Dir ModuleGenPath 40*333d2b36SAndroid Build Coastguard Worker SubDir ModuleGenPath 41*333d2b36SAndroid Build Coastguard Worker OutTypeFlag string 42*333d2b36SAndroid Build Coastguard Worker OutParams []string 43*333d2b36SAndroid Build Coastguard Worker Deps Paths 44*333d2b36SAndroid Build Coastguard Worker} 45*333d2b36SAndroid Build Coastguard Worker 46*333d2b36SAndroid Build Coastguard Workertype protoDependencyTag struct { 47*333d2b36SAndroid Build Coastguard Worker blueprint.BaseDependencyTag 48*333d2b36SAndroid Build Coastguard Worker name string 49*333d2b36SAndroid Build Coastguard Worker} 50*333d2b36SAndroid Build Coastguard Worker 51*333d2b36SAndroid Build Coastguard Workervar ProtoPluginDepTag = protoDependencyTag{name: "plugin"} 52*333d2b36SAndroid Build Coastguard Worker 53*333d2b36SAndroid Build Coastguard Workerfunc ProtoDeps(ctx BottomUpMutatorContext, p *ProtoProperties) { 54*333d2b36SAndroid Build Coastguard Worker if String(p.Proto.Plugin) != "" && String(p.Proto.Type) != "" { 55*333d2b36SAndroid Build Coastguard Worker ctx.ModuleErrorf("only one of proto.type and proto.plugin can be specified.") 56*333d2b36SAndroid Build Coastguard Worker } 57*333d2b36SAndroid Build Coastguard Worker 58*333d2b36SAndroid Build Coastguard Worker if plugin := String(p.Proto.Plugin); plugin != "" { 59*333d2b36SAndroid Build Coastguard Worker ctx.AddFarVariationDependencies(ctx.Config().BuildOSTarget.Variations(), 60*333d2b36SAndroid Build Coastguard Worker ProtoPluginDepTag, "protoc-gen-"+plugin) 61*333d2b36SAndroid Build Coastguard Worker } 62*333d2b36SAndroid Build Coastguard Worker} 63*333d2b36SAndroid Build Coastguard Worker 64*333d2b36SAndroid Build Coastguard Workerfunc GetProtoFlags(ctx ModuleContext, p *ProtoProperties) ProtoFlags { 65*333d2b36SAndroid Build Coastguard Worker var flags []string 66*333d2b36SAndroid Build Coastguard Worker var deps Paths 67*333d2b36SAndroid Build Coastguard Worker 68*333d2b36SAndroid Build Coastguard Worker if len(p.Proto.Local_include_dirs) > 0 { 69*333d2b36SAndroid Build Coastguard Worker localProtoIncludeDirs := PathsForModuleSrc(ctx, p.Proto.Local_include_dirs) 70*333d2b36SAndroid Build Coastguard Worker flags = append(flags, JoinWithPrefix(localProtoIncludeDirs.Strings(), "-I")) 71*333d2b36SAndroid Build Coastguard Worker } 72*333d2b36SAndroid Build Coastguard Worker if len(p.Proto.Include_dirs) > 0 { 73*333d2b36SAndroid Build Coastguard Worker rootProtoIncludeDirs := PathsForSource(ctx, p.Proto.Include_dirs) 74*333d2b36SAndroid Build Coastguard Worker flags = append(flags, JoinWithPrefix(rootProtoIncludeDirs.Strings(), "-I")) 75*333d2b36SAndroid Build Coastguard Worker } 76*333d2b36SAndroid Build Coastguard Worker 77*333d2b36SAndroid Build Coastguard Worker ctx.VisitDirectDepsProxyWithTag(ProtoPluginDepTag, func(dep ModuleProxy) { 78*333d2b36SAndroid Build Coastguard Worker if h, ok := OtherModuleProvider(ctx, dep, HostToolProviderKey); !ok || !h.HostToolPath.Valid() { 79*333d2b36SAndroid Build Coastguard Worker ctx.PropertyErrorf("proto.plugin", "module %q is not a host tool provider", 80*333d2b36SAndroid Build Coastguard Worker ctx.OtherModuleName(dep)) 81*333d2b36SAndroid Build Coastguard Worker } else { 82*333d2b36SAndroid Build Coastguard Worker plugin := String(p.Proto.Plugin) 83*333d2b36SAndroid Build Coastguard Worker deps = append(deps, h.HostToolPath.Path()) 84*333d2b36SAndroid Build Coastguard Worker flags = append(flags, "--plugin=protoc-gen-"+plugin+"="+h.HostToolPath.String()) 85*333d2b36SAndroid Build Coastguard Worker } 86*333d2b36SAndroid Build Coastguard Worker }) 87*333d2b36SAndroid Build Coastguard Worker 88*333d2b36SAndroid Build Coastguard Worker var protoOutFlag string 89*333d2b36SAndroid Build Coastguard Worker if plugin := String(p.Proto.Plugin); plugin != "" { 90*333d2b36SAndroid Build Coastguard Worker protoOutFlag = "--" + plugin + "_out" 91*333d2b36SAndroid Build Coastguard Worker } 92*333d2b36SAndroid Build Coastguard Worker 93*333d2b36SAndroid Build Coastguard Worker return ProtoFlags{ 94*333d2b36SAndroid Build Coastguard Worker Flags: flags, 95*333d2b36SAndroid Build Coastguard Worker Deps: deps, 96*333d2b36SAndroid Build Coastguard Worker OutTypeFlag: protoOutFlag, 97*333d2b36SAndroid Build Coastguard Worker CanonicalPathFromRoot: proptools.BoolDefault(p.Proto.Canonical_path_from_root, canonicalPathFromRootDefault), 98*333d2b36SAndroid Build Coastguard Worker Dir: PathForModuleGen(ctx, "proto"), 99*333d2b36SAndroid Build Coastguard Worker SubDir: PathForModuleGen(ctx, "proto", ctx.ModuleDir()), 100*333d2b36SAndroid Build Coastguard Worker } 101*333d2b36SAndroid Build Coastguard Worker} 102*333d2b36SAndroid Build Coastguard Worker 103*333d2b36SAndroid Build Coastguard Workertype ProtoProperties struct { 104*333d2b36SAndroid Build Coastguard Worker Proto struct { 105*333d2b36SAndroid Build Coastguard Worker // Proto generator type. C++: full or lite. Java: micro, nano, stream, or lite. 106*333d2b36SAndroid Build Coastguard Worker Type *string `android:"arch_variant"` 107*333d2b36SAndroid Build Coastguard Worker 108*333d2b36SAndroid Build Coastguard Worker // Proto plugin to use as the generator. Must be a cc_binary_host module. 109*333d2b36SAndroid Build Coastguard Worker Plugin *string `android:"arch_variant"` 110*333d2b36SAndroid Build Coastguard Worker 111*333d2b36SAndroid Build Coastguard Worker // list of directories that will be added to the protoc include paths. 112*333d2b36SAndroid Build Coastguard Worker Include_dirs []string 113*333d2b36SAndroid Build Coastguard Worker 114*333d2b36SAndroid Build Coastguard Worker // list of directories relative to the bp file that will 115*333d2b36SAndroid Build Coastguard Worker // be added to the protoc include paths. 116*333d2b36SAndroid Build Coastguard Worker Local_include_dirs []string 117*333d2b36SAndroid Build Coastguard Worker 118*333d2b36SAndroid Build Coastguard Worker // whether to identify the proto files from the root of the 119*333d2b36SAndroid Build Coastguard Worker // source tree (the original method in Android, useful for 120*333d2b36SAndroid Build Coastguard Worker // android-specific protos), or relative from where they were 121*333d2b36SAndroid Build Coastguard Worker // specified (useful for external/third party protos). 122*333d2b36SAndroid Build Coastguard Worker // 123*333d2b36SAndroid Build Coastguard Worker // This defaults to true today, but is expected to default to 124*333d2b36SAndroid Build Coastguard Worker // false in the future. 125*333d2b36SAndroid Build Coastguard Worker Canonical_path_from_root *bool 126*333d2b36SAndroid Build Coastguard Worker } `android:"arch_variant"` 127*333d2b36SAndroid Build Coastguard Worker} 128*333d2b36SAndroid Build Coastguard Worker 129*333d2b36SAndroid Build Coastguard Workerfunc ProtoRule(rule *RuleBuilder, protoFile Path, flags ProtoFlags, deps Paths, 130*333d2b36SAndroid Build Coastguard Worker outDir WritablePath, depFile WritablePath, outputs WritablePaths) { 131*333d2b36SAndroid Build Coastguard Worker 132*333d2b36SAndroid Build Coastguard Worker var protoBase string 133*333d2b36SAndroid Build Coastguard Worker if flags.CanonicalPathFromRoot { 134*333d2b36SAndroid Build Coastguard Worker protoBase = "." 135*333d2b36SAndroid Build Coastguard Worker } else { 136*333d2b36SAndroid Build Coastguard Worker rel := protoFile.Rel() 137*333d2b36SAndroid Build Coastguard Worker protoBase = strings.TrimSuffix(protoFile.String(), rel) 138*333d2b36SAndroid Build Coastguard Worker } 139*333d2b36SAndroid Build Coastguard Worker 140*333d2b36SAndroid Build Coastguard Worker rule.Command(). 141*333d2b36SAndroid Build Coastguard Worker BuiltTool("aprotoc"). 142*333d2b36SAndroid Build Coastguard Worker FlagWithArg(flags.OutTypeFlag+"=", strings.Join(flags.OutParams, ",")+":"+outDir.String()). 143*333d2b36SAndroid Build Coastguard Worker FlagWithDepFile("--dependency_out=", depFile). 144*333d2b36SAndroid Build Coastguard Worker FlagWithArg("-I ", protoBase). 145*333d2b36SAndroid Build Coastguard Worker Flags(flags.Flags). 146*333d2b36SAndroid Build Coastguard Worker Input(protoFile). 147*333d2b36SAndroid Build Coastguard Worker Implicits(deps). 148*333d2b36SAndroid Build Coastguard Worker ImplicitOutputs(outputs) 149*333d2b36SAndroid Build Coastguard Worker 150*333d2b36SAndroid Build Coastguard Worker rule.Command(). 151*333d2b36SAndroid Build Coastguard Worker BuiltTool("dep_fixer").Flag(depFile.String()) 152*333d2b36SAndroid Build Coastguard Worker} 153