blob: 0be7893c89d87a495788d088757ca0ded2d5d691 [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 != "" {
Colin Cross0f7d2ef2019-10-16 11:03:10 -070055 ctx.AddFarVariationDependencies(ctx.Config().BuildOSTarget.Variations(),
56 ProtoPluginDepTag, "protoc-gen-"+plugin)
Colin Crossfe17f6f2019-03-28 19:30:56 -070057 }
Colin Cross19878da2019-03-28 14:45:07 -070058}
Colin Crossa3b25002017-12-15 13:41:30 -080059
Colin Cross19878da2019-03-28 14:45:07 -070060func GetProtoFlags(ctx ModuleContext, p *ProtoProperties) ProtoFlags {
Colin Crossfe17f6f2019-03-28 19:30:56 -070061 var flags []string
62 var deps Paths
63
Colin Cross38f794e2017-09-07 10:53:07 -070064 if len(p.Proto.Local_include_dirs) > 0 {
65 localProtoIncludeDirs := PathsForModuleSrc(ctx, p.Proto.Local_include_dirs)
Colin Crossfe17f6f2019-03-28 19:30:56 -070066 flags = append(flags, JoinWithPrefix(localProtoIncludeDirs.Strings(), "-I"))
Colin Cross38f794e2017-09-07 10:53:07 -070067 }
68 if len(p.Proto.Include_dirs) > 0 {
69 rootProtoIncludeDirs := PathsForSource(ctx, p.Proto.Include_dirs)
Colin Crossfe17f6f2019-03-28 19:30:56 -070070 flags = append(flags, JoinWithPrefix(rootProtoIncludeDirs.Strings(), "-I"))
71 }
72
73 ctx.VisitDirectDepsWithTag(ProtoPluginDepTag, func(dep Module) {
74 if hostTool, ok := dep.(HostToolProvider); !ok || !hostTool.HostToolPath().Valid() {
75 ctx.PropertyErrorf("proto.plugin", "module %q is not a host tool provider",
76 ctx.OtherModuleName(dep))
77 } else {
78 plugin := String(p.Proto.Plugin)
79 deps = append(deps, hostTool.HostToolPath().Path())
80 flags = append(flags, "--plugin=protoc-gen-"+plugin+"="+hostTool.HostToolPath().String())
81 }
82 })
83
84 var protoOutFlag string
85 if plugin := String(p.Proto.Plugin); plugin != "" {
86 protoOutFlag = "--" + plugin + "_out"
Colin Cross38f794e2017-09-07 10:53:07 -070087 }
88
Colin Cross19878da2019-03-28 14:45:07 -070089 return ProtoFlags{
Colin Crossfe17f6f2019-03-28 19:30:56 -070090 Flags: flags,
91 Deps: deps,
92 OutTypeFlag: protoOutFlag,
Colin Cross19878da2019-03-28 14:45:07 -070093 CanonicalPathFromRoot: proptools.BoolDefault(p.Proto.Canonical_path_from_root, true),
94 Dir: PathForModuleGen(ctx, "proto"),
95 SubDir: PathForModuleGen(ctx, "proto", ctx.ModuleDir()),
Dan Willemsenab9f4262018-02-14 13:58:34 -080096 }
Colin Cross38f794e2017-09-07 10:53:07 -070097}
98
99type ProtoProperties struct {
100 Proto struct {
101 // Proto generator type. C++: full or lite. Java: micro, nano, stream, or lite.
102 Type *string `android:"arch_variant"`
103
Colin Crossfe17f6f2019-03-28 19:30:56 -0700104 // Proto plugin to use as the generator. Must be a cc_binary_host module.
105 Plugin *string `android:"arch_variant"`
106
Colin Cross38f794e2017-09-07 10:53:07 -0700107 // list of directories that will be added to the protoc include paths.
108 Include_dirs []string
109
110 // list of directories relative to the bp file that will
111 // be added to the protoc include paths.
112 Local_include_dirs []string
Dan Willemsenab9f4262018-02-14 13:58:34 -0800113
114 // whether to identify the proto files from the root of the
115 // source tree (the original method in Android, useful for
116 // android-specific protos), or relative from where they were
117 // specified (useful for external/third party protos).
118 //
119 // This defaults to true today, but is expected to default to
120 // false in the future.
121 Canonical_path_from_root *bool
Colin Cross38f794e2017-09-07 10:53:07 -0700122 } `android:"arch_variant"`
123}
Colin Cross19878da2019-03-28 14:45:07 -0700124
Colin Crossf1a035e2020-11-16 17:32:30 -0800125func ProtoRule(rule *RuleBuilder, protoFile Path, flags ProtoFlags, deps Paths,
Colin Cross19878da2019-03-28 14:45:07 -0700126 outDir WritablePath, depFile WritablePath, outputs WritablePaths) {
127
128 var protoBase string
129 if flags.CanonicalPathFromRoot {
130 protoBase = "."
131 } else {
132 rel := protoFile.Rel()
133 protoBase = strings.TrimSuffix(protoFile.String(), rel)
134 }
135
136 rule.Command().
Colin Crossf1a035e2020-11-16 17:32:30 -0800137 BuiltTool("aprotoc").
Colin Cross19878da2019-03-28 14:45:07 -0700138 FlagWithArg(flags.OutTypeFlag+"=", strings.Join(flags.OutParams, ",")+":"+outDir.String()).
139 FlagWithDepFile("--dependency_out=", depFile).
140 FlagWithArg("-I ", protoBase).
141 Flags(flags.Flags).
142 Input(protoFile).
143 Implicits(deps).
144 ImplicitOutputs(outputs)
145
146 rule.Command().
Colin Crossf1a035e2020-11-16 17:32:30 -0800147 BuiltTool("dep_fixer").Flag(depFile.String())
Colin Cross19878da2019-03-28 14:45:07 -0700148}