xref: /aosp_15_r20/build/make/tools/compliance/graph.go (revision 9e94795a3d4ef5c1d47486f9a02bb378756cea8a)
1*9e94795aSAndroid Build Coastguard Worker// Copyright 2021 Google LLC
2*9e94795aSAndroid Build Coastguard Worker//
3*9e94795aSAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License");
4*9e94795aSAndroid Build Coastguard Worker// you may not use this file except in compliance with the License.
5*9e94795aSAndroid Build Coastguard Worker// You may obtain a copy of the License at
6*9e94795aSAndroid Build Coastguard Worker//
7*9e94795aSAndroid Build Coastguard Worker//      http://www.apache.org/licenses/LICENSE-2.0
8*9e94795aSAndroid Build Coastguard Worker//
9*9e94795aSAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software
10*9e94795aSAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS,
11*9e94795aSAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*9e94795aSAndroid Build Coastguard Worker// See the License for the specific language governing permissions and
13*9e94795aSAndroid Build Coastguard Worker// limitations under the License.
14*9e94795aSAndroid Build Coastguard Worker
15*9e94795aSAndroid Build Coastguard Workerpackage compliance
16*9e94795aSAndroid Build Coastguard Worker
17*9e94795aSAndroid Build Coastguard Workerimport (
18*9e94795aSAndroid Build Coastguard Worker	"fmt"
19*9e94795aSAndroid Build Coastguard Worker	"sort"
20*9e94795aSAndroid Build Coastguard Worker	"strings"
21*9e94795aSAndroid Build Coastguard Worker	"sync"
22*9e94795aSAndroid Build Coastguard Worker)
23*9e94795aSAndroid Build Coastguard Worker
24*9e94795aSAndroid Build Coastguard Worker// LicenseGraph describes the immutable license metadata for a set of root
25*9e94795aSAndroid Build Coastguard Worker// targets and the transitive closure of their dependencies.
26*9e94795aSAndroid Build Coastguard Worker//
27*9e94795aSAndroid Build Coastguard Worker// Alternatively, a graph is a set of edges. In this case directed, annotated
28*9e94795aSAndroid Build Coastguard Worker// edges from targets to dependencies.
29*9e94795aSAndroid Build Coastguard Worker//
30*9e94795aSAndroid Build Coastguard Worker// A LicenseGraph provides the frame of reference for all of the other types
31*9e94795aSAndroid Build Coastguard Worker// defined here. It is possible to have multiple graphs, and to have targets,
32*9e94795aSAndroid Build Coastguard Worker// edges, and resolutions from multiple graphs. But it is an error to try to
33*9e94795aSAndroid Build Coastguard Worker// mix items from different graphs in the same operation.
34*9e94795aSAndroid Build Coastguard Worker// May panic if attempted.
35*9e94795aSAndroid Build Coastguard Worker//
36*9e94795aSAndroid Build Coastguard Worker// The compliance package assumes specific private implementations of each of
37*9e94795aSAndroid Build Coastguard Worker// these interfaces. May panic if attempts are made to combine different
38*9e94795aSAndroid Build Coastguard Worker// implementations of some interfaces with expected implementations of other
39*9e94795aSAndroid Build Coastguard Worker// interfaces here.
40*9e94795aSAndroid Build Coastguard Workertype LicenseGraph struct {
41*9e94795aSAndroid Build Coastguard Worker	// rootFiles identifies the original set of files to read. (immutable)
42*9e94795aSAndroid Build Coastguard Worker	//
43*9e94795aSAndroid Build Coastguard Worker	// Defines the starting "top" for top-down walks.
44*9e94795aSAndroid Build Coastguard Worker	//
45*9e94795aSAndroid Build Coastguard Worker	// Alternatively, an instance of licenseGraphImp conceptually defines a scope within
46*9e94795aSAndroid Build Coastguard Worker	// the universe of build graphs as a sub-graph rooted at rootFiles where all edges
47*9e94795aSAndroid Build Coastguard Worker	// and targets for the instance are defined relative to and within that scope. For
48*9e94795aSAndroid Build Coastguard Worker	// most analyses, the correct scope is to root the graph at all of the distributed
49*9e94795aSAndroid Build Coastguard Worker	// artifacts.
50*9e94795aSAndroid Build Coastguard Worker	rootFiles []string
51*9e94795aSAndroid Build Coastguard Worker
52*9e94795aSAndroid Build Coastguard Worker	// edges lists the directed edges in the graph from target to dependency. (guarded by mu)
53*9e94795aSAndroid Build Coastguard Worker	//
54*9e94795aSAndroid Build Coastguard Worker	// Alternatively, the graph is the set of `edges`.
55*9e94795aSAndroid Build Coastguard Worker	edges TargetEdgeList
56*9e94795aSAndroid Build Coastguard Worker
57*9e94795aSAndroid Build Coastguard Worker	// targets identifies, indexes, and describes the entire set of target node files.
58*9e94795aSAndroid Build Coastguard Worker	/// (guarded by mu)
59*9e94795aSAndroid Build Coastguard Worker	targets map[string]*TargetNode
60*9e94795aSAndroid Build Coastguard Worker
61*9e94795aSAndroid Build Coastguard Worker	// onceBottomUp makes sure the bottom-up resolve walk only happens one time.
62*9e94795aSAndroid Build Coastguard Worker	onceBottomUp sync.Once
63*9e94795aSAndroid Build Coastguard Worker
64*9e94795aSAndroid Build Coastguard Worker	// onceTopDown makes sure the top-down resolve walk only happens one time.
65*9e94795aSAndroid Build Coastguard Worker	onceTopDown sync.Once
66*9e94795aSAndroid Build Coastguard Worker
67*9e94795aSAndroid Build Coastguard Worker	// shippedNodes caches the results of a full walk of nodes identifying targets
68*9e94795aSAndroid Build Coastguard Worker	// distributed either directly or as derivative works. (creation guarded by mu)
69*9e94795aSAndroid Build Coastguard Worker	shippedNodes *TargetNodeSet
70*9e94795aSAndroid Build Coastguard Worker
71*9e94795aSAndroid Build Coastguard Worker	// mu guards against concurrent update.
72*9e94795aSAndroid Build Coastguard Worker	mu sync.Mutex
73*9e94795aSAndroid Build Coastguard Worker}
74*9e94795aSAndroid Build Coastguard Worker
75*9e94795aSAndroid Build Coastguard Worker// Edges returns the list of edges in the graph. (unordered)
76*9e94795aSAndroid Build Coastguard Workerfunc (lg *LicenseGraph) Edges() TargetEdgeList {
77*9e94795aSAndroid Build Coastguard Worker	edges := make(TargetEdgeList, 0, len(lg.edges))
78*9e94795aSAndroid Build Coastguard Worker	edges = append(edges, lg.edges...)
79*9e94795aSAndroid Build Coastguard Worker	return edges
80*9e94795aSAndroid Build Coastguard Worker}
81*9e94795aSAndroid Build Coastguard Worker
82*9e94795aSAndroid Build Coastguard Worker// Targets returns the list of target nodes in the graph. (unordered)
83*9e94795aSAndroid Build Coastguard Workerfunc (lg *LicenseGraph) Targets() TargetNodeList {
84*9e94795aSAndroid Build Coastguard Worker	targets := make(TargetNodeList, 0, len(lg.targets))
85*9e94795aSAndroid Build Coastguard Worker	for _, target := range lg.targets {
86*9e94795aSAndroid Build Coastguard Worker		targets = append(targets, target)
87*9e94795aSAndroid Build Coastguard Worker	}
88*9e94795aSAndroid Build Coastguard Worker	return targets
89*9e94795aSAndroid Build Coastguard Worker}
90*9e94795aSAndroid Build Coastguard Worker
91*9e94795aSAndroid Build Coastguard Worker// TargetNames returns the list of target node names in the graph. (unordered)
92*9e94795aSAndroid Build Coastguard Workerfunc (lg *LicenseGraph) TargetNames() []string {
93*9e94795aSAndroid Build Coastguard Worker	targets := make([]string, 0, len(lg.targets))
94*9e94795aSAndroid Build Coastguard Worker	for target := range lg.targets {
95*9e94795aSAndroid Build Coastguard Worker		targets = append(targets, target)
96*9e94795aSAndroid Build Coastguard Worker	}
97*9e94795aSAndroid Build Coastguard Worker	return targets
98*9e94795aSAndroid Build Coastguard Worker}
99*9e94795aSAndroid Build Coastguard Worker
100*9e94795aSAndroid Build Coastguard Worker// compliance-only LicenseGraph methods
101*9e94795aSAndroid Build Coastguard Worker
102*9e94795aSAndroid Build Coastguard Worker// newLicenseGraph constructs a new, empty instance of LicenseGraph.
103*9e94795aSAndroid Build Coastguard Workerfunc newLicenseGraph() *LicenseGraph {
104*9e94795aSAndroid Build Coastguard Worker	return &LicenseGraph{
105*9e94795aSAndroid Build Coastguard Worker		rootFiles: []string{},
106*9e94795aSAndroid Build Coastguard Worker		targets:   make(map[string]*TargetNode),
107*9e94795aSAndroid Build Coastguard Worker	}
108*9e94795aSAndroid Build Coastguard Worker}
109*9e94795aSAndroid Build Coastguard Worker
110*9e94795aSAndroid Build Coastguard Worker// TargetEdge describes a directed, annotated edge from a target to a
111*9e94795aSAndroid Build Coastguard Worker// dependency. (immutable)
112*9e94795aSAndroid Build Coastguard Worker//
113*9e94795aSAndroid Build Coastguard Worker// A LicenseGraph, above, is a set of TargetEdges.
114*9e94795aSAndroid Build Coastguard Worker//
115*9e94795aSAndroid Build Coastguard Worker// i.e. `Target` depends on `Dependency` in the manner described by
116*9e94795aSAndroid Build Coastguard Worker// `Annotations`.
117*9e94795aSAndroid Build Coastguard Workertype TargetEdge struct {
118*9e94795aSAndroid Build Coastguard Worker	// target and dependency identify the nodes connected by the edge.
119*9e94795aSAndroid Build Coastguard Worker	target, dependency *TargetNode
120*9e94795aSAndroid Build Coastguard Worker
121*9e94795aSAndroid Build Coastguard Worker	// annotations identifies the set of compliance-relevant annotations describing the edge.
122*9e94795aSAndroid Build Coastguard Worker	annotations TargetEdgeAnnotations
123*9e94795aSAndroid Build Coastguard Worker}
124*9e94795aSAndroid Build Coastguard Worker
125*9e94795aSAndroid Build Coastguard Worker// Target identifies the target that depends on the dependency.
126*9e94795aSAndroid Build Coastguard Worker//
127*9e94795aSAndroid Build Coastguard Worker// Target needs Dependency to build.
128*9e94795aSAndroid Build Coastguard Workerfunc (e *TargetEdge) Target() *TargetNode {
129*9e94795aSAndroid Build Coastguard Worker	return e.target
130*9e94795aSAndroid Build Coastguard Worker}
131*9e94795aSAndroid Build Coastguard Worker
132*9e94795aSAndroid Build Coastguard Worker// Dependency identifies the target depended on by the target.
133*9e94795aSAndroid Build Coastguard Worker//
134*9e94795aSAndroid Build Coastguard Worker// Dependency builds without Target, but Target needs Dependency to build.
135*9e94795aSAndroid Build Coastguard Workerfunc (e *TargetEdge) Dependency() *TargetNode {
136*9e94795aSAndroid Build Coastguard Worker	return e.dependency
137*9e94795aSAndroid Build Coastguard Worker}
138*9e94795aSAndroid Build Coastguard Worker
139*9e94795aSAndroid Build Coastguard Worker// Annotations describes the type of edge by the set of annotations attached to
140*9e94795aSAndroid Build Coastguard Worker// it.
141*9e94795aSAndroid Build Coastguard Worker//
142*9e94795aSAndroid Build Coastguard Worker// Only annotations prescribed by policy have any meaning for licensing, and
143*9e94795aSAndroid Build Coastguard Worker// the meaning for licensing is likewise prescribed by policy. Other annotations
144*9e94795aSAndroid Build Coastguard Worker// are preserved and ignored by policy.
145*9e94795aSAndroid Build Coastguard Workerfunc (e *TargetEdge) Annotations() TargetEdgeAnnotations {
146*9e94795aSAndroid Build Coastguard Worker	return e.annotations
147*9e94795aSAndroid Build Coastguard Worker}
148*9e94795aSAndroid Build Coastguard Worker
149*9e94795aSAndroid Build Coastguard Worker// IsRuntimeDependency returns true for edges representing shared libraries
150*9e94795aSAndroid Build Coastguard Worker// linked dynamically at runtime.
151*9e94795aSAndroid Build Coastguard Workerfunc (e *TargetEdge) IsRuntimeDependency() bool {
152*9e94795aSAndroid Build Coastguard Worker	return edgeIsDynamicLink(e)
153*9e94795aSAndroid Build Coastguard Worker}
154*9e94795aSAndroid Build Coastguard Worker
155*9e94795aSAndroid Build Coastguard Worker// IsDerivation returns true for edges where the target is a derivative
156*9e94795aSAndroid Build Coastguard Worker// work of dependency.
157*9e94795aSAndroid Build Coastguard Workerfunc (e *TargetEdge) IsDerivation() bool {
158*9e94795aSAndroid Build Coastguard Worker	return edgeIsDerivation(e)
159*9e94795aSAndroid Build Coastguard Worker}
160*9e94795aSAndroid Build Coastguard Worker
161*9e94795aSAndroid Build Coastguard Worker// IsBuildTool returns true for edges where the target is built
162*9e94795aSAndroid Build Coastguard Worker// by dependency.
163*9e94795aSAndroid Build Coastguard Workerfunc (e *TargetEdge) IsBuildTool() bool {
164*9e94795aSAndroid Build Coastguard Worker	return !edgeIsDerivation(e) && !edgeIsDynamicLink(e)
165*9e94795aSAndroid Build Coastguard Worker}
166*9e94795aSAndroid Build Coastguard Worker
167*9e94795aSAndroid Build Coastguard Worker// String returns a human-readable string representation of the edge.
168*9e94795aSAndroid Build Coastguard Workerfunc (e *TargetEdge) String() string {
169*9e94795aSAndroid Build Coastguard Worker	return fmt.Sprintf("%s -[%s]> %s", e.target.name, strings.Join(e.annotations.AsList(), ", "), e.dependency.name)
170*9e94795aSAndroid Build Coastguard Worker}
171*9e94795aSAndroid Build Coastguard Worker
172*9e94795aSAndroid Build Coastguard Worker// TargetEdgeList orders lists of edges by target then dependency then annotations.
173*9e94795aSAndroid Build Coastguard Workertype TargetEdgeList []*TargetEdge
174*9e94795aSAndroid Build Coastguard Worker
175*9e94795aSAndroid Build Coastguard Worker// Len returns the count of the elmements in the list.
176*9e94795aSAndroid Build Coastguard Workerfunc (l TargetEdgeList) Len() int { return len(l) }
177*9e94795aSAndroid Build Coastguard Worker
178*9e94795aSAndroid Build Coastguard Worker// Swap rearranges 2 elements so that each occupies the other's former position.
179*9e94795aSAndroid Build Coastguard Workerfunc (l TargetEdgeList) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
180*9e94795aSAndroid Build Coastguard Worker
181*9e94795aSAndroid Build Coastguard Worker// Less returns true when the `i`th element is lexicographically less than the `j`th.
182*9e94795aSAndroid Build Coastguard Workerfunc (l TargetEdgeList) Less(i, j int) bool {
183*9e94795aSAndroid Build Coastguard Worker	namei := l[i].target.name
184*9e94795aSAndroid Build Coastguard Worker	namej := l[j].target.name
185*9e94795aSAndroid Build Coastguard Worker	if namei == namej {
186*9e94795aSAndroid Build Coastguard Worker		namei = l[i].dependency.name
187*9e94795aSAndroid Build Coastguard Worker		namej = l[j].dependency.name
188*9e94795aSAndroid Build Coastguard Worker	}
189*9e94795aSAndroid Build Coastguard Worker	if namei == namej {
190*9e94795aSAndroid Build Coastguard Worker		return l[i].annotations.Compare(l[j].annotations) < 0
191*9e94795aSAndroid Build Coastguard Worker	}
192*9e94795aSAndroid Build Coastguard Worker	return namei < namej
193*9e94795aSAndroid Build Coastguard Worker}
194*9e94795aSAndroid Build Coastguard Worker
195*9e94795aSAndroid Build Coastguard Worker// TargetEdgePathSegment describes a single arc in a TargetPath associating the
196*9e94795aSAndroid Build Coastguard Worker// edge with a context `ctx` defined by whatever process is creating the path.
197*9e94795aSAndroid Build Coastguard Workertype TargetEdgePathSegment struct {
198*9e94795aSAndroid Build Coastguard Worker	edge *TargetEdge
199*9e94795aSAndroid Build Coastguard Worker	ctx  interface{}
200*9e94795aSAndroid Build Coastguard Worker}
201*9e94795aSAndroid Build Coastguard Worker
202*9e94795aSAndroid Build Coastguard Worker// Target identifies the target that depends on the dependency.
203*9e94795aSAndroid Build Coastguard Worker//
204*9e94795aSAndroid Build Coastguard Worker// Target needs Dependency to build.
205*9e94795aSAndroid Build Coastguard Workerfunc (s TargetEdgePathSegment) Target() *TargetNode {
206*9e94795aSAndroid Build Coastguard Worker	return s.edge.target
207*9e94795aSAndroid Build Coastguard Worker}
208*9e94795aSAndroid Build Coastguard Worker
209*9e94795aSAndroid Build Coastguard Worker// Dependency identifies the target depended on by the target.
210*9e94795aSAndroid Build Coastguard Worker//
211*9e94795aSAndroid Build Coastguard Worker// Dependency builds without Target, but Target needs Dependency to build.
212*9e94795aSAndroid Build Coastguard Workerfunc (s TargetEdgePathSegment) Dependency() *TargetNode {
213*9e94795aSAndroid Build Coastguard Worker	return s.edge.dependency
214*9e94795aSAndroid Build Coastguard Worker}
215*9e94795aSAndroid Build Coastguard Worker
216*9e94795aSAndroid Build Coastguard Worker// Edge describes the target edge.
217*9e94795aSAndroid Build Coastguard Workerfunc (s TargetEdgePathSegment) Edge() *TargetEdge {
218*9e94795aSAndroid Build Coastguard Worker	return s.edge
219*9e94795aSAndroid Build Coastguard Worker}
220*9e94795aSAndroid Build Coastguard Worker
221*9e94795aSAndroid Build Coastguard Worker// Annotations describes the type of edge by the set of annotations attached to
222*9e94795aSAndroid Build Coastguard Worker// it.
223*9e94795aSAndroid Build Coastguard Worker//
224*9e94795aSAndroid Build Coastguard Worker// Only annotations prescribed by policy have any meaning for licensing, and
225*9e94795aSAndroid Build Coastguard Worker// the meaning for licensing is likewise prescribed by policy. Other annotations
226*9e94795aSAndroid Build Coastguard Worker// are preserved and ignored by policy.
227*9e94795aSAndroid Build Coastguard Workerfunc (s TargetEdgePathSegment) Annotations() TargetEdgeAnnotations {
228*9e94795aSAndroid Build Coastguard Worker	return s.edge.annotations
229*9e94795aSAndroid Build Coastguard Worker}
230*9e94795aSAndroid Build Coastguard Worker
231*9e94795aSAndroid Build Coastguard Worker// Context returns the context associated with the path segment. The type and
232*9e94795aSAndroid Build Coastguard Worker// value of the context defined by the process creating the path.
233*9e94795aSAndroid Build Coastguard Workerfunc (s TargetEdgePathSegment) Context() interface{} {
234*9e94795aSAndroid Build Coastguard Worker	return s.ctx
235*9e94795aSAndroid Build Coastguard Worker}
236*9e94795aSAndroid Build Coastguard Worker
237*9e94795aSAndroid Build Coastguard Worker// String returns a human-readable string representation of the edge.
238*9e94795aSAndroid Build Coastguard Workerfunc (s TargetEdgePathSegment) String() string {
239*9e94795aSAndroid Build Coastguard Worker	return fmt.Sprintf("%s -[%s]> %s", s.edge.target.name, strings.Join(s.edge.annotations.AsList(), ", "), s.edge.dependency.name)
240*9e94795aSAndroid Build Coastguard Worker}
241*9e94795aSAndroid Build Coastguard Worker
242*9e94795aSAndroid Build Coastguard Worker// TargetEdgePath describes a sequence of edges starting at a root and ending
243*9e94795aSAndroid Build Coastguard Worker// at some final dependency.
244*9e94795aSAndroid Build Coastguard Workertype TargetEdgePath []TargetEdgePathSegment
245*9e94795aSAndroid Build Coastguard Worker
246*9e94795aSAndroid Build Coastguard Worker// NewTargetEdgePath creates a new, empty path with capacity `cap`.
247*9e94795aSAndroid Build Coastguard Workerfunc NewTargetEdgePath(cap int) *TargetEdgePath {
248*9e94795aSAndroid Build Coastguard Worker	p := make(TargetEdgePath, 0, cap)
249*9e94795aSAndroid Build Coastguard Worker	return &p
250*9e94795aSAndroid Build Coastguard Worker}
251*9e94795aSAndroid Build Coastguard Worker
252*9e94795aSAndroid Build Coastguard Worker// Push appends a new edge to the list verifying that the target of the new
253*9e94795aSAndroid Build Coastguard Worker// edge is the dependency of the prior.
254*9e94795aSAndroid Build Coastguard Workerfunc (p *TargetEdgePath) Push(edge *TargetEdge, ctx interface{}) {
255*9e94795aSAndroid Build Coastguard Worker	if len(*p) == 0 {
256*9e94795aSAndroid Build Coastguard Worker		*p = append(*p, TargetEdgePathSegment{edge, ctx})
257*9e94795aSAndroid Build Coastguard Worker		return
258*9e94795aSAndroid Build Coastguard Worker	}
259*9e94795aSAndroid Build Coastguard Worker	if (*p)[len(*p)-1].edge.dependency != edge.target {
260*9e94795aSAndroid Build Coastguard Worker		panic(fmt.Errorf("disjoint path %s does not end at %s", p.String(), edge.target.name))
261*9e94795aSAndroid Build Coastguard Worker	}
262*9e94795aSAndroid Build Coastguard Worker	*p = append(*p, TargetEdgePathSegment{edge, ctx})
263*9e94795aSAndroid Build Coastguard Worker}
264*9e94795aSAndroid Build Coastguard Worker
265*9e94795aSAndroid Build Coastguard Worker// Pop shortens the path by 1 edge.
266*9e94795aSAndroid Build Coastguard Workerfunc (p *TargetEdgePath) Pop() {
267*9e94795aSAndroid Build Coastguard Worker	if len(*p) == 0 {
268*9e94795aSAndroid Build Coastguard Worker		panic(fmt.Errorf("attempt to remove edge from empty path"))
269*9e94795aSAndroid Build Coastguard Worker	}
270*9e94795aSAndroid Build Coastguard Worker	*p = (*p)[:len(*p)-1]
271*9e94795aSAndroid Build Coastguard Worker}
272*9e94795aSAndroid Build Coastguard Worker
273*9e94795aSAndroid Build Coastguard Worker// Clear makes the path length 0.
274*9e94795aSAndroid Build Coastguard Workerfunc (p *TargetEdgePath) Clear() {
275*9e94795aSAndroid Build Coastguard Worker	*p = (*p)[:0]
276*9e94795aSAndroid Build Coastguard Worker}
277*9e94795aSAndroid Build Coastguard Worker
278*9e94795aSAndroid Build Coastguard Worker// Copy makes a new path with the same value.
279*9e94795aSAndroid Build Coastguard Workerfunc (p *TargetEdgePath) Copy() *TargetEdgePath {
280*9e94795aSAndroid Build Coastguard Worker	result := make(TargetEdgePath, 0, len(*p))
281*9e94795aSAndroid Build Coastguard Worker	for _, e := range *p {
282*9e94795aSAndroid Build Coastguard Worker		result = append(result, e)
283*9e94795aSAndroid Build Coastguard Worker	}
284*9e94795aSAndroid Build Coastguard Worker	return &result
285*9e94795aSAndroid Build Coastguard Worker}
286*9e94795aSAndroid Build Coastguard Worker
287*9e94795aSAndroid Build Coastguard Worker// String returns a string representation of the path: [n1 -> n2 -> ... -> nn].
288*9e94795aSAndroid Build Coastguard Workerfunc (p *TargetEdgePath) String() string {
289*9e94795aSAndroid Build Coastguard Worker	if p == nil {
290*9e94795aSAndroid Build Coastguard Worker		return "nil"
291*9e94795aSAndroid Build Coastguard Worker	}
292*9e94795aSAndroid Build Coastguard Worker	if len(*p) == 0 {
293*9e94795aSAndroid Build Coastguard Worker		return "[]"
294*9e94795aSAndroid Build Coastguard Worker	}
295*9e94795aSAndroid Build Coastguard Worker	var sb strings.Builder
296*9e94795aSAndroid Build Coastguard Worker	fmt.Fprintf(&sb, "[")
297*9e94795aSAndroid Build Coastguard Worker	for _, s := range *p {
298*9e94795aSAndroid Build Coastguard Worker		fmt.Fprintf(&sb, "%s -> ", s.edge.target.name)
299*9e94795aSAndroid Build Coastguard Worker	}
300*9e94795aSAndroid Build Coastguard Worker	lastSegment := (*p)[len(*p)-1]
301*9e94795aSAndroid Build Coastguard Worker	fmt.Fprintf(&sb, "%s]", lastSegment.edge.dependency.name)
302*9e94795aSAndroid Build Coastguard Worker	return sb.String()
303*9e94795aSAndroid Build Coastguard Worker}
304*9e94795aSAndroid Build Coastguard Worker
305*9e94795aSAndroid Build Coastguard Worker// TargetNode describes a module or target identified by the name of a specific
306*9e94795aSAndroid Build Coastguard Worker// metadata file. (immutable)
307*9e94795aSAndroid Build Coastguard Worker//
308*9e94795aSAndroid Build Coastguard Worker// Each metadata file corresponds to a Soong module or to a Make target.
309*9e94795aSAndroid Build Coastguard Worker//
310*9e94795aSAndroid Build Coastguard Worker// A target node can appear as the target or as the dependency in edges.
311*9e94795aSAndroid Build Coastguard Worker// Most target nodes appear as both target in one edge and as dependency in
312*9e94795aSAndroid Build Coastguard Worker// other edges.
313*9e94795aSAndroid Build Coastguard Workertype TargetNode targetNode
314*9e94795aSAndroid Build Coastguard Worker
315*9e94795aSAndroid Build Coastguard Worker// Name returns the string that identifies the target node.
316*9e94795aSAndroid Build Coastguard Worker// i.e. path to license metadata file
317*9e94795aSAndroid Build Coastguard Workerfunc (tn *TargetNode) Name() string {
318*9e94795aSAndroid Build Coastguard Worker	return tn.name
319*9e94795aSAndroid Build Coastguard Worker}
320*9e94795aSAndroid Build Coastguard Worker
321*9e94795aSAndroid Build Coastguard Worker// Dependencies returns the list of edges to dependencies of `tn`.
322*9e94795aSAndroid Build Coastguard Workerfunc (tn *TargetNode) Dependencies() TargetEdgeList {
323*9e94795aSAndroid Build Coastguard Worker	edges := make(TargetEdgeList, 0, len(tn.edges))
324*9e94795aSAndroid Build Coastguard Worker	edges = append(edges, tn.edges...)
325*9e94795aSAndroid Build Coastguard Worker	return edges
326*9e94795aSAndroid Build Coastguard Worker}
327*9e94795aSAndroid Build Coastguard Worker
328*9e94795aSAndroid Build Coastguard Worker// PackageName returns the string that identifes the package for the target.
329*9e94795aSAndroid Build Coastguard Workerfunc (tn *TargetNode) PackageName() string {
330*9e94795aSAndroid Build Coastguard Worker	return tn.proto.GetPackageName()
331*9e94795aSAndroid Build Coastguard Worker}
332*9e94795aSAndroid Build Coastguard Worker
333*9e94795aSAndroid Build Coastguard Worker// ModuleName returns the module name of the target.
334*9e94795aSAndroid Build Coastguard Workerfunc (tn *TargetNode) ModuleName() string {
335*9e94795aSAndroid Build Coastguard Worker	return tn.proto.GetModuleName()
336*9e94795aSAndroid Build Coastguard Worker}
337*9e94795aSAndroid Build Coastguard Worker
338*9e94795aSAndroid Build Coastguard Worker// Projects returns the projects defining the target node. (unordered)
339*9e94795aSAndroid Build Coastguard Worker//
340*9e94795aSAndroid Build Coastguard Worker// In an ideal world, only 1 project defines a target, but the interaction
341*9e94795aSAndroid Build Coastguard Worker// between Soong and Make for a variety of architectures and for host versus
342*9e94795aSAndroid Build Coastguard Worker// product means a module is sometimes defined more than once.
343*9e94795aSAndroid Build Coastguard Workerfunc (tn *TargetNode) Projects() []string {
344*9e94795aSAndroid Build Coastguard Worker	return append([]string{}, tn.proto.Projects...)
345*9e94795aSAndroid Build Coastguard Worker}
346*9e94795aSAndroid Build Coastguard Worker
347*9e94795aSAndroid Build Coastguard Worker// LicenseConditions returns a copy of the set of license conditions
348*9e94795aSAndroid Build Coastguard Worker// originating at the target. The values that appear and how each is resolved
349*9e94795aSAndroid Build Coastguard Worker// is a matter of policy. (unordered)
350*9e94795aSAndroid Build Coastguard Worker//
351*9e94795aSAndroid Build Coastguard Worker// e.g. notice or proprietary
352*9e94795aSAndroid Build Coastguard Workerfunc (tn *TargetNode) LicenseConditions() LicenseConditionSet {
353*9e94795aSAndroid Build Coastguard Worker	return tn.licenseConditions
354*9e94795aSAndroid Build Coastguard Worker}
355*9e94795aSAndroid Build Coastguard Worker
356*9e94795aSAndroid Build Coastguard Worker// LicenseTexts returns the paths to the files containing the license texts for
357*9e94795aSAndroid Build Coastguard Worker// the target. (unordered)
358*9e94795aSAndroid Build Coastguard Workerfunc (tn *TargetNode) LicenseTexts() []string {
359*9e94795aSAndroid Build Coastguard Worker	return append([]string{}, tn.proto.LicenseTexts...)
360*9e94795aSAndroid Build Coastguard Worker}
361*9e94795aSAndroid Build Coastguard Worker
362*9e94795aSAndroid Build Coastguard Worker// IsContainer returns true if the target represents a container that merely
363*9e94795aSAndroid Build Coastguard Worker// aggregates other targets.
364*9e94795aSAndroid Build Coastguard Workerfunc (tn *TargetNode) IsContainer() bool {
365*9e94795aSAndroid Build Coastguard Worker	return tn.proto.GetIsContainer()
366*9e94795aSAndroid Build Coastguard Worker}
367*9e94795aSAndroid Build Coastguard Worker
368*9e94795aSAndroid Build Coastguard Worker// Built returns the list of files built by the module or target. (unordered)
369*9e94795aSAndroid Build Coastguard Workerfunc (tn *TargetNode) Built() []string {
370*9e94795aSAndroid Build Coastguard Worker	return append([]string{}, tn.proto.Built...)
371*9e94795aSAndroid Build Coastguard Worker}
372*9e94795aSAndroid Build Coastguard Worker
373*9e94795aSAndroid Build Coastguard Worker// Installed returns the list of files installed by the module or target.
374*9e94795aSAndroid Build Coastguard Worker// (unordered)
375*9e94795aSAndroid Build Coastguard Workerfunc (tn *TargetNode) Installed() []string {
376*9e94795aSAndroid Build Coastguard Worker	return append([]string{}, tn.proto.Installed...)
377*9e94795aSAndroid Build Coastguard Worker}
378*9e94795aSAndroid Build Coastguard Worker
379*9e94795aSAndroid Build Coastguard Worker// TargetFiles returns the list of files built or installed by the module or
380*9e94795aSAndroid Build Coastguard Worker// target. (unordered)
381*9e94795aSAndroid Build Coastguard Workerfunc (tn *TargetNode) TargetFiles() []string {
382*9e94795aSAndroid Build Coastguard Worker	return append(tn.proto.Built, tn.proto.Installed...)
383*9e94795aSAndroid Build Coastguard Worker}
384*9e94795aSAndroid Build Coastguard Worker
385*9e94795aSAndroid Build Coastguard Worker// InstallMap returns the list of path name transformations to make to move
386*9e94795aSAndroid Build Coastguard Worker// files from their original location in the file system to their destination
387*9e94795aSAndroid Build Coastguard Worker// inside a container. (unordered)
388*9e94795aSAndroid Build Coastguard Workerfunc (tn *TargetNode) InstallMap() []InstallMap {
389*9e94795aSAndroid Build Coastguard Worker	result := make([]InstallMap, 0, len(tn.proto.InstallMap))
390*9e94795aSAndroid Build Coastguard Worker	for _, im := range tn.proto.InstallMap {
391*9e94795aSAndroid Build Coastguard Worker		result = append(result, InstallMap{im.GetFromPath(), im.GetContainerPath()})
392*9e94795aSAndroid Build Coastguard Worker	}
393*9e94795aSAndroid Build Coastguard Worker	return result
394*9e94795aSAndroid Build Coastguard Worker}
395*9e94795aSAndroid Build Coastguard Worker
396*9e94795aSAndroid Build Coastguard Worker// Sources returns the list of file names depended on by the target, which may
397*9e94795aSAndroid Build Coastguard Worker// be a proper subset of those made available by dependency modules.
398*9e94795aSAndroid Build Coastguard Worker// (unordered)
399*9e94795aSAndroid Build Coastguard Workerfunc (tn *TargetNode) Sources() []string {
400*9e94795aSAndroid Build Coastguard Worker	return append([]string{}, tn.proto.Sources...)
401*9e94795aSAndroid Build Coastguard Worker}
402*9e94795aSAndroid Build Coastguard Worker
403*9e94795aSAndroid Build Coastguard Worker// InstallMap describes the mapping from an input filesystem file to file in a
404*9e94795aSAndroid Build Coastguard Worker// container.
405*9e94795aSAndroid Build Coastguard Workertype InstallMap struct {
406*9e94795aSAndroid Build Coastguard Worker	// FromPath is the input path on the filesystem.
407*9e94795aSAndroid Build Coastguard Worker	FromPath string
408*9e94795aSAndroid Build Coastguard Worker
409*9e94795aSAndroid Build Coastguard Worker	// ContainerPath is the path to the same file inside the container or
410*9e94795aSAndroid Build Coastguard Worker	// installed location.
411*9e94795aSAndroid Build Coastguard Worker	ContainerPath string
412*9e94795aSAndroid Build Coastguard Worker}
413*9e94795aSAndroid Build Coastguard Worker
414*9e94795aSAndroid Build Coastguard Worker// TargetEdgeAnnotations describes an immutable set of annotations attached to
415*9e94795aSAndroid Build Coastguard Worker// an edge from a target to a dependency.
416*9e94795aSAndroid Build Coastguard Worker//
417*9e94795aSAndroid Build Coastguard Worker// Annotations typically distinguish between static linkage versus dynamic
418*9e94795aSAndroid Build Coastguard Worker// versus tools that are used at build time but are not linked in any way.
419*9e94795aSAndroid Build Coastguard Workertype TargetEdgeAnnotations struct {
420*9e94795aSAndroid Build Coastguard Worker	annotations map[string]struct{}
421*9e94795aSAndroid Build Coastguard Worker}
422*9e94795aSAndroid Build Coastguard Worker
423*9e94795aSAndroid Build Coastguard Worker// newEdgeAnnotations creates a new instance of TargetEdgeAnnotations.
424*9e94795aSAndroid Build Coastguard Workerfunc newEdgeAnnotations() TargetEdgeAnnotations {
425*9e94795aSAndroid Build Coastguard Worker	return TargetEdgeAnnotations{make(map[string]struct{})}
426*9e94795aSAndroid Build Coastguard Worker}
427*9e94795aSAndroid Build Coastguard Worker
428*9e94795aSAndroid Build Coastguard Worker// HasAnnotation returns true if an annotation `ann` is in the set.
429*9e94795aSAndroid Build Coastguard Workerfunc (ea TargetEdgeAnnotations) HasAnnotation(ann string) bool {
430*9e94795aSAndroid Build Coastguard Worker	_, ok := ea.annotations[ann]
431*9e94795aSAndroid Build Coastguard Worker	return ok
432*9e94795aSAndroid Build Coastguard Worker}
433*9e94795aSAndroid Build Coastguard Worker
434*9e94795aSAndroid Build Coastguard Worker// Compare orders TargetAnnotations returning:
435*9e94795aSAndroid Build Coastguard Worker// -1 when ea < other,
436*9e94795aSAndroid Build Coastguard Worker// +1 when ea > other, and
437*9e94795aSAndroid Build Coastguard Worker// 0 when ea == other.
438*9e94795aSAndroid Build Coastguard Workerfunc (ea TargetEdgeAnnotations) Compare(other TargetEdgeAnnotations) int {
439*9e94795aSAndroid Build Coastguard Worker	a1 := ea.AsList()
440*9e94795aSAndroid Build Coastguard Worker	a2 := other.AsList()
441*9e94795aSAndroid Build Coastguard Worker	sort.Strings(a1)
442*9e94795aSAndroid Build Coastguard Worker	sort.Strings(a2)
443*9e94795aSAndroid Build Coastguard Worker	for k := 0; k < len(a1) && k < len(a2); k++ {
444*9e94795aSAndroid Build Coastguard Worker		if a1[k] < a2[k] {
445*9e94795aSAndroid Build Coastguard Worker			return -1
446*9e94795aSAndroid Build Coastguard Worker		}
447*9e94795aSAndroid Build Coastguard Worker		if a1[k] > a2[k] {
448*9e94795aSAndroid Build Coastguard Worker			return 1
449*9e94795aSAndroid Build Coastguard Worker		}
450*9e94795aSAndroid Build Coastguard Worker	}
451*9e94795aSAndroid Build Coastguard Worker	if len(a1) < len(a2) {
452*9e94795aSAndroid Build Coastguard Worker		return -1
453*9e94795aSAndroid Build Coastguard Worker	}
454*9e94795aSAndroid Build Coastguard Worker	if len(a1) > len(a2) {
455*9e94795aSAndroid Build Coastguard Worker		return 1
456*9e94795aSAndroid Build Coastguard Worker	}
457*9e94795aSAndroid Build Coastguard Worker	return 0
458*9e94795aSAndroid Build Coastguard Worker}
459*9e94795aSAndroid Build Coastguard Worker
460*9e94795aSAndroid Build Coastguard Worker// AsList returns the list of annotation names attached to the edge.
461*9e94795aSAndroid Build Coastguard Worker// (unordered)
462*9e94795aSAndroid Build Coastguard Workerfunc (ea TargetEdgeAnnotations) AsList() []string {
463*9e94795aSAndroid Build Coastguard Worker	l := make([]string, 0, len(ea.annotations))
464*9e94795aSAndroid Build Coastguard Worker	for ann := range ea.annotations {
465*9e94795aSAndroid Build Coastguard Worker		l = append(l, ann)
466*9e94795aSAndroid Build Coastguard Worker	}
467*9e94795aSAndroid Build Coastguard Worker	return l
468*9e94795aSAndroid Build Coastguard Worker}
469*9e94795aSAndroid Build Coastguard Worker
470*9e94795aSAndroid Build Coastguard Worker// TargetNodeSet describes a set of distinct nodes in a license graph.
471*9e94795aSAndroid Build Coastguard Workertype TargetNodeSet map[*TargetNode]struct{}
472*9e94795aSAndroid Build Coastguard Worker
473*9e94795aSAndroid Build Coastguard Worker// Contains returns true when `target` is an element of the set.
474*9e94795aSAndroid Build Coastguard Workerfunc (ts TargetNodeSet) Contains(target *TargetNode) bool {
475*9e94795aSAndroid Build Coastguard Worker	_, isPresent := ts[target]
476*9e94795aSAndroid Build Coastguard Worker	return isPresent
477*9e94795aSAndroid Build Coastguard Worker}
478*9e94795aSAndroid Build Coastguard Worker
479*9e94795aSAndroid Build Coastguard Worker// Names returns the array of target node namess in the set. (unordered)
480*9e94795aSAndroid Build Coastguard Workerfunc (ts TargetNodeSet) Names() []string {
481*9e94795aSAndroid Build Coastguard Worker	result := make([]string, 0, len(ts))
482*9e94795aSAndroid Build Coastguard Worker	for tn := range ts {
483*9e94795aSAndroid Build Coastguard Worker		result = append(result, tn.name)
484*9e94795aSAndroid Build Coastguard Worker	}
485*9e94795aSAndroid Build Coastguard Worker	return result
486*9e94795aSAndroid Build Coastguard Worker}
487*9e94795aSAndroid Build Coastguard Worker
488*9e94795aSAndroid Build Coastguard Worker// String returns a human-readable string representation of the set.
489*9e94795aSAndroid Build Coastguard Workerfunc (ts TargetNodeSet) String() string {
490*9e94795aSAndroid Build Coastguard Worker	return fmt.Sprintf("{%s}", strings.Join(ts.Names(), ", "))
491*9e94795aSAndroid Build Coastguard Worker}
492*9e94795aSAndroid Build Coastguard Worker
493*9e94795aSAndroid Build Coastguard Worker// TargetNodeList orders a list of targets by name.
494*9e94795aSAndroid Build Coastguard Workertype TargetNodeList []*TargetNode
495*9e94795aSAndroid Build Coastguard Worker
496*9e94795aSAndroid Build Coastguard Worker// Len returns the count of elements in the list.
497*9e94795aSAndroid Build Coastguard Workerfunc (l TargetNodeList) Len() int { return len(l) }
498*9e94795aSAndroid Build Coastguard Worker
499*9e94795aSAndroid Build Coastguard Worker// Swap rearranges 2 elements so that each occupies the other's former position.
500*9e94795aSAndroid Build Coastguard Workerfunc (l TargetNodeList) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
501*9e94795aSAndroid Build Coastguard Worker
502*9e94795aSAndroid Build Coastguard Worker// Less returns true when the `i`th element is lexicographicallt less than the `j`th.
503*9e94795aSAndroid Build Coastguard Workerfunc (l TargetNodeList) Less(i, j int) bool {
504*9e94795aSAndroid Build Coastguard Worker	return l[i].name < l[j].name
505*9e94795aSAndroid Build Coastguard Worker}
506*9e94795aSAndroid Build Coastguard Worker
507*9e94795aSAndroid Build Coastguard Worker// String returns a string representation of the list.
508*9e94795aSAndroid Build Coastguard Workerfunc (l TargetNodeList) String() string {
509*9e94795aSAndroid Build Coastguard Worker	var sb strings.Builder
510*9e94795aSAndroid Build Coastguard Worker	fmt.Fprintf(&sb, "[")
511*9e94795aSAndroid Build Coastguard Worker	sep := ""
512*9e94795aSAndroid Build Coastguard Worker	for _, tn := range l {
513*9e94795aSAndroid Build Coastguard Worker		fmt.Fprintf(&sb, "%s%s", sep, tn.name)
514*9e94795aSAndroid Build Coastguard Worker		sep = " "
515*9e94795aSAndroid Build Coastguard Worker	}
516*9e94795aSAndroid Build Coastguard Worker	fmt.Fprintf(&sb, "]")
517*9e94795aSAndroid Build Coastguard Worker	return sb.String()
518*9e94795aSAndroid Build Coastguard Worker}
519*9e94795aSAndroid Build Coastguard Worker
520*9e94795aSAndroid Build Coastguard Worker// Names returns an array the names of the nodes in the same order as the nodes in the list.
521*9e94795aSAndroid Build Coastguard Workerfunc (l TargetNodeList) Names() []string {
522*9e94795aSAndroid Build Coastguard Worker	result := make([]string, 0, len(l))
523*9e94795aSAndroid Build Coastguard Worker	for _, tn := range l {
524*9e94795aSAndroid Build Coastguard Worker		result = append(result, tn.name)
525*9e94795aSAndroid Build Coastguard Worker	}
526*9e94795aSAndroid Build Coastguard Worker	return result
527*9e94795aSAndroid Build Coastguard Worker}
528