From 068e0feace82595d98f08fadc855ed5fab6ea43e Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Tue, 13 Dec 2016 15:23:47 -0800 Subject: [PATCH] Support filegroups filegroup is a module that contains a list of files, and can be used to export files across package boundaries. filegroups (and genrules) can be referenced from srcs properties of other modules using the syntax ":module". Test: m -j Change-Id: I3d6fc4819c0b4225b474e0ad42f0d947f55a5961 --- Android.bp | 1 + README.md | 4 ++- android/module.go | 41 ++++++++++++++++++++++++++++- cc/cc.go | 2 +- cc/compiler.go | 4 +++ genrule/filegroup.go | 61 ++++++++++++++++++++++++++++++++++++++++++++ genrule/genrule.go | 4 +++ 7 files changed, 114 insertions(+), 3 deletions(-) create mode 100644 genrule/filegroup.go diff --git a/Android.bp b/Android.bp index a941ca491..23cbad830 100644 --- a/Android.bp +++ b/Android.bp @@ -159,6 +159,7 @@ bootstrap_go_package { "soong-android", ], srcs: [ + "genrule/filegroup.go", "genrule/genrule.go", ], pluginFor: ["soong_build"], diff --git a/README.md b/README.md index 9d3dde65f..8b086dfda 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,9 @@ declarative descriptions of modules to build. By design, Android.bp files are very simple. There are no conditionals or control flow statements - any complexity is handled in build logic written in -Go. +Go. The syntax and semantics of Android.bp files are intentionally similar +to [Bazel BUILD files](https://www.bazel.io/versions/master/docs/be/overview.html) +when possible. ### Modules diff --git a/android/module.go b/android/module.go index c0b9c474e..7156e8c8f 100644 --- a/android/module.go +++ b/android/module.go @@ -711,6 +711,38 @@ func findStringInSlice(str string, slice []string) int { return -1 } +func SrcIsModule(s string) string { + if len(s) > 1 && s[0] == ':' { + return s[1:] + } + return "" +} + +type sourceDependencyTag struct { + blueprint.BaseDependencyTag +} + +var SourceDepTag sourceDependencyTag + +// Returns a list of modules that must be depended on to satisfy filegroup or generated sources +// modules listed in srcFiles using ":module" syntax +func ExtractSourcesDeps(ctx BottomUpMutatorContext, srcFiles []string) { + var deps []string + for _, s := range srcFiles { + if m := SrcIsModule(s); m != "" { + deps = append(deps, m) + } + } + + ctx.AddDependency(ctx.Module(), SourceDepTag, deps...) +} + +type SourceFileProducer interface { + Srcs() Paths +} + +// Returns a list of paths expanded from globs and modules referenced using ":module" syntax. +// ExpandSourceDeps must have already been called during the dependency resolution phase. func (ctx *androidModuleContext) ExpandSources(srcFiles, excludes []string) Paths { prefix := PathForModuleSrc(ctx).String() for i, e := range excludes { @@ -724,7 +756,14 @@ func (ctx *androidModuleContext) ExpandSources(srcFiles, excludes []string) Path globbedSrcFiles := make(Paths, 0, len(srcFiles)) for _, s := range srcFiles { - if pathtools.IsGlob(s) { + if m := SrcIsModule(s); m != "" { + module := ctx.GetDirectDepWithTag(m, SourceDepTag) + if srcProducer, ok := module.(SourceFileProducer); ok { + globbedSrcFiles = append(globbedSrcFiles, srcProducer.Srcs()...) + } else { + ctx.ModuleErrorf("srcs dependency %q is not a source file producing module", m) + } + } else if pathtools.IsGlob(s) { globbedSrcFiles = append(globbedSrcFiles, ctx.Glob(filepath.Join(prefix, s), excludes)...) } else { globbedSrcFiles = append(globbedSrcFiles, PathForModuleSrc(ctx, s)) diff --git a/cc/cc.go b/cc/cc.go index a17108fd7..8bf146783 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -833,7 +833,7 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { cc, _ := m.(*Module) if cc == nil { switch tag { - case android.DefaultsDepTag: + case android.DefaultsDepTag, android.SourceDepTag: case genSourceDepTag: if genRule, ok := m.(genrule.SourceFileGenerator); ok { depPaths.GeneratedSources = append(depPaths.GeneratedSources, diff --git a/cc/compiler.go b/cc/compiler.go index e6f432c67..d53e799a8 100644 --- a/cc/compiler.go +++ b/cc/compiler.go @@ -29,6 +29,8 @@ import ( type BaseCompilerProperties struct { // list of source files used to compile the C/C++ module. May be .c, .cpp, or .S files. + // srcs may reference the outputs of other modules that produce source files like genrule + // or filegroup using the syntax ":module". Srcs []string `android:"arch_variant"` // list of source files that should not be used to build the C/C++ module. @@ -133,6 +135,8 @@ func (compiler *baseCompiler) compilerDeps(ctx DepsContext, deps Deps) Deps { deps.GeneratedSources = append(deps.GeneratedSources, compiler.Properties.Generated_sources...) deps.GeneratedHeaders = append(deps.GeneratedHeaders, compiler.Properties.Generated_headers...) + android.ExtractSourcesDeps(ctx, compiler.Properties.Srcs) + if compiler.hasSrcExt(".proto") { deps = protoDeps(ctx, deps, &compiler.Proto) } diff --git a/genrule/filegroup.go b/genrule/filegroup.go new file mode 100644 index 000000000..9b53c9f7b --- /dev/null +++ b/genrule/filegroup.go @@ -0,0 +1,61 @@ +// Copyright 2016 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 genrule + +import ( + "github.com/google/blueprint" + + "android/soong/android" +) + +func init() { + android.RegisterModuleType("filegroup", fileGroupFactory) +} + +type fileGroupProperties struct { + // srcs lists files that will be included in this filegroup + Srcs []string + + Exclude_srcs []string +} + +type fileGroup struct { + android.ModuleBase + properties fileGroupProperties + srcs android.Paths +} + +var _ android.SourceFileProducer = (*fileGroup)(nil) + +// filegroup modules contain a list of files, and can be used to export files across package +// boundaries. filegroups (and genrules) can be referenced from srcs properties of other modules +// using the syntax ":module". +func fileGroupFactory() (blueprint.Module, []interface{}) { + module := &fileGroup{} + + return android.InitAndroidModule(module, &module.properties) +} + +func (fg *fileGroup) DepsMutator(ctx android.BottomUpMutatorContext) { + android.ExtractSourcesDeps(ctx, fg.properties.Srcs) +} + +func (fg *fileGroup) GenerateAndroidBuildActions(ctx android.ModuleContext) { + fg.srcs = ctx.ExpandSources(fg.properties.Srcs, fg.properties.Exclude_srcs) +} + +func (fg *fileGroup) Srcs() android.Paths { + return fg.srcs +} diff --git a/genrule/genrule.go b/genrule/genrule.go index bb78b1f81..5a2ac845a 100644 --- a/genrule/genrule.go +++ b/genrule/genrule.go @@ -96,6 +96,10 @@ func (g *generator) GeneratedSourceFiles() android.Paths { return g.outputFiles } +func (g *generator) Srcs() android.Paths { + return g.outputFiles +} + func (g *generator) GeneratedHeaderDirs() android.Paths { return g.exportedIncludeDirs }