blob: 5247c68dc300f29945ee17a88a3282dd612ab1d5 [file] [log] [blame]
Colin Cross38f794e2017-09-07 10:53:07 -07001// 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 android
16
Colin Cross19878da2019-03-28 14:45:07 -070017import (
18 "strings"
19
Colin Crossfe17f6f2019-03-28 19:30:56 -070020 "github.com/google/blueprint"
Colin Cross19878da2019-03-28 14:45:07 -070021 "github.com/google/blueprint/proptools"
22)
23
Colin Cross38f794e2017-09-07 10:53:07 -070024// TODO(ccross): protos are often used to communicate between multiple modules. If the only
25// way to convert a proto to source is to reference it as a source file, and external modules cannot
26// reference source files in other modules, then every module that owns a proto file will need to
27// export a library for every type of external user (lite vs. full, c vs. c++ vs. java). It would
28// be better to support a proto module type that exported a proto file along with some include dirs,
29// and then external modules could depend on the proto module but use their own settings to
30// generate the source.
31
Colin Cross19878da2019-03-28 14:45:07 -070032type ProtoFlags struct {
33 Flags []string
34 CanonicalPathFromRoot bool
35 Dir ModuleGenPath
36 SubDir ModuleGenPath
37 OutTypeFlag string
38 OutParams []string
Colin Crossfe17f6f2019-03-28 19:30:56 -070039 Deps Paths
40}
41
42type protoDependencyTag struct {
43 blueprint.BaseDependencyTag
44 name string
45}
46
47var ProtoPluginDepTag = protoDependencyTag{name: "plugin"}
48
49func ProtoDeps(ctx BottomUpMutatorContext, p *ProtoProperties) {
50 if String(p.Proto.Plugin) != "" && String(p.Proto.Type) != "" {
51 ctx.ModuleErrorf("only one of proto.type and proto.plugin can be specified.")
52 }
53
54 if plugin := String(p.Proto.Plugin); plugin != "" {
55 ctx.AddFarVariationDependencies([]blueprint.Variation{
56 {Mutator: "arch", Variation: ctx.Config().BuildOsVariant},
57 }, ProtoPluginDepTag, "protoc-gen-"+plugin)
58 }
Colin Cross19878da2019-03-28 14:45:07 -070059}
Colin Crossa3b25002017-12-15 13:41:30 -080060
Colin Cross19878da2019-03-28 14:45:07 -070061func GetProtoFlags(ctx ModuleContext, p *ProtoProperties) ProtoFlags {
Colin Crossfe17f6f2019-03-28 19:30:56 -070062 var flags []string
63 var deps Paths
64
Colin Cross38f794e2017-09-07 10:53:07 -070065 if len(p.Proto.Local_include_dirs) > 0 {
66 localProtoIncludeDirs := PathsForModuleSrc(ctx, p.Proto.Local_include_dirs)
Colin Crossfe17f6f2019-03-28 19:30:56 -070067 flags = append(flags, JoinWithPrefix(localProtoIncludeDirs.Strings(), "-I"))
Colin Cross38f794e2017-09-07 10:53:07 -070068 }
69 if len(p.Proto.Include_dirs) > 0 {
70 rootProtoIncludeDirs := PathsForSource(ctx, p.Proto.Include_dirs)
Colin Crossfe17f6f2019-03-28 19:30:56 -070071 flags = append(flags, JoinWithPrefix(rootProtoIncludeDirs.Strings(), "-I"))
72 }
73
74 ctx.VisitDirectDepsWithTag(ProtoPluginDepTag, func(dep Module) {
75 if hostTool, ok := dep.(HostToolProvider); !ok || !hostTool.HostToolPath().Valid() {
76 ctx.PropertyErrorf("proto.plugin", "module %q is not a host tool provider",
77 ctx.OtherModuleName(dep))
78 } else {
79 plugin := String(p.Proto.Plugin)
80 deps = append(deps, hostTool.HostToolPath().Path())
81 flags = append(flags, "--plugin=protoc-gen-"+plugin+"="+hostTool.HostToolPath().String())
82 }
83 })
84
85 var protoOutFlag string
86 if plugin := String(p.Proto.Plugin); plugin != "" {
87 protoOutFlag = "--" + plugin + "_out"
Colin Cross38f794e2017-09-07 10:53:07 -070088 }
89
Colin Cross19878da2019-03-28 14:45:07 -070090 return ProtoFlags{
Colin Crossfe17f6f2019-03-28 19:30:56 -070091 Flags: flags,
92 Deps: deps,
93 OutTypeFlag: protoOutFlag,
Colin Cross19878da2019-03-28 14:45:07 -070094 CanonicalPathFromRoot: proptools.BoolDefault(p.Proto.Canonical_path_from_root, true),
95 Dir: PathForModuleGen(ctx, "proto"),
96 SubDir: PathForModuleGen(ctx, "proto", ctx.ModuleDir()),
Dan Willemsenab9f4262018-02-14 13:58:34 -080097 }
Colin Cross38f794e2017-09-07 10:53:07 -070098}
99
100type ProtoProperties struct {
101 Proto struct {
102 // Proto generator type. C++: full or lite. Java: micro, nano, stream, or lite.
103 Type *string `android:"arch_variant"`
104
Colin Crossfe17f6f2019-03-28 19:30:56 -0700105 // Proto plugin to use as the generator. Must be a cc_binary_host module.
106 Plugin *string `android:"arch_variant"`
107
Colin Cross38f794e2017-09-07 10:53:07 -0700108 // list of directories that will be added to the protoc include paths.
109 Include_dirs []string
110
111 // list of directories relative to the bp file that will
112 // be added to the protoc include paths.
113 Local_include_dirs []string
Dan Willemsenab9f4262018-02-14 13:58:34 -0800114
115 // whether to identify the proto files from the root of the
116 // source tree (the original method in Android, useful for
117 // android-specific protos), or relative from where they were
118 // specified (useful for external/third party protos).
119 //
120 // This defaults to true today, but is expected to default to
121 // false in the future.
122 Canonical_path_from_root *bool
Colin Cross38f794e2017-09-07 10:53:07 -0700123 } `android:"arch_variant"`
124}
Colin Cross19878da2019-03-28 14:45:07 -0700125
126func ProtoRule(ctx ModuleContext, rule *RuleBuilder, protoFile Path, flags ProtoFlags, deps Paths,
127 outDir WritablePath, depFile WritablePath, outputs WritablePaths) {
128
129 var protoBase string
130 if flags.CanonicalPathFromRoot {
131 protoBase = "."
132 } else {
133 rel := protoFile.Rel()
134 protoBase = strings.TrimSuffix(protoFile.String(), rel)
135 }
136
137 rule.Command().
138 Tool(ctx.Config().HostToolPath(ctx, "aprotoc")).
139 FlagWithArg(flags.OutTypeFlag+"=", strings.Join(flags.OutParams, ",")+":"+outDir.String()).
140 FlagWithDepFile("--dependency_out=", depFile).
141 FlagWithArg("-I ", protoBase).
142 Flags(flags.Flags).
143 Input(protoFile).
144 Implicits(deps).
145 ImplicitOutputs(outputs)
146
147 rule.Command().
148 Tool(ctx.Config().HostToolPath(ctx, "dep_fixer")).Flag(depFile.String())
149}