blob: 01be396d5a6b372657af13bfe0522dc49ce00373 [file] [log] [blame]
Ronald Braunstein73b08ff2023-12-19 10:24:47 -08001package android
2
3import (
Ronald Braunstein4a2f3682024-08-15 13:34:46 -07004 "path"
Ronald Braunstein73b08ff2023-12-19 10:24:47 -08005 "path/filepath"
6
Yu Liu663e4502024-08-12 18:23:59 +00007 "android/soong/android/team_proto"
8
Ronald Braunstein73b08ff2023-12-19 10:24:47 -08009 "google.golang.org/protobuf/proto"
10)
11
12const ownershipDirectory = "ownership"
13const allTeamsFile = "all_teams.pb"
14
15func AllTeamsFactory() Singleton {
16 return &allTeamsSingleton{}
17}
18
19func init() {
20 registerAllTeamBuildComponents(InitRegistrationContext)
21}
22
23func registerAllTeamBuildComponents(ctx RegistrationContext) {
24 ctx.RegisterParallelSingletonType("all_teams", AllTeamsFactory)
25}
26
27// For each module, list the team or the bpFile the module is defined in.
Ronald Braunsteinc5603092024-03-27 06:46:47 -070028type moduleTeamAndTestInfo struct {
29 // Name field from bp file for the team
Ronald Braunstein73b08ff2023-12-19 10:24:47 -080030 teamName string
Ronald Braunsteinc5603092024-03-27 06:46:47 -070031 // Blueprint file the module is located in.
32 bpFile string
33 // Is this module only used by tests.
34 testOnly bool
35 // Is this a directly testable target by running the module directly
36 // or via tradefed.
37 topLevelTestTarget bool
38 // String name indicating the module, like `java_library` for reporting.
39 kind string
Ronald Braunstein73b08ff2023-12-19 10:24:47 -080040}
41
42type allTeamsSingleton struct {
43 // Path where the collected metadata is stored after successful validation.
44 outputPath OutputPath
45
46 // Map of all package modules we visit during GenerateBuildActions
47 packages map[string]packageProperties
48 // Map of all team modules we visit during GenerateBuildActions
49 teams map[string]teamProperties
50 // Keeps track of team information or bp file for each module we visit.
Ronald Braunsteinc5603092024-03-27 06:46:47 -070051 teams_for_mods map[string]moduleTeamAndTestInfo
Ronald Braunstein73b08ff2023-12-19 10:24:47 -080052}
53
54// See if there is a package module for the given bpFilePath with a team defined, if so return the team.
55// If not ascend up to the parent directory and do the same.
Ronald Braunsteinc5603092024-03-27 06:46:47 -070056func (t *allTeamsSingleton) lookupDefaultTeam(bpFilePath string) (teamProperties, bool) {
Ronald Braunstein73b08ff2023-12-19 10:24:47 -080057 // return the Default_team listed in the package if is there.
Ronald Braunsteinc5603092024-03-27 06:46:47 -070058 if p, ok := t.packages[bpFilePath]; ok {
59 if defaultTeam := p.Default_team; defaultTeam != nil {
60 return t.teams[*defaultTeam], true
Ronald Braunstein73b08ff2023-12-19 10:24:47 -080061 }
62 }
63 // Strip a directory and go up.
64 // Does android/paths.go basePath,SourcePath help?
65 current, base := filepath.Split(bpFilePath)
66 current = filepath.Clean(current) // removes trailing slash, convert "" -> "."
67 parent, _ := filepath.Split(current)
68 if current == "." {
69 return teamProperties{}, false
70 }
Ronald Braunsteinc5603092024-03-27 06:46:47 -070071 return t.lookupDefaultTeam(filepath.Join(parent, base))
Ronald Braunstein73b08ff2023-12-19 10:24:47 -080072}
73
Ronald Braunsteinc5603092024-03-27 06:46:47 -070074// Visit all modules and collect all teams and use WriteFileRuleVerbatim
75// to write it out.
76func (t *allTeamsSingleton) GenerateBuildActions(ctx SingletonContext) {
77 t.packages = make(map[string]packageProperties)
78 t.teams = make(map[string]teamProperties)
79 t.teams_for_mods = make(map[string]moduleTeamAndTestInfo)
Ronald Braunstein73b08ff2023-12-19 10:24:47 -080080
81 ctx.VisitAllModules(func(module Module) {
Ronald Braunstein73b08ff2023-12-19 10:24:47 -080082 bpFile := ctx.BlueprintFile(module)
83
84 // Package Modules and Team Modules are stored in a map so we can look them up by name for
85 // modules without a team.
86 if pack, ok := module.(*packageModule); ok {
Ronald Braunsteinc5603092024-03-27 06:46:47 -070087 // Packages don't have names, use the blueprint file as the key. we can't get qualifiedModuleId in t context.
Ronald Braunstein73b08ff2023-12-19 10:24:47 -080088 pkgKey := bpFile
Ronald Braunsteinc5603092024-03-27 06:46:47 -070089 t.packages[pkgKey] = pack.properties
Ronald Braunstein73b08ff2023-12-19 10:24:47 -080090 return
91 }
92 if team, ok := module.(*teamModule); ok {
Ronald Braunsteinc5603092024-03-27 06:46:47 -070093 t.teams[team.Name()] = team.properties
Ronald Braunstein73b08ff2023-12-19 10:24:47 -080094 return
95 }
96
Ronald Braunsteinc864b242024-04-16 07:33:52 -070097 testModInfo := TestModuleInformation{}
Yu Liu663e4502024-08-12 18:23:59 +000098 if tmi, ok := OtherModuleProvider(ctx, module, TestOnlyProviderKey); ok {
Ronald Braunsteinc864b242024-04-16 07:33:52 -070099 testModInfo = tmi
100 }
101
102 // Some modules, like java_test_host don't set the provider when the module isn't enabled:
103 // test_only, top_level
104 // AVFHostTestCases{os:linux_glibc,arch:common} {true true}
105 // AVFHostTestCases{os:windows,arch:common} {false false}
106 // Generally variant information of true override false or unset.
107 if testModInfo.TestOnly == false {
108 if prevValue, exists := t.teams_for_mods[module.Name()]; exists {
109 if prevValue.testOnly == true {
110 return
111 }
112 }
113 }
Ronald Braunsteinc5603092024-03-27 06:46:47 -0700114 entry := moduleTeamAndTestInfo{
115 bpFile: bpFile,
116 testOnly: testModInfo.TestOnly,
117 topLevelTestTarget: testModInfo.TopLevelTarget,
118 kind: ctx.ModuleType(module),
119 teamName: module.base().Team(),
Ronald Braunstein73b08ff2023-12-19 10:24:47 -0800120 }
Ronald Braunsteinc5603092024-03-27 06:46:47 -0700121 t.teams_for_mods[module.Name()] = entry
122
Ronald Braunstein73b08ff2023-12-19 10:24:47 -0800123 })
124
125 // Visit all modules again and lookup the team name in the package or parent package if the team
126 // isn't assignged at the module level.
Ronald Braunsteinc5603092024-03-27 06:46:47 -0700127 allTeams := t.lookupTeamForAllModules()
Ronald Braunstein73b08ff2023-12-19 10:24:47 -0800128
Ronald Braunsteinc5603092024-03-27 06:46:47 -0700129 t.outputPath = PathForOutput(ctx, ownershipDirectory, allTeamsFile)
Ronald Braunstein73b08ff2023-12-19 10:24:47 -0800130 data, err := proto.Marshal(allTeams)
131 if err != nil {
132 ctx.Errorf("Unable to marshal team data. %s", err)
133 }
134
Ronald Braunsteinc5603092024-03-27 06:46:47 -0700135 WriteFileRuleVerbatim(ctx, t.outputPath, string(data))
136 ctx.Phony("all_teams", t.outputPath)
Ronald Braunstein73b08ff2023-12-19 10:24:47 -0800137}
138
Ronald Braunsteinc5603092024-03-27 06:46:47 -0700139func (t *allTeamsSingleton) MakeVars(ctx MakeVarsContext) {
140 ctx.DistForGoal("all_teams", t.outputPath)
Ronald Braunstein73b08ff2023-12-19 10:24:47 -0800141}
142
143// Visit every (non-package, non-team) module and write out a proto containing
144// either the declared team data for that module or the package default team data for that module.
Ronald Braunsteinc5603092024-03-27 06:46:47 -0700145func (t *allTeamsSingleton) lookupTeamForAllModules() *team_proto.AllTeams {
146 teamsProto := make([]*team_proto.Team, len(t.teams_for_mods))
147 for i, moduleName := range SortedKeys(t.teams_for_mods) {
148 m, _ := t.teams_for_mods[moduleName]
Ronald Braunstein73b08ff2023-12-19 10:24:47 -0800149 teamName := m.teamName
150 var teamProperties teamProperties
151 found := false
152 if teamName != "" {
Ronald Braunsteinc5603092024-03-27 06:46:47 -0700153 teamProperties, found = t.teams[teamName]
Ronald Braunstein73b08ff2023-12-19 10:24:47 -0800154 } else {
Ronald Braunsteinc5603092024-03-27 06:46:47 -0700155 teamProperties, found = t.lookupDefaultTeam(m.bpFile)
Ronald Braunstein73b08ff2023-12-19 10:24:47 -0800156 }
Ronald Braunstein4a2f3682024-08-15 13:34:46 -0700157 // Deal with one blueprint file including another by looking up the default
158 // in the main Android.bp rather than one listed with "build = [My.bp]"
159 if !found {
160 teamProperties, found = t.lookupDefaultTeam(path.Join(path.Dir(m.bpFile), "Android.bp"))
161 }
Ronald Braunstein73b08ff2023-12-19 10:24:47 -0800162
163 trendy_team_id := ""
164 if found {
165 trendy_team_id = *teamProperties.Trendy_team_id
166 }
167
Ronald Braunstein73b08ff2023-12-19 10:24:47 -0800168 teamData := new(team_proto.Team)
Ronald Braunsteinc5603092024-03-27 06:46:47 -0700169 *teamData = team_proto.Team{
170 TargetName: proto.String(moduleName),
171 Path: proto.String(m.bpFile),
172 TestOnly: proto.Bool(m.testOnly),
173 TopLevelTarget: proto.Bool(m.topLevelTestTarget),
174 Kind: proto.String(m.kind),
175 }
Ronald Braunstein73b08ff2023-12-19 10:24:47 -0800176 if trendy_team_id != "" {
Ronald Braunsteinc5603092024-03-27 06:46:47 -0700177 teamData.TrendyTeamId = proto.String(trendy_team_id)
Ronald Braunstein73b08ff2023-12-19 10:24:47 -0800178 } else {
179 // Clients rely on the TrendyTeamId optional field not being set.
Ronald Braunstein73b08ff2023-12-19 10:24:47 -0800180 }
181 teamsProto[i] = teamData
Ronald Braunstein73b08ff2023-12-19 10:24:47 -0800182 }
183 return &team_proto.AllTeams{Teams: teamsProto}
184}