diff options
39 files changed, 1425 insertions, 466 deletions
diff --git a/android/Android.bp b/android/Android.bp index 8de0c7650..e73f35574 100644 --- a/android/Android.bp +++ b/android/Android.bp @@ -11,6 +11,7 @@ bootstrap_go_package { "blueprint-metrics", "sbox_proto", "soong", + "soong-android_team_proto", "soong-android-soongconfig", "soong-remoteexec", "soong-response", @@ -28,6 +29,7 @@ bootstrap_go_package { ], srcs: [ "aconfig_providers.go", + "all_teams.go", "androidmk.go", "apex.go", "apex_contributions.go", @@ -35,6 +37,7 @@ bootstrap_go_package { "api_levels.go", "arch.go", "arch_list.go", + "arch_module_context.go", "base_module_context.go", "buildinfo_prop.go", "config.go", @@ -91,6 +94,7 @@ bootstrap_go_package { "singleton.go", "singleton_module.go", "soong_config_modules.go", + "team.go", "test_asserts.go", "test_suites.go", "testing.go", diff --git a/android/aconfig_providers.go b/android/aconfig_providers.go index 4ba1a88f0..68fff58c1 100644 --- a/android/aconfig_providers.go +++ b/android/aconfig_providers.go @@ -49,13 +49,7 @@ func CollectDependencyAconfigFiles(ctx ModuleContext, mergedAconfigFiles *map[st if *mergedAconfigFiles == nil { *mergedAconfigFiles = make(map[string]Paths) } - ctx.VisitDirectDepsBlueprint(func(module blueprint.Module) { - // Walk our direct dependencies, ignoring blueprint Modules and disabled Android Modules. - aModule, _ := module.(Module) - if aModule == nil || !aModule.Enabled() { - return - } - + ctx.VisitDirectDepsIgnoreBlueprint(func(module Module) { if dep, _ := OtherModuleProvider(ctx, module, AconfigDeclarationsProviderKey); dep.IntermediateCacheOutputPath != nil { (*mergedAconfigFiles)[dep.Container] = append((*mergedAconfigFiles)[dep.Container], dep.IntermediateCacheOutputPath) return diff --git a/android/all_teams.go b/android/all_teams.go new file mode 100644 index 000000000..6c3a219ab --- /dev/null +++ b/android/all_teams.go @@ -0,0 +1,158 @@ +package android + +import ( + "android/soong/android/team_proto" + "path/filepath" + + "google.golang.org/protobuf/proto" +) + +const ownershipDirectory = "ownership" +const allTeamsFile = "all_teams.pb" + +func AllTeamsFactory() Singleton { + return &allTeamsSingleton{} +} + +func init() { + registerAllTeamBuildComponents(InitRegistrationContext) +} + +func registerAllTeamBuildComponents(ctx RegistrationContext) { + ctx.RegisterParallelSingletonType("all_teams", AllTeamsFactory) +} + +// For each module, list the team or the bpFile the module is defined in. +type moduleTeamInfo struct { + teamName string + bpFile string +} + +type allTeamsSingleton struct { + // Path where the collected metadata is stored after successful validation. + outputPath OutputPath + + // Map of all package modules we visit during GenerateBuildActions + packages map[string]packageProperties + // Map of all team modules we visit during GenerateBuildActions + teams map[string]teamProperties + // Keeps track of team information or bp file for each module we visit. + teams_for_mods map[string]moduleTeamInfo +} + +// See if there is a package module for the given bpFilePath with a team defined, if so return the team. +// If not ascend up to the parent directory and do the same. +func (this *allTeamsSingleton) lookupDefaultTeam(bpFilePath string) (teamProperties, bool) { + // return the Default_team listed in the package if is there. + if p, ok := this.packages[bpFilePath]; ok { + if t := p.Default_team; t != nil { + return this.teams[*p.Default_team], true + } + } + // Strip a directory and go up. + // Does android/paths.go basePath,SourcePath help? + current, base := filepath.Split(bpFilePath) + current = filepath.Clean(current) // removes trailing slash, convert "" -> "." + parent, _ := filepath.Split(current) + if current == "." { + return teamProperties{}, false + } + return this.lookupDefaultTeam(filepath.Join(parent, base)) +} + +// Create a rule to run a tool to collect all the intermediate files +// which list the team per module into one proto file. +func (this *allTeamsSingleton) GenerateBuildActions(ctx SingletonContext) { + this.packages = make(map[string]packageProperties) + this.teams = make(map[string]teamProperties) + this.teams_for_mods = make(map[string]moduleTeamInfo) + + ctx.VisitAllModules(func(module Module) { + if !module.Enabled() { + return + } + + bpFile := ctx.BlueprintFile(module) + + // Package Modules and Team Modules are stored in a map so we can look them up by name for + // modules without a team. + if pack, ok := module.(*packageModule); ok { + // Packages don't have names, use the blueprint file as the key. we can't get qualifiedModuleId in this context. + pkgKey := bpFile + this.packages[pkgKey] = pack.properties + return + } + if team, ok := module.(*teamModule); ok { + this.teams[team.Name()] = team.properties + return + } + + // If a team name is given for a module, store it. + // Otherwise store the bpFile so we can do a package walk later. + if module.base().Team() != "" { + this.teams_for_mods[module.Name()] = moduleTeamInfo{teamName: module.base().Team(), bpFile: bpFile} + } else { + this.teams_for_mods[module.Name()] = moduleTeamInfo{bpFile: bpFile} + } + }) + + // Visit all modules again and lookup the team name in the package or parent package if the team + // isn't assignged at the module level. + allTeams := this.lookupTeamForAllModules() + + this.outputPath = PathForOutput(ctx, ownershipDirectory, allTeamsFile) + data, err := proto.Marshal(allTeams) + if err != nil { + ctx.Errorf("Unable to marshal team data. %s", err) + } + + WriteFileRuleVerbatim(ctx, this.outputPath, string(data)) + ctx.Phony("all_teams", this.outputPath) +} + +func (this *allTeamsSingleton) MakeVars(ctx MakeVarsContext) { + ctx.DistForGoal("all_teams", this.outputPath) +} + +// Visit every (non-package, non-team) module and write out a proto containing +// either the declared team data for that module or the package default team data for that module. +func (this *allTeamsSingleton) lookupTeamForAllModules() *team_proto.AllTeams { + teamsProto := make([]*team_proto.Team, len(this.teams_for_mods)) + i := 0 + for moduleName, m := range this.teams_for_mods { + teamName := m.teamName + var teamProperties teamProperties + found := false + if teamName != "" { + teamProperties, found = this.teams[teamName] + } else { + teamProperties, found = this.lookupDefaultTeam(m.bpFile) + } + + trendy_team_id := "" + if found { + trendy_team_id = *teamProperties.Trendy_team_id + } + + var files []string + teamData := new(team_proto.Team) + if trendy_team_id != "" { + *teamData = team_proto.Team{ + TrendyTeamId: proto.String(trendy_team_id), + TargetName: proto.String(moduleName), + Path: proto.String(m.bpFile), + File: files, + } + } else { + // Clients rely on the TrendyTeamId optional field not being set. + *teamData = team_proto.Team{ + TargetName: proto.String(moduleName), + Path: proto.String(m.bpFile), + File: files, + } + } + teamsProto[i] = teamData + i++ + } + return &team_proto.AllTeams{Teams: teamsProto} +} diff --git a/android/all_teams_test.go b/android/all_teams_test.go new file mode 100644 index 000000000..a02b86e06 --- /dev/null +++ b/android/all_teams_test.go @@ -0,0 +1,208 @@ +// Copyright 2024 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 ( + "android/soong/android/team_proto" + "log" + "testing" + + "google.golang.org/protobuf/proto" +) + +func TestAllTeams(t *testing.T) { + t.Parallel() + ctx := GroupFixturePreparers( + PrepareForTestWithTeamBuildComponents, + FixtureRegisterWithContext(func(ctx RegistrationContext) { + ctx.RegisterModuleType("fake", fakeModuleFactory) + ctx.RegisterParallelSingletonType("all_teams", AllTeamsFactory) + }), + ).RunTestWithBp(t, ` + fake { + name: "main_test", + team: "someteam", + } + team { + name: "someteam", + trendy_team_id: "cool_team", + } + + team { + name: "team2", + trendy_team_id: "22222", + } + + fake { + name: "tool", + team: "team2", + } + + fake { + name: "noteam", + } + `) + + var teams *team_proto.AllTeams + teams = getTeamProtoOutput(t, ctx) + + // map of module name -> trendy team name. + actualTeams := make(map[string]*string) + for _, teamProto := range teams.Teams { + actualTeams[teamProto.GetTargetName()] = teamProto.TrendyTeamId + } + expectedTeams := map[string]*string{ + "main_test": proto.String("cool_team"), + "tool": proto.String("22222"), + "noteam": nil, + } + + AssertDeepEquals(t, "compare maps", expectedTeams, actualTeams) +} + +func getTeamProtoOutput(t *testing.T, ctx *TestResult) *team_proto.AllTeams { + teams := new(team_proto.AllTeams) + config := ctx.SingletonForTests("all_teams") + allOutputs := config.AllOutputs() + + protoPath := allOutputs[0] + + out := config.MaybeOutput(protoPath) + outProto := []byte(ContentFromFileRuleForTests(t, ctx.TestContext, out)) + if err := proto.Unmarshal(outProto, teams); err != nil { + log.Fatalln("Failed to parse teams proto:", err) + } + return teams +} + +// Android.bp +// +// team: team_top +// +// # dir1 has no modules with teams, +// # but has a dir with no Android.bp +// dir1/Android.bp +// +// module_dir1 +// +// # dirs without and Android.bp should be fine. +// dir1/dir2/dir3/Android.bp +// +// package {} +// module_dir123 +// +// teams_dir/Android.bp +// +// module_with_team1: team1 +// team1: 111 +// +// # team comes from upper package default +// teams_dir/deeper/Android.bp +// +// module2_with_team1: team1 +// +// package_defaults/Android.bp +// package_defaults/pd2/Android.bp +// +// package{ default_team: team_top} +// module_pd2 ## should get team_top +// +// package_defaults/pd2/pd3/Android.bp +// +// module_pd3 ## should get team_top +func TestPackageLookup(t *testing.T) { + t.Parallel() + rootBp := ` + team { + name: "team_top", + trendy_team_id: "trendy://team_top", + } ` + + dir1Bp := ` + fake { + name: "module_dir1", + } ` + dir3Bp := ` + package {} + fake { + name: "module_dir123", + } ` + teamsDirBp := ` + fake { + name: "module_with_team1", + team: "team1" + + } + team { + name: "team1", + trendy_team_id: "111", + } ` + teamsDirDeeper := ` + fake { + name: "module2_with_team1", + team: "team1" + } ` + // create an empty one. + packageDefaultsBp := "" + packageDefaultspd2 := ` + package { default_team: "team_top"} + fake { + name: "modulepd2", + } ` + + packageDefaultspd3 := ` + fake { + name: "modulepd3", + } + fake { + name: "modulepd3b", + team: "team1" + } ` + + ctx := GroupFixturePreparers( + PrepareForTestWithTeamBuildComponents, + PrepareForTestWithPackageModule, + FixtureRegisterWithContext(func(ctx RegistrationContext) { + ctx.RegisterModuleType("fake", fakeModuleFactory) + ctx.RegisterParallelSingletonType("all_teams", AllTeamsFactory) + }), + FixtureAddTextFile("Android.bp", rootBp), + FixtureAddTextFile("dir1/Android.bp", dir1Bp), + FixtureAddTextFile("dir1/dir2/dir3/Android.bp", dir3Bp), + FixtureAddTextFile("teams_dir/Android.bp", teamsDirBp), + FixtureAddTextFile("teams_dir/deeper/Android.bp", teamsDirDeeper), + FixtureAddTextFile("package_defaults/Android.bp", packageDefaultsBp), + FixtureAddTextFile("package_defaults/pd2/Android.bp", packageDefaultspd2), + FixtureAddTextFile("package_defaults/pd2/pd3/Android.bp", packageDefaultspd3), + ).RunTest(t) + + var teams *team_proto.AllTeams + teams = getTeamProtoOutput(t, ctx) + + // map of module name -> trendy team name. + actualTeams := make(map[string]*string) + for _, teamProto := range teams.Teams { + actualTeams[teamProto.GetTargetName()] = teamProto.TrendyTeamId + } + expectedTeams := map[string]*string{ + "module_with_team1": proto.String("111"), + "module2_with_team1": proto.String("111"), + "modulepd2": proto.String("trendy://team_top"), + "modulepd3": proto.String("trendy://team_top"), + "modulepd3b": proto.String("111"), + "module_dir1": nil, + "module_dir123": nil, + } + AssertDeepEquals(t, "compare maps", expectedTeams, actualTeams) +} diff --git a/android/arch_module_context.go b/android/arch_module_context.go new file mode 100644 index 000000000..3cf4b4115 --- /dev/null +++ b/android/arch_module_context.go @@ -0,0 +1,83 @@ +// Copyright 2024 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 + +// ArchModuleContext can be embedded in other contexts to provide information about the module set by +// the archMutator. +type ArchModuleContext interface { + Target() Target + TargetPrimary() bool + + // The additional arch specific targets (e.g. 32/64 bit) that this module variant is + // responsible for creating. + MultiTargets() []Target + Arch() Arch + Os() OsType + Host() bool + Device() bool + Darwin() bool + Windows() bool + PrimaryArch() bool +} + +type archModuleContext struct { + // TODO: these should eventually go through a (possibly cached) provider like any other configuration instead + // of being special cased. + os OsType + target Target + targetPrimary bool + multiTargets []Target + primaryArch bool +} + +func (a *archModuleContext) Target() Target { + return a.target +} + +func (a *archModuleContext) TargetPrimary() bool { + return a.targetPrimary +} + +func (a *archModuleContext) MultiTargets() []Target { + return a.multiTargets +} + +func (a *archModuleContext) Arch() Arch { + return a.target.Arch +} + +func (a *archModuleContext) Os() OsType { + return a.os +} + +func (a *archModuleContext) Host() bool { + return a.os.Class == Host +} + +func (a *archModuleContext) Device() bool { + return a.os.Class == Device +} + +func (a *archModuleContext) Darwin() bool { + return a.os == Darwin +} + +func (a *archModuleContext) Windows() bool { + return a.os == Windows +} + +func (b *archModuleContext) PrimaryArch() bool { + return b.primaryArch +} diff --git a/android/base_module_context.go b/android/base_module_context.go index 3dfe1234b..b9c115349 100644 --- a/android/base_module_context.go +++ b/android/base_module_context.go @@ -26,6 +26,7 @@ import ( // instead of a blueprint.Module, plus some extra methods that return Android-specific information // about the current module. type BaseModuleContext interface { + ArchModuleContext EarlyModuleContext blueprintBaseModuleContext() blueprint.BaseModuleContext @@ -105,7 +106,7 @@ type BaseModuleContext interface { // dependencies that are not an android.Module. GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module - // GetDirectDep returns the Module and DependencyTag for the direct dependency with the specified + // GetDirectDep returns the Module and DependencyTag for the direct dependency with the specified // name, or nil if none exists. If there are multiple dependencies on the same module it returns // the first DependencyTag. GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag) @@ -118,6 +119,15 @@ type BaseModuleContext interface { // function, it may be invalidated by future mutators. VisitDirectDepsBlueprint(visit func(blueprint.Module)) + // VisitDirectDepsIgnoreBlueprint calls visit for each direct dependency. If there are multiple + // direct dependencies on the same module visit will be called multiple times on that module + // and OtherModuleDependencyTag will return a different tag for each. It silently ignores any + // dependencies that are not an android.Module. + // + // The Module passed to the visit function should not be retained outside of the visit + // function, it may be invalidated by future mutators. + VisitDirectDepsIgnoreBlueprint(visit func(Module)) + // VisitDirectDeps calls visit for each direct dependency. If there are multiple // direct dependencies on the same module visit will be called multiple times on that module // and OtherModuleDependencyTag will return a different tag for each. It raises an error if any of the @@ -204,29 +214,12 @@ type BaseModuleContext interface { // getMissingDependencies returns the list of missing dependencies. // Calling this function prevents adding new dependencies. getMissingDependencies() []string - - Target() Target - TargetPrimary() bool - - // The additional arch specific targets (e.g. 32/64 bit) that this module variant is - // responsible for creating. - MultiTargets() []Target - Arch() Arch - Os() OsType - Host() bool - Device() bool - Darwin() bool - Windows() bool - PrimaryArch() bool } type baseModuleContext struct { bp blueprint.BaseModuleContext earlyModuleContext - os OsType - target Target - multiTargets []Target - targetPrimary bool + archModuleContext walkPath []Module tagPath []blueprint.DependencyTag @@ -306,7 +299,7 @@ type AllowDisabledModuleDependency interface { AllowDisabledModuleDependency(target Module) bool } -func (b *baseModuleContext) validateAndroidModule(module blueprint.Module, tag blueprint.DependencyTag, strict bool) Module { +func (b *baseModuleContext) validateAndroidModule(module blueprint.Module, tag blueprint.DependencyTag, strict bool, ignoreBlueprint bool) Module { aModule, _ := module.(Module) if !strict { @@ -314,7 +307,9 @@ func (b *baseModuleContext) validateAndroidModule(module blueprint.Module, tag b } if aModule == nil { - b.ModuleErrorf("module %q (%#v) not an android module", b.OtherModuleName(module), tag) + if !ignoreBlueprint { + b.ModuleErrorf("module %q (%#v) not an android module", b.OtherModuleName(module), tag) + } return nil } @@ -411,8 +406,16 @@ func (b *baseModuleContext) VisitDirectDepsBlueprint(visit func(blueprint.Module } func (b *baseModuleContext) VisitDirectDeps(visit func(Module)) { + b.visitDirectDeps(visit, false) +} + +func (b *baseModuleContext) VisitDirectDepsIgnoreBlueprint(visit func(Module)) { + b.visitDirectDeps(visit, true) +} + +func (b *baseModuleContext) visitDirectDeps(visit func(Module), ignoreBlueprint bool) { b.bp.VisitDirectDeps(func(module blueprint.Module) { - if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil { + if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps, ignoreBlueprint); aModule != nil { visit(aModule) } }) @@ -421,7 +424,7 @@ func (b *baseModuleContext) VisitDirectDeps(visit func(Module)) { func (b *baseModuleContext) VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) { b.bp.VisitDirectDeps(func(module blueprint.Module) { if b.bp.OtherModuleDependencyTag(module) == tag { - if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil { + if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps, false); aModule != nil { visit(aModule) } } @@ -432,7 +435,7 @@ func (b *baseModuleContext) VisitDirectDepsIf(pred func(Module) bool, visit func b.bp.VisitDirectDepsIf( // pred func(module blueprint.Module) bool { - if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil { + if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps, false); aModule != nil { return pred(aModule) } else { return false @@ -446,7 +449,7 @@ func (b *baseModuleContext) VisitDirectDepsIf(pred func(Module) bool, visit func func (b *baseModuleContext) VisitDepsDepthFirst(visit func(Module)) { b.bp.VisitDepsDepthFirst(func(module blueprint.Module) { - if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil { + if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps, false); aModule != nil { visit(aModule) } }) @@ -456,7 +459,7 @@ func (b *baseModuleContext) VisitDepsDepthFirstIf(pred func(Module) bool, visit b.bp.VisitDepsDepthFirstIf( // pred func(module blueprint.Module) bool { - if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil { + if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps, false); aModule != nil { return pred(aModule) } else { return false @@ -561,46 +564,3 @@ func (b *baseModuleContext) GetPathString(skipFirst bool) string { } return sb.String() } - -func (b *baseModuleContext) Target() Target { - return b.target -} - -func (b *baseModuleContext) TargetPrimary() bool { - return b.targetPrimary -} - -func (b *baseModuleContext) MultiTargets() []Target { - return b.multiTargets -} - -func (b *baseModuleContext) Arch() Arch { - return b.target.Arch -} - -func (b *baseModuleContext) Os() OsType { - return b.os -} - -func (b *baseModuleContext) Host() bool { - return b.os.Class == Host -} - -func (b *baseModuleContext) Device() bool { - return b.os.Class == Device -} - -func (b *baseModuleContext) Darwin() bool { - return b.os == Darwin -} - -func (b *baseModuleContext) Windows() bool { - return b.os == Windows -} - -func (b *baseModuleContext) PrimaryArch() bool { - if len(b.config.Targets[b.target.Os]) <= 1 { - return true - } - return b.target.Arch.ArchType == b.config.Targets[b.target.Os][0].Arch.ArchType -} diff --git a/android/defs.go b/android/defs.go index fe5293640..dab012d04 100644 --- a/android/defs.go +++ b/android/defs.go @@ -86,9 +86,8 @@ var ( // A symlink rule. Symlink = pctx.AndroidStaticRule("Symlink", blueprint.RuleParams{ - Command: "rm -f $out && ln -f -s $fromPath $out", - Description: "symlink $out", - SymlinkOutputs: []string{"$out"}, + Command: "rm -f $out && ln -f -s $fromPath $out", + Description: "symlink $out", }, "fromPath") diff --git a/android/module.go b/android/module.go index d8f004c61..6fd8657ff 100644 --- a/android/module.go +++ b/android/module.go @@ -519,6 +519,9 @@ type commonProperties struct { // trace, but influence modules among products. SoongConfigTrace soongConfigTrace `blueprint:"mutated"` SoongConfigTraceHash string `blueprint:"mutated"` + + // The team (defined by the owner/vendor) who owns the property. + Team *string `android:"path"` } type distProperties struct { @@ -531,6 +534,12 @@ type distProperties struct { Dists []Dist `android:"arch_variant"` } +type TeamDepTagType struct { + blueprint.BaseDependencyTag +} + +var teamDepTag = TeamDepTagType{} + // CommonTestOptions represents the common `test_options` properties in // Android.bp. type CommonTestOptions struct { @@ -992,6 +1001,12 @@ func (m *ModuleBase) ComponentDepsMutator(BottomUpMutatorContext) {} func (m *ModuleBase) DepsMutator(BottomUpMutatorContext) {} +func (m *ModuleBase) baseDepsMutator(ctx BottomUpMutatorContext) { + if m.Team() != "" { + ctx.AddDependency(ctx.Module(), teamDepTag, m.Team()) + } +} + // AddProperties "registers" the provided props // each value in props MUST be a pointer to a struct func (m *ModuleBase) AddProperties(props ...interface{}) { @@ -1437,6 +1452,10 @@ func (m *ModuleBase) Owner() string { return String(m.commonProperties.Owner) } +func (m *ModuleBase) Team() string { + return String(m.commonProperties.Team) +} + func (m *ModuleBase) setImageVariation(variant string) { m.commonProperties.ImageVariation = variant } @@ -1622,14 +1641,31 @@ func (m *ModuleBase) earlyModuleContextFactory(ctx blueprint.EarlyModuleContext) func (m *ModuleBase) baseModuleContextFactory(ctx blueprint.BaseModuleContext) baseModuleContext { return baseModuleContext{ bp: ctx, + archModuleContext: m.archModuleContextFactory(ctx), earlyModuleContext: m.earlyModuleContextFactory(ctx), - os: m.commonProperties.CompileOS, - target: m.commonProperties.CompileTarget, - targetPrimary: m.commonProperties.CompilePrimary, - multiTargets: m.commonProperties.CompileMultiTargets, } } +func (m *ModuleBase) archModuleContextFactory(ctx blueprint.IncomingTransitionContext) archModuleContext { + config := ctx.Config().(Config) + target := m.Target() + primaryArch := false + if len(config.Targets[target.Os]) <= 1 { + primaryArch = true + } else { + primaryArch = target.Arch.ArchType == config.Targets[target.Os][0].Arch.ArchType + } + + return archModuleContext{ + os: m.commonProperties.CompileOS, + target: m.commonProperties.CompileTarget, + targetPrimary: m.commonProperties.CompilePrimary, + multiTargets: m.commonProperties.CompileMultiTargets, + primaryArch: primaryArch, + } + +} + func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) { ctx := &moduleContext{ module: m.module, @@ -1692,7 +1728,7 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) // ensure all direct android.Module deps are enabled ctx.VisitDirectDepsBlueprint(func(bm blueprint.Module) { if m, ok := bm.(Module); ok { - ctx.validateAndroidModule(bm, ctx.OtherModuleDependencyTag(m), ctx.baseModuleContext.strictVisitDeps) + ctx.validateAndroidModule(bm, ctx.OtherModuleDependencyTag(m), ctx.baseModuleContext.strictVisitDeps, false) } }) diff --git a/android/module_context.go b/android/module_context.go index e772f8bc4..1cab63022 100644 --- a/android/module_context.go +++ b/android/module_context.go @@ -16,11 +16,12 @@ package android import ( "fmt" - "github.com/google/blueprint" - "github.com/google/blueprint/proptools" "path" "path/filepath" "strings" + + "github.com/google/blueprint" + "github.com/google/blueprint/proptools" ) // BuildParameters describes the set of potential parameters to build a Ninja rule. @@ -44,10 +45,6 @@ type BuildParams struct { // Outputs is a slice of output file of the action. When using this field, references to $out in // the Ninja command will refer to these files. Outputs WritablePaths - // SymlinkOutput is an output file specifically that is a symlink. - SymlinkOutput WritablePath - // SymlinkOutputs is a slice of output files specifically that is a symlink. - SymlinkOutputs WritablePaths // ImplicitOutput is an output file generated by the action. Note: references to `$out` in the // Ninja command will NOT include references to this file. ImplicitOutput WritablePath @@ -255,25 +252,6 @@ func (m *moduleContext) ModuleBuild(pctx PackageContext, params ModuleBuildParam m.Build(pctx, BuildParams(params)) } -func validateBuildParams(params blueprint.BuildParams) error { - // Validate that the symlink outputs are declared outputs or implicit outputs - allOutputs := map[string]bool{} - for _, output := range params.Outputs { - allOutputs[output] = true - } - for _, output := range params.ImplicitOutputs { - allOutputs[output] = true - } - for _, symlinkOutput := range params.SymlinkOutputs { - if !allOutputs[symlinkOutput] { - return fmt.Errorf( - "Symlink output %s is not a declared output or implicit output", - symlinkOutput) - } - } - return nil -} - // Convert build parameters from their concrete Android types into their string representations, // and combine the singular and plural fields of the same type (e.g. Output and Outputs). func convertBuildParams(params BuildParams) blueprint.BuildParams { @@ -283,7 +261,6 @@ func convertBuildParams(params BuildParams) blueprint.BuildParams { Deps: params.Deps, Outputs: params.Outputs.Strings(), ImplicitOutputs: params.ImplicitOutputs.Strings(), - SymlinkOutputs: params.SymlinkOutputs.Strings(), Inputs: params.Inputs.Strings(), Implicits: params.Implicits.Strings(), OrderOnly: params.OrderOnly.Strings(), @@ -298,9 +275,6 @@ func convertBuildParams(params BuildParams) blueprint.BuildParams { if params.Output != nil { bparams.Outputs = append(bparams.Outputs, params.Output.String()) } - if params.SymlinkOutput != nil { - bparams.SymlinkOutputs = append(bparams.SymlinkOutputs, params.SymlinkOutput.String()) - } if params.ImplicitOutput != nil { bparams.ImplicitOutputs = append(bparams.ImplicitOutputs, params.ImplicitOutput.String()) } @@ -316,7 +290,6 @@ func convertBuildParams(params BuildParams) blueprint.BuildParams { bparams.Outputs = proptools.NinjaEscapeList(bparams.Outputs) bparams.ImplicitOutputs = proptools.NinjaEscapeList(bparams.ImplicitOutputs) - bparams.SymlinkOutputs = proptools.NinjaEscapeList(bparams.SymlinkOutputs) bparams.Inputs = proptools.NinjaEscapeList(bparams.Inputs) bparams.Implicits = proptools.NinjaEscapeList(bparams.Implicits) bparams.OrderOnly = proptools.NinjaEscapeList(bparams.OrderOnly) @@ -374,13 +347,6 @@ func (m *moduleContext) Build(pctx PackageContext, params BuildParams) { } bparams := convertBuildParams(params) - err := validateBuildParams(bparams) - if err != nil { - m.ModuleErrorf( - "%s: build parameter validation failed: %s", - m.ModuleName(), - err.Error()) - } m.bp.Build(pctx.PackageContext, bparams) } diff --git a/android/module_test.go b/android/module_test.go index 1ca742213..1f3db5c5c 100644 --- a/android/module_test.go +++ b/android/module_test.go @@ -15,10 +15,11 @@ package android import ( - "github.com/google/blueprint" "path/filepath" "runtime" "testing" + + "github.com/google/blueprint" ) func TestSrcIsModule(t *testing.T) { @@ -244,52 +245,6 @@ func TestErrorDependsOnDisabledModule(t *testing.T) { RunTestWithBp(t, bp) } -func TestValidateCorrectBuildParams(t *testing.T) { - config := TestConfig(t.TempDir(), nil, "", nil) - pathContext := PathContextForTesting(config) - bparams := convertBuildParams(BuildParams{ - // Test with Output - Output: PathForOutput(pathContext, "undeclared_symlink"), - SymlinkOutput: PathForOutput(pathContext, "undeclared_symlink"), - }) - - err := validateBuildParams(bparams) - if err != nil { - t.Error(err) - } - - bparams = convertBuildParams(BuildParams{ - // Test with ImplicitOutput - ImplicitOutput: PathForOutput(pathContext, "undeclared_symlink"), - SymlinkOutput: PathForOutput(pathContext, "undeclared_symlink"), - }) - - err = validateBuildParams(bparams) - if err != nil { - t.Error(err) - } -} - -func TestValidateIncorrectBuildParams(t *testing.T) { - config := TestConfig(t.TempDir(), nil, "", nil) - pathContext := PathContextForTesting(config) - params := BuildParams{ - Output: PathForOutput(pathContext, "regular_output"), - Outputs: PathsForOutput(pathContext, []string{"out1", "out2"}), - ImplicitOutput: PathForOutput(pathContext, "implicit_output"), - ImplicitOutputs: PathsForOutput(pathContext, []string{"i_out1", "_out2"}), - SymlinkOutput: PathForOutput(pathContext, "undeclared_symlink"), - } - - bparams := convertBuildParams(params) - err := validateBuildParams(bparams) - if err != nil { - FailIfNoMatchingErrors(t, "undeclared_symlink is not a declared output or implicit output", []error{err}) - } else { - t.Errorf("Expected build params to fail validation: %+v", bparams) - } -} - func TestDistErrorChecking(t *testing.T) { bp := ` deps { diff --git a/android/mutator.go b/android/mutator.go index 93c519d27..22e91603c 100644 --- a/android/mutator.go +++ b/android/mutator.go @@ -365,15 +365,21 @@ func (x *registerMutatorsContext) BottomUpBlueprint(name string, m blueprint.Bot } type IncomingTransitionContext interface { + ArchModuleContext + // Module returns the target of the dependency edge for which the transition // is being computed Module() Module // Config returns the configuration for the build. Config() Config + + DeviceConfig() DeviceConfig } type OutgoingTransitionContext interface { + ArchModuleContext + // Module returns the target of the dependency edge for which the transition // is being computed Module() Module @@ -381,9 +387,14 @@ type OutgoingTransitionContext interface { // DepTag() Returns the dependency tag through which this dependency is // reached DepTag() blueprint.DependencyTag + + // Config returns the configuration for the build. + Config() Config + + DeviceConfig() DeviceConfig } -// Transition mutators implement a top-down mechanism where a module tells its +// TransitionMutator implements a top-down mechanism where a module tells its // direct dependencies what variation they should be built in but the dependency // has the final say. // @@ -448,18 +459,18 @@ type TransitionMutator interface { // called on. Split(ctx BaseModuleContext) []string - // Called on a module to determine which variation it wants from its direct - // dependencies. The dependency itself can override this decision. This method - // should not mutate the module itself. + // OutgoingTransition is called on a module to determine which variation it wants + // from its direct dependencies. The dependency itself can override this decision. + // This method should not mutate the module itself. OutgoingTransition(ctx OutgoingTransitionContext, sourceVariation string) string - // Called on a module to determine which variation it should be in based on - // the variation modules that depend on it want. This gives the module a final - // say about its own variations. This method should not mutate the module + // IncomingTransition is called on a module to determine which variation it should + // be in based on the variation modules that depend on it want. This gives the module + // a final say about its own variations. This method should not mutate the module // itself. IncomingTransition(ctx IncomingTransitionContext, incomingVariation string) string - // Called after a module was split into multiple variations on each variation. + // Mutate is called after a module was split into multiple variations on each variation. // It should not split the module any further but adding new dependencies is // fine. Unlike all the other methods on TransitionMutator, this method is // allowed to mutate the module. @@ -481,6 +492,7 @@ func (a *androidTransitionMutator) Split(ctx blueprint.BaseModuleContext) []stri } type outgoingTransitionContextImpl struct { + archModuleContext bp blueprint.OutgoingTransitionContext } @@ -492,15 +504,28 @@ func (c *outgoingTransitionContextImpl) DepTag() blueprint.DependencyTag { return c.bp.DepTag() } -func (a *androidTransitionMutator) OutgoingTransition(ctx blueprint.OutgoingTransitionContext, sourceVariation string) string { - if _, ok := ctx.Module().(Module); ok { - return a.mutator.OutgoingTransition(&outgoingTransitionContextImpl{bp: ctx}, sourceVariation) +func (c *outgoingTransitionContextImpl) Config() Config { + return c.bp.Config().(Config) +} + +func (c *outgoingTransitionContextImpl) DeviceConfig() DeviceConfig { + return DeviceConfig{c.bp.Config().(Config).deviceConfig} +} + +func (a *androidTransitionMutator) OutgoingTransition(bpctx blueprint.OutgoingTransitionContext, sourceVariation string) string { + if m, ok := bpctx.Module().(Module); ok { + ctx := &outgoingTransitionContextImpl{ + archModuleContext: m.base().archModuleContextFactory(bpctx), + bp: bpctx, + } + return a.mutator.OutgoingTransition(ctx, sourceVariation) } else { return "" } } type incomingTransitionContextImpl struct { + archModuleContext bp blueprint.IncomingTransitionContext } @@ -512,9 +537,17 @@ func (c *incomingTransitionContextImpl) Config() Config { return c.bp.Config().(Config) } -func (a *androidTransitionMutator) IncomingTransition(ctx blueprint.IncomingTransitionContext, incomingVariation string) string { - if _, ok := ctx.Module().(Module); ok { - return a.mutator.IncomingTransition(&incomingTransitionContextImpl{bp: ctx}, incomingVariation) +func (c *incomingTransitionContextImpl) DeviceConfig() DeviceConfig { + return DeviceConfig{c.bp.Config().(Config).deviceConfig} +} + +func (a *androidTransitionMutator) IncomingTransition(bpctx blueprint.IncomingTransitionContext, incomingVariation string) string { + if m, ok := bpctx.Module().(Module); ok { + ctx := &incomingTransitionContextImpl{ + archModuleContext: m.base().archModuleContextFactory(bpctx), + bp: bpctx, + } + return a.mutator.IncomingTransition(ctx, incomingVariation) } else { return "" } @@ -600,6 +633,7 @@ func componentDepsMutator(ctx BottomUpMutatorContext) { func depsMutator(ctx BottomUpMutatorContext) { if m := ctx.Module(); m.Enabled() { + m.base().baseDepsMutator(ctx) m.DepsMutator(ctx) } } diff --git a/android/package.go b/android/package.go index 878e4c4ed..eb76751f5 100644 --- a/android/package.go +++ b/android/package.go @@ -35,6 +35,7 @@ type packageProperties struct { Default_visibility []string // Specifies the default license terms for all modules defined in this package. Default_applicable_licenses []string + Default_team *string `android:"path"` } type packageModule struct { @@ -47,6 +48,13 @@ func (p *packageModule) GenerateAndroidBuildActions(ModuleContext) { // Nothing to do. } +func (p *packageModule) DepsMutator(ctx BottomUpMutatorContext) { + // Add the dependency to do a validity check + if p.properties.Default_team != nil { + ctx.AddDependency(ctx.Module(), nil, *p.properties.Default_team) + } +} + func (p *packageModule) GenerateBuildActions(ctx blueprint.ModuleContext) { // Nothing to do. } diff --git a/android/paths_test.go b/android/paths_test.go index bf46c34f3..93b9b9a16 100644 --- a/android/paths_test.go +++ b/android/paths_test.go @@ -268,8 +268,10 @@ func TestPathForModuleInstall(t *testing.T) { name: "host binary", ctx: &testModuleInstallPathContext{ baseModuleContext: baseModuleContext{ - os: hostTarget.Os, - target: hostTarget, + archModuleContext: archModuleContext{ + os: hostTarget.Os, + target: hostTarget, + }, }, }, in: []string{"bin", "my_test"}, @@ -281,8 +283,10 @@ func TestPathForModuleInstall(t *testing.T) { name: "system binary", ctx: &testModuleInstallPathContext{ baseModuleContext: baseModuleContext{ - os: deviceTarget.Os, - target: deviceTarget, + archModuleContext: archModuleContext{ + os: deviceTarget.Os, + target: deviceTarget, + }, }, }, in: []string{"bin", "my_test"}, @@ -293,8 +297,10 @@ func TestPathForModuleInstall(t *testing.T) { name: "vendor binary", ctx: &testModuleInstallPathContext{ baseModuleContext: baseModuleContext{ - os: deviceTarget.Os, - target: deviceTarget, + archModuleContext: archModuleContext{ + os: deviceTarget.Os, + target: deviceTarget, + }, earlyModuleContext: earlyModuleContext{ kind: socSpecificModule, }, @@ -308,8 +314,10 @@ func TestPathForModuleInstall(t *testing.T) { name: "odm binary", ctx: &testModuleInstallPathContext{ baseModuleContext: baseModuleContext{ - os: deviceTarget.Os, - target: deviceTarget, + archModuleContext: archModuleContext{ + os: deviceTarget.Os, + target: deviceTarget, + }, earlyModuleContext: earlyModuleContext{ kind: deviceSpecificModule, }, @@ -323,8 +331,10 @@ func TestPathForModuleInstall(t *testing.T) { name: "product binary", ctx: &testModuleInstallPathContext{ baseModuleContext: baseModuleContext{ - os: deviceTarget.Os, - target: deviceTarget, + archModuleContext: archModuleContext{ + os: deviceTarget.Os, + target: deviceTarget, + }, earlyModuleContext: earlyModuleContext{ kind: productSpecificModule, }, @@ -338,8 +348,10 @@ func TestPathForModuleInstall(t *testing.T) { name: "system_ext binary", ctx: &testModuleInstallPathContext{ baseModuleContext: baseModuleContext{ - os: deviceTarget.Os, - target: deviceTarget, + archModuleContext: archModuleContext{ + os: deviceTarget.Os, + target: deviceTarget, + }, earlyModuleContext: earlyModuleContext{ kind: systemExtSpecificModule, }, @@ -353,8 +365,10 @@ func TestPathForModuleInstall(t *testing.T) { name: "root binary", ctx: &testModuleInstallPathContext{ baseModuleContext: baseModuleContext{ - os: deviceTarget.Os, - target: deviceTarget, + archModuleContext: archModuleContext{ + os: deviceTarget.Os, + target: deviceTarget, + }, }, inRoot: true, }, @@ -366,8 +380,10 @@ func TestPathForModuleInstall(t *testing.T) { name: "recovery binary", ctx: &testModuleInstallPathContext{ baseModuleContext: baseModuleContext{ - os: deviceTarget.Os, - target: deviceTarget, + archModuleContext: archModuleContext{ + os: deviceTarget.Os, + target: deviceTarget, + }, }, inRecovery: true, }, @@ -379,8 +395,10 @@ func TestPathForModuleInstall(t *testing.T) { name: "recovery root binary", ctx: &testModuleInstallPathContext{ baseModuleContext: baseModuleContext{ - os: deviceTarget.Os, - target: deviceTarget, + archModuleContext: archModuleContext{ + os: deviceTarget.Os, + target: deviceTarget, + }, }, inRecovery: true, inRoot: true, @@ -394,8 +412,10 @@ func TestPathForModuleInstall(t *testing.T) { name: "ramdisk binary", ctx: &testModuleInstallPathContext{ baseModuleContext: baseModuleContext{ - os: deviceTarget.Os, - target: deviceTarget, + archModuleContext: archModuleContext{ + os: deviceTarget.Os, + target: deviceTarget, + }, }, inRamdisk: true, }, @@ -407,8 +427,10 @@ func TestPathForModuleInstall(t *testing.T) { name: "ramdisk root binary", ctx: &testModuleInstallPathContext{ baseModuleContext: baseModuleContext{ - os: deviceTarget.Os, - target: deviceTarget, + archModuleContext: archModuleContext{ + os: deviceTarget.Os, + target: deviceTarget, + }, }, inRamdisk: true, inRoot: true, @@ -421,8 +443,10 @@ func TestPathForModuleInstall(t *testing.T) { name: "vendor_ramdisk binary", ctx: &testModuleInstallPathContext{ baseModuleContext: baseModuleContext{ - os: deviceTarget.Os, - target: deviceTarget, + archModuleContext: archModuleContext{ + os: deviceTarget.Os, + target: deviceTarget, + }, }, inVendorRamdisk: true, }, @@ -434,8 +458,10 @@ func TestPathForModuleInstall(t *testing.T) { name: "vendor_ramdisk root binary", ctx: &testModuleInstallPathContext{ baseModuleContext: baseModuleContext{ - os: deviceTarget.Os, - target: deviceTarget, + archModuleContext: archModuleContext{ + os: deviceTarget.Os, + target: deviceTarget, + }, }, inVendorRamdisk: true, inRoot: true, @@ -448,8 +474,10 @@ func TestPathForModuleInstall(t *testing.T) { name: "debug_ramdisk binary", ctx: &testModuleInstallPathContext{ baseModuleContext: baseModuleContext{ - os: deviceTarget.Os, - target: deviceTarget, + archModuleContext: archModuleContext{ + os: deviceTarget.Os, + target: deviceTarget, + }, }, inDebugRamdisk: true, }, @@ -461,8 +489,10 @@ func TestPathForModuleInstall(t *testing.T) { name: "system native test binary", ctx: &testModuleInstallPathContext{ baseModuleContext: baseModuleContext{ - os: deviceTarget.Os, - target: deviceTarget, + archModuleContext: archModuleContext{ + os: deviceTarget.Os, + target: deviceTarget, + }, }, inData: true, }, @@ -474,8 +504,10 @@ func TestPathForModuleInstall(t *testing.T) { name: "vendor native test binary", ctx: &testModuleInstallPathContext{ baseModuleContext: baseModuleContext{ - os: deviceTarget.Os, - target: deviceTarget, + archModuleContext: archModuleContext{ + os: deviceTarget.Os, + target: deviceTarget, + }, earlyModuleContext: earlyModuleContext{ kind: socSpecificModule, }, @@ -490,8 +522,10 @@ func TestPathForModuleInstall(t *testing.T) { name: "odm native test binary", ctx: &testModuleInstallPathContext{ baseModuleContext: baseModuleContext{ - os: deviceTarget.Os, - target: deviceTarget, + archModuleContext: archModuleContext{ + os: deviceTarget.Os, + target: deviceTarget, + }, earlyModuleContext: earlyModuleContext{ kind: deviceSpecificModule, }, @@ -506,8 +540,10 @@ func TestPathForModuleInstall(t *testing.T) { name: "product native test binary", ctx: &testModuleInstallPathContext{ baseModuleContext: baseModuleContext{ - os: deviceTarget.Os, - target: deviceTarget, + archModuleContext: archModuleContext{ + os: deviceTarget.Os, + target: deviceTarget, + }, earlyModuleContext: earlyModuleContext{ kind: productSpecificModule, }, @@ -523,8 +559,10 @@ func TestPathForModuleInstall(t *testing.T) { name: "system_ext native test binary", ctx: &testModuleInstallPathContext{ baseModuleContext: baseModuleContext{ - os: deviceTarget.Os, - target: deviceTarget, + archModuleContext: archModuleContext{ + os: deviceTarget.Os, + target: deviceTarget, + }, earlyModuleContext: earlyModuleContext{ kind: systemExtSpecificModule, }, @@ -540,8 +578,10 @@ func TestPathForModuleInstall(t *testing.T) { name: "sanitized system binary", ctx: &testModuleInstallPathContext{ baseModuleContext: baseModuleContext{ - os: deviceTarget.Os, - target: deviceTarget, + archModuleContext: archModuleContext{ + os: deviceTarget.Os, + target: deviceTarget, + }, }, inSanitizerDir: true, }, @@ -553,8 +593,10 @@ func TestPathForModuleInstall(t *testing.T) { name: "sanitized vendor binary", ctx: &testModuleInstallPathContext{ baseModuleContext: baseModuleContext{ - os: deviceTarget.Os, - target: deviceTarget, + archModuleContext: archModuleContext{ + os: deviceTarget.Os, + target: deviceTarget, + }, earlyModuleContext: earlyModuleContext{ kind: socSpecificModule, }, @@ -569,8 +611,10 @@ func TestPathForModuleInstall(t *testing.T) { name: "sanitized odm binary", ctx: &testModuleInstallPathContext{ baseModuleContext: baseModuleContext{ - os: deviceTarget.Os, - target: deviceTarget, + archModuleContext: archModuleContext{ + os: deviceTarget.Os, + target: deviceTarget, + }, earlyModuleContext: earlyModuleContext{ kind: deviceSpecificModule, }, @@ -585,8 +629,10 @@ func TestPathForModuleInstall(t *testing.T) { name: "sanitized product binary", ctx: &testModuleInstallPathContext{ baseModuleContext: baseModuleContext{ - os: deviceTarget.Os, - target: deviceTarget, + archModuleContext: archModuleContext{ + os: deviceTarget.Os, + target: deviceTarget, + }, earlyModuleContext: earlyModuleContext{ kind: productSpecificModule, }, @@ -602,8 +648,10 @@ func TestPathForModuleInstall(t *testing.T) { name: "sanitized system_ext binary", ctx: &testModuleInstallPathContext{ baseModuleContext: baseModuleContext{ - os: deviceTarget.Os, - target: deviceTarget, + archModuleContext: archModuleContext{ + os: deviceTarget.Os, + target: deviceTarget, + }, earlyModuleContext: earlyModuleContext{ kind: systemExtSpecificModule, }, @@ -619,8 +667,10 @@ func TestPathForModuleInstall(t *testing.T) { name: "sanitized system native test binary", ctx: &testModuleInstallPathContext{ baseModuleContext: baseModuleContext{ - os: deviceTarget.Os, - target: deviceTarget, + archModuleContext: archModuleContext{ + os: deviceTarget.Os, + target: deviceTarget, + }, }, inData: true, inSanitizerDir: true, @@ -633,8 +683,10 @@ func TestPathForModuleInstall(t *testing.T) { name: "sanitized vendor native test binary", ctx: &testModuleInstallPathContext{ baseModuleContext: baseModuleContext{ - os: deviceTarget.Os, - target: deviceTarget, + archModuleContext: archModuleContext{ + os: deviceTarget.Os, + target: deviceTarget, + }, earlyModuleContext: earlyModuleContext{ kind: socSpecificModule, }, @@ -650,8 +702,10 @@ func TestPathForModuleInstall(t *testing.T) { name: "sanitized odm native test binary", ctx: &testModuleInstallPathContext{ baseModuleContext: baseModuleContext{ - os: deviceTarget.Os, - target: deviceTarget, + archModuleContext: archModuleContext{ + os: deviceTarget.Os, + target: deviceTarget, + }, earlyModuleContext: earlyModuleContext{ kind: deviceSpecificModule, }, @@ -667,8 +721,10 @@ func TestPathForModuleInstall(t *testing.T) { name: "sanitized product native test binary", ctx: &testModuleInstallPathContext{ baseModuleContext: baseModuleContext{ - os: deviceTarget.Os, - target: deviceTarget, + archModuleContext: archModuleContext{ + os: deviceTarget.Os, + target: deviceTarget, + }, earlyModuleContext: earlyModuleContext{ kind: productSpecificModule, }, @@ -684,8 +740,10 @@ func TestPathForModuleInstall(t *testing.T) { name: "sanitized system_ext native test binary", ctx: &testModuleInstallPathContext{ baseModuleContext: baseModuleContext{ - os: deviceTarget.Os, - target: deviceTarget, + archModuleContext: archModuleContext{ + os: deviceTarget.Os, + target: deviceTarget, + }, earlyModuleContext: earlyModuleContext{ kind: systemExtSpecificModule, }, @@ -700,8 +758,10 @@ func TestPathForModuleInstall(t *testing.T) { name: "device testcases", ctx: &testModuleInstallPathContext{ baseModuleContext: baseModuleContext{ - os: deviceTarget.Os, - target: deviceTarget, + archModuleContext: archModuleContext{ + os: deviceTarget.Os, + target: deviceTarget, + }, }, inTestcases: true, }, @@ -712,8 +772,10 @@ func TestPathForModuleInstall(t *testing.T) { name: "host testcases", ctx: &testModuleInstallPathContext{ baseModuleContext: baseModuleContext{ - os: hostTarget.Os, - target: hostTarget, + archModuleContext: archModuleContext{ + os: hostTarget.Os, + target: hostTarget, + }, }, inTestcases: true, }, @@ -724,8 +786,10 @@ func TestPathForModuleInstall(t *testing.T) { name: "forced host testcases", ctx: &testModuleInstallPathContext{ baseModuleContext: baseModuleContext{ - os: deviceTarget.Os, - target: deviceTarget, + archModuleContext: archModuleContext{ + os: deviceTarget.Os, + target: deviceTarget, + }, }, inTestcases: true, forceOS: &Linux, @@ -771,8 +835,10 @@ func TestPathForModuleInstallRecoveryAsBoot(t *testing.T) { name: "ramdisk binary", ctx: &testModuleInstallPathContext{ baseModuleContext: baseModuleContext{ - os: deviceTarget.Os, - target: deviceTarget, + archModuleContext: archModuleContext{ + os: deviceTarget.Os, + target: deviceTarget, + }, }, inRamdisk: true, inRoot: true, @@ -786,8 +852,10 @@ func TestPathForModuleInstallRecoveryAsBoot(t *testing.T) { name: "vendor_ramdisk binary", ctx: &testModuleInstallPathContext{ baseModuleContext: baseModuleContext{ - os: deviceTarget.Os, - target: deviceTarget, + archModuleContext: archModuleContext{ + os: deviceTarget.Os, + target: deviceTarget, + }, }, inVendorRamdisk: true, inRoot: true, @@ -821,8 +889,10 @@ func TestBaseDirForInstallPath(t *testing.T) { ctx := &testModuleInstallPathContext{ baseModuleContext: baseModuleContext{ - os: deviceTarget.Os, - target: deviceTarget, + archModuleContext: archModuleContext{ + os: deviceTarget.Os, + target: deviceTarget, + }, }, } ctx.baseModuleContext.config = testConfig @@ -1491,8 +1561,10 @@ func TestPathRelativeToTop(t *testing.T) { ctx := &testModuleInstallPathContext{ baseModuleContext: baseModuleContext{ - os: deviceTarget.Os, - target: deviceTarget, + archModuleContext: archModuleContext{ + os: deviceTarget.Os, + target: deviceTarget, + }, }, } ctx.baseModuleContext.config = testConfig diff --git a/android/rule_builder.go b/android/rule_builder.go index 1454357ec..e8dbd48c6 100644 --- a/android/rule_builder.go +++ b/android/rule_builder.go @@ -336,41 +336,6 @@ func (r *RuleBuilder) Outputs() WritablePaths { return outputList } -func (r *RuleBuilder) symlinkOutputSet() map[string]WritablePath { - symlinkOutputs := make(map[string]WritablePath) - for _, c := range r.commands { - for _, symlinkOutput := range c.symlinkOutputs { - symlinkOutputs[symlinkOutput.String()] = symlinkOutput - } - } - return symlinkOutputs -} - -// SymlinkOutputs returns the list of paths that the executor (Ninja) would -// verify, after build edge completion, that: -// -// 1) Created output symlinks match the list of paths in this list exactly (no more, no fewer) -// 2) Created output files are *not* declared in this list. -// -// These symlink outputs are expected to be a subset of outputs or implicit -// outputs, or they would fail validation at build param construction time -// later, to support other non-rule-builder approaches for constructing -// statements. -func (r *RuleBuilder) SymlinkOutputs() WritablePaths { - symlinkOutputs := r.symlinkOutputSet() - - var symlinkOutputList WritablePaths - for _, symlinkOutput := range symlinkOutputs { - symlinkOutputList = append(symlinkOutputList, symlinkOutput) - } - - sort.Slice(symlinkOutputList, func(i, j int) bool { - return symlinkOutputList[i].String() < symlinkOutputList[j].String() - }) - - return symlinkOutputList -} - func (r *RuleBuilder) depFileSet() map[string]WritablePath { depFiles := make(map[string]WritablePath) for _, c := range r.commands { @@ -629,8 +594,9 @@ func (r *RuleBuilder) build(name string, desc string, ninjaEscapeCommandString b name, r.sboxManifestPath.String(), r.outDir.String()) } - // Create a rule to write the manifest as textproto. - pbText, err := prototext.Marshal(&manifest) + // Create a rule to write the manifest as textproto. Pretty print it by indenting and + // splitting across multiple lines. + pbText, err := prototext.MarshalOptions{Indent: " "}.Marshal(&manifest) if err != nil { ReportPathErrorf(r.ctx, "sbox manifest failed to marshal: %q", err) } @@ -775,7 +741,6 @@ func (r *RuleBuilder) build(name string, desc string, ninjaEscapeCommandString b Validations: r.Validations(), Output: output, ImplicitOutputs: implicitOutputs, - SymlinkOutputs: r.SymlinkOutputs(), Depfile: depFile, Deps: depFormat, Description: desc, @@ -789,17 +754,16 @@ func (r *RuleBuilder) build(name string, desc string, ninjaEscapeCommandString b type RuleBuilderCommand struct { rule *RuleBuilder - buf strings.Builder - inputs Paths - implicits Paths - orderOnlys Paths - validations Paths - outputs WritablePaths - symlinkOutputs WritablePaths - depFiles WritablePaths - tools Paths - packagedTools []PackagingSpec - rspFiles []rspFileAndPaths + buf strings.Builder + inputs Paths + implicits Paths + orderOnlys Paths + validations Paths + outputs WritablePaths + depFiles WritablePaths + tools Paths + packagedTools []PackagingSpec + rspFiles []rspFileAndPaths } type rspFileAndPaths struct { @@ -1223,42 +1187,6 @@ func (c *RuleBuilderCommand) ImplicitOutputs(paths WritablePaths) *RuleBuilderCo return c } -// ImplicitSymlinkOutput declares the specified path as an implicit output that -// will be a symlink instead of a regular file. Does not modify the command -// line. -func (c *RuleBuilderCommand) ImplicitSymlinkOutput(path WritablePath) *RuleBuilderCommand { - checkPathNotNil(path) - c.symlinkOutputs = append(c.symlinkOutputs, path) - return c.ImplicitOutput(path) -} - -// ImplicitSymlinkOutputs declares the specified paths as implicit outputs that -// will be a symlinks instead of regular files. Does not modify the command -// line. -func (c *RuleBuilderCommand) ImplicitSymlinkOutputs(paths WritablePaths) *RuleBuilderCommand { - for _, path := range paths { - c.ImplicitSymlinkOutput(path) - } - return c -} - -// SymlinkOutput declares the specified path as an output that will be a symlink -// instead of a regular file. Modifies the command line. -func (c *RuleBuilderCommand) SymlinkOutput(path WritablePath) *RuleBuilderCommand { - checkPathNotNil(path) - c.symlinkOutputs = append(c.symlinkOutputs, path) - return c.Output(path) -} - -// SymlinkOutputsl declares the specified paths as outputs that will be symlinks -// instead of regular files. Modifies the command line. -func (c *RuleBuilderCommand) SymlinkOutputs(paths WritablePaths) *RuleBuilderCommand { - for _, path := range paths { - c.SymlinkOutput(path) - } - return c -} - // ImplicitDepFile adds the specified depfile path to the paths returned by RuleBuilder.DepFiles without modifying // 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 diff --git a/android/rule_builder_test.go b/android/rule_builder_test.go index 9e5f12dff..6a8a964a1 100644 --- a/android/rule_builder_test.go +++ b/android/rule_builder_test.go @@ -48,7 +48,6 @@ func builderContext() BuilderContext { "a": nil, "b": nil, "ls": nil, - "ln": nil, "turbine": nil, "java": nil, "javac": nil, @@ -81,32 +80,6 @@ func ExampleRuleBuilder() { // outputs: ["out/soong/linked"] } -func ExampleRuleBuilder_SymlinkOutputs() { - ctx := builderContext() - - rule := NewRuleBuilder(pctx, ctx) - - rule.Command(). - Tool(PathForSource(ctx, "ln")). - FlagWithInput("-s ", PathForTesting("a.o")). - SymlinkOutput(PathForOutput(ctx, "a")) - rule.Command().Text("cp out/soong/a out/soong/b"). - ImplicitSymlinkOutput(PathForOutput(ctx, "b")) - - fmt.Printf("commands: %q\n", strings.Join(rule.Commands(), " && ")) - fmt.Printf("tools: %q\n", rule.Tools()) - fmt.Printf("inputs: %q\n", rule.Inputs()) - fmt.Printf("outputs: %q\n", rule.Outputs()) - fmt.Printf("symlink_outputs: %q\n", rule.SymlinkOutputs()) - - // Output: - // commands: "ln -s a.o out/soong/a && cp out/soong/a out/soong/b" - // tools: ["ln"] - // inputs: ["a.o"] - // outputs: ["out/soong/a" "out/soong/b"] - // symlink_outputs: ["out/soong/a" "out/soong/b"] -} - func ExampleRuleBuilder_Temporary() { ctx := builderContext() @@ -334,8 +307,6 @@ func TestRuleBuilder(t *testing.T) { Output(PathForOutput(ctx, "module/Output")). OrderOnly(PathForSource(ctx, "OrderOnly")). Validation(PathForSource(ctx, "Validation")). - SymlinkOutput(PathForOutput(ctx, "module/SymlinkOutput")). - ImplicitSymlinkOutput(PathForOutput(ctx, "module/ImplicitSymlinkOutput")). Text("Text"). Tool(PathForSource(ctx, "Tool")) @@ -367,15 +338,13 @@ func TestRuleBuilder(t *testing.T) { wantRspFileInputs := Paths{PathForSource(ctx, "RspInput"), PathForOutput(ctx, "other/RspOutput2")} wantOutputs := PathsForOutput(ctx, []string{ - "module/ImplicitOutput", "module/ImplicitSymlinkOutput", "module/Output", "module/SymlinkOutput", - "module/output", "module/output2", "module/output3"}) + "module/ImplicitOutput", "module/Output", "module/output", "module/output2", + "module/output3"}) wantDepFiles := PathsForOutput(ctx, []string{ "module/DepFile", "module/depfile", "module/ImplicitDepFile", "module/depfile2"}) wantTools := PathsForSource(ctx, []string{"Tool", "tool2"}) wantOrderOnlys := PathsForSource(ctx, []string{"OrderOnly", "OrderOnlys"}) wantValidations := PathsForSource(ctx, []string{"Validation", "Validations"}) - wantSymlinkOutputs := PathsForOutput(ctx, []string{ - "module/ImplicitSymlinkOutput", "module/SymlinkOutput"}) t.Run("normal", func(t *testing.T) { rule := NewRuleBuilder(pctx, ctx) @@ -384,7 +353,7 @@ func TestRuleBuilder(t *testing.T) { wantCommands := []string{ "out_local/soong/module/DepFile Flag FlagWithArg=arg FlagWithDepFile=out_local/soong/module/depfile " + "FlagWithInput=input FlagWithOutput=out_local/soong/module/output FlagWithRspFileInputList=out_local/soong/rsp " + - "Input out_local/soong/module/Output out_local/soong/module/SymlinkOutput Text Tool after command2 old cmd", + "Input out_local/soong/module/Output Text Tool after command2 old cmd", "command2 out_local/soong/module/depfile2 input2 out_local/soong/module/output2 tool2", "command3 input3 out_local/soong/module/output2 out_local/soong/module/output3 input3 out_local/soong/module/output2", } @@ -397,7 +366,6 @@ func TestRuleBuilder(t *testing.T) { AssertDeepEquals(t, "rule.Inputs()", wantInputs, rule.Inputs()) AssertDeepEquals(t, "rule.RspfileInputs()", wantRspFileInputs, rule.RspFileInputs()) AssertDeepEquals(t, "rule.Outputs()", wantOutputs, rule.Outputs()) - AssertDeepEquals(t, "rule.SymlinkOutputs()", wantSymlinkOutputs, rule.SymlinkOutputs()) AssertDeepEquals(t, "rule.DepFiles()", wantDepFiles, rule.DepFiles()) AssertDeepEquals(t, "rule.Tools()", wantTools, rule.Tools()) AssertDeepEquals(t, "rule.OrderOnlys()", wantOrderOnlys, rule.OrderOnlys()) @@ -415,7 +383,7 @@ func TestRuleBuilder(t *testing.T) { "__SBOX_SANDBOX_DIR__/out/DepFile Flag FlagWithArg=arg FlagWithDepFile=__SBOX_SANDBOX_DIR__/out/depfile " + "FlagWithInput=input FlagWithOutput=__SBOX_SANDBOX_DIR__/out/output " + "FlagWithRspFileInputList=out_local/soong/rsp Input __SBOX_SANDBOX_DIR__/out/Output " + - "__SBOX_SANDBOX_DIR__/out/SymlinkOutput Text Tool after command2 old cmd", + "Text Tool after command2 old cmd", "command2 __SBOX_SANDBOX_DIR__/out/depfile2 input2 __SBOX_SANDBOX_DIR__/out/output2 tool2", "command3 input3 __SBOX_SANDBOX_DIR__/out/output2 __SBOX_SANDBOX_DIR__/out/output3 input3 __SBOX_SANDBOX_DIR__/out/output2", } @@ -427,7 +395,6 @@ func TestRuleBuilder(t *testing.T) { AssertDeepEquals(t, "rule.Inputs()", wantInputs, rule.Inputs()) AssertDeepEquals(t, "rule.RspfileInputs()", wantRspFileInputs, rule.RspFileInputs()) AssertDeepEquals(t, "rule.Outputs()", wantOutputs, rule.Outputs()) - AssertDeepEquals(t, "rule.SymlinkOutputs()", wantSymlinkOutputs, rule.SymlinkOutputs()) AssertDeepEquals(t, "rule.DepFiles()", wantDepFiles, rule.DepFiles()) AssertDeepEquals(t, "rule.Tools()", wantTools, rule.Tools()) AssertDeepEquals(t, "rule.OrderOnlys()", wantOrderOnlys, rule.OrderOnlys()) @@ -445,7 +412,7 @@ func TestRuleBuilder(t *testing.T) { "__SBOX_SANDBOX_DIR__/out/DepFile Flag FlagWithArg=arg FlagWithDepFile=__SBOX_SANDBOX_DIR__/out/depfile " + "FlagWithInput=input FlagWithOutput=__SBOX_SANDBOX_DIR__/out/output " + "FlagWithRspFileInputList=out_local/soong/rsp Input __SBOX_SANDBOX_DIR__/out/Output " + - "__SBOX_SANDBOX_DIR__/out/SymlinkOutput Text __SBOX_SANDBOX_DIR__/tools/src/Tool after command2 old cmd", + "Text __SBOX_SANDBOX_DIR__/tools/src/Tool after command2 old cmd", "command2 __SBOX_SANDBOX_DIR__/out/depfile2 input2 __SBOX_SANDBOX_DIR__/out/output2 __SBOX_SANDBOX_DIR__/tools/src/tool2", "command3 input3 __SBOX_SANDBOX_DIR__/out/output2 __SBOX_SANDBOX_DIR__/out/output3 input3 __SBOX_SANDBOX_DIR__/out/output2", } @@ -457,7 +424,6 @@ func TestRuleBuilder(t *testing.T) { AssertDeepEquals(t, "rule.Inputs()", wantInputs, rule.Inputs()) AssertDeepEquals(t, "rule.RspfileInputs()", wantRspFileInputs, rule.RspFileInputs()) AssertDeepEquals(t, "rule.Outputs()", wantOutputs, rule.Outputs()) - AssertDeepEquals(t, "rule.SymlinkOutputs()", wantSymlinkOutputs, rule.SymlinkOutputs()) AssertDeepEquals(t, "rule.DepFiles()", wantDepFiles, rule.DepFiles()) AssertDeepEquals(t, "rule.Tools()", wantTools, rule.Tools()) AssertDeepEquals(t, "rule.OrderOnlys()", wantOrderOnlys, rule.OrderOnlys()) @@ -475,7 +441,7 @@ func TestRuleBuilder(t *testing.T) { "__SBOX_SANDBOX_DIR__/out/DepFile Flag FlagWithArg=arg FlagWithDepFile=__SBOX_SANDBOX_DIR__/out/depfile " + "FlagWithInput=input FlagWithOutput=__SBOX_SANDBOX_DIR__/out/output " + "FlagWithRspFileInputList=__SBOX_SANDBOX_DIR__/out/soong/rsp Input __SBOX_SANDBOX_DIR__/out/Output " + - "__SBOX_SANDBOX_DIR__/out/SymlinkOutput Text __SBOX_SANDBOX_DIR__/tools/src/Tool after command2 old cmd", + "Text __SBOX_SANDBOX_DIR__/tools/src/Tool after command2 old cmd", "command2 __SBOX_SANDBOX_DIR__/out/depfile2 input2 __SBOX_SANDBOX_DIR__/out/output2 __SBOX_SANDBOX_DIR__/tools/src/tool2", "command3 input3 __SBOX_SANDBOX_DIR__/out/output2 __SBOX_SANDBOX_DIR__/out/output3 input3 __SBOX_SANDBOX_DIR__/out/output2", } @@ -487,7 +453,6 @@ func TestRuleBuilder(t *testing.T) { AssertDeepEquals(t, "rule.Inputs()", wantInputs, rule.Inputs()) AssertDeepEquals(t, "rule.RspfileInputs()", wantRspFileInputs, rule.RspFileInputs()) AssertDeepEquals(t, "rule.Outputs()", wantOutputs, rule.Outputs()) - AssertDeepEquals(t, "rule.SymlinkOutputs()", wantSymlinkOutputs, rule.SymlinkOutputs()) AssertDeepEquals(t, "rule.DepFiles()", wantDepFiles, rule.DepFiles()) AssertDeepEquals(t, "rule.Tools()", wantTools, rule.Tools()) AssertDeepEquals(t, "rule.OrderOnlys()", wantOrderOnlys, rule.OrderOnlys()) diff --git a/android/singleton.go b/android/singleton.go index 47cfb2818..e0e552ebc 100644 --- a/android/singleton.go +++ b/android/singleton.go @@ -170,12 +170,7 @@ func (s *singletonContextAdaptor) Build(pctx PackageContext, params BuildParams) s.buildParams = append(s.buildParams, params) } bparams := convertBuildParams(params) - err := validateBuildParams(bparams) - if err != nil { - s.Errorf("%s: build parameter validation failed: %s", s.Name(), err.Error()) - } s.SingletonContext.Build(pctx.PackageContext, bparams) - } func (s *singletonContextAdaptor) Phony(name string, deps ...Path) { diff --git a/android/singleton_module_test.go b/android/singleton_module_test.go index 9d98478e2..3b1bf39e3 100644 --- a/android/singleton_module_test.go +++ b/android/singleton_module_test.go @@ -103,6 +103,9 @@ func testVariantSingletonModuleMutator(ctx BottomUpMutatorContext) { } func TestVariantSingletonModule(t *testing.T) { + if testing.Short() { + t.Skip("test fails with data race enabled") + } bp := ` test_singleton_module { name: "test_singleton_module", diff --git a/android/team.go b/android/team.go new file mode 100644 index 000000000..df61f4021 --- /dev/null +++ b/android/team.go @@ -0,0 +1,58 @@ +// Copyright 2020 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 + +func init() { + RegisterTeamBuildComponents(InitRegistrationContext) +} + +func RegisterTeamBuildComponents(ctx RegistrationContext) { + ctx.RegisterModuleType("team", TeamFactory) +} + +var PrepareForTestWithTeamBuildComponents = GroupFixturePreparers( + FixtureRegisterWithContext(RegisterTeamBuildComponents), +) + +type teamProperties struct { + Trendy_team_id *string `json:"trendy_team_id"` +} + +type teamModule struct { + ModuleBase + DefaultableModuleBase + + properties teamProperties +} + +// Real work is done for the module that depends on us. +// If needed, the team can serialize the config to json/proto file as well. +func (t *teamModule) GenerateAndroidBuildActions(ctx ModuleContext) {} + +func (t *teamModule) TrendyTeamId(ctx ModuleContext) string { + return *t.properties.Trendy_team_id +} + +func TeamFactory() Module { + module := &teamModule{} + + base := module.base() + module.AddProperties(&base.nameProperties, &module.properties) + + InitAndroidModule(module) + InitDefaultableModule(module) + + return module +} diff --git a/android/team_proto/Android.bp b/android/team_proto/Android.bp new file mode 100644 index 000000000..061e77e03 --- /dev/null +++ b/android/team_proto/Android.bp @@ -0,0 +1,29 @@ +// Copyright 2022 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 { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +bootstrap_go_package { + name: "soong-android_team_proto", + pkgPath: "android/soong/android/team_proto", + deps: [ + "golang-protobuf-reflect-protoreflect", + "golang-protobuf-runtime-protoimpl", + ], + srcs: [ + "team.pb.go", + ], +} diff --git a/android/team_proto/OWNERS b/android/team_proto/OWNERS new file mode 100644 index 000000000..2beb4f47d --- /dev/null +++ b/android/team_proto/OWNERS @@ -0,0 +1,5 @@ +dariofreni@google.com +joeo@google.com +ronish@google.com +caditya@google.com +rbraunstein@google.com diff --git a/android/team_proto/regen.sh b/android/team_proto/regen.sh new file mode 100755 index 000000000..63b2016e1 --- /dev/null +++ b/android/team_proto/regen.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +aprotoc --go_out=paths=source_relative:. team.proto diff --git a/android/team_proto/team.pb.go b/android/team_proto/team.pb.go new file mode 100644 index 000000000..61260cf78 --- /dev/null +++ b/android/team_proto/team.pb.go @@ -0,0 +1,253 @@ +// 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. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.30.0 +// protoc v3.21.12 +// source: team.proto + +package team_proto + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type Team struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // REQUIRED: Name of the build target + TargetName *string `protobuf:"bytes,1,opt,name=target_name,json=targetName" json:"target_name,omitempty"` + // REQUIRED: Code location of the target. + // To be used to support legacy/backup systems that use OWNERS file and is + // also required for our dashboard to support per code location basis UI + Path *string `protobuf:"bytes,2,opt,name=path" json:"path,omitempty"` + // REQUIRED: Team ID of the team that owns this target. + TrendyTeamId *string `protobuf:"bytes,3,opt,name=trendy_team_id,json=trendyTeamId" json:"trendy_team_id,omitempty"` + // OPTIONAL: Files directly owned by this module. + File []string `protobuf:"bytes,4,rep,name=file" json:"file,omitempty"` +} + +func (x *Team) Reset() { + *x = Team{} + if protoimpl.UnsafeEnabled { + mi := &file_team_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Team) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Team) ProtoMessage() {} + +func (x *Team) ProtoReflect() protoreflect.Message { + mi := &file_team_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Team.ProtoReflect.Descriptor instead. +func (*Team) Descriptor() ([]byte, []int) { + return file_team_proto_rawDescGZIP(), []int{0} +} + +func (x *Team) GetTargetName() string { + if x != nil && x.TargetName != nil { + return *x.TargetName + } + return "" +} + +func (x *Team) GetPath() string { + if x != nil && x.Path != nil { + return *x.Path + } + return "" +} + +func (x *Team) GetTrendyTeamId() string { + if x != nil && x.TrendyTeamId != nil { + return *x.TrendyTeamId + } + return "" +} + +func (x *Team) GetFile() []string { + if x != nil { + return x.File + } + return nil +} + +type AllTeams struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Teams []*Team `protobuf:"bytes,1,rep,name=teams" json:"teams,omitempty"` +} + +func (x *AllTeams) Reset() { + *x = AllTeams{} + if protoimpl.UnsafeEnabled { + mi := &file_team_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AllTeams) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AllTeams) ProtoMessage() {} + +func (x *AllTeams) ProtoReflect() protoreflect.Message { + mi := &file_team_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AllTeams.ProtoReflect.Descriptor instead. +func (*AllTeams) Descriptor() ([]byte, []int) { + return file_team_proto_rawDescGZIP(), []int{1} +} + +func (x *AllTeams) GetTeams() []*Team { + if x != nil { + return x.Teams + } + return nil +} + +var File_team_proto protoreflect.FileDescriptor + +var file_team_proto_rawDesc = []byte{ + 0x0a, 0x0a, 0x74, 0x65, 0x61, 0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x74, 0x65, + 0x61, 0x6d, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x75, 0x0a, 0x04, 0x54, 0x65, 0x61, 0x6d, + 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4e, 0x61, 0x6d, + 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x72, 0x65, 0x6e, 0x64, 0x79, 0x5f, + 0x74, 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x74, + 0x72, 0x65, 0x6e, 0x64, 0x79, 0x54, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x66, + 0x69, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x22, + 0x32, 0x0a, 0x08, 0x41, 0x6c, 0x6c, 0x54, 0x65, 0x61, 0x6d, 0x73, 0x12, 0x26, 0x0a, 0x05, 0x74, + 0x65, 0x61, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x74, 0x65, 0x61, + 0x6d, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x65, 0x61, 0x6d, 0x52, 0x05, 0x74, 0x65, + 0x61, 0x6d, 0x73, 0x42, 0x22, 0x5a, 0x20, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, + 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x74, 0x65, 0x61, + 0x6d, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, +} + +var ( + file_team_proto_rawDescOnce sync.Once + file_team_proto_rawDescData = file_team_proto_rawDesc +) + +func file_team_proto_rawDescGZIP() []byte { + file_team_proto_rawDescOnce.Do(func() { + file_team_proto_rawDescData = protoimpl.X.CompressGZIP(file_team_proto_rawDescData) + }) + return file_team_proto_rawDescData +} + +var file_team_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_team_proto_goTypes = []interface{}{ + (*Team)(nil), // 0: team_proto.Team + (*AllTeams)(nil), // 1: team_proto.AllTeams +} +var file_team_proto_depIdxs = []int32{ + 0, // 0: team_proto.AllTeams.teams:type_name -> team_proto.Team + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_team_proto_init() } +func file_team_proto_init() { + if File_team_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_team_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Team); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_team_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AllTeams); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_team_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_team_proto_goTypes, + DependencyIndexes: file_team_proto_depIdxs, + MessageInfos: file_team_proto_msgTypes, + }.Build() + File_team_proto = out.File + file_team_proto_rawDesc = nil + file_team_proto_goTypes = nil + file_team_proto_depIdxs = nil +} diff --git a/android/team_proto/team.proto b/android/team_proto/team.proto new file mode 100644 index 000000000..401eccc6e --- /dev/null +++ b/android/team_proto/team.proto @@ -0,0 +1,34 @@ +// 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. + +syntax = "proto2"; +package team_proto; +option go_package = "android/soong/android/team_proto"; + +message Team { + // REQUIRED: Name of the build target + optional string target_name = 1; + + // REQUIRED: Code location of the target. + // To be used to support legacy/backup systems that use OWNERS file and is + // also required for our dashboard to support per code location basis UI + optional string path = 2; + + // REQUIRED: Team ID of the team that owns this target. + optional string trendy_team_id = 3; + + // OPTIONAL: Files directly owned by this module. + repeated string file = 4; +} + +message AllTeams { + repeated Team teams = 1; +} diff --git a/android/team_test.go b/android/team_test.go new file mode 100644 index 000000000..75b3e9fbb --- /dev/null +++ b/android/team_test.go @@ -0,0 +1,99 @@ +// Copyright 2024 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" +) + +type fakeModuleForTests struct { + ModuleBase +} + +func fakeModuleFactory() Module { + module := &fakeModuleForTests{} + InitAndroidModule(module) + return module +} + +func (*fakeModuleForTests) GenerateAndroidBuildActions(ModuleContext) {} + +func TestTeam(t *testing.T) { + t.Parallel() + ctx := GroupFixturePreparers( + PrepareForTestWithTeamBuildComponents, + FixtureRegisterWithContext(func(ctx RegistrationContext) { + ctx.RegisterModuleType("fake", fakeModuleFactory) + }), + ).RunTestWithBp(t, ` + fake { + name: "main_test", + team: "someteam", + } + team { + name: "someteam", + trendy_team_id: "cool_team", + } + + team { + name: "team2", + trendy_team_id: "22222", + } + + fake { + name: "tool", + team: "team2", + } + `) + + // Assert the rule from GenerateAndroidBuildActions exists. + m := ctx.ModuleForTests("main_test", "") + AssertStringEquals(t, "msg", m.Module().base().Team(), "someteam") + m = ctx.ModuleForTests("tool", "") + AssertStringEquals(t, "msg", m.Module().base().Team(), "team2") +} + +func TestMissingTeamFails(t *testing.T) { + t.Parallel() + GroupFixturePreparers( + PrepareForTestWithTeamBuildComponents, + FixtureRegisterWithContext(func(ctx RegistrationContext) { + ctx.RegisterModuleType("fake", fakeModuleFactory) + }), + ). + ExtendWithErrorHandler(FixtureExpectsAtLeastOneErrorMatchingPattern("depends on undefined module \"ring-bearer")). + RunTestWithBp(t, ` + fake { + name: "you_cannot_pass", + team: "ring-bearer", + } + `) +} + +func TestPackageBadTeamNameFails(t *testing.T) { + t.Parallel() + GroupFixturePreparers( + PrepareForTestWithTeamBuildComponents, + PrepareForTestWithPackageModule, + FixtureRegisterWithContext(func(ctx RegistrationContext) { + ctx.RegisterModuleType("fake", fakeModuleFactory) + }), + ). + ExtendWithErrorHandler(FixtureExpectsAtLeastOneErrorMatchingPattern("depends on undefined module \"ring-bearer")). + RunTestWithBp(t, ` + package { + default_team: "ring-bearer", + } + `) +} diff --git a/android/testing.go b/android/testing.go index 78afaa5fc..f88049c6a 100644 --- a/android/testing.go +++ b/android/testing.go @@ -725,7 +725,6 @@ type TestingBuildParams struct { // - Depfile // - Rspfile // - RspfileContent -// - SymlinkOutputs // - CommandDeps // - CommandOrderOnly // @@ -747,8 +746,6 @@ func (p TestingBuildParams) RelativeToTop() TestingBuildParams { bparams.Depfile = normalizeWritablePathRelativeToTop(bparams.Depfile) bparams.Output = normalizeWritablePathRelativeToTop(bparams.Output) bparams.Outputs = bparams.Outputs.RelativeToTop() - bparams.SymlinkOutput = normalizeWritablePathRelativeToTop(bparams.SymlinkOutput) - bparams.SymlinkOutputs = bparams.SymlinkOutputs.RelativeToTop() bparams.ImplicitOutput = normalizeWritablePathRelativeToTop(bparams.ImplicitOutput) bparams.ImplicitOutputs = bparams.ImplicitOutputs.RelativeToTop() bparams.Input = normalizePathRelativeToTop(bparams.Input) @@ -766,7 +763,6 @@ func (p TestingBuildParams) RelativeToTop() TestingBuildParams { rparams.Depfile = normalizeStringRelativeToTop(p.config, rparams.Depfile) rparams.Rspfile = normalizeStringRelativeToTop(p.config, rparams.Rspfile) rparams.RspfileContent = normalizeStringRelativeToTop(p.config, rparams.RspfileContent) - rparams.SymlinkOutputs = normalizeStringArrayRelativeToTop(p.config, rparams.SymlinkOutputs) rparams.CommandDeps = normalizeStringArrayRelativeToTop(p.config, rparams.CommandDeps) rparams.CommandOrderOnly = normalizeStringArrayRelativeToTop(p.config, rparams.CommandOrderOnly) diff --git a/cc/config/global.go b/cc/config/global.go index 85ebd6076..5fed7f189 100644 --- a/cc/config/global.go +++ b/cc/config/global.go @@ -16,6 +16,7 @@ package config import ( "runtime" + "slices" "strings" "android/soong/android" @@ -271,7 +272,8 @@ var ( "-Wno-range-loop-construct", // http://b/153747076 "-Wno-zero-as-null-pointer-constant", // http://b/68236239 "-Wno-deprecated-anon-enum-enum-conversion", // http://b/153746485 - "-Wno-pessimizing-move", // http://b/154270751 + "-Wno-deprecated-enum-enum-conversion", + "-Wno-pessimizing-move", // http://b/154270751 // New warnings to be fixed after clang-r399163 "-Wno-non-c-typedef-for-linkage", // http://b/161304145 // New warnings to be fixed after clang-r428724 @@ -285,6 +287,13 @@ var ( // New warnings to be fixed after clang-r475365 "-Wno-error=single-bit-bitfield-constant-conversion", // http://b/243965903 "-Wno-error=enum-constexpr-conversion", // http://b/243964282 + + // Irrelevant on Android because _we_ don't use exceptions, but causes + // lots of build noise because libcxx/libcxxabi do. This can probably + // go away when we're on a new enough libc++, but has to be global + // until then because it causes warnings in the _callers_, not the + // project itself. + "-Wno-deprecated-dynamic-exception-spec", } noOverride64GlobalCflags = []string{} @@ -319,6 +328,9 @@ var ( // http://b/239661264 "-Wno-deprecated-non-prototype", + + "-Wno-unused", + "-Wno-deprecated", } // Similar to noOverrideGlobalCflags, but applies only to third-party code @@ -400,7 +412,7 @@ func init() { exportedVars.ExportStringList("CommonGlobalCflags", commonGlobalCflags) pctx.VariableFunc("CommonGlobalCflags", func(ctx android.PackageVarContext) string { - flags := commonGlobalCflags + flags := slices.Clone(commonGlobalCflags) // http://b/131390872 // Automatically initialize any uninitialized stack variables. diff --git a/cc/config/riscv64_device.go b/cc/config/riscv64_device.go index ac5f74cc8..deb922bd2 100644 --- a/cc/config/riscv64_device.go +++ b/cc/config/riscv64_device.go @@ -30,7 +30,9 @@ var ( "-Xclang -target-feature -Xclang +unaligned-scalar-mem", "-Xclang -target-feature -Xclang +unaligned-vector-mem", // Until https://gitlab.com/qemu-project/qemu/-/issues/1976 is fixed... - "-fno-vectorize", + "-mno-implicit-float", + // (https://github.com/google/android-riscv64/issues/124) + "-mllvm -jump-is-expensive=false", } riscv64ArchVariantCflags = map[string][]string{} @@ -43,7 +45,7 @@ var ( "-Xclang -target-feature -Xclang +unaligned-vector-mem", // We should change the default for this in clang, but for now... // (https://github.com/google/android-riscv64/issues/124) - "-mllvm -jump-is-expensive=false", + "-Wl,-mllvm -Wl,-jump-is-expensive=false", } riscv64Lldflags = append(riscv64Ldflags, diff --git a/filesystem/avb_add_hash_footer.go b/filesystem/avb_add_hash_footer.go index ead579fc4..469f1fb0a 100644 --- a/filesystem/avb_add_hash_footer.go +++ b/filesystem/avb_add_hash_footer.go @@ -138,7 +138,7 @@ func (a *avbAddHashFooter) GenerateAndroidBuildActions(ctx android.ModuleContext if rollbackIndex < 0 { ctx.PropertyErrorf("rollback_index", "Rollback index must be non-negative") } - cmd.Flag(fmt.Sprintf(" --rollback_index %x", rollbackIndex)) + cmd.Flag(fmt.Sprintf(" --rollback_index %d", rollbackIndex)) } cmd.FlagWithOutput("--image ", a.output) diff --git a/finder/finder_test.go b/finder/finder_test.go index 8f73719a6..be22d13b6 100644 --- a/finder/finder_test.go +++ b/finder/finder_test.go @@ -813,6 +813,7 @@ func TestFileAdded(t *testing.T) { IncludeFiles: []string{"findme.txt"}, }, ) + finder.WaitForDbDump() filesystem.Clock.Tick() foundPaths := finder.FindNamedAt("/tmp", "findme.txt") finder.Shutdown() @@ -1445,6 +1446,7 @@ func TestUpdatingDbIffChanged(t *testing.T) { IncludeFiles: []string{"hi.txt"}, }, ) + finder.WaitForDbDump() filesystem.Clock.Tick() foundPaths := finder.FindAll() finder.Shutdown() @@ -1506,6 +1508,7 @@ func TestDirectoryNotPermitted(t *testing.T) { IncludeFiles: []string{"hi.txt"}, }, ) + finder.WaitForDbDump() filesystem.Clock.Tick() foundPaths := finder.FindAll() finder.Shutdown() @@ -1552,6 +1555,7 @@ func TestFileNotPermitted(t *testing.T) { IncludeFiles: []string{"hi.txt"}, }, ) + finder.WaitForDbDump() filesystem.Clock.Tick() foundPaths := finder.FindAll() finder.Shutdown() @@ -1573,6 +1577,7 @@ func TestCacheEntryPathUnexpectedError(t *testing.T) { IncludeFiles: []string{"hi.txt"}, }, ) + finder.WaitForDbDump() filesystem.Clock.Tick() foundPaths := finder.FindAll() finder.Shutdown() diff --git a/java/aar.go b/java/aar.go index 7fc39b6da..b162ef639 100644 --- a/java/aar.go +++ b/java/aar.go @@ -44,7 +44,7 @@ func RegisterAARBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("android_library_import", AARImportFactory) ctx.RegisterModuleType("android_library", AndroidLibraryFactory) ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) { - ctx.TopDown("propagate_rro_enforcement", propagateRROEnforcementMutator).Parallel() + ctx.TopDown("propagate_rro_enforcement", propagateRROEnforcementMutator) }) } diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go index 82cece346..ec8b4c8b3 100644 --- a/java/dexpreopt_bootjars.go +++ b/java/dexpreopt_bootjars.go @@ -238,8 +238,7 @@ func init() { // // WARNING: All fields in this struct should be initialized in the genBootImageConfigs function. // Failure to do so can lead to data races if there is no synchronization enforced ordering between -// the writer and the reader. Fields which break this rule are marked as deprecated and should be -// removed and replaced with something else, e.g. providers. +// the writer and the reader. type bootImageConfig struct { // If this image is an extension, the image that it extends. extends *bootImageConfig @@ -279,16 +278,6 @@ type bootImageConfig struct { // File path to a zip archive with all image files (or nil, if not needed). zip android.WritablePath - // Rules which should be used in make to install the outputs. - // - // Deprecated: Not initialized correctly, see struct comment. - profileInstalls android.RuleBuilderInstalls - - // Path to the license metadata file for the module that built the profile. - // - // Deprecated: Not initialized correctly, see struct comment. - profileLicenseMetadataFile android.OptionalPath - // Target-dependent fields. variants []*bootImageVariant @@ -602,6 +591,7 @@ func (d *dexpreoptBootJars) GenerateAndroidBuildActions(ctx android.ModuleContex imageConfigs := genBootImageConfigs(ctx) d.defaultBootImage = defaultBootImageConfig(ctx) d.otherImages = make([]*bootImageConfig, 0, len(imageConfigs)-1) + var profileInstalls android.RuleBuilderInstalls for _, name := range getImageNames() { config := imageConfigs[name] if config != d.defaultBootImage { @@ -610,11 +600,19 @@ func (d *dexpreoptBootJars) GenerateAndroidBuildActions(ctx android.ModuleContex if !config.isEnabled(ctx) { continue } - generateBootImage(ctx, config) + installs := generateBootImage(ctx, config) + profileInstalls = append(profileInstalls, installs...) if config == d.defaultBootImage { - bootFrameworkProfileRule(ctx, config) + _, installs := bootFrameworkProfileRule(ctx, config) + profileInstalls = append(profileInstalls, installs...) } } + if len(profileInstalls) > 0 { + android.SetProvider(ctx, profileInstallInfoProvider, profileInstallInfo{ + profileInstalls: profileInstalls, + profileLicenseMetadataFile: android.OptionalPathForPath(ctx.LicenseMetadataFile()), + }) + } } // GenerateSingletonBuildActions generates build rules for the dexpreopt config for Make. @@ -635,7 +633,7 @@ func shouldBuildBootImages(config android.Config, global *dexpreopt.GlobalConfig return true } -func generateBootImage(ctx android.ModuleContext, imageConfig *bootImageConfig) { +func generateBootImage(ctx android.ModuleContext, imageConfig *bootImageConfig) android.RuleBuilderInstalls { apexJarModulePairs := getModulesForImage(ctx, imageConfig) // Copy module dex jars to their predefined locations. @@ -644,12 +642,12 @@ func generateBootImage(ctx android.ModuleContext, imageConfig *bootImageConfig) // Build a profile for the image config from the profile at the default path. The profile will // then be used along with profiles imported from APEXes to build the boot image. - profile := bootImageProfileRule(ctx, imageConfig) + profile, profileInstalls := bootImageProfileRule(ctx, imageConfig) // If dexpreopt of boot image jars should be skipped, stop after generating a profile. global := dexpreopt.GetGlobalConfig(ctx) if SkipDexpreoptBootJars(ctx) || (global.OnlyPreoptArtBootImage && imageConfig.name != "art") { - return + return profileInstalls } // Build boot image files for the android variants. @@ -663,6 +661,8 @@ func generateBootImage(ctx android.ModuleContext, imageConfig *bootImageConfig) // Create a `dump-oat-<image-name>` rule that runs `oatdump` for debugging purposes. dumpOatRules(ctx, imageConfig) + + return profileInstalls } type apexJarModulePair struct { @@ -1177,9 +1177,19 @@ func bootImageProfileRuleCommon(ctx android.ModuleContext, name string, dexFiles return profile } -func bootImageProfileRule(ctx android.ModuleContext, image *bootImageConfig) android.WritablePath { +type profileInstallInfo struct { + // Rules which should be used in make to install the outputs. + profileInstalls android.RuleBuilderInstalls + + // Path to the license metadata file for the module that built the profile. + profileLicenseMetadataFile android.OptionalPath +} + +var profileInstallInfoProvider = blueprint.NewProvider[profileInstallInfo]() + +func bootImageProfileRule(ctx android.ModuleContext, image *bootImageConfig) (android.WritablePath, android.RuleBuilderInstalls) { if !image.isProfileGuided() { - return nil + return nil, nil } profile := bootImageProfileRuleCommon(ctx, image.name, image.dexPathsDeps.Paths(), image.getAnyAndroidVariant().dexLocationsDeps) @@ -1187,21 +1197,19 @@ func bootImageProfileRule(ctx android.ModuleContext, image *bootImageConfig) and if image == defaultBootImageConfig(ctx) { rule := android.NewRuleBuilder(pctx, ctx) rule.Install(profile, "/system/etc/boot-image.prof") - image.profileInstalls = append(image.profileInstalls, rule.Installs()...) - image.profileLicenseMetadataFile = android.OptionalPathForPath(ctx.LicenseMetadataFile()) + return profile, rule.Installs() } - - return profile + return profile, nil } // bootFrameworkProfileRule generates the rule to create the boot framework profile and // returns a path to the generated file. -func bootFrameworkProfileRule(ctx android.ModuleContext, image *bootImageConfig) android.WritablePath { +func bootFrameworkProfileRule(ctx android.ModuleContext, image *bootImageConfig) (android.WritablePath, android.RuleBuilderInstalls) { globalSoong := dexpreopt.GetGlobalSoongConfig(ctx) global := dexpreopt.GetGlobalConfig(ctx) if global.DisableGenerateProfile || ctx.Config().UnbundledBuild() { - return nil + return nil, nil } defaultProfile := "frameworks/base/config/boot-profile.txt" @@ -1221,10 +1229,7 @@ func bootFrameworkProfileRule(ctx android.ModuleContext, image *bootImageConfig) rule.Install(profile, "/system/etc/boot-image.bprof") rule.Build("bootFrameworkProfile", "profile boot framework jars") - image.profileInstalls = append(image.profileInstalls, rule.Installs()...) - image.profileLicenseMetadataFile = android.OptionalPathForPath(ctx.LicenseMetadataFile()) - - return profile + return profile, rule.Installs() } func dumpOatRules(ctx android.ModuleContext, image *bootImageConfig) { @@ -1292,9 +1297,11 @@ func (d *dexpreoptBootJars) MakeVars(ctx android.MakeVarsContext) { image := d.defaultBootImage if image != nil { - ctx.Strict("DEXPREOPT_IMAGE_PROFILE_BUILT_INSTALLED", image.profileInstalls.String()) - if image.profileLicenseMetadataFile.Valid() { - ctx.Strict("DEXPREOPT_IMAGE_PROFILE_LICENSE_METADATA", image.profileLicenseMetadataFile.String()) + if profileInstallInfo, ok := android.SingletonModuleProvider(ctx, d, profileInstallInfoProvider); ok { + ctx.Strict("DEXPREOPT_IMAGE_PROFILE_BUILT_INSTALLED", profileInstallInfo.profileInstalls.String()) + if profileInstallInfo.profileLicenseMetadataFile.Valid() { + ctx.Strict("DEXPREOPT_IMAGE_PROFILE_LICENSE_METADATA", profileInstallInfo.profileLicenseMetadataFile.String()) + } } if SkipDexpreoptBootJars(ctx) { diff --git a/java/dexpreopt_config_testing.go b/java/dexpreopt_config_testing.go index 41d4b72a1..104829f5f 100644 --- a/java/dexpreopt_config_testing.go +++ b/java/dexpreopt_config_testing.go @@ -523,7 +523,7 @@ func checkArtBootImageConfig(t *testing.T, result *android.TestResult, mutated b }, } - checkBootImageConfig(t, imageConfig, mutated, expected) + checkBootImageConfig(t, result, imageConfig, mutated, expected) } // getFrameworkImageConfig gets the framework bootImageConfig that was created during the test. @@ -904,7 +904,7 @@ func checkFrameworkBootImageConfig(t *testing.T, result *android.TestResult, mut profileLicenseMetadataFile: expectedLicenseMetadataFile, } - checkBootImageConfig(t, imageConfig, mutated, expected) + checkBootImageConfig(t, result, imageConfig, mutated, expected) } // getMainlineImageConfig gets the framework bootImageConfig that was created during the test. @@ -1183,7 +1183,7 @@ func CheckMainlineBootImageConfig(t *testing.T, result *android.TestResult) { profileLicenseMetadataFile: expectedLicenseMetadataFile, } - checkBootImageConfig(t, imageConfig, false, expected) + checkBootImageConfig(t, result, imageConfig, false, expected) } // clearMutatedFields clears fields in the expectedConfig that correspond to fields in the @@ -1211,19 +1211,19 @@ func clearMutatedFields(expected *expectedConfig) { // zero value so that they will match the unmodified values in the boot image. // // It runs the checks in an image specific subtest of the current test. -func checkBootImageConfig(t *testing.T, imageConfig *bootImageConfig, mutated bool, expected *expectedConfig) { +func checkBootImageConfig(t *testing.T, result *android.TestResult, imageConfig *bootImageConfig, mutated bool, expected *expectedConfig) { if !mutated { clearMutatedFields(expected) } t.Run(imageConfig.name, func(t *testing.T) { - nestedCheckBootImageConfig(t, imageConfig, expected) + nestedCheckBootImageConfig(t, result, imageConfig, mutated, expected) }) } // nestedCheckBootImageConfig does the work of comparing the image against the expected values and // is run in an image specific subtest. -func nestedCheckBootImageConfig(t *testing.T, imageConfig *bootImageConfig, expected *expectedConfig) { +func nestedCheckBootImageConfig(t *testing.T, result *android.TestResult, imageConfig *bootImageConfig, mutated bool, expected *expectedConfig) { android.AssertStringEquals(t, "name", expected.name, imageConfig.name) android.AssertStringEquals(t, "stem", expected.stem, imageConfig.stem) android.AssertPathRelativeToTopEquals(t, "dir", expected.dir, imageConfig.dir) @@ -1234,8 +1234,13 @@ func nestedCheckBootImageConfig(t *testing.T, imageConfig *bootImageConfig, expe android.AssertPathsRelativeToTopEquals(t, "dexPathsDeps", expected.dexPathsDeps, imageConfig.dexPathsDeps.Paths()) // dexPathsByModule is just a different representation of the other information in the config. android.AssertPathRelativeToTopEquals(t, "zip", expected.zip, imageConfig.zip) - assertInstallsEqual(t, "profileInstalls", expected.profileInstalls, imageConfig.profileInstalls) - android.AssertStringEquals(t, "profileLicenseMetadataFile", expected.profileLicenseMetadataFile, imageConfig.profileLicenseMetadataFile.RelativeToTop().String()) + + if !mutated { + dexBootJarModule := result.ModuleForTests("dex_bootjars", "android_common") + profileInstallInfo, _ := android.SingletonModuleProvider(result, dexBootJarModule.Module(), profileInstallInfoProvider) + assertInstallsEqual(t, "profileInstalls", expected.profileInstalls, profileInstallInfo.profileInstalls) + android.AssertStringEquals(t, "profileLicenseMetadataFile", expected.profileLicenseMetadataFile, profileInstallInfo.profileLicenseMetadataFile.RelativeToTop().String()) + } android.AssertIntEquals(t, "variant count", 4, len(imageConfig.variants)) for i, variant := range imageConfig.variants { diff --git a/java/droiddoc.go b/java/droiddoc.go index 7a610344f..cfbf2b49c 100644 --- a/java/droiddoc.go +++ b/java/droiddoc.go @@ -182,6 +182,17 @@ func InitDroiddocModule(module android.DefaultableModule, hod android.HostOrDevi func apiCheckEnabled(ctx android.ModuleContext, apiToCheck ApiToCheck, apiVersionTag string) bool { if ctx.Config().IsEnvTrue("WITHOUT_CHECK_API") { + if ctx.Config().BuildFromTextStub() { + ctx.ModuleErrorf("Generating stubs from api signature files is not available " + + "with WITHOUT_CHECK_API=true, as sync between the source Java files and the " + + "api signature files is not guaranteed.\n" + + "In order to utilize WITHOUT_CHECK_API, generate stubs from the source Java " + + "files with BUILD_FROM_SOURCE_STUB=true.\n" + + "However, the usage of WITHOUT_CHECK_API is not preferred as the incremental " + + "build is slower when generating stubs from the source Java files.\n" + + "Consider updating the api signature files and generating the stubs from " + + "them instead.") + } return false } else if String(apiToCheck.Api_file) != "" && String(apiToCheck.Removed_api_file) != "" { return true diff --git a/java/droidstubs.go b/java/droidstubs.go index c2e822df8..6ef2afe0e 100644 --- a/java/droidstubs.go +++ b/java/droidstubs.go @@ -1155,7 +1155,8 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) { `either of the two choices above and try re-building the target.\n`+ `If the mismatch between the stubs and the current.txt is intended,\n`+ `you can try re-building the target by executing the following command:\n`+ - `m DISABLE_STUB_VALIDATION=true <your build target>\n`+ + `m DISABLE_STUB_VALIDATION=true <your build target>.\n`+ + `Note that DISABLE_STUB_VALIDATION=true does not bypass checkapi.\n`+ `******************************\n`, ctx.ModuleName()) rule.Command(). diff --git a/rust/config/global.go b/rust/config/global.go index 377ae585e..aebbb1b89 100644 --- a/rust/config/global.go +++ b/rust/config/global.go @@ -25,7 +25,7 @@ var ( pctx = android.NewPackageContext("android/soong/rust/config") ExportedVars = android.NewExportedVariables(pctx) - RustDefaultVersion = "1.73.0" + RustDefaultVersion = "1.74.1" RustDefaultBase = "prebuilts/rust/" DefaultEdition = "2021" Stdlibs = []string{ diff --git a/scripts/run-soong-tests-with-go-tools.sh b/scripts/run-soong-tests-with-go-tools.sh new file mode 100755 index 000000000..93c622ea4 --- /dev/null +++ b/scripts/run-soong-tests-with-go-tools.sh @@ -0,0 +1,79 @@ +#!/bin/bash -ex + +: "${OUT_DIR:?Must set OUT_DIR}" +TOP=$(cd $(dirname $0)/../../..; pwd) +cd ${TOP} + +UNAME="$(uname)" +case "$UNAME" in +Linux) + OS='linux' + ;; +Darwin) + OS='darwin' + ;; +*) + exit 1 + ;; +esac + +# Verify that go test and go build work on all the same projects that are parsed by +# build/soong/build_kzip.bash +declare -ar go_modules=(build/blueprint build/soong + build/make/tools/canoninja build/make/tools/compliance build/make/tools/rbcrun) +export GOROOT=${TOP}/prebuilts/go/${OS}-x86 +export GOENV=off +export GOPROXY=off +abs_out_dir=$(cd ${OUT_DIR}; pwd) +export GOPATH=${abs_out_dir}/gopath +export GOCACHE=${abs_out_dir}/gocache +export GOMODCACHE=${abs_out_dir}/gomodcache +export TMPDIR=${abs_out_dir}/gotemp +mkdir -p ${TMPDIR} +${GOROOT}/bin/go env + +if [[ ${OS} = linux ]]; then + # Building with the race detector enabled uses the host linker, set the + # path to use the hermetic one. + CLANG_VERSION=$(build/soong/scripts/get_clang_version.py) + export CC="${TOP}/prebuilts/clang/host/${OS}-x86/${CLANG_VERSION}/bin/clang" + export CXX="${TOP}/prebuilts/clang/host/${OS}-x86/${CLANG_VERSION}/bin/clang++" +fi + +# androidmk_test.go gets confused if ANDROID_BUILD_TOP is set. +unset ANDROID_BUILD_TOP + +network_jail="" +if [[ ${OS} = linux ]]; then + # The go tools often try to fetch dependencies from the network, + # wrap them in an nsjail to prevent network access. + network_jail=${TOP}/prebuilts/build-tools/linux-x86/bin/nsjail + # Quiet + network_jail="${network_jail} -q" + # No timeout + network_jail="${network_jail} -t 0" + # Set working directory + network_jail="${network_jail} --cwd=\$PWD" + # Pass environment variables through + network_jail="${network_jail} -e" + # Allow read-only access to everything + network_jail="${network_jail} -R /" + # Allow write access to the out directory + network_jail="${network_jail} -B ${abs_out_dir}" + # Allow write access to the /tmp directory + network_jail="${network_jail} -B /tmp" + # Set high values, as network_jail uses low defaults. + network_jail="${network_jail} --rlimit_as soft" + network_jail="${network_jail} --rlimit_core soft" + network_jail="${network_jail} --rlimit_cpu soft" + network_jail="${network_jail} --rlimit_fsize soft" + network_jail="${network_jail} --rlimit_nofile soft" +fi + +for dir in "${go_modules[@]}"; do + (cd "$dir"; + eval ${network_jail} -- ${GOROOT}/bin/go build ./... + eval ${network_jail} -- ${GOROOT}/bin/go test ./... + eval ${network_jail} -- ${GOROOT}/bin/go test -race -short ./... + ) +done diff --git a/snapshot/recovery_snapshot.go b/snapshot/recovery_snapshot.go index 8ff59cbcf..ab114b411 100644 --- a/snapshot/recovery_snapshot.go +++ b/snapshot/recovery_snapshot.go @@ -22,16 +22,14 @@ type RecoverySnapshotModuleInterface interface { ExcludeFromRecoverySnapshot() bool } -var recoverySnapshotSingleton = SnapshotSingleton{ - "recovery", // name - "SOONG_RECOVERY_SNAPSHOT_ZIP", // makeVar - android.OptionalPath{}, // snapshotZipFile - RecoverySnapshotImageSingleton, // Image - false, // Fake -} - func RecoverySnapshotSingleton() android.Singleton { - return &recoverySnapshotSingleton + return &SnapshotSingleton{ + "recovery", // name + "SOONG_RECOVERY_SNAPSHOT_ZIP", // makeVar + android.OptionalPath{}, // snapshotZipFile + RecoverySnapshotImageSingleton, // Image + false, // Fake + } } // Determine if a dir under source tree is an SoC-owned proprietary directory based diff --git a/snapshot/vendor_snapshot.go b/snapshot/vendor_snapshot.go index 4484c855d..3e5f54669 100644 --- a/snapshot/vendor_snapshot.go +++ b/snapshot/vendor_snapshot.go @@ -22,28 +22,24 @@ type VendorSnapshotModuleInterface interface { ExcludeFromVendorSnapshot() bool } -var vendorSnapshotSingleton = SnapshotSingleton{ - "vendor", // name - "SOONG_VENDOR_SNAPSHOT_ZIP", // makeVar - android.OptionalPath{}, // snapshotZipFile - VendorSnapshotImageSingleton, // Image - false, // Fake -} - -var vendorFakeSnapshotSingleton = SnapshotSingleton{ - "vendor", // name - "SOONG_VENDOR_FAKE_SNAPSHOT_ZIP", // makeVar - android.OptionalPath{}, // snapshotZipFile - VendorSnapshotImageSingleton, // Image - true, // Fake -} - func VendorSnapshotSingleton() android.Singleton { - return &vendorSnapshotSingleton + return &SnapshotSingleton{ + "vendor", // name + "SOONG_VENDOR_SNAPSHOT_ZIP", // makeVar + android.OptionalPath{}, // snapshotZipFile + VendorSnapshotImageSingleton, // Image + false, // Fake + } } func VendorFakeSnapshotSingleton() android.Singleton { - return &vendorFakeSnapshotSingleton + return &SnapshotSingleton{ + "vendor", // name + "SOONG_VENDOR_FAKE_SNAPSHOT_ZIP", // makeVar + android.OptionalPath{}, // snapshotZipFile + VendorSnapshotImageSingleton, // Image + true, // Fake + } } // Determine if a dir under source tree is an SoC-owned proprietary directory based diff --git a/ui/build/kati.go b/ui/build/kati.go index 31e744029..d599c99a7 100644 --- a/ui/build/kati.go +++ b/ui/build/kati.go @@ -100,8 +100,6 @@ func runKati(ctx Context, config Config, extraSuffix string, args []string, envF "--no_ninja_prelude", // Support declaring phony outputs in AOSP Ninja. "--use_ninja_phony_output", - // Support declaring symlink outputs in AOSP Ninja. - "--use_ninja_symlink_outputs", // Regenerate the Ninja file if environment inputs have changed. e.g. // CLI flags, .mk file timestamps, env vars, $(wildcard ..) and some // $(shell ..) results. |