blob: d4bf7d0c43dbdf5b860c8bee86d4f65793cbf27f [file] [log] [blame]
Ronald Braunstein73b08ff2023-12-19 10:24:47 -08001package android
2
3import (
4 "android/soong/android/team_proto"
5 "path/filepath"
6
7 "google.golang.org/protobuf/proto"
8)
9
10const ownershipDirectory = "ownership"
11const allTeamsFile = "all_teams.pb"
12
13func AllTeamsFactory() Singleton {
14 return &allTeamsSingleton{}
15}
16
17func init() {
18 registerAllTeamBuildComponents(InitRegistrationContext)
19}
20
21func registerAllTeamBuildComponents(ctx RegistrationContext) {
22 ctx.RegisterParallelSingletonType("all_teams", AllTeamsFactory)
23}
24
25// For each module, list the team or the bpFile the module is defined in.
Ronald Braunsteinc5603092024-03-27 06:46:47 -070026type moduleTeamAndTestInfo struct {
27 // Name field from bp file for the team
Ronald Braunstein73b08ff2023-12-19 10:24:47 -080028 teamName string
Ronald Braunsteinc5603092024-03-27 06:46:47 -070029 // Blueprint file the module is located in.
30 bpFile string
31 // Is this module only used by tests.
32 testOnly bool
33 // Is this a directly testable target by running the module directly
34 // or via tradefed.
35 topLevelTestTarget bool
36 // String name indicating the module, like `java_library` for reporting.
37 kind string
Ronald Braunstein73b08ff2023-12-19 10:24:47 -080038}
39
40type allTeamsSingleton struct {
41 // Path where the collected metadata is stored after successful validation.
42 outputPath OutputPath
43
44 // Map of all package modules we visit during GenerateBuildActions
45 packages map[string]packageProperties
46 // Map of all team modules we visit during GenerateBuildActions
47 teams map[string]teamProperties
48 // Keeps track of team information or bp file for each module we visit.
Ronald Braunsteinc5603092024-03-27 06:46:47 -070049 teams_for_mods map[string]moduleTeamAndTestInfo
Ronald Braunstein73b08ff2023-12-19 10:24:47 -080050}
51
52// See if there is a package module for the given bpFilePath with a team defined, if so return the team.
53// If not ascend up to the parent directory and do the same.
Ronald Braunsteinc5603092024-03-27 06:46:47 -070054func (t *allTeamsSingleton) lookupDefaultTeam(bpFilePath string) (teamProperties, bool) {
Ronald Braunstein73b08ff2023-12-19 10:24:47 -080055 // return the Default_team listed in the package if is there.
Ronald Braunsteinc5603092024-03-27 06:46:47 -070056 if p, ok := t.packages[bpFilePath]; ok {
57 if defaultTeam := p.Default_team; defaultTeam != nil {
58 return t.teams[*defaultTeam], true
Ronald Braunstein73b08ff2023-12-19 10:24:47 -080059 }
60 }
61 // Strip a directory and go up.
62 // Does android/paths.go basePath,SourcePath help?
63 current, base := filepath.Split(bpFilePath)
64 current = filepath.Clean(current) // removes trailing slash, convert "" -> "."
65 parent, _ := filepath.Split(current)
66 if current == "." {
67 return teamProperties{}, false
68 }
Ronald Braunsteinc5603092024-03-27 06:46:47 -070069 return t.lookupDefaultTeam(filepath.Join(parent, base))
Ronald Braunstein73b08ff2023-12-19 10:24:47 -080070}
71
Ronald Braunsteinc5603092024-03-27 06:46:47 -070072// Visit all modules and collect all teams and use WriteFileRuleVerbatim
73// to write it out.
74func (t *allTeamsSingleton) GenerateBuildActions(ctx SingletonContext) {
75 t.packages = make(map[string]packageProperties)
76 t.teams = make(map[string]teamProperties)
77 t.teams_for_mods = make(map[string]moduleTeamAndTestInfo)
Ronald Braunstein73b08ff2023-12-19 10:24:47 -080078
79 ctx.VisitAllModules(func(module Module) {
Ronald Braunstein73b08ff2023-12-19 10:24:47 -080080 bpFile := ctx.BlueprintFile(module)
81
82 // Package Modules and Team Modules are stored in a map so we can look them up by name for
83 // modules without a team.
84 if pack, ok := module.(*packageModule); ok {
Ronald Braunsteinc5603092024-03-27 06:46:47 -070085 // 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 -080086 pkgKey := bpFile
Ronald Braunsteinc5603092024-03-27 06:46:47 -070087 t.packages[pkgKey] = pack.properties
Ronald Braunstein73b08ff2023-12-19 10:24:47 -080088 return
89 }
90 if team, ok := module.(*teamModule); ok {
Ronald Braunsteinc5603092024-03-27 06:46:47 -070091 t.teams[team.Name()] = team.properties
Ronald Braunstein73b08ff2023-12-19 10:24:47 -080092 return
93 }
94
Ronald Braunsteinc864b242024-04-16 07:33:52 -070095 testModInfo := TestModuleInformation{}
96 if tmi, ok := SingletonModuleProvider(ctx, module, TestOnlyProviderKey); ok {
97 testModInfo = tmi
98 }
99
100 // Some modules, like java_test_host don't set the provider when the module isn't enabled:
101 // test_only, top_level
102 // AVFHostTestCases{os:linux_glibc,arch:common} {true true}
103 // AVFHostTestCases{os:windows,arch:common} {false false}
104 // Generally variant information of true override false or unset.
105 if testModInfo.TestOnly == false {
106 if prevValue, exists := t.teams_for_mods[module.Name()]; exists {
107 if prevValue.testOnly == true {
108 return
109 }
110 }
111 }
Ronald Braunsteinc5603092024-03-27 06:46:47 -0700112 entry := moduleTeamAndTestInfo{
113 bpFile: bpFile,
114 testOnly: testModInfo.TestOnly,
115 topLevelTestTarget: testModInfo.TopLevelTarget,
116 kind: ctx.ModuleType(module),
117 teamName: module.base().Team(),
Ronald Braunstein73b08ff2023-12-19 10:24:47 -0800118 }
Ronald Braunsteinc5603092024-03-27 06:46:47 -0700119 t.teams_for_mods[module.Name()] = entry
120
Ronald Braunstein73b08ff2023-12-19 10:24:47 -0800121 })
122
123 // Visit all modules again and lookup the team name in the package or parent package if the team
124 // isn't assignged at the module level.
Ronald Braunsteinc5603092024-03-27 06:46:47 -0700125 allTeams := t.lookupTeamForAllModules()
Ronald Braunstein73b08ff2023-12-19 10:24:47 -0800126
Ronald Braunsteinc5603092024-03-27 06:46:47 -0700127 t.outputPath = PathForOutput(ctx, ownershipDirectory, allTeamsFile)
Ronald Braunstein73b08ff2023-12-19 10:24:47 -0800128 data, err := proto.Marshal(allTeams)
129 if err != nil {
130 ctx.Errorf("Unable to marshal team data. %s", err)
131 }
132
Ronald Braunsteinc5603092024-03-27 06:46:47 -0700133 WriteFileRuleVerbatim(ctx, t.outputPath, string(data))
134 ctx.Phony("all_teams", t.outputPath)
Ronald Braunstein73b08ff2023-12-19 10:24:47 -0800135}
136
Ronald Braunsteinc5603092024-03-27 06:46:47 -0700137func (t *allTeamsSingleton) MakeVars(ctx MakeVarsContext) {
138 ctx.DistForGoal("all_teams", t.outputPath)
Ronald Braunstein73b08ff2023-12-19 10:24:47 -0800139}
140
141// Visit every (non-package, non-team) module and write out a proto containing
142// either the declared team data for that module or the package default team data for that module.
Ronald Braunsteinc5603092024-03-27 06:46:47 -0700143func (t *allTeamsSingleton) lookupTeamForAllModules() *team_proto.AllTeams {
144 teamsProto := make([]*team_proto.Team, len(t.teams_for_mods))
145 for i, moduleName := range SortedKeys(t.teams_for_mods) {
146 m, _ := t.teams_for_mods[moduleName]
Ronald Braunstein73b08ff2023-12-19 10:24:47 -0800147 teamName := m.teamName
148 var teamProperties teamProperties
149 found := false
150 if teamName != "" {
Ronald Braunsteinc5603092024-03-27 06:46:47 -0700151 teamProperties, found = t.teams[teamName]
Ronald Braunstein73b08ff2023-12-19 10:24:47 -0800152 } else {
Ronald Braunsteinc5603092024-03-27 06:46:47 -0700153 teamProperties, found = t.lookupDefaultTeam(m.bpFile)
Ronald Braunstein73b08ff2023-12-19 10:24:47 -0800154 }
155
156 trendy_team_id := ""
157 if found {
158 trendy_team_id = *teamProperties.Trendy_team_id
159 }
160
Ronald Braunstein73b08ff2023-12-19 10:24:47 -0800161 teamData := new(team_proto.Team)
Ronald Braunsteinc5603092024-03-27 06:46:47 -0700162 *teamData = team_proto.Team{
163 TargetName: proto.String(moduleName),
164 Path: proto.String(m.bpFile),
165 TestOnly: proto.Bool(m.testOnly),
166 TopLevelTarget: proto.Bool(m.topLevelTestTarget),
167 Kind: proto.String(m.kind),
168 }
Ronald Braunstein73b08ff2023-12-19 10:24:47 -0800169 if trendy_team_id != "" {
Ronald Braunsteinc5603092024-03-27 06:46:47 -0700170 teamData.TrendyTeamId = proto.String(trendy_team_id)
Ronald Braunstein73b08ff2023-12-19 10:24:47 -0800171 } else {
172 // Clients rely on the TrendyTeamId optional field not being set.
Ronald Braunstein73b08ff2023-12-19 10:24:47 -0800173 }
174 teamsProto[i] = teamData
Ronald Braunstein73b08ff2023-12-19 10:24:47 -0800175 }
176 return &team_proto.AllTeams{Teams: teamsProto}
177}