diff --git a/Android.bp b/Android.bp index 89bd6ea9f..0875a2bc1 100644 --- a/Android.bp +++ b/Android.bp @@ -53,6 +53,7 @@ bootstrap_go_package { "android/package_ctx.go", "android/paths.go", "android/prebuilt.go", + "android/proto.go", "android/register.go", "android/testing.go", "android/util.go", diff --git a/android/proto.go b/android/proto.go new file mode 100644 index 000000000..9bb9cfbb5 --- /dev/null +++ b/android/proto.go @@ -0,0 +1,103 @@ +// Copyright 2017 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package android + +import ( + "github.com/google/blueprint" +) + +func init() { + pctx.HostBinToolVariable("protocCmd", "aprotoc") +} + +var ( + proto = pctx.AndroidStaticRule("protoc", + blueprint.RuleParams{ + Command: "$protocCmd $protoOut=$protoOutFlags:$outDir $protoFlags $in", + CommandDeps: []string{"$protocCmd"}, + }, "protoFlags", "protoOut", "protoOutFlags", "outDir") +) + +// TODO(ccross): protos are often used to communicate between multiple modules. If the only +// way to convert a proto to source is to reference it as a source file, and external modules cannot +// reference source files in other modules, then every module that owns a proto file will need to +// export a library for every type of external user (lite vs. full, c vs. c++ vs. java). It would +// be better to support a proto module type that exported a proto file along with some include dirs, +// and then external modules could depend on the proto module but use their own settings to +// generate the source. + +func GenProto(ctx ModuleContext, protoFile Path, + protoFlags string, protoOut, protoOutFlags string, extensions []string) WritablePaths { + + var outFiles WritablePaths + for _, ext := range extensions { + outFiles = append(outFiles, GenPathWithExt(ctx, "proto", protoFile, ext)) + } + + ctx.ModuleBuild(pctx, ModuleBuildParams{ + Rule: proto, + Description: "protoc " + protoFile.Rel(), + Outputs: outFiles, + Input: protoFile, + Args: map[string]string{ + "outDir": ProtoDir(ctx).String(), + "protoOut": protoOut, + "protoOutFlags": protoOutFlags, + "protoFlags": protoFlags, + }, + }) + + return outFiles +} + +func ProtoFlags(ctx ModuleContext, p *ProtoProperties) []string { + var protoFlags []string + if len(p.Proto.Local_include_dirs) > 0 { + localProtoIncludeDirs := PathsForModuleSrc(ctx, p.Proto.Local_include_dirs) + protoFlags = append(protoFlags, JoinWithPrefix(localProtoIncludeDirs.Strings(), "-I")) + } + if len(p.Proto.Include_dirs) > 0 { + rootProtoIncludeDirs := PathsForSource(ctx, p.Proto.Include_dirs) + protoFlags = append(protoFlags, JoinWithPrefix(rootProtoIncludeDirs.Strings(), "-I")) + } + + protoFlags = append(protoFlags, "-I .") + + return protoFlags +} + +// ProtoDir returns the module's "gen/proto" directory +func ProtoDir(ctx ModuleContext) ModuleGenPath { + return PathForModuleGen(ctx, "proto") +} + +// ProtoSubDir returns the module's "gen/proto/path/to/module" directory +func ProtoSubDir(ctx ModuleContext) ModuleGenPath { + return PathForModuleGen(ctx, "proto", ctx.ModuleDir()) +} + +type ProtoProperties struct { + Proto struct { + // Proto generator type. C++: full or lite. Java: micro, nano, stream, or lite. + Type *string `android:"arch_variant"` + + // list of directories that will be added to the protoc include paths. + Include_dirs []string + + // list of directories relative to the bp file that will + // be added to the protoc include paths. + Local_include_dirs []string + } `android:"arch_variant"` +} diff --git a/androidmk/cmd/androidmk/android.go b/androidmk/cmd/androidmk/android.go index 8cc882053..bdd3e97e9 100644 --- a/androidmk/cmd/androidmk/android.go +++ b/androidmk/cmd/androidmk/android.go @@ -661,6 +661,15 @@ func allJavaFilesUnder(args []string) string { return fmt.Sprintf("%s/**/*.java", dir) } +func allProtoFilesUnder(args []string) string { + dir := "" + if len(args) > 0 { + dir = strings.TrimSpace(args[0]) + } + + return fmt.Sprintf("%s/**/*.proto", dir) +} + func allSubdirJavaFiles(args []string) string { return "**/*.java" } @@ -699,6 +708,7 @@ func androidScope() mkparser.Scope { globalScope.Set("CLEAR_VARS", clear_vars) globalScope.SetFunc("my-dir", mydir) globalScope.SetFunc("all-java-files-under", allJavaFilesUnder) + globalScope.SetFunc("all-proto-files-under", allProtoFilesUnder) globalScope.SetFunc("all-subdir-java-files", allSubdirJavaFiles) for k, v := range moduleTypes { diff --git a/cc/compiler.go b/cc/compiler.go index 5ffaf1752..a65ddf873 100644 --- a/cc/compiler.go +++ b/cc/compiler.go @@ -141,6 +141,11 @@ type BaseCompilerProperties struct { } } + Proto struct { + // Link statically against the protobuf runtime + Static bool `android:"arch_variant"` + } `android:"arch_variant"` + // Stores the original list of source files before being cleared by library reuse OriginalSrcs []string `blueprint:"mutated"` } @@ -151,7 +156,7 @@ func NewBaseCompiler() *baseCompiler { type baseCompiler struct { Properties BaseCompilerProperties - Proto ProtoProperties + Proto android.ProtoProperties deps android.Paths srcs android.Paths flags builderFlags @@ -188,7 +193,7 @@ func (compiler *baseCompiler) compilerDeps(ctx DepsContext, deps Deps) Deps { android.ExtractSourcesDeps(ctx, compiler.Properties.Srcs) if compiler.hasSrcExt(".proto") { - deps = protoDeps(ctx, deps, &compiler.Proto) + deps = protoDeps(ctx, deps, &compiler.Proto, compiler.Properties.Proto.Static) } return deps diff --git a/cc/gen.go b/cc/gen.go index 6c9579edd..9fc14c50c 100644 --- a/cc/gen.go +++ b/cc/gen.go @@ -153,9 +153,10 @@ func genSources(ctx android.ModuleContext, srcFiles android.Paths, srcFiles[i] = cppFile genLex(ctx, srcFile, cppFile) case ".proto": - cppFile, headerFile := genProto(ctx, srcFile, buildFlags.protoFlags) - srcFiles[i] = cppFile - deps = append(deps, headerFile) + protoFiles := android.GenProto(ctx, srcFile, buildFlags.protoFlags, + "--cpp_out", "", []string{"pb.cc", "pb.h"}) + srcFiles[i] = protoFiles[0] + deps = append(deps, protoFiles[1]) case ".aidl": cppFile := android.GenPathWithExt(ctx, "aidl", srcFile, "cpp") srcFiles[i] = cppFile diff --git a/cc/library.go b/cc/library.go index 1537fd47d..577521cde 100644 --- a/cc/library.go +++ b/cc/library.go @@ -655,8 +655,8 @@ func (library *libraryDecorator) link(ctx ModuleContext, if library.Properties.Proto.Export_proto_headers { if library.baseCompiler.hasSrcExt(".proto") { flags := []string{ - "-I" + protoSubDir(ctx).String(), - "-I" + protoDir(ctx).String(), + "-I" + android.ProtoSubDir(ctx).String(), + "-I" + android.ProtoDir(ctx).String(), } library.reexportFlags(flags) library.reuseExportedFlags = append(library.reuseExportedFlags, flags...) diff --git a/cc/proto.go b/cc/proto.go index 6c1789abf..6049d44ad 100644 --- a/cc/proto.go +++ b/cc/proto.go @@ -15,81 +15,13 @@ package cc import ( - "github.com/google/blueprint" "github.com/google/blueprint/proptools" "android/soong/android" ) -func init() { - pctx.HostBinToolVariable("protocCmd", "aprotoc") -} - -var ( - proto = pctx.AndroidStaticRule("protoc", - blueprint.RuleParams{ - Command: "$protocCmd --cpp_out=$outDir $protoFlags $in", - CommandDeps: []string{"$protocCmd"}, - }, "protoFlags", "outDir") -) - -// TODO(ccross): protos are often used to communicate between multiple modules. If the only -// way to convert a proto to source is to reference it as a source file, and external modules cannot -// reference source files in other modules, then every module that owns a proto file will need to -// export a library for every type of external user (lite vs. full, c vs. c++ vs. java). It would -// be better to support a proto module type that exported a proto file along with some include dirs, -// and then external modules could depend on the proto module but use their own settings to -// generate the source. - -func genProto(ctx android.ModuleContext, protoFile android.Path, - protoFlags string) (android.ModuleGenPath, android.ModuleGenPath) { - - outFile := android.GenPathWithExt(ctx, "proto", protoFile, "pb.cc") - headerFile := android.GenPathWithExt(ctx, "proto", protoFile, "pb.h") - ctx.ModuleBuild(pctx, android.ModuleBuildParams{ - Rule: proto, - Description: "protoc " + protoFile.Rel(), - Outputs: android.WritablePaths{outFile, headerFile}, - Input: protoFile, - Args: map[string]string{ - "outDir": protoDir(ctx).String(), - "protoFlags": protoFlags, - }, - }) - - return outFile, headerFile -} - -// protoDir returns the module's "gen/proto" directory -func protoDir(ctx android.ModuleContext) android.ModuleGenPath { - return android.PathForModuleGen(ctx, "proto") -} - -// protoSubDir returns the module's "gen/proto/path/to/module" directory -func protoSubDir(ctx android.ModuleContext) android.ModuleGenPath { - return android.PathForModuleGen(ctx, "proto", ctx.ModuleDir()) -} - -type ProtoProperties struct { - Proto struct { - // Proto generator type (full, lite) - Type *string `android:"arch_variant"` - - // Link statically against the protobuf runtime - Static bool `android:"arch_variant"` - - // list of directories that will be added to the protoc include paths. - Include_dirs []string - - // list of directories relative to the Android.bp file that will - // be added to the protoc include paths. - Local_include_dirs []string - } `android:"arch_variant"` -} - -func protoDeps(ctx BaseModuleContext, deps Deps, p *ProtoProperties) Deps { +func protoDeps(ctx BaseModuleContext, deps Deps, p *android.ProtoProperties, static bool) Deps { var lib string - var static bool switch proptools.String(p.Proto.Type) { case "full": @@ -105,9 +37,6 @@ func protoDeps(ctx BaseModuleContext, deps Deps, p *ProtoProperties) Deps { static = true } else { lib = "libprotobuf-cpp-lite" - if p.Proto.Static { - static = true - } } default: ctx.PropertyErrorf("proto.type", "unknown proto type %q", @@ -125,23 +54,14 @@ func protoDeps(ctx BaseModuleContext, deps Deps, p *ProtoProperties) Deps { return deps } -func protoFlags(ctx ModuleContext, flags Flags, p *ProtoProperties) Flags { +func protoFlags(ctx ModuleContext, flags Flags, p *android.ProtoProperties) Flags { flags.CFlags = append(flags.CFlags, "-DGOOGLE_PROTOBUF_NO_RTTI") flags.GlobalFlags = append(flags.GlobalFlags, - "-I"+protoSubDir(ctx).String(), - "-I"+protoDir(ctx).String(), + "-I"+android.ProtoSubDir(ctx).String(), + "-I"+android.ProtoDir(ctx).String(), ) - if len(p.Proto.Local_include_dirs) > 0 { - localProtoIncludeDirs := android.PathsForModuleSrc(ctx, p.Proto.Local_include_dirs) - flags.protoFlags = append(flags.protoFlags, includeDirsToFlags(localProtoIncludeDirs)) - } - if len(p.Proto.Include_dirs) > 0 { - rootProtoIncludeDirs := android.PathsForSource(ctx, p.Proto.Include_dirs) - flags.protoFlags = append(flags.protoFlags, includeDirsToFlags(rootProtoIncludeDirs)) - } - - flags.protoFlags = append(flags.protoFlags, "-I .") + flags.protoFlags = android.ProtoFlags(ctx, p) return flags }