• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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	"github.com/google/blueprint/proptools"
20
21	"android/soong/android"
22	"android/soong/bazel"
23)
24
25const (
26	protoTypeDefault = "lite"
27)
28
29// genProto creates a rule to convert a .proto file to generated .pb.cc and .pb.h files and returns
30// the paths to the generated files.
31func genProto(ctx android.ModuleContext, protoFile android.Path, flags builderFlags) (cc, header android.WritablePath) {
32	var ccFile, headerFile android.ModuleGenPath
33
34	srcSuffix := ".cc"
35	if flags.protoC {
36		srcSuffix = ".c"
37	}
38
39	if flags.proto.CanonicalPathFromRoot {
40		ccFile = android.GenPathWithExt(ctx, "proto", protoFile, "pb"+srcSuffix)
41		headerFile = android.GenPathWithExt(ctx, "proto", protoFile, "pb.h")
42	} else {
43		rel := protoFile.Rel()
44		ccFile = android.PathForModuleGen(ctx, "proto", pathtools.ReplaceExtension(rel, "pb"+srcSuffix))
45		headerFile = android.PathForModuleGen(ctx, "proto", pathtools.ReplaceExtension(rel, "pb.h"))
46	}
47
48	protoDeps := flags.proto.Deps
49	if flags.protoOptionsFile {
50		optionsFile := pathtools.ReplaceExtension(protoFile.String(), "options")
51		optionsPath := android.PathForSource(ctx, optionsFile)
52		protoDeps = append(android.Paths{optionsPath}, protoDeps...)
53	}
54
55	outDir := flags.proto.Dir
56	depFile := ccFile.ReplaceExtension(ctx, "d")
57	outputs := android.WritablePaths{ccFile, headerFile}
58
59	rule := android.NewRuleBuilder(pctx, ctx)
60
61	android.ProtoRule(rule, protoFile, flags.proto, protoDeps, outDir, depFile, outputs)
62
63	rule.Build("protoc_"+protoFile.Rel(), "protoc "+protoFile.Rel())
64
65	return ccFile, headerFile
66}
67
68func protoDeps(ctx DepsContext, deps Deps, p *android.ProtoProperties, static bool) Deps {
69	var lib string
70
71	if String(p.Proto.Plugin) == "" {
72		switch proptools.StringDefault(p.Proto.Type, protoTypeDefault) {
73		case "full":
74			if ctx.useSdk() {
75				lib = "libprotobuf-cpp-full-ndk"
76				static = true
77			} else {
78				lib = "libprotobuf-cpp-full"
79			}
80		case "lite":
81			if ctx.useSdk() {
82				lib = "libprotobuf-cpp-lite-ndk"
83				static = true
84			} else {
85				lib = "libprotobuf-cpp-lite"
86			}
87		case "nanopb-c":
88			lib = "libprotobuf-c-nano"
89			static = true
90		case "nanopb-c-enable_malloc":
91			lib = "libprotobuf-c-nano-enable_malloc"
92			static = true
93		case "nanopb-c-16bit":
94			lib = "libprotobuf-c-nano-16bit"
95			static = true
96		case "nanopb-c-enable_malloc-16bit":
97			lib = "libprotobuf-c-nano-enable_malloc-16bit"
98			static = true
99		case "nanopb-c-32bit":
100			lib = "libprotobuf-c-nano-32bit"
101			static = true
102		case "nanopb-c-enable_malloc-32bit":
103			lib = "libprotobuf-c-nano-enable_malloc-32bit"
104			static = true
105		default:
106			ctx.PropertyErrorf("proto.type", "unknown proto type %q",
107				String(p.Proto.Type))
108		}
109
110		if static {
111			deps.StaticLibs = append(deps.StaticLibs, lib)
112			deps.ReexportStaticLibHeaders = append(deps.ReexportStaticLibHeaders, lib)
113		} else {
114			deps.SharedLibs = append(deps.SharedLibs, lib)
115			deps.ReexportSharedLibHeaders = append(deps.ReexportSharedLibHeaders, lib)
116		}
117	}
118
119	return deps
120}
121
122func protoFlags(ctx ModuleContext, flags Flags, p *android.ProtoProperties) Flags {
123	flags.Local.CFlags = append(flags.Local.CFlags, "-DGOOGLE_PROTOBUF_NO_RTTI")
124
125	flags.proto = android.GetProtoFlags(ctx, p)
126	if flags.proto.CanonicalPathFromRoot {
127		flags.Local.CommonFlags = append(flags.Local.CommonFlags, "-I"+flags.proto.SubDir.String())
128	}
129	flags.Local.CommonFlags = append(flags.Local.CommonFlags, "-I"+flags.proto.Dir.String())
130
131	if String(p.Proto.Plugin) == "" {
132		var plugin string
133
134		switch String(p.Proto.Type) {
135		case "nanopb-c", "nanopb-c-enable_malloc", "nanopb-c-16bit", "nanopb-c-enable_malloc-16bit", "nanopb-c-32bit", "nanopb-c-enable_malloc-32bit":
136			flags.protoC = true
137			flags.protoOptionsFile = true
138			flags.proto.OutTypeFlag = "--nanopb_out"
139			// Disable nanopb timestamps to support remote caching.
140			flags.proto.OutParams = append(flags.proto.OutParams, "-T")
141			plugin = "protoc-gen-nanopb"
142		case "full":
143			flags.proto.OutTypeFlag = "--cpp_out"
144		case "lite":
145			flags.proto.OutTypeFlag = "--cpp_out"
146			flags.proto.OutParams = append(flags.proto.OutParams, "lite")
147		case "":
148			// TODO(b/119714316): this should be equivalent to "lite" in
149			// order to match protoDeps, but some modules are depending on
150			// this behavior
151			flags.proto.OutTypeFlag = "--cpp_out"
152		default:
153			ctx.PropertyErrorf("proto.type", "unknown proto type %q",
154				String(p.Proto.Type))
155		}
156
157		if plugin != "" {
158			path := ctx.Config().HostToolPath(ctx, plugin)
159			flags.proto.Deps = append(flags.proto.Deps, path)
160			flags.proto.Flags = append(flags.proto.Flags, "--plugin="+path.String())
161		}
162	}
163
164	return flags
165}
166
167type protoAttributes struct {
168	Deps bazel.LabelListAttribute
169}
170
171type bp2buildProtoDeps struct {
172	wholeStaticLib               *bazel.LabelAttribute
173	implementationWholeStaticLib *bazel.LabelAttribute
174	protoDep                     *bazel.LabelAttribute
175}
176
177func bp2buildProto(ctx android.Bp2buildMutatorContext, m *Module, protoSrcs bazel.LabelListAttribute) bp2buildProtoDeps {
178	var ret bp2buildProtoDeps
179
180	protoInfo, ok := android.Bp2buildProtoProperties(ctx, &m.ModuleBase, protoSrcs)
181	if !ok {
182		return ret
183	}
184
185	var depName string
186	typ := proptools.StringDefault(protoInfo.Type, protoTypeDefault)
187	var rule_class string
188	suffix := "_cc_proto"
189	switch typ {
190	case "lite":
191		suffix += "_lite"
192		rule_class = "cc_lite_proto_library"
193		depName = "libprotobuf-cpp-lite"
194	case "full":
195		rule_class = "cc_proto_library"
196		depName = "libprotobuf-cpp-full"
197	default:
198		ctx.PropertyErrorf("proto.type", "cannot handle conversion at this time: %q", typ)
199	}
200
201	dep := android.BazelLabelForModuleDepSingle(ctx, depName)
202	ret.protoDep = &bazel.LabelAttribute{Value: &dep}
203
204	protoLabel := bazel.Label{Label: ":" + protoInfo.Name}
205	var protoAttrs protoAttributes
206	protoAttrs.Deps.SetValue(bazel.LabelList{Includes: []bazel.Label{protoLabel}})
207
208	name := m.Name() + suffix
209
210	ctx.CreateBazelTargetModule(
211		bazel.BazelTargetModuleProperties{
212			Rule_class:        rule_class,
213			Bzl_load_location: "//build/bazel/rules/cc:cc_proto.bzl",
214		},
215		android.CommonAttributes{Name: name},
216		&protoAttrs)
217
218	var privateHdrs bool
219	if lib, ok := m.linker.(*libraryDecorator); ok {
220		privateHdrs = !proptools.Bool(lib.Properties.Proto.Export_proto_headers)
221	}
222
223	labelAttr := &bazel.LabelAttribute{Value: &bazel.Label{Label: ":" + name}}
224	if privateHdrs {
225		ret.implementationWholeStaticLib = labelAttr
226	} else {
227		ret.wholeStaticLib = labelAttr
228	}
229
230	return ret
231}
232