xref: /aosp_15_r20/build/soong/android/all_teams.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1*333d2b36SAndroid Build Coastguard Workerpackage android
2*333d2b36SAndroid Build Coastguard Worker
3*333d2b36SAndroid Build Coastguard Workerimport (
4*333d2b36SAndroid Build Coastguard Worker	"path"
5*333d2b36SAndroid Build Coastguard Worker	"path/filepath"
6*333d2b36SAndroid Build Coastguard Worker
7*333d2b36SAndroid Build Coastguard Worker	"android/soong/android/team_proto"
8*333d2b36SAndroid Build Coastguard Worker
9*333d2b36SAndroid Build Coastguard Worker	"google.golang.org/protobuf/proto"
10*333d2b36SAndroid Build Coastguard Worker)
11*333d2b36SAndroid Build Coastguard Worker
12*333d2b36SAndroid Build Coastguard Workerconst ownershipDirectory = "ownership"
13*333d2b36SAndroid Build Coastguard Workerconst allTeamsFile = "all_teams.pb"
14*333d2b36SAndroid Build Coastguard Worker
15*333d2b36SAndroid Build Coastguard Workerfunc AllTeamsFactory() Singleton {
16*333d2b36SAndroid Build Coastguard Worker	return &allTeamsSingleton{}
17*333d2b36SAndroid Build Coastguard Worker}
18*333d2b36SAndroid Build Coastguard Worker
19*333d2b36SAndroid Build Coastguard Workerfunc init() {
20*333d2b36SAndroid Build Coastguard Worker	registerAllTeamBuildComponents(InitRegistrationContext)
21*333d2b36SAndroid Build Coastguard Worker}
22*333d2b36SAndroid Build Coastguard Worker
23*333d2b36SAndroid Build Coastguard Workerfunc registerAllTeamBuildComponents(ctx RegistrationContext) {
24*333d2b36SAndroid Build Coastguard Worker	ctx.RegisterParallelSingletonType("all_teams", AllTeamsFactory)
25*333d2b36SAndroid Build Coastguard Worker}
26*333d2b36SAndroid Build Coastguard Worker
27*333d2b36SAndroid Build Coastguard Worker// For each module, list the team or the bpFile the module is defined in.
28*333d2b36SAndroid Build Coastguard Workertype moduleTeamAndTestInfo struct {
29*333d2b36SAndroid Build Coastguard Worker	// Name field from bp file for the team
30*333d2b36SAndroid Build Coastguard Worker	teamName string
31*333d2b36SAndroid Build Coastguard Worker	// Blueprint file the module is located in.
32*333d2b36SAndroid Build Coastguard Worker	bpFile string
33*333d2b36SAndroid Build Coastguard Worker	// Is this module only used by tests.
34*333d2b36SAndroid Build Coastguard Worker	testOnly bool
35*333d2b36SAndroid Build Coastguard Worker	// Is this a directly testable target by running the module directly
36*333d2b36SAndroid Build Coastguard Worker	// or via tradefed.
37*333d2b36SAndroid Build Coastguard Worker	topLevelTestTarget bool
38*333d2b36SAndroid Build Coastguard Worker	// String name indicating the module, like `java_library` for reporting.
39*333d2b36SAndroid Build Coastguard Worker	kind string
40*333d2b36SAndroid Build Coastguard Worker}
41*333d2b36SAndroid Build Coastguard Worker
42*333d2b36SAndroid Build Coastguard Workertype allTeamsSingleton struct {
43*333d2b36SAndroid Build Coastguard Worker	// Path where the collected metadata is stored after successful validation.
44*333d2b36SAndroid Build Coastguard Worker	outputPath OutputPath
45*333d2b36SAndroid Build Coastguard Worker
46*333d2b36SAndroid Build Coastguard Worker	// Map of all package modules we visit during GenerateBuildActions
47*333d2b36SAndroid Build Coastguard Worker	packages map[string]packageProperties
48*333d2b36SAndroid Build Coastguard Worker	// Map of all team modules we visit during GenerateBuildActions
49*333d2b36SAndroid Build Coastguard Worker	teams map[string]teamProperties
50*333d2b36SAndroid Build Coastguard Worker	// Keeps track of team information or bp file for each module we visit.
51*333d2b36SAndroid Build Coastguard Worker	teams_for_mods map[string]moduleTeamAndTestInfo
52*333d2b36SAndroid Build Coastguard Worker}
53*333d2b36SAndroid Build Coastguard Worker
54*333d2b36SAndroid Build Coastguard Worker// See if there is a package module for the given bpFilePath with a team defined, if so return the team.
55*333d2b36SAndroid Build Coastguard Worker// If not ascend up to the parent directory and do the same.
56*333d2b36SAndroid Build Coastguard Workerfunc (t *allTeamsSingleton) lookupDefaultTeam(bpFilePath string) (teamProperties, bool) {
57*333d2b36SAndroid Build Coastguard Worker	// return the Default_team listed in the package if is there.
58*333d2b36SAndroid Build Coastguard Worker	if p, ok := t.packages[bpFilePath]; ok {
59*333d2b36SAndroid Build Coastguard Worker		if defaultTeam := p.Default_team; defaultTeam != nil {
60*333d2b36SAndroid Build Coastguard Worker			return t.teams[*defaultTeam], true
61*333d2b36SAndroid Build Coastguard Worker		}
62*333d2b36SAndroid Build Coastguard Worker	}
63*333d2b36SAndroid Build Coastguard Worker	// Strip a directory and go up.
64*333d2b36SAndroid Build Coastguard Worker	// Does android/paths.go basePath,SourcePath help?
65*333d2b36SAndroid Build Coastguard Worker	current, base := filepath.Split(bpFilePath)
66*333d2b36SAndroid Build Coastguard Worker	current = filepath.Clean(current) // removes trailing slash, convert "" -> "."
67*333d2b36SAndroid Build Coastguard Worker	parent, _ := filepath.Split(current)
68*333d2b36SAndroid Build Coastguard Worker	if current == "." {
69*333d2b36SAndroid Build Coastguard Worker		return teamProperties{}, false
70*333d2b36SAndroid Build Coastguard Worker	}
71*333d2b36SAndroid Build Coastguard Worker	return t.lookupDefaultTeam(filepath.Join(parent, base))
72*333d2b36SAndroid Build Coastguard Worker}
73*333d2b36SAndroid Build Coastguard Worker
74*333d2b36SAndroid Build Coastguard Worker// Visit all modules and collect all teams and use WriteFileRuleVerbatim
75*333d2b36SAndroid Build Coastguard Worker// to write it out.
76*333d2b36SAndroid Build Coastguard Workerfunc (t *allTeamsSingleton) GenerateBuildActions(ctx SingletonContext) {
77*333d2b36SAndroid Build Coastguard Worker	t.packages = make(map[string]packageProperties)
78*333d2b36SAndroid Build Coastguard Worker	t.teams = make(map[string]teamProperties)
79*333d2b36SAndroid Build Coastguard Worker	t.teams_for_mods = make(map[string]moduleTeamAndTestInfo)
80*333d2b36SAndroid Build Coastguard Worker
81*333d2b36SAndroid Build Coastguard Worker	ctx.VisitAllModules(func(module Module) {
82*333d2b36SAndroid Build Coastguard Worker		bpFile := ctx.BlueprintFile(module)
83*333d2b36SAndroid Build Coastguard Worker
84*333d2b36SAndroid Build Coastguard Worker		// Package Modules and Team Modules are stored in a map so we can look them up by name for
85*333d2b36SAndroid Build Coastguard Worker		// modules without a team.
86*333d2b36SAndroid Build Coastguard Worker		if pack, ok := module.(*packageModule); ok {
87*333d2b36SAndroid Build Coastguard Worker			// Packages don't have names, use the blueprint file as the key. we can't get qualifiedModuleId in t context.
88*333d2b36SAndroid Build Coastguard Worker			pkgKey := bpFile
89*333d2b36SAndroid Build Coastguard Worker			t.packages[pkgKey] = pack.properties
90*333d2b36SAndroid Build Coastguard Worker			return
91*333d2b36SAndroid Build Coastguard Worker		}
92*333d2b36SAndroid Build Coastguard Worker		if team, ok := module.(*teamModule); ok {
93*333d2b36SAndroid Build Coastguard Worker			t.teams[team.Name()] = team.properties
94*333d2b36SAndroid Build Coastguard Worker			return
95*333d2b36SAndroid Build Coastguard Worker		}
96*333d2b36SAndroid Build Coastguard Worker
97*333d2b36SAndroid Build Coastguard Worker		testModInfo := TestModuleInformation{}
98*333d2b36SAndroid Build Coastguard Worker		if tmi, ok := OtherModuleProvider(ctx, module, TestOnlyProviderKey); ok {
99*333d2b36SAndroid Build Coastguard Worker			testModInfo = tmi
100*333d2b36SAndroid Build Coastguard Worker		}
101*333d2b36SAndroid Build Coastguard Worker
102*333d2b36SAndroid Build Coastguard Worker		// Some modules, like java_test_host don't set the provider when the module isn't enabled:
103*333d2b36SAndroid Build Coastguard Worker		//                                                test_only, top_level
104*333d2b36SAndroid Build Coastguard Worker		//     AVFHostTestCases{os:linux_glibc,arch:common} {true true}
105*333d2b36SAndroid Build Coastguard Worker		//     AVFHostTestCases{os:windows,arch:common} {false false}
106*333d2b36SAndroid Build Coastguard Worker		// Generally variant information of true override false or unset.
107*333d2b36SAndroid Build Coastguard Worker		if testModInfo.TestOnly == false {
108*333d2b36SAndroid Build Coastguard Worker			if prevValue, exists := t.teams_for_mods[module.Name()]; exists {
109*333d2b36SAndroid Build Coastguard Worker				if prevValue.testOnly == true {
110*333d2b36SAndroid Build Coastguard Worker					return
111*333d2b36SAndroid Build Coastguard Worker				}
112*333d2b36SAndroid Build Coastguard Worker			}
113*333d2b36SAndroid Build Coastguard Worker		}
114*333d2b36SAndroid Build Coastguard Worker		entry := moduleTeamAndTestInfo{
115*333d2b36SAndroid Build Coastguard Worker			bpFile:             bpFile,
116*333d2b36SAndroid Build Coastguard Worker			testOnly:           testModInfo.TestOnly,
117*333d2b36SAndroid Build Coastguard Worker			topLevelTestTarget: testModInfo.TopLevelTarget,
118*333d2b36SAndroid Build Coastguard Worker			kind:               ctx.ModuleType(module),
119*333d2b36SAndroid Build Coastguard Worker			teamName:           module.base().Team(),
120*333d2b36SAndroid Build Coastguard Worker		}
121*333d2b36SAndroid Build Coastguard Worker		t.teams_for_mods[module.Name()] = entry
122*333d2b36SAndroid Build Coastguard Worker
123*333d2b36SAndroid Build Coastguard Worker	})
124*333d2b36SAndroid Build Coastguard Worker
125*333d2b36SAndroid Build Coastguard Worker	// Visit all modules again and lookup the team name in the package or parent package if the team
126*333d2b36SAndroid Build Coastguard Worker	// isn't assignged at the module level.
127*333d2b36SAndroid Build Coastguard Worker	allTeams := t.lookupTeamForAllModules()
128*333d2b36SAndroid Build Coastguard Worker
129*333d2b36SAndroid Build Coastguard Worker	t.outputPath = PathForOutput(ctx, ownershipDirectory, allTeamsFile)
130*333d2b36SAndroid Build Coastguard Worker	data, err := proto.Marshal(allTeams)
131*333d2b36SAndroid Build Coastguard Worker	if err != nil {
132*333d2b36SAndroid Build Coastguard Worker		ctx.Errorf("Unable to marshal team data. %s", err)
133*333d2b36SAndroid Build Coastguard Worker	}
134*333d2b36SAndroid Build Coastguard Worker
135*333d2b36SAndroid Build Coastguard Worker	WriteFileRuleVerbatim(ctx, t.outputPath, string(data))
136*333d2b36SAndroid Build Coastguard Worker	ctx.Phony("all_teams", t.outputPath)
137*333d2b36SAndroid Build Coastguard Worker}
138*333d2b36SAndroid Build Coastguard Worker
139*333d2b36SAndroid Build Coastguard Workerfunc (t *allTeamsSingleton) MakeVars(ctx MakeVarsContext) {
140*333d2b36SAndroid Build Coastguard Worker	ctx.DistForGoal("all_teams", t.outputPath)
141*333d2b36SAndroid Build Coastguard Worker}
142*333d2b36SAndroid Build Coastguard Worker
143*333d2b36SAndroid Build Coastguard Worker// Visit every (non-package, non-team) module and write out a proto containing
144*333d2b36SAndroid Build Coastguard Worker// either the declared team data for that module or the package default team data for that module.
145*333d2b36SAndroid Build Coastguard Workerfunc (t *allTeamsSingleton) lookupTeamForAllModules() *team_proto.AllTeams {
146*333d2b36SAndroid Build Coastguard Worker	teamsProto := make([]*team_proto.Team, len(t.teams_for_mods))
147*333d2b36SAndroid Build Coastguard Worker	for i, moduleName := range SortedKeys(t.teams_for_mods) {
148*333d2b36SAndroid Build Coastguard Worker		m, _ := t.teams_for_mods[moduleName]
149*333d2b36SAndroid Build Coastguard Worker		teamName := m.teamName
150*333d2b36SAndroid Build Coastguard Worker		var teamProperties teamProperties
151*333d2b36SAndroid Build Coastguard Worker		found := false
152*333d2b36SAndroid Build Coastguard Worker		if teamName != "" {
153*333d2b36SAndroid Build Coastguard Worker			teamProperties, found = t.teams[teamName]
154*333d2b36SAndroid Build Coastguard Worker		} else {
155*333d2b36SAndroid Build Coastguard Worker			teamProperties, found = t.lookupDefaultTeam(m.bpFile)
156*333d2b36SAndroid Build Coastguard Worker		}
157*333d2b36SAndroid Build Coastguard Worker		// Deal with one blueprint file including another by looking up the default
158*333d2b36SAndroid Build Coastguard Worker		// in the main Android.bp rather than one listed with "build = [My.bp]"
159*333d2b36SAndroid Build Coastguard Worker		if !found {
160*333d2b36SAndroid Build Coastguard Worker			teamProperties, found = t.lookupDefaultTeam(path.Join(path.Dir(m.bpFile), "Android.bp"))
161*333d2b36SAndroid Build Coastguard Worker		}
162*333d2b36SAndroid Build Coastguard Worker
163*333d2b36SAndroid Build Coastguard Worker		trendy_team_id := ""
164*333d2b36SAndroid Build Coastguard Worker		if found {
165*333d2b36SAndroid Build Coastguard Worker			trendy_team_id = *teamProperties.Trendy_team_id
166*333d2b36SAndroid Build Coastguard Worker		}
167*333d2b36SAndroid Build Coastguard Worker
168*333d2b36SAndroid Build Coastguard Worker		teamData := new(team_proto.Team)
169*333d2b36SAndroid Build Coastguard Worker		*teamData = team_proto.Team{
170*333d2b36SAndroid Build Coastguard Worker			TargetName:     proto.String(moduleName),
171*333d2b36SAndroid Build Coastguard Worker			Path:           proto.String(m.bpFile),
172*333d2b36SAndroid Build Coastguard Worker			TestOnly:       proto.Bool(m.testOnly),
173*333d2b36SAndroid Build Coastguard Worker			TopLevelTarget: proto.Bool(m.topLevelTestTarget),
174*333d2b36SAndroid Build Coastguard Worker			Kind:           proto.String(m.kind),
175*333d2b36SAndroid Build Coastguard Worker		}
176*333d2b36SAndroid Build Coastguard Worker		if trendy_team_id != "" {
177*333d2b36SAndroid Build Coastguard Worker			teamData.TrendyTeamId = proto.String(trendy_team_id)
178*333d2b36SAndroid Build Coastguard Worker		} else {
179*333d2b36SAndroid Build Coastguard Worker			// Clients rely on the TrendyTeamId optional field not being set.
180*333d2b36SAndroid Build Coastguard Worker		}
181*333d2b36SAndroid Build Coastguard Worker		teamsProto[i] = teamData
182*333d2b36SAndroid Build Coastguard Worker	}
183*333d2b36SAndroid Build Coastguard Worker	return &team_proto.AllTeams{Teams: teamsProto}
184*333d2b36SAndroid Build Coastguard Worker}
185