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	"strings"
19
20	"github.com/google/blueprint"
21	"github.com/google/blueprint/pathtools"
22	"github.com/google/blueprint/proptools"
23
24	"android/soong/android"
25)
26
27func init() {
28	pctx.HostBinToolVariable("protocCmd", "aprotoc")
29}
30
31var (
32	proto = pctx.AndroidStaticRule("protoc",
33		blueprint.RuleParams{
34			Command:     "$protocCmd --cpp_out=$protoOutParams:$outDir -I $protoBase $protoFlags $in",
35			CommandDeps: []string{"$protocCmd"},
36		}, "protoFlags", "protoOutParams", "protoBase", "outDir")
37)
38
39// genProto creates a rule to convert a .proto file to generated .pb.cc and .pb.h files and returns
40// the paths to the generated files.
41func genProto(ctx android.ModuleContext, protoFile android.Path,
42	protoFlags, protoOutParams string, root bool) (ccFile, headerFile android.WritablePath) {
43
44	var protoBase string
45	if root {
46		protoBase = "."
47		ccFile = android.GenPathWithExt(ctx, "proto", protoFile, "pb.cc")
48		headerFile = android.GenPathWithExt(ctx, "proto", protoFile, "pb.h")
49	} else {
50		rel := protoFile.Rel()
51		protoBase = strings.TrimSuffix(protoFile.String(), rel)
52		ccFile = android.PathForModuleGen(ctx, "proto", pathtools.ReplaceExtension(rel, "pb.cc"))
53		headerFile = android.PathForModuleGen(ctx, "proto", pathtools.ReplaceExtension(rel, "pb.h"))
54	}
55
56	ctx.Build(pctx, android.BuildParams{
57		Rule:        proto,
58		Description: "protoc " + protoFile.Rel(),
59		Outputs:     android.WritablePaths{ccFile, headerFile},
60		Input:       protoFile,
61		Args: map[string]string{
62			"outDir":         android.ProtoDir(ctx).String(),
63			"protoFlags":     protoFlags,
64			"protoOutParams": protoOutParams,
65			"protoBase":      protoBase,
66		},
67	})
68
69	return ccFile, headerFile
70}
71
72func protoDeps(ctx BaseModuleContext, deps Deps, p *android.ProtoProperties, static bool) Deps {
73	var lib string
74
75	switch String(p.Proto.Type) {
76	case "full":
77		if ctx.useSdk() {
78			lib = "libprotobuf-cpp-full-ndk"
79			static = true
80		} else {
81			lib = "libprotobuf-cpp-full"
82		}
83	case "lite", "":
84		if ctx.useSdk() {
85			lib = "libprotobuf-cpp-lite-ndk"
86			static = true
87		} else {
88			lib = "libprotobuf-cpp-lite"
89		}
90	default:
91		ctx.PropertyErrorf("proto.type", "unknown proto type %q",
92			String(p.Proto.Type))
93	}
94
95	if static {
96		deps.StaticLibs = append(deps.StaticLibs, lib)
97		deps.ReexportStaticLibHeaders = append(deps.ReexportStaticLibHeaders, lib)
98	} else {
99		deps.SharedLibs = append(deps.SharedLibs, lib)
100		deps.ReexportSharedLibHeaders = append(deps.ReexportSharedLibHeaders, lib)
101	}
102
103	return deps
104}
105
106func protoFlags(ctx ModuleContext, flags Flags, p *android.ProtoProperties) Flags {
107	flags.CFlags = append(flags.CFlags, "-DGOOGLE_PROTOBUF_NO_RTTI")
108
109	flags.ProtoRoot = android.ProtoCanonicalPathFromRoot(ctx, p)
110	if flags.ProtoRoot {
111		flags.GlobalFlags = append(flags.GlobalFlags, "-I"+android.ProtoSubDir(ctx).String())
112	}
113	flags.GlobalFlags = append(flags.GlobalFlags, "-I"+android.ProtoDir(ctx).String())
114
115	flags.protoFlags = android.ProtoFlags(ctx, p)
116
117	if proptools.String(p.Proto.Type) == "lite" {
118		flags.protoOutParams = append(flags.protoOutParams, "lite")
119	}
120
121	return flags
122}
123