diff options
34 files changed, 583 insertions, 491 deletions
diff --git a/Android.bp b/Android.bp index 4db98f851..614e71fdb 100644 --- a/Android.bp +++ b/Android.bp @@ -78,10 +78,12 @@ bootstrap_go_package { "android/env.go", ], testSrcs: [ + "android/android_test.go", "android/arch_test.go", "android/config_test.go", "android/expand_test.go", "android/module_test.go", + "android/mutator_test.go", "android/namespace_test.go", "android/neverallow_test.go", "android/onceper_test.go", diff --git a/android/android_test.go b/android/android_test.go new file mode 100644 index 000000000..46b705468 --- /dev/null +++ b/android/android_test.go @@ -0,0 +1,46 @@ +// Copyright 2019 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 ( + "io/ioutil" + "os" + "testing" +) + +var buildDir string + +func setUp() { + var err error + buildDir, err = ioutil.TempDir("", "soong_android_test") + if err != nil { + panic(err) + } +} + +func tearDown() { + os.RemoveAll(buildDir) +} + +func TestMain(m *testing.M) { + run := func() int { + setUp() + defer tearDown() + + return m.Run() + } + + os.Exit(run()) +} diff --git a/android/defaults.go b/android/defaults.go index d4fbf487d..844b4d408 100644 --- a/android/defaults.go +++ b/android/defaults.go @@ -80,6 +80,9 @@ func (d *DefaultsModuleBase) properties() []interface{} { return d.defaultableProperties } +func (d *DefaultsModuleBase) GenerateAndroidBuildActions(ctx ModuleContext) { +} + func InitDefaultsModule(module DefaultableModule) { module.AddProperties( &hostAndDeviceProperties{}, diff --git a/android/defaults_test.go b/android/defaults_test.go new file mode 100644 index 000000000..fa2659563 --- /dev/null +++ b/android/defaults_test.go @@ -0,0 +1,116 @@ +// Copyright 2019 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 ( + "testing" + + "github.com/google/blueprint/proptools" +) + +type defaultsTestProperties struct { + Foo []string +} + +type defaultsTestModule struct { + ModuleBase + DefaultableModuleBase + properties defaultsTestProperties +} + +func (d *defaultsTestModule) GenerateAndroidBuildActions(ctx ModuleContext) { + ctx.Build(pctx, BuildParams{ + Rule: Touch, + Output: PathForModuleOut(ctx, "out"), + }) +} + +func defaultsTestModuleFactory() Module { + module := &defaultsTestModule{} + module.AddProperties(&module.properties) + InitDefaultableModule(module) + InitAndroidModule(module) + return module +} + +type defaultsTestDefaults struct { + ModuleBase + DefaultsModuleBase +} + +func defaultsTestDefaultsFactory() Module { + defaults := &defaultsTestDefaults{} + defaults.AddProperties(&defaultsTestProperties{}) + InitDefaultsModule(defaults) + return defaults +} + +func TestDefaultsAllowMissingDependencies(t *testing.T) { + config := TestConfig(buildDir, nil) + config.TestProductVariables.Allow_missing_dependencies = proptools.BoolPtr(true) + + ctx := NewTestContext() + ctx.SetAllowMissingDependencies(true) + + ctx.RegisterModuleType("test", ModuleFactoryAdaptor(defaultsTestModuleFactory)) + ctx.RegisterModuleType("defaults", ModuleFactoryAdaptor(defaultsTestDefaultsFactory)) + + ctx.PreArchMutators(RegisterDefaultsPreArchMutators) + + ctx.Register() + + bp := ` + defaults { + name: "defaults", + defaults: ["missing"], + foo: ["defaults"], + } + + test { + name: "missing_defaults", + defaults: ["missing"], + foo: ["module"], + } + + test { + name: "missing_transitive_defaults", + defaults: ["defaults"], + foo: ["module"], + } + ` + + ctx.MockFileSystem(map[string][]byte{ + "Android.bp": []byte(bp), + }) + + _, errs := ctx.ParseFileList(".", []string{"Android.bp"}) + FailIfErrored(t, errs) + _, errs = ctx.PrepareBuildActions(config) + FailIfErrored(t, errs) + + missingDefaults := ctx.ModuleForTests("missing_defaults", "").Output("out") + missingTransitiveDefaults := ctx.ModuleForTests("missing_transitive_defaults", "").Output("out") + + if missingDefaults.Rule != ErrorRule { + t.Errorf("expected missing_defaults rule to be ErrorRule, got %#v", missingDefaults.Rule) + } + + if g, w := missingDefaults.Args["error"], "module missing_defaults missing dependencies: missing\n"; g != w { + t.Errorf("want error %q, got %q", w, g) + } + + // TODO: missing transitive defaults is currently not handled + _ = missingTransitiveDefaults +} diff --git a/android/module.go b/android/module.go index 88eba87db..87e2ca7d9 100644 --- a/android/module.go +++ b/android/module.go @@ -56,14 +56,40 @@ type BuildParams struct { type ModuleBuildParams BuildParams // BaseModuleContext is the same as blueprint.BaseModuleContext except that Config() returns -// a Config instead of an interface{}, plus some extra methods that return Android-specific information +// a Config instead of an interface{}, and some methods have been wrapped to use an android.Module +// instead of a blueprint.Module, plus some extra methods that return Android-specific information // about the current module. type BaseModuleContext interface { + Module() Module ModuleName() string ModuleDir() string ModuleType() string Config() Config + OtherModuleName(m blueprint.Module) string + OtherModuleDir(m blueprint.Module) string + OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{}) + OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag + OtherModuleExists(name string) bool + + GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module + GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module + GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag) + + VisitDirectDepsBlueprint(visit func(blueprint.Module)) + VisitDirectDeps(visit func(Module)) + VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) + VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) + // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module + VisitDepsDepthFirst(visit func(Module)) + // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module + VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module)) + WalkDeps(visit func(Module, Module) bool) + WalkDepsBlueprint(visit func(blueprint.Module, blueprint.Module) bool) + // GetWalkPath is supposed to be called in visit function passed in WalkDeps() + // and returns a top-down dependency path from a start module to current child module. + GetWalkPath() []Module + ContainsProperty(name string) bool Errorf(pos scanner.Position, fmt string, args ...interface{}) ModuleErrorf(fmt string, args ...interface{}) @@ -76,9 +102,14 @@ type BaseModuleContext interface { // file that does not match the pattern is added to a searched directory. GlobWithDeps(pattern string, excludes []string) ([]string, error) + Glob(globPattern string, excludes []string) Paths + GlobFiles(globPattern string, excludes []string) Paths + Fs() pathtools.FileSystem AddNinjaFileDeps(deps ...string) + AddMissingDependencies(missingDeps []string) + Target() Target TargetPrimary() bool MultiTargets() []Target @@ -114,8 +145,6 @@ type ModuleContext interface { ExpandSources(srcFiles, excludes []string) Paths ExpandSource(srcFile, prop string) Path ExpandOptionalSource(srcFile *string, prop string) OptionalPath - Glob(globPattern string, excludes []string) Paths - GlobFiles(globPattern string, excludes []string) Paths InstallExecutable(installPath OutputPath, name string, srcPath Path, deps ...Path) OutputPath InstallFile(installPath OutputPath, name string, srcPath Path, deps ...Path) OutputPath @@ -123,8 +152,6 @@ type ModuleContext interface { InstallAbsoluteSymlink(installPath OutputPath, name string, absPath string) OutputPath CheckbuildFile(srcPath Path) - AddMissingDependencies(deps []string) - InstallInData() bool InstallInSanitizerDir() bool InstallInRecovery() bool @@ -133,30 +160,8 @@ type ModuleContext interface { HostRequiredModuleNames() []string TargetRequiredModuleNames() []string - // android.ModuleContext methods - // These are duplicated instead of embedded so that can eventually be wrapped to take an - // android.Module instead of a blueprint.Module - OtherModuleName(m blueprint.Module) string - OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{}) - OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag - - GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module - GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module - GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag) - ModuleSubDir() string - VisitDirectDepsBlueprint(visit func(blueprint.Module)) - VisitDirectDeps(visit func(Module)) - VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) - VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) - // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module - VisitDepsDepthFirst(visit func(Module)) - // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module - VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module)) - WalkDeps(visit func(Module, Module) bool) - WalkDepsBlueprint(visit func(blueprint.Module, blueprint.Module) bool) - Variable(pctx PackageContext, name, value string) Rule(pctx PackageContext, name string, params blueprint.RuleParams, argNames ...string) blueprint.Rule // Similar to blueprint.ModuleContext.Build, but takes Paths instead of []string, @@ -338,6 +343,8 @@ type commonProperties struct { SkipInstall bool `blueprint:"mutated"` NamespaceExportedToMake bool `blueprint:"mutated"` + + MissingDeps []string `blueprint:"mutated"` } type hostAndDeviceProperties struct { @@ -837,14 +844,22 @@ func (m *ModuleBase) baseModuleContextFactory(ctx blueprint.BaseModuleContext) b func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) { ctx := &moduleContext{ module: m.module, - ModuleContext: blueprintCtx, + bp: blueprintCtx, baseModuleContext: m.baseModuleContextFactory(blueprintCtx), installDeps: m.computeInstallDeps(blueprintCtx), installFiles: m.installFiles, - missingDeps: blueprintCtx.GetMissingDependencies(), variables: make(map[string]string), } + // Temporarily continue to call blueprintCtx.GetMissingDependencies() to maintain the previous behavior of never + // reporting missing dependency errors in Blueprint when AllowMissingDependencies == true. + // TODO: This will be removed once defaults modules handle missing dependency errors + blueprintCtx.GetMissingDependencies() + + // For the final GenerateAndroidBuildActions pass, require that all visited dependencies Soong modules and + // are enabled. + ctx.baseModuleContext.strictVisitDeps = true + if ctx.config.captureBuild { ctx.ruleParams = make(map[blueprint.Rule]blueprint.RuleParams) } @@ -901,6 +916,12 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) noticePath := filepath.Join(ctx.ModuleDir(), notice) m.noticeFile = ExistentPathForSource(ctx, noticePath) } + } else if ctx.Config().AllowMissingDependencies() { + // If the module is not enabled it will not create any build rules, nothing will call + // ctx.GetMissingDependencies(), and blueprint will consider the missing dependencies to be unhandled + // and report them as an error even when AllowMissingDependencies = true. Call + // ctx.GetMissingDependencies() here to tell blueprint not to handle them. + ctx.GetMissingDependencies() } if m == ctx.FinalModule().(Module).base() { @@ -923,15 +944,18 @@ type baseModuleContext struct { debug bool kind moduleKind config Config + + walkPath []Module + + strictVisitDeps bool // If true, enforce that all dependencies are enabled } type moduleContext struct { - blueprint.ModuleContext + bp blueprint.ModuleContext baseModuleContext installDeps Paths installFiles Paths checkbuildFiles Paths - missingDeps []string module Module // For tests @@ -940,21 +964,18 @@ type moduleContext struct { variables map[string]string } -func (m *moduleContext) ninjaError(desc string, outputs []string, err error) { - m.ModuleContext.Build(pctx.PackageContext, blueprint.BuildParams{ - Rule: ErrorRule, - Description: desc, - Outputs: outputs, - Optional: true, +func (m *moduleContext) ninjaError(params BuildParams, err error) (PackageContext, BuildParams) { + return pctx, BuildParams{ + Rule: ErrorRule, + Description: params.Description, + Output: params.Output, + Outputs: params.Outputs, + ImplicitOutput: params.ImplicitOutput, + ImplicitOutputs: params.ImplicitOutputs, Args: map[string]string{ "error": err.Error(), }, - }) - return -} - -func (m *moduleContext) Config() Config { - return m.ModuleContext.Config().(Config) + } } func (m *moduleContext) ModuleBuild(pctx PackageContext, params ModuleBuildParams) { @@ -1006,13 +1027,13 @@ func (m *moduleContext) Variable(pctx PackageContext, name, value string) { m.variables[name] = value } - m.ModuleContext.Variable(pctx.PackageContext, name, value) + m.bp.Variable(pctx.PackageContext, name, value) } func (m *moduleContext) Rule(pctx PackageContext, name string, params blueprint.RuleParams, argNames ...string) blueprint.Rule { - rule := m.ModuleContext.Rule(pctx.PackageContext, name, params, argNames...) + rule := m.bp.Rule(pctx.PackageContext, name, params, argNames...) if m.config.captureBuild { m.ruleParams[rule] = params @@ -1022,65 +1043,79 @@ func (m *moduleContext) Rule(pctx PackageContext, name string, params blueprint. } func (m *moduleContext) Build(pctx PackageContext, params BuildParams) { - if m.config.captureBuild { - m.buildParams = append(m.buildParams, params) + if params.Description != "" { + params.Description = "${moduleDesc}" + params.Description + "${moduleDescSuffix}" } - bparams := convertBuildParams(params) - - if bparams.Description != "" { - bparams.Description = "${moduleDesc}" + params.Description + "${moduleDescSuffix}" + if missingDeps := m.GetMissingDependencies(); len(missingDeps) > 0 { + pctx, params = m.ninjaError(params, fmt.Errorf("module %s missing dependencies: %s\n", + m.ModuleName(), strings.Join(missingDeps, ", "))) } - if m.missingDeps != nil { - m.ninjaError(bparams.Description, bparams.Outputs, - fmt.Errorf("module %s missing dependencies: %s\n", - m.ModuleName(), strings.Join(m.missingDeps, ", "))) - return + if m.config.captureBuild { + m.buildParams = append(m.buildParams, params) } - m.ModuleContext.Build(pctx.PackageContext, bparams) + m.bp.Build(pctx.PackageContext, convertBuildParams(params)) +} + +func (b *baseModuleContext) Module() Module { + module, _ := b.BaseModuleContext.Module().(Module) + return module +} + +func (b *baseModuleContext) Config() Config { + return b.BaseModuleContext.Config().(Config) } func (m *moduleContext) GetMissingDependencies() []string { - return m.missingDeps + var missingDeps []string + missingDeps = append(missingDeps, m.Module().base().commonProperties.MissingDeps...) + missingDeps = append(missingDeps, m.bp.GetMissingDependencies()...) + missingDeps = FirstUniqueStrings(missingDeps) + return missingDeps } -func (m *moduleContext) AddMissingDependencies(deps []string) { +func (b *baseModuleContext) AddMissingDependencies(deps []string) { if deps != nil { - m.missingDeps = append(m.missingDeps, deps...) - m.missingDeps = FirstUniqueStrings(m.missingDeps) + missingDeps := &b.Module().base().commonProperties.MissingDeps + *missingDeps = append(*missingDeps, deps...) + *missingDeps = FirstUniqueStrings(*missingDeps) } } -func (m *moduleContext) validateAndroidModule(module blueprint.Module) Module { +func (b *baseModuleContext) validateAndroidModule(module blueprint.Module, strict bool) Module { aModule, _ := module.(Module) + + if !strict { + return aModule + } + if aModule == nil { - m.ModuleErrorf("module %q not an android module", m.OtherModuleName(aModule)) + b.ModuleErrorf("module %q not an android module", b.OtherModuleName(module)) return nil } if !aModule.Enabled() { - if m.Config().AllowMissingDependencies() { - m.AddMissingDependencies([]string{m.OtherModuleName(aModule)}) + if b.Config().AllowMissingDependencies() { + b.AddMissingDependencies([]string{b.OtherModuleName(aModule)}) } else { - m.ModuleErrorf("depends on disabled module %q", m.OtherModuleName(aModule)) + b.ModuleErrorf("depends on disabled module %q", b.OtherModuleName(aModule)) } return nil } - return aModule } -func (m *moduleContext) getDirectDepInternal(name string, tag blueprint.DependencyTag) (blueprint.Module, blueprint.DependencyTag) { +func (b *baseModuleContext) getDirectDepInternal(name string, tag blueprint.DependencyTag) (blueprint.Module, blueprint.DependencyTag) { type dep struct { mod blueprint.Module tag blueprint.DependencyTag } var deps []dep - m.VisitDirectDepsBlueprint(func(module blueprint.Module) { + b.VisitDirectDepsBlueprint(func(module blueprint.Module) { if aModule, _ := module.(Module); aModule != nil && aModule.base().BaseModuleName() == name { - returnedTag := m.ModuleContext.OtherModuleDependencyTag(aModule) + returnedTag := b.BaseModuleContext.OtherModuleDependencyTag(aModule) if tag == nil || returnedTag == tag { deps = append(deps, dep{aModule, returnedTag}) } @@ -1090,17 +1125,17 @@ func (m *moduleContext) getDirectDepInternal(name string, tag blueprint.Dependen return deps[0].mod, deps[0].tag } else if len(deps) >= 2 { panic(fmt.Errorf("Multiple dependencies having same BaseModuleName() %q found from %q", - name, m.ModuleName())) + name, b.ModuleName())) } else { return nil, nil } } -func (m *moduleContext) GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module { +func (b *baseModuleContext) GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module { var deps []Module - m.VisitDirectDepsBlueprint(func(module blueprint.Module) { + b.VisitDirectDepsBlueprint(func(module blueprint.Module) { if aModule, _ := module.(Module); aModule != nil { - if m.ModuleContext.OtherModuleDependencyTag(aModule) == tag { + if b.BaseModuleContext.OtherModuleDependencyTag(aModule) == tag { deps = append(deps, aModule) } } @@ -1113,37 +1148,37 @@ func (m *moduleContext) GetDirectDepWithTag(name string, tag blueprint.Dependenc return module } -func (m *moduleContext) GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag) { - return m.getDirectDepInternal(name, nil) +func (b *baseModuleContext) GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag) { + return b.getDirectDepInternal(name, nil) } -func (m *moduleContext) VisitDirectDepsBlueprint(visit func(blueprint.Module)) { - m.ModuleContext.VisitDirectDeps(visit) +func (b *baseModuleContext) VisitDirectDepsBlueprint(visit func(blueprint.Module)) { + b.BaseModuleContext.VisitDirectDeps(visit) } -func (m *moduleContext) VisitDirectDeps(visit func(Module)) { - m.ModuleContext.VisitDirectDeps(func(module blueprint.Module) { - if aModule := m.validateAndroidModule(module); aModule != nil { +func (b *baseModuleContext) VisitDirectDeps(visit func(Module)) { + b.BaseModuleContext.VisitDirectDeps(func(module blueprint.Module) { + if aModule := b.validateAndroidModule(module, b.strictVisitDeps); aModule != nil { visit(aModule) } }) } -func (m *moduleContext) VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) { - m.ModuleContext.VisitDirectDeps(func(module blueprint.Module) { - if aModule := m.validateAndroidModule(module); aModule != nil { - if m.ModuleContext.OtherModuleDependencyTag(aModule) == tag { +func (b *baseModuleContext) VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) { + b.BaseModuleContext.VisitDirectDeps(func(module blueprint.Module) { + if aModule := b.validateAndroidModule(module, b.strictVisitDeps); aModule != nil { + if b.BaseModuleContext.OtherModuleDependencyTag(aModule) == tag { visit(aModule) } } }) } -func (m *moduleContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) { - m.ModuleContext.VisitDirectDepsIf( +func (b *baseModuleContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) { + b.BaseModuleContext.VisitDirectDepsIf( // pred func(module blueprint.Module) bool { - if aModule := m.validateAndroidModule(module); aModule != nil { + if aModule := b.validateAndroidModule(module, b.strictVisitDeps); aModule != nil { return pred(aModule) } else { return false @@ -1155,19 +1190,19 @@ func (m *moduleContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Mod }) } -func (m *moduleContext) VisitDepsDepthFirst(visit func(Module)) { - m.ModuleContext.VisitDepsDepthFirst(func(module blueprint.Module) { - if aModule := m.validateAndroidModule(module); aModule != nil { +func (b *baseModuleContext) VisitDepsDepthFirst(visit func(Module)) { + b.BaseModuleContext.VisitDepsDepthFirst(func(module blueprint.Module) { + if aModule := b.validateAndroidModule(module, b.strictVisitDeps); aModule != nil { visit(aModule) } }) } -func (m *moduleContext) VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module)) { - m.ModuleContext.VisitDepsDepthFirstIf( +func (b *baseModuleContext) VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module)) { + b.BaseModuleContext.VisitDepsDepthFirstIf( // pred func(module blueprint.Module) bool { - if aModule := m.validateAndroidModule(module); aModule != nil { + if aModule := b.validateAndroidModule(module, b.strictVisitDeps); aModule != nil { return pred(aModule) } else { return false @@ -1179,15 +1214,21 @@ func (m *moduleContext) VisitDepsDepthFirstIf(pred func(Module) bool, visit func }) } -func (m *moduleContext) WalkDepsBlueprint(visit func(blueprint.Module, blueprint.Module) bool) { - m.ModuleContext.WalkDeps(visit) +func (b *baseModuleContext) WalkDepsBlueprint(visit func(blueprint.Module, blueprint.Module) bool) { + b.BaseModuleContext.WalkDeps(visit) } -func (m *moduleContext) WalkDeps(visit func(Module, Module) bool) { - m.ModuleContext.WalkDeps(func(child, parent blueprint.Module) bool { - childAndroidModule := m.validateAndroidModule(child) - parentAndroidModule := m.validateAndroidModule(parent) +func (b *baseModuleContext) WalkDeps(visit func(Module, Module) bool) { + b.walkPath = []Module{b.Module()} + b.BaseModuleContext.WalkDeps(func(child, parent blueprint.Module) bool { + childAndroidModule, _ := child.(Module) + parentAndroidModule, _ := parent.(Module) if childAndroidModule != nil && parentAndroidModule != nil { + // record walkPath before visit + for b.walkPath[len(b.walkPath)-1] != parentAndroidModule { + b.walkPath = b.walkPath[0 : len(b.walkPath)-1] + } + b.walkPath = append(b.walkPath, childAndroidModule) return visit(childAndroidModule, parentAndroidModule) } else { return false @@ -1195,18 +1236,26 @@ func (m *moduleContext) WalkDeps(visit func(Module, Module) bool) { }) } +func (b *baseModuleContext) GetWalkPath() []Module { + return b.walkPath +} + func (m *moduleContext) VisitAllModuleVariants(visit func(Module)) { - m.ModuleContext.VisitAllModuleVariants(func(module blueprint.Module) { + m.bp.VisitAllModuleVariants(func(module blueprint.Module) { visit(module.(Module)) }) } func (m *moduleContext) PrimaryModule() Module { - return m.ModuleContext.PrimaryModule().(Module) + return m.bp.PrimaryModule().(Module) } func (m *moduleContext) FinalModule() Module { - return m.ModuleContext.FinalModule().(Module) + return m.bp.FinalModule().(Module) +} + +func (m *moduleContext) ModuleSubDir() string { + return m.bp.ModuleSubDir() } func (b *baseModuleContext) Target() Target { @@ -1584,20 +1633,20 @@ func (m *moduleContext) TargetRequiredModuleNames() []string { return m.module.base().commonProperties.Target_required } -func (m *moduleContext) Glob(globPattern string, excludes []string) Paths { - ret, err := m.GlobWithDeps(globPattern, excludes) +func (b *baseModuleContext) Glob(globPattern string, excludes []string) Paths { + ret, err := b.GlobWithDeps(globPattern, excludes) if err != nil { - m.ModuleErrorf("glob: %s", err.Error()) + b.ModuleErrorf("glob: %s", err.Error()) } - return pathsForModuleSrcFromFullPath(m, ret, true) + return pathsForModuleSrcFromFullPath(b, ret, true) } -func (m *moduleContext) GlobFiles(globPattern string, excludes []string) Paths { - ret, err := m.GlobWithDeps(globPattern, excludes) +func (b *baseModuleContext) GlobFiles(globPattern string, excludes []string) Paths { + ret, err := b.GlobWithDeps(globPattern, excludes) if err != nil { - m.ModuleErrorf("glob: %s", err.Error()) + b.ModuleErrorf("glob: %s", err.Error()) } - return pathsForModuleSrcFromFullPath(m, ret, false) + return pathsForModuleSrcFromFullPath(b, ret, false) } func init() { diff --git a/android/mutator.go b/android/mutator.go index cd0d152db..081c2b248 100644 --- a/android/mutator.go +++ b/android/mutator.go @@ -115,35 +115,14 @@ type TopDownMutator func(TopDownMutatorContext) type TopDownMutatorContext interface { BaseModuleContext - OtherModuleExists(name string) bool Rename(name string) - Module() Module - - OtherModuleName(m blueprint.Module) string - OtherModuleDir(m blueprint.Module) string - OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{}) - OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag CreateModule(blueprint.ModuleFactory, ...interface{}) - - GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module - GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag) - - VisitDirectDeps(visit func(Module)) - VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) - VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) - VisitDepsDepthFirst(visit func(Module)) - VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module)) - WalkDeps(visit func(Module, Module) bool) - // GetWalkPath is supposed to be called in visit function passed in WalkDeps() - // and returns a top-down dependency path from a start module to current child module. - GetWalkPath() []Module } type topDownMutatorContext struct { - blueprint.TopDownMutatorContext + bp blueprint.TopDownMutatorContext baseModuleContext - walkPath []Module } type BottomUpMutator func(BottomUpMutatorContext) @@ -151,9 +130,7 @@ type BottomUpMutator func(BottomUpMutatorContext) type BottomUpMutatorContext interface { BaseModuleContext - OtherModuleExists(name string) bool Rename(name string) - Module() blueprint.Module AddDependency(module blueprint.Module, tag blueprint.DependencyTag, name ...string) AddReverseDependency(module blueprint.Module, tag blueprint.DependencyTag, name string) @@ -167,7 +144,7 @@ type BottomUpMutatorContext interface { } type bottomUpMutatorContext struct { - blueprint.BottomUpMutatorContext + bp blueprint.BottomUpMutatorContext baseModuleContext } @@ -175,8 +152,8 @@ func (x *registerMutatorsContext) BottomUp(name string, m BottomUpMutator) Mutat f := func(ctx blueprint.BottomUpMutatorContext) { if a, ok := ctx.Module().(Module); ok { actx := &bottomUpMutatorContext{ - BottomUpMutatorContext: ctx, - baseModuleContext: a.base().baseModuleContextFactory(ctx), + bp: ctx, + baseModuleContext: a.base().baseModuleContextFactory(ctx), } m(actx) } @@ -190,8 +167,8 @@ func (x *registerMutatorsContext) TopDown(name string, m TopDownMutator) Mutator f := func(ctx blueprint.TopDownMutatorContext) { if a, ok := ctx.Module().(Module); ok { actx := &topDownMutatorContext{ - TopDownMutatorContext: ctx, - baseModuleContext: a.base().baseModuleContextFactory(ctx), + bp: ctx, + baseModuleContext: a.base().baseModuleContextFactory(ctx), } m(actx) } @@ -216,99 +193,6 @@ func depsMutator(ctx BottomUpMutatorContext) { } } -func (t *topDownMutatorContext) Config() Config { - return t.config -} - -func (b *bottomUpMutatorContext) Config() Config { - return b.config -} - -func (t *topDownMutatorContext) Module() Module { - module, _ := t.TopDownMutatorContext.Module().(Module) - return module -} - -func (t *topDownMutatorContext) VisitDirectDeps(visit func(Module)) { - t.TopDownMutatorContext.VisitDirectDeps(func(module blueprint.Module) { - if aModule, _ := module.(Module); aModule != nil { - visit(aModule) - } - }) -} - -func (t *topDownMutatorContext) VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) { - t.TopDownMutatorContext.VisitDirectDeps(func(module blueprint.Module) { - if aModule, _ := module.(Module); aModule != nil { - if t.TopDownMutatorContext.OtherModuleDependencyTag(aModule) == tag { - visit(aModule) - } - } - }) -} - -func (t *topDownMutatorContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) { - t.TopDownMutatorContext.VisitDirectDepsIf( - // pred - func(module blueprint.Module) bool { - if aModule, _ := module.(Module); aModule != nil { - return pred(aModule) - } else { - return false - } - }, - // visit - func(module blueprint.Module) { - visit(module.(Module)) - }) -} - -func (t *topDownMutatorContext) VisitDepsDepthFirst(visit func(Module)) { - t.TopDownMutatorContext.VisitDepsDepthFirst(func(module blueprint.Module) { - if aModule, _ := module.(Module); aModule != nil { - visit(aModule) - } - }) -} - -func (t *topDownMutatorContext) VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module)) { - t.TopDownMutatorContext.VisitDepsDepthFirstIf( - // pred - func(module blueprint.Module) bool { - if aModule, _ := module.(Module); aModule != nil { - return pred(aModule) - } else { - return false - } - }, - // visit - func(module blueprint.Module) { - visit(module.(Module)) - }) -} - -func (t *topDownMutatorContext) WalkDeps(visit func(Module, Module) bool) { - t.walkPath = []Module{t.Module()} - t.TopDownMutatorContext.WalkDeps(func(child, parent blueprint.Module) bool { - childAndroidModule, _ := child.(Module) - parentAndroidModule, _ := parent.(Module) - if childAndroidModule != nil && parentAndroidModule != nil { - // record walkPath before visit - for t.walkPath[len(t.walkPath)-1] != parentAndroidModule { - t.walkPath = t.walkPath[0 : len(t.walkPath)-1] - } - t.walkPath = append(t.walkPath, childAndroidModule) - return visit(childAndroidModule, parentAndroidModule) - } else { - return false - } - }) -} - -func (t *topDownMutatorContext) GetWalkPath() []Module { - return t.walkPath -} - func (t *topDownMutatorContext) AppendProperties(props ...interface{}) { for _, p := range props { err := proptools.AppendMatchingProperties(t.Module().base().customizableProperties, @@ -336,3 +220,61 @@ func (t *topDownMutatorContext) PrependProperties(props ...interface{}) { } } } + +// android.topDownMutatorContext either has to embed blueprint.TopDownMutatorContext, in which case every method that +// has an overridden version in android.BaseModuleContext has to be manually forwarded to BaseModuleContext to avoid +// ambiguous method errors, or it has to store a blueprint.TopDownMutatorContext non-embedded, in which case every +// non-overridden method has to be forwarded. There are fewer non-overridden methods, so use the latter. The following +// methods forward to the identical blueprint versions for topDownMutatorContext and bottomUpMutatorContext. + +func (t *topDownMutatorContext) Rename(name string) { + t.bp.Rename(name) +} + +func (t *topDownMutatorContext) CreateModule(factory blueprint.ModuleFactory, props ...interface{}) { + t.bp.CreateModule(factory, props...) +} + +func (b *bottomUpMutatorContext) Rename(name string) { + b.bp.Rename(name) +} + +func (b *bottomUpMutatorContext) AddDependency(module blueprint.Module, tag blueprint.DependencyTag, name ...string) { + b.bp.AddDependency(module, tag, name...) +} + +func (b *bottomUpMutatorContext) AddReverseDependency(module blueprint.Module, tag blueprint.DependencyTag, name string) { + b.bp.AddReverseDependency(module, tag, name) +} + +func (b *bottomUpMutatorContext) CreateVariations(variations ...string) []blueprint.Module { + return b.bp.CreateVariations(variations...) +} + +func (b *bottomUpMutatorContext) CreateLocalVariations(variations ...string) []blueprint.Module { + return b.bp.CreateLocalVariations(variations...) +} + +func (b *bottomUpMutatorContext) SetDependencyVariation(variation string) { + b.bp.SetDependencyVariation(variation) +} + +func (b *bottomUpMutatorContext) AddVariationDependencies(variations []blueprint.Variation, tag blueprint.DependencyTag, + names ...string) { + + b.bp.AddVariationDependencies(variations, tag, names...) +} + +func (b *bottomUpMutatorContext) AddFarVariationDependencies(variations []blueprint.Variation, + tag blueprint.DependencyTag, names ...string) { + + b.bp.AddFarVariationDependencies(variations, tag, names...) +} + +func (b *bottomUpMutatorContext) AddInterVariantDependency(tag blueprint.DependencyTag, from, to blueprint.Module) { + b.bp.AddInterVariantDependency(tag, from, to) +} + +func (b *bottomUpMutatorContext) ReplaceDependencies(name string) { + b.bp.ReplaceDependencies(name) +} diff --git a/android/mutator_test.go b/android/mutator_test.go new file mode 100644 index 000000000..4cef40006 --- /dev/null +++ b/android/mutator_test.go @@ -0,0 +1,99 @@ +// Copyright 2015 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 ( + "io/ioutil" + "os" + "reflect" + "testing" + + "github.com/google/blueprint/proptools" +) + +type mutatorTestModule struct { + ModuleBase + props struct { + } + + missingDeps []string +} + +func mutatorTestModuleFactory() Module { + module := &mutatorTestModule{} + module.AddProperties(&module.props) + InitAndroidModule(module) + return module +} + +func (m *mutatorTestModule) GenerateAndroidBuildActions(ctx ModuleContext) { + ctx.Build(pctx, BuildParams{ + Rule: Touch, + Output: PathForModuleOut(ctx, "output"), + }) + + m.missingDeps = ctx.GetMissingDependencies() +} + +func (m *mutatorTestModule) DepsMutator(ctx BottomUpMutatorContext) { + ctx.AddDependency(ctx.Module(), nil, "regular_missing_dep") +} + +func addMissingDependenciesMutator(ctx TopDownMutatorContext) { + ctx.AddMissingDependencies([]string{"added_missing_dep"}) +} + +func TestMutatorAddMissingDependencies(t *testing.T) { + buildDir, err := ioutil.TempDir("", "soong_mutator_test") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(buildDir) + + config := TestConfig(buildDir, nil) + config.TestProductVariables.Allow_missing_dependencies = proptools.BoolPtr(true) + + ctx := NewTestContext() + ctx.SetAllowMissingDependencies(true) + + ctx.RegisterModuleType("test", ModuleFactoryAdaptor(mutatorTestModuleFactory)) + ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) { + ctx.TopDown("add_missing_dependencies", addMissingDependenciesMutator) + }) + + bp := ` + test { + name: "foo", + } + ` + + mockFS := map[string][]byte{ + "Android.bp": []byte(bp), + } + + ctx.MockFileSystem(mockFS) + + ctx.Register() + _, errs := ctx.ParseFileList(".", []string{"Android.bp"}) + FailIfErrored(t, errs) + _, errs = ctx.PrepareBuildActions(config) + FailIfErrored(t, errs) + + foo := ctx.ModuleForTests("foo", "").Module().(*mutatorTestModule) + + if g, w := foo.missingDeps, []string{"added_missing_dep", "regular_missing_dep"}; !reflect.DeepEqual(g, w) { + t.Errorf("want foo missing deps %q, got %q", w, g) + } +} diff --git a/android/namespace_test.go b/android/namespace_test.go index 9a791a534..51a0af225 100644 --- a/android/namespace_test.go +++ b/android/namespace_test.go @@ -16,8 +16,6 @@ package android import ( "errors" - "io/ioutil" - "os" "path/filepath" "reflect" "testing" @@ -613,12 +611,6 @@ func mockFiles(bps map[string]string) (files map[string][]byte) { } func setupTestFromFiles(bps map[string][]byte) (ctx *TestContext, errs []error) { - buildDir, err := ioutil.TempDir("", "soong_namespace_test") - if err != nil { - return nil, []error{err} - } - defer os.RemoveAll(buildDir) - config := TestConfig(buildDir, nil) ctx = NewTestContext() diff --git a/android/neverallow_test.go b/android/neverallow_test.go index c60de217c..40ccf14a1 100644 --- a/android/neverallow_test.go +++ b/android/neverallow_test.go @@ -15,8 +15,6 @@ package android import ( - "io/ioutil" - "os" "testing" ) @@ -183,12 +181,6 @@ var neverallowTests = []struct { } func TestNeverallow(t *testing.T) { - buildDir, err := ioutil.TempDir("", "soong_neverallow_test") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(buildDir) - config := TestConfig(buildDir, nil) for _, test := range neverallowTests { diff --git a/android/paths.go b/android/paths.go index 52d22d531..20b8b823c 100644 --- a/android/paths.go +++ b/android/paths.go @@ -367,7 +367,7 @@ func expandOneSrcPath(ctx ModuleContext, s string, expandedExcludes []string) (P // each string. If incDirs is false, strip paths with a trailing '/' from the list. // It intended for use in globs that only list files that exist, so it allows '$' in // filenames. -func pathsForModuleSrcFromFullPath(ctx ModuleContext, paths []string, incDirs bool) Paths { +func pathsForModuleSrcFromFullPath(ctx BaseModuleContext, paths []string, incDirs bool) Paths { prefix := filepath.Join(ctx.Config().srcDir, ctx.ModuleDir()) + "/" if prefix == "./" { prefix = "" diff --git a/android/paths_test.go b/android/paths_test.go index 78cfbbe78..7bcfe41d1 100644 --- a/android/paths_test.go +++ b/android/paths_test.go @@ -17,8 +17,6 @@ package android import ( "errors" "fmt" - "io/ioutil" - "os" "reflect" "strings" "testing" @@ -758,6 +756,11 @@ func (p *pathForModuleSrcTestModule) GenerateAndroidBuildActions(ctx ModuleConte if !p.props.Module_handles_missing_deps { p.missingDeps = ctx.GetMissingDependencies() } + + ctx.Build(pctx, BuildParams{ + Rule: Touch, + Output: PathForModuleOut(ctx, "output"), + }) } type pathForModuleSrcOutputFileProviderModule struct { @@ -875,12 +878,6 @@ func testPathForModuleSrc(t *testing.T, buildDir string, tests []pathForModuleSr } func TestPathsForModuleSrc(t *testing.T) { - buildDir, err := ioutil.TempDir("", "soong_paths_for_module_src_test") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(buildDir) - tests := []pathForModuleSrcTestCase{ { name: "path", @@ -961,12 +958,6 @@ func TestPathsForModuleSrc(t *testing.T) { } func TestPathForModuleSrc(t *testing.T) { - buildDir, err := ioutil.TempDir("", "soong_path_for_module_src_test") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(buildDir) - tests := []pathForModuleSrcTestCase{ { name: "path", @@ -1034,12 +1025,6 @@ func TestPathForModuleSrc(t *testing.T) { } func TestPathsForModuleSrc_AllowMissingDependencies(t *testing.T) { - buildDir, err := ioutil.TempDir("", "soong_paths_for_module_src_allow_missing_dependencies_test") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(buildDir) - config := TestConfig(buildDir, nil) config.TestProductVariables.Allow_missing_dependencies = proptools.BoolPtr(true) diff --git a/android/prebuilt_etc_test.go b/android/prebuilt_etc_test.go index d977c307e..0a2c7a4f5 100644 --- a/android/prebuilt_etc_test.go +++ b/android/prebuilt_etc_test.go @@ -15,16 +15,13 @@ package android import ( - "io/ioutil" - "os" "path/filepath" "reflect" "testing" ) func testPrebuiltEtc(t *testing.T, bp string) (*TestContext, Config) { - config, buildDir := setUp(t) - defer tearDown(buildDir) + config := TestArchConfig(buildDir, nil) ctx := NewTestArchContext() ctx.RegisterModuleType("prebuilt_etc", ModuleFactoryAdaptor(PrebuiltEtcFactory)) ctx.RegisterModuleType("prebuilt_etc_host", ModuleFactoryAdaptor(PrebuiltEtcHostFactory)) @@ -51,20 +48,6 @@ func testPrebuiltEtc(t *testing.T, bp string) (*TestContext, Config) { return ctx, config } -func setUp(t *testing.T) (config Config, buildDir string) { - buildDir, err := ioutil.TempDir("", "soong_prebuilt_etc_test") - if err != nil { - t.Fatal(err) - } - - config = TestArchConfig(buildDir, nil) - return -} - -func tearDown(buildDir string) { - os.RemoveAll(buildDir) -} - func TestPrebuiltEtcVariants(t *testing.T) { ctx, _ := testPrebuiltEtc(t, ` prebuilt_etc { diff --git a/android/prebuilt_test.go b/android/prebuilt_test.go index a5b85c8c2..0a18e2c90 100644 --- a/android/prebuilt_test.go +++ b/android/prebuilt_test.go @@ -16,8 +16,6 @@ package android import ( "fmt" - "io/ioutil" - "os" "testing" "github.com/google/blueprint" @@ -127,12 +125,6 @@ var prebuiltsTests = []struct { } func TestPrebuilts(t *testing.T) { - buildDir, err := ioutil.TempDir("", "soong_prebuilt_test") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(buildDir) - config := TestConfig(buildDir, nil) for _, test := range prebuiltsTests { diff --git a/android/rule_builder.go b/android/rule_builder.go index 4a3b02233..8d7e74b7a 100644 --- a/android/rule_builder.go +++ b/android/rule_builder.go @@ -525,6 +525,15 @@ func (c *RuleBuilderCommand) Outputs(paths WritablePaths) *RuleBuilderCommand { return c } +// OutputDir adds the output directory to the command line. This is only available when used with RuleBuilder.Sbox, +// and will be the temporary output directory managed by sbox, not the final one. +func (c *RuleBuilderCommand) OutputDir() *RuleBuilderCommand { + if !c.sbox { + panic("OutputDir only valid with Sbox") + } + return c.Text("__SBOX_OUT_DIR__") +} + // DepFile adds the specified depfile path to the paths returned by RuleBuilder.DepFiles and adds it to the command // line, and causes RuleBuilder.Build file to set the depfile flag for ninja. If multiple depfiles are added to // commands in a single RuleBuilder then RuleBuilder.Build will add an extra command to merge the depfiles together. diff --git a/android/rule_builder_test.go b/android/rule_builder_test.go index df0f25640..cfbc2abee 100644 --- a/android/rule_builder_test.go +++ b/android/rule_builder_test.go @@ -16,8 +16,6 @@ package android import ( "fmt" - "io/ioutil" - "os" "path/filepath" "reflect" "strings" @@ -418,12 +416,6 @@ func testRuleBuilder_Build(ctx BuilderContext, in Path, out, outDep, outDir Writ } func TestRuleBuilder_Build(t *testing.T) { - buildDir, err := ioutil.TempDir("", "soong_test_rule_builder") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(buildDir) - bp := ` rule_builder_test { name: "foo", diff --git a/android/sh_binary_test.go b/android/sh_binary_test.go index becb35a21..c99e18c3e 100644 --- a/android/sh_binary_test.go +++ b/android/sh_binary_test.go @@ -1,19 +1,11 @@ package android import ( - "io/ioutil" - "os" "reflect" "testing" ) func testShBinary(t *testing.T, bp string) (*TestContext, Config) { - buildDir, err := ioutil.TempDir("", "soong_sh_binary_test") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(buildDir) - config := TestArchConfig(buildDir, nil) ctx := NewTestArchContext() diff --git a/android/testing.go b/android/testing.go index c0db75ecc..44bee4b7d 100644 --- a/android/testing.go +++ b/android/testing.go @@ -179,7 +179,7 @@ func buildParamsFromRule(provider testBuildProvider, rule string) TestingBuildPa func maybeBuildParamsFromDescription(provider testBuildProvider, desc string) TestingBuildParams { for _, p := range provider.BuildParamsForTests() { - if p.Description == desc { + if strings.Contains(p.Description, desc) { return newTestingBuildParams(provider, p) } } diff --git a/android/visibility_test.go b/android/visibility_test.go index 09c5b1b34..1a514955d 100644 --- a/android/visibility_test.go +++ b/android/visibility_test.go @@ -1,8 +1,6 @@ package android import ( - "io/ioutil" - "os" "testing" "github.com/google/blueprint" @@ -663,12 +661,6 @@ var visibilityTests = []struct { } func TestVisibility(t *testing.T) { - buildDir, err := ioutil.TempDir("", "soong_neverallow_test") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(buildDir) - for _, test := range visibilityTests { t.Run(test.name, func(t *testing.T) { _, errs := testVisibility(buildDir, test.fs) @@ -759,6 +751,3 @@ func defaultsFactory() Module { InitDefaultsModule(m) return m } - -func (*mockDefaults) GenerateAndroidBuildActions(ctx ModuleContext) { -} diff --git a/android/vts_config_test.go b/android/vts_config_test.go index 7d4c9b1cf..142b2f591 100644 --- a/android/vts_config_test.go +++ b/android/vts_config_test.go @@ -15,19 +15,11 @@ package android import ( - "io/ioutil" - "os" "testing" ) func testVtsConfig(test *testing.T, bpFileContents string) *TestContext { - buildDir, err := ioutil.TempDir("", "soong_vts_config_test") - if err != nil { - test.Fatal(err) - } - config := TestArchConfig(buildDir, nil) - defer func() { os.RemoveAll(buildDir) }() ctx := NewTestArchContext() ctx.RegisterModuleType("vts_config", ModuleFactoryAdaptor(VtsConfigFactory)) diff --git a/apex/apex.go b/apex/apex.go index 41a21c92c..11b433c95 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -1295,9 +1295,6 @@ type Defaults struct { android.DefaultsModuleBase } -func (*Defaults) GenerateAndroidBuildActions(ctx android.ModuleContext) { -} - func defaultsFactory() android.Module { return DefaultsFactory() } diff --git a/cc/builder.go b/cc/builder.go index 3a8afc0d8..1e1236173 100644 --- a/cc/builder.go +++ b/cc/builder.go @@ -22,7 +22,6 @@ import ( "fmt" "path/filepath" "runtime" - "strconv" "strings" "github.com/google/blueprint" @@ -93,20 +92,6 @@ var ( }, "arCmd", "arFlags") - darwinAr = pctx.AndroidStaticRule("darwinAr", - blueprint.RuleParams{ - Command: "rm -f ${out} && ${config.MacArPath} $arFlags $out $in", - CommandDeps: []string{"${config.MacArPath}"}, - }, - "arFlags") - - darwinAppendAr = pctx.AndroidStaticRule("darwinAppendAr", - blueprint.RuleParams{ - Command: "cp -f ${inAr} ${out}.tmp && ${config.MacArPath} $arFlags ${out}.tmp $in && mv ${out}.tmp ${out}", - CommandDeps: []string{"${config.MacArPath}", "${inAr}"}, - }, - "arFlags", "inAr") - darwinStrip = pctx.AndroidStaticRule("darwinStrip", blueprint.RuleParams{ Command: "${config.MacStripPath} -u -r -o $out $in", @@ -515,11 +500,6 @@ func TransformSourceToObj(ctx android.ModuleContext, subdir string, srcFiles and func TransformObjToStaticLib(ctx android.ModuleContext, objFiles android.Paths, flags builderFlags, outputFile android.ModuleOutPath, deps android.Paths) { - if ctx.Darwin() { - transformDarwinObjToStaticLib(ctx, objFiles, flags, outputFile, deps) - return - } - arCmd := "${config.ClangBin}/llvm-ar" arFlags := "crsD" if !ctx.Darwin() { @@ -542,82 +522,6 @@ func TransformObjToStaticLib(ctx android.ModuleContext, objFiles android.Paths, }) } -// Generate a rule for compiling multiple .o files to a static library (.a) on -// darwin. The darwin ar tool doesn't support @file for list files, and has a -// very small command line length limit, so we have to split the ar into multiple -// steps, each appending to the previous one. -func transformDarwinObjToStaticLib(ctx android.ModuleContext, objFiles android.Paths, - flags builderFlags, outputFile android.ModuleOutPath, deps android.Paths) { - - arFlags := "cqs" - - if len(objFiles) == 0 { - dummy := android.PathForModuleOut(ctx, "dummy"+objectExtension) - dummyAr := android.PathForModuleOut(ctx, "dummy"+staticLibraryExtension) - - ctx.Build(pctx, android.BuildParams{ - Rule: emptyFile, - Description: "empty object file", - Output: dummy, - Implicits: deps, - }) - - ctx.Build(pctx, android.BuildParams{ - Rule: darwinAr, - Description: "empty static archive", - Output: dummyAr, - Input: dummy, - Args: map[string]string{ - "arFlags": arFlags, - }, - }) - - ctx.Build(pctx, android.BuildParams{ - Rule: darwinAppendAr, - Description: "static link " + outputFile.Base(), - Output: outputFile, - Input: dummy, - Args: map[string]string{ - "arFlags": "d", - "inAr": dummyAr.String(), - }, - }) - - return - } - - // ARG_MAX on darwin is 262144, use half that to be safe - objFilesLists, err := splitListForSize(objFiles, 131072) - if err != nil { - ctx.ModuleErrorf("%s", err.Error()) - } - - var in, out android.WritablePath - for i, l := range objFilesLists { - in = out - out = outputFile - if i != len(objFilesLists)-1 { - out = android.PathForModuleOut(ctx, outputFile.Base()+strconv.Itoa(i)) - } - - build := android.BuildParams{ - Rule: darwinAr, - Description: "static link " + out.Base(), - Output: out, - Inputs: l, - Implicits: deps, - Args: map[string]string{ - "arFlags": arFlags, - }, - } - if i != 0 { - build.Rule = darwinAppendAr - build.Args["inAr"] = in.String() - } - ctx.Build(pctx, build) - } -} - // Generate a rule for compiling multiple .o files, plus static libraries, whole static libraries, // and shared libraries, to a shared library (.so) or dynamic executable func TransformObjToDynamicBinary(ctx android.ModuleContext, @@ -2060,9 +2060,6 @@ type Defaults struct { android.ApexModuleBase } -func (*Defaults) GenerateAndroidBuildActions(ctx android.ModuleContext) { -} - // cc_defaults provides a set of properties that can be inherited by other cc // modules. A module can use the properties from a cc_defaults using // `defaults: ["<:default_module_name>"]`. Properties of both modules are @@ -16,6 +16,7 @@ package cc import ( "path/filepath" + "strings" "github.com/google/blueprint" @@ -36,15 +37,6 @@ var ( CommandDeps: []string{"$lexCmd"}, }) - aidl = pctx.AndroidStaticRule("aidl", - blueprint.RuleParams{ - Command: "$aidlCmd -d${out}.d --ninja $aidlFlags $in $outDir $out", - CommandDeps: []string{"$aidlCmd"}, - Depfile: "${out}.d", - Deps: blueprint.DepsGCC, - }, - "aidlFlags", "outDir") - sysprop = pctx.AndroidStaticRule("sysprop", blueprint.RuleParams{ Command: "$syspropCmd --header-dir=$headerOutDir --system-header-dir=$systemOutDir " + @@ -114,20 +106,37 @@ func genYacc(ctx android.ModuleContext, rule *android.RuleBuilder, yaccFile andr return ret } -func genAidl(ctx android.ModuleContext, aidlFile android.Path, outFile android.ModuleGenPath, aidlFlags string) android.Paths { - ctx.Build(pctx, android.BuildParams{ - Rule: aidl, - Description: "aidl " + aidlFile.Rel(), - Output: outFile, - Input: aidlFile, - Args: map[string]string{ - "aidlFlags": aidlFlags, - "outDir": android.PathForModuleGen(ctx, "aidl").String(), - }, - }) +func genAidl(ctx android.ModuleContext, rule *android.RuleBuilder, aidlFile android.Path, + outFile, depFile android.ModuleGenPath, aidlFlags string) android.Paths { + + aidlPackage := strings.TrimSuffix(aidlFile.Rel(), aidlFile.Base()) + baseName := strings.TrimSuffix(aidlFile.Base(), aidlFile.Ext()) + shortName := strings.TrimPrefix(baseName, "I") - // TODO: This should return the generated headers, not the source file. - return android.Paths{outFile} + outDir := android.PathForModuleGen(ctx, "aidl") + headerI := outDir.Join(ctx, aidlPackage, baseName+".h") + headerBn := outDir.Join(ctx, aidlPackage, "Bn"+shortName+".h") + headerBp := outDir.Join(ctx, aidlPackage, "Bp"+shortName+".h") + + cmd := rule.Command() + cmd.Tool(ctx.Config().HostToolPath(ctx, "aidl-cpp")). + FlagWithDepFile("-d", depFile). + Flag("--ninja"). + Flag(aidlFlags). + Input(aidlFile). + OutputDir(). + Output(outFile). + ImplicitOutputs(android.WritablePaths{ + headerI, + headerBn, + headerBp, + }) + + return android.Paths{ + headerI, + headerBn, + headerBp, + } } func genLex(ctx android.ModuleContext, lexFile android.Path, outFile android.ModuleGenPath) { @@ -187,6 +196,8 @@ func genSources(ctx android.ModuleContext, srcFiles android.Paths, var deps android.Paths var rsFiles android.Paths + var aidlRule *android.RuleBuilder + var yaccRule_ *android.RuleBuilder yaccRule := func() *android.RuleBuilder { if yaccRule_ == nil { @@ -218,9 +229,13 @@ func genSources(ctx android.ModuleContext, srcFiles android.Paths, srcFiles[i] = ccFile deps = append(deps, headerFile) case ".aidl": + if aidlRule == nil { + aidlRule = android.NewRuleBuilder().Sbox(android.PathForModuleGen(ctx, "aidl")) + } cppFile := android.GenPathWithExt(ctx, "aidl", srcFile, "cpp") + depFile := android.GenPathWithExt(ctx, "aidl", srcFile, "cpp.d") srcFiles[i] = cppFile - deps = append(deps, genAidl(ctx, srcFile, cppFile, buildFlags.aidlFlags)...) + deps = append(deps, genAidl(ctx, aidlRule, srcFile, cppFile, depFile, buildFlags.aidlFlags)...) case ".rs", ".fs": cppFile := rsGeneratedCppFile(ctx, srcFile) rsFiles = append(rsFiles, srcFiles[i]) @@ -236,6 +251,10 @@ func genSources(ctx android.ModuleContext, srcFiles android.Paths, } } + if aidlRule != nil { + aidlRule.Build(pctx, ctx, "aidl", "gen aidl") + } + if yaccRule_ != nil { yaccRule_.Build(pctx, ctx, "yacc", "gen yacc") } diff --git a/cc/gen_test.go b/cc/gen_test.go index a0f7308c2..e4219d999 100644 --- a/cc/gen_test.go +++ b/cc/gen_test.go @@ -15,6 +15,7 @@ package cc import ( + "path/filepath" "testing" ) @@ -32,7 +33,7 @@ func TestGen(t *testing.T) { aidl := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_core_shared").Rule("aidl") libfoo := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_core_shared").Module().(*Module) - if !inList("-I"+aidl.Args["outDir"], libfoo.flags.GlobalFlags) { + if !inList("-I"+filepath.Dir(aidl.Output.String()), libfoo.flags.GlobalFlags) { t.Errorf("missing aidl includes in global flags") } }) @@ -55,7 +56,7 @@ func TestGen(t *testing.T) { aidl := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_core_shared").Rule("aidl") libfoo := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_core_shared").Module().(*Module) - if !inList("-I"+aidl.Args["outDir"], libfoo.flags.GlobalFlags) { + if !inList("-I"+filepath.Dir(aidl.Output.String()), libfoo.flags.GlobalFlags) { t.Errorf("missing aidl includes in global flags") } }) diff --git a/cc/genrule.go b/cc/genrule.go index decf6ea57..e594f4b2f 100644 --- a/cc/genrule.go +++ b/cc/genrule.go @@ -42,5 +42,7 @@ func genRuleFactory() android.Module { android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibBoth) + android.InitApexModule(module) + return module } diff --git a/genrule/genrule.go b/genrule/genrule.go index 87e6747e9..b0657ff14 100644 --- a/genrule/genrule.go +++ b/genrule/genrule.go @@ -101,6 +101,7 @@ type generatorProperties struct { type Module struct { android.ModuleBase android.DefaultableModuleBase + android.ApexModuleBase // For other packages to make their own genrules with extra // properties @@ -582,9 +583,6 @@ type Defaults struct { android.DefaultsModuleBase } -func (*Defaults) GenerateAndroidBuildActions(ctx android.ModuleContext) { -} - func defaultsFactory() android.Module { return DefaultsFactory() } diff --git a/java/app.go b/java/app.go index cf9354f57..78e05012c 100644 --- a/java/app.go +++ b/java/app.go @@ -938,16 +938,18 @@ type usesLibrary struct { } func (u *usesLibrary) deps(ctx android.BottomUpMutatorContext, noFrameworkLibs bool) { - ctx.AddVariationDependencies(nil, usesLibTag, u.usesLibraryProperties.Uses_libs...) - ctx.AddVariationDependencies(nil, usesLibTag, u.presentOptionalUsesLibs(ctx)...) - if !noFrameworkLibs { - // dexpreopt/dexpreopt.go needs the paths to the dex jars of these libraries in case construct_context.sh needs - // to pass them to dex2oat. Add them as a dependency so we can determine the path to the dex jar of each - // library to dexpreopt. - ctx.AddVariationDependencies(nil, usesLibTag, - "org.apache.http.legacy", - "android.hidl.base-V1.0-java", - "android.hidl.manager-V1.0-java") + if !ctx.Config().UnbundledBuild() { + ctx.AddVariationDependencies(nil, usesLibTag, u.usesLibraryProperties.Uses_libs...) + ctx.AddVariationDependencies(nil, usesLibTag, u.presentOptionalUsesLibs(ctx)...) + if !noFrameworkLibs { + // dexpreopt/dexpreopt.go needs the paths to the dex jars of these libraries in case construct_context.sh needs + // to pass them to dex2oat. Add them as a dependency so we can determine the path to the dex jar of each + // library to dexpreopt. + ctx.AddVariationDependencies(nil, usesLibTag, + "org.apache.http.legacy", + "android.hidl.base-V1.0-java", + "android.hidl.manager-V1.0-java") + } } } diff --git a/java/app_builder.go b/java/app_builder.go index fa77bbf1d..348c8b4bb 100644 --- a/java/app_builder.go +++ b/java/app_builder.go @@ -31,7 +31,7 @@ import ( var ( Signapk = pctx.AndroidStaticRule("signapk", blueprint.RuleParams{ - Command: `${config.JavaCmd} -Djava.library.path=$$(dirname $signapkJniLibrary) ` + + Command: `${config.JavaCmd} ${config.JavaVmFlags} -Djava.library.path=$$(dirname $signapkJniLibrary) ` + `-jar $signapkCmd $flags $certificates $in $out`, CommandDeps: []string{"$signapkCmd", "$signapkJniLibrary"}, }, diff --git a/java/builder.go b/java/builder.go index d257d1da1..e1a912b2f 100644 --- a/java/builder.go +++ b/java/builder.go @@ -43,7 +43,8 @@ var ( Command: `rm -rf "$outDir" "$annoDir" "$srcJarDir" && mkdir -p "$outDir" "$annoDir" "$srcJarDir" && ` + `${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` + `(if [ -s $srcJarDir/list ] || [ -s $out.rsp ] ; then ` + - `${config.SoongJavacWrapper} ${config.JavacWrapper}${config.JavacCmd} ${config.JavacHeapFlags} ${config.CommonJdkFlags} ` + + `${config.SoongJavacWrapper} ${config.JavacWrapper}${config.JavacCmd} ` + + `${config.JavacHeapFlags} ${config.JavacVmFlags} ${config.CommonJdkFlags} ` + `$processorpath $processor $javacFlags $bootClasspath $classpath ` + `-source $javaVersion -target $javaVersion ` + `-d $outDir -s $annoDir @$out.rsp @$srcJarDir/list ; fi ) && ` + @@ -64,7 +65,7 @@ var ( turbine = pctx.AndroidStaticRule("turbine", blueprint.RuleParams{ Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` + - `${config.JavaCmd} -jar ${config.TurbineJar} --output $out.tmp ` + + `${config.JavaCmd} ${config.JavaVmFlags} -jar ${config.TurbineJar} --output $out.tmp ` + `--temp_dir "$outDir" --sources @$out.rsp --source_jars $srcJars ` + `--javacopts ${config.CommonJdkFlags} ` + `$javacFlags -source $javaVersion -target $javaVersion -- $bootClasspath $classpath && ` + @@ -108,7 +109,7 @@ var ( jarjar = pctx.AndroidStaticRule("jarjar", blueprint.RuleParams{ - Command: "${config.JavaCmd} -jar ${config.JarjarCmd} process $rulesFile $in $out", + Command: "${config.JavaCmd} ${config.JavaVmFlags} -jar ${config.JarjarCmd} process $rulesFile $in $out", CommandDeps: []string{"${config.JavaCmd}", "${config.JarjarCmd}", "$rulesFile"}, }, "rulesFile") @@ -124,7 +125,7 @@ var ( jetifier = pctx.AndroidStaticRule("jetifier", blueprint.RuleParams{ - Command: "${config.JavaCmd} -jar ${config.JetifierJar} -l error -o $out -i $in", + Command: "${config.JavaCmd} ${config.JavaVmFlags} -jar ${config.JetifierJar} -l error -o $out -i $in", CommandDeps: []string{"${config.JavaCmd}", "${config.JetifierJar}"}, }, ) diff --git a/java/config/config.go b/java/config/config.go index f9552d5a1..6ade6493f 100644 --- a/java/config/config.go +++ b/java/config/config.go @@ -69,6 +69,8 @@ func init() { // b/65004097: prevent using java.lang.invoke.StringConcatFactory when using -target 1.9 `-XDstringConcat=inline`, }, " ")) + pctx.StaticVariable("JavaVmFlags", "-XX:OnError=\"cat hs_err_pid%p.log\" -XX:CICompilerCount=6 -XX:+UseDynamicNumberOfGCThreads") + pctx.StaticVariable("JavacVmFlags", "-J-XX:OnError=\"cat hs_err_pid%p.log\" -J-XX:CICompilerCount=6 -J-XX:+UseDynamicNumberOfGCThreads") pctx.VariableConfigMethod("hostPrebuiltTag", android.Config.PrebuiltOS) diff --git a/java/config/makevars.go b/java/config/makevars.go index 9c7851174..ead298acd 100644 --- a/java/config/makevars.go +++ b/java/config/makevars.go @@ -39,8 +39,8 @@ func makeVarsProvider(ctx android.MakeVarsContext) { ctx.Strict("ANDROID_JAVA8_HOME", "prebuilts/jdk/jdk8/${hostPrebuiltTag}") ctx.Strict("ANDROID_JAVA9_HOME", "prebuilts/jdk/jdk9/${hostPrebuiltTag}") ctx.Strict("ANDROID_JAVA_TOOLCHAIN", "${JavaToolchain}") - ctx.Strict("JAVA", "${JavaCmd}") - ctx.Strict("JAVAC", "${JavacCmd}") + ctx.Strict("JAVA", "${JavaCmd} ${JavaVmFlags}") + ctx.Strict("JAVAC", "${JavacCmd} ${JavacVmFlags}") ctx.Strict("JAR", "${JarCmd}") ctx.Strict("JAR_ARGS", "${JarArgsCmd}") ctx.Strict("JAVADOC", "${JavadocCmd}") @@ -58,8 +58,8 @@ func makeVarsProvider(ctx android.MakeVarsContext) { ctx.Strict("ERROR_PRONE_CHECKS", "${ErrorProneChecks}") } - ctx.Strict("TARGET_JAVAC", "${JavacCmd} ${CommonJdkFlags}") - ctx.Strict("HOST_JAVAC", "${JavacCmd} ${CommonJdkFlags}") + ctx.Strict("TARGET_JAVAC", "${JavacCmd} ${JavacVmFlags} ${CommonJdkFlags}") + ctx.Strict("HOST_JAVAC", "${JavacCmd} ${JavacVmFlags} ${CommonJdkFlags}") ctx.Strict("JLINK", "${JlinkCmd}") ctx.Strict("JMOD", "${JmodCmd}") diff --git a/java/droiddoc.go b/java/droiddoc.go index c4624d8ad..992c8b57c 100644 --- a/java/droiddoc.go +++ b/java/droiddoc.go @@ -73,7 +73,7 @@ var ( Command: `rm -rf "$outDir" "$srcJarDir" "$stubsDir" && ` + `mkdir -p "$outDir" "$srcJarDir" "$stubsDir" && ` + `${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` + - `${config.JavaCmd} -jar ${config.MetalavaJar} -encoding UTF-8 -source $javaVersion @$out.rsp @$srcJarDir/list ` + + `${config.JavaCmd} ${config.JavaVmFlags} -jar ${config.MetalavaJar} -encoding UTF-8 -source $javaVersion @$out.rsp @$srcJarDir/list ` + `$bootclasspathArgs $classpathArgs $sourcepathArgs --no-banner --color --quiet --format=v2 ` + `$opts && ` + `${config.SoongZipCmd} -write_if_changed -jar -o $out -C $stubsDir -D $stubsDir && ` + @@ -95,7 +95,7 @@ var ( blueprint.RuleParams{ Command: `( rm -rf "$srcJarDir" && mkdir -p "$srcJarDir" && ` + `${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` + - `${config.JavaCmd} -jar ${config.MetalavaJar} -encoding UTF-8 -source $javaVersion @$out.rsp @$srcJarDir/list ` + + `${config.JavaCmd} ${config.JavaVmFlags} -jar ${config.MetalavaJar} -encoding UTF-8 -source $javaVersion @$out.rsp @$srcJarDir/list ` + `$bootclasspathArgs $classpathArgs $sourcepathArgs --no-banner --color --quiet --format=v2 ` + `$opts && touch $out && rm -rf "$srcJarDir") || ` + `( echo -e "$msg" ; exit 38 )`, @@ -120,7 +120,7 @@ var ( Command: `rm -rf "$outDir" "$srcJarDir" "$stubsDir" && ` + `mkdir -p "$outDir" "$srcJarDir" "$stubsDir" && ` + `${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` + - `${config.JavaCmd} -jar ${config.DokkaJar} $srcJarDir ` + + `${config.JavaCmd} ${config.JavaVmFlags} -jar ${config.DokkaJar} $srcJarDir ` + `$classpathArgs -format dac -dacRoot /reference/kotlin -output $outDir $opts && ` + `${config.SoongZipCmd} -write_if_changed -d -o $docZip -C $outDir -D $outDir && ` + `${config.SoongZipCmd} -write_if_changed -jar -o $out -C $stubsDir -D $stubsDir && ` + @@ -1808,9 +1808,6 @@ type DocDefaults struct { android.DefaultsModuleBase } -func (*DocDefaults) GenerateAndroidBuildActions(ctx android.ModuleContext) { -} - func DocDefaultsFactory() android.Module { module := &DocDefaults{} diff --git a/java/jacoco.go b/java/jacoco.go index 8b6d4ac87..bce9822f4 100644 --- a/java/jacoco.go +++ b/java/jacoco.go @@ -31,7 +31,7 @@ var ( jacoco = pctx.AndroidStaticRule("jacoco", blueprint.RuleParams{ Command: `rm -rf $tmpDir && mkdir -p $tmpDir && ` + `${config.Zip2ZipCmd} -i $in -o $strippedJar $stripSpec && ` + - `${config.JavaCmd} -jar ${config.JacocoCLIJar} ` + + `${config.JavaCmd} ${config.JavaVmFlags} -jar ${config.JacocoCLIJar} ` + ` instrument --quiet --dest $tmpDir $strippedJar && ` + `${config.Ziptime} $tmpJar && ` + `${config.MergeZipsCmd} --ignore-duplicates -j $out $tmpJar $in`, diff --git a/java/java.go b/java/java.go index fee262d83..a1addb38c 100644 --- a/java/java.go +++ b/java/java.go @@ -2131,9 +2131,6 @@ type Defaults struct { android.DefaultsModuleBase } -func (*Defaults) GenerateAndroidBuildActions(ctx android.ModuleContext) { -} - // java_defaults provides a set of properties that can be inherited by other java or android modules. // // A module can use the properties from a java_defaults module using `defaults: ["defaults_module_name"]`. Each |