瀏覽代碼

Support multiple library names per target.

The prior interface to make supported only a single package name per
target; although, a target might have multiple licenses each with its
own package name.

Bug: 151177513
Bug: 210912771

Test: m all dist
Test: flash; About Phone -> Legal Information -> Third-party licenses

Change-Id: I1db5fcfd4c066afd162adb4eb4177960c7a503bd
Bob Badour 2 年之前
父節點
當前提交
4101c71e63
共有 6 個文件被更改,包括 198 次插入11 次删除
  1. 1 1
      android/license.go
  2. 4 1
      android/license_sdk_member.go
  3. 18 4
      android/licenses.go
  4. 3 3
      android/licenses_test.go
  5. 55 2
      android/module.go
  6. 117 0
      android/module_test.go

+ 1 - 1
android/license.go

@@ -63,7 +63,7 @@ func (m *licenseModule) DepsMutator(ctx BottomUpMutatorContext) {
 func (m *licenseModule) GenerateAndroidBuildActions(ctx ModuleContext) {
 	// license modules have no licenses, but license_kinds must refer to license_kind modules
 	mergeStringProps(&m.base().commonProperties.Effective_licenses, ctx.ModuleName())
-	mergePathProps(&m.base().commonProperties.Effective_license_text, PathsForModuleSrc(ctx, m.properties.License_text)...)
+	namePathProps(&m.base().commonProperties.Effective_license_text, m.properties.Package_name, PathsForModuleSrc(ctx, m.properties.License_text)...)
 	for _, module := range ctx.GetDirectDepsWithTag(licenseKindTag) {
 		if lk, ok := module.(*licenseKindModule); ok {
 			mergeStringProps(&m.base().commonProperties.Effective_license_conditions, lk.properties.Conditions...)

+ 4 - 1
android/license_sdk_member.go

@@ -90,7 +90,10 @@ func (p *licenseSdkMemberProperties) PopulateFromVariant(_ SdkMemberContext, var
 	// Populate the properties from the variant.
 	l := variant.(*licenseModule)
 	p.License_kinds = l.properties.License_kinds
-	p.License_text = l.base().commonProperties.Effective_license_text
+	p.License_text = make(Paths, 0, len(l.base().commonProperties.Effective_license_text))
+	for _, np := range l.base().commonProperties.Effective_license_text {
+		p.License_text = append(p.License_text, np.Path)
+	}
 }
 
 func (p *licenseSdkMemberProperties) AddToPropertySet(ctx SdkMemberContext, propertySet BpPropertySet) {

+ 18 - 4
android/licenses.go

@@ -213,7 +213,7 @@ func licensesPropertyFlattener(ctx ModuleContext) {
 				m.base().commonProperties.Effective_package_name = l.properties.Package_name
 			}
 			mergeStringProps(&m.base().commonProperties.Effective_licenses, module.base().commonProperties.Effective_licenses...)
-			mergePathProps(&m.base().commonProperties.Effective_license_text, module.base().commonProperties.Effective_license_text...)
+			mergeNamedPathProps(&m.base().commonProperties.Effective_license_text, module.base().commonProperties.Effective_license_text...)
 			mergeStringProps(&m.base().commonProperties.Effective_license_kinds, module.base().commonProperties.Effective_license_kinds...)
 			mergeStringProps(&m.base().commonProperties.Effective_license_conditions, module.base().commonProperties.Effective_license_conditions...)
 		} else {
@@ -239,10 +239,24 @@ func mergeStringProps(prop *[]string, values ...string) {
 	*prop = SortedUniqueStrings(*prop)
 }
 
-// Update a property Path array with a distinct union of its values and a list of new values.
-func mergePathProps(prop *Paths, values ...Path) {
+// Update a property NamedPath array with a distinct union of its values and a list of new values.
+func namePathProps(prop *NamedPaths, name *string, values ...Path) {
+	if name == nil {
+		for _, value := range values {
+			*prop = append(*prop, NamedPath{value, ""})
+		}
+	} else {
+		for _, value := range values {
+			*prop = append(*prop, NamedPath{value, *name})
+		}
+	}
+	*prop = SortedUniqueNamedPaths(*prop)
+}
+
+// Update a property NamedPath array with a distinct union of its values and a list of new values.
+func mergeNamedPathProps(prop *NamedPaths, values ...NamedPath) {
 	*prop = append(*prop, values...)
-	*prop = SortedUniquePaths(*prop)
+	*prop = SortedUniqueNamedPaths(*prop)
 }
 
 // Get the licenses property falling back to the package default.

+ 3 - 3
android/licenses_test.go

@@ -90,9 +90,9 @@ var licensesTests = []struct {
 			"libother":    []string{"shownotice"},
 		},
 		effectiveNotices: map[string][]string{
-			"libexample1": []string{"top/LICENSE", "top/NOTICE"},
-			"libnested":   []string{"top/LICENSE", "top/NOTICE"},
-			"libother":    []string{"top/LICENSE", "top/NOTICE"},
+			"libexample1": []string{"top/LICENSE:topDog", "top/NOTICE:topDog"},
+			"libnested":   []string{"top/LICENSE:topDog", "top/NOTICE:topDog"},
+			"libother":    []string{"top/LICENSE:topDog", "top/NOTICE:topDog"},
 		},
 	},
 

+ 55 - 2
android/module.go

@@ -16,11 +16,13 @@ package android
 
 import (
 	"fmt"
+	"net/url"
 	"os"
 	"path"
 	"path/filepath"
 	"reflect"
 	"regexp"
+	"sort"
 	"strings"
 	"text/scanner"
 
@@ -616,6 +618,53 @@ type Dist struct {
 	Tag *string `android:"arch_variant"`
 }
 
+// NamedPath associates a path with a name. e.g. a license text path with a package name
+type NamedPath struct {
+	Path Path
+	Name string
+}
+
+// String returns an escaped string representing the `NamedPath`.
+func (p NamedPath) String() string {
+	if len(p.Name) > 0 {
+		return p.Path.String() + ":" + url.QueryEscape(p.Name)
+	}
+	return p.Path.String()
+}
+
+// NamedPaths describes a list of paths each associated with a name.
+type NamedPaths []NamedPath
+
+// Strings returns a list of escaped strings representing each `NamedPath` in the list.
+func (l NamedPaths) Strings() []string {
+	result := make([]string, 0, len(l))
+	for _, p := range l {
+		result = append(result, p.String())
+	}
+	return result
+}
+
+// SortedUniqueNamedPaths modifies `l` in place to return the sorted unique subset.
+func SortedUniqueNamedPaths(l NamedPaths) NamedPaths {
+	if len(l) == 0 {
+		return l
+	}
+	sort.Slice(l, func(i, j int) bool {
+		return l[i].String() < l[j].String()
+	})
+	k := 0
+	for i := 1; i < len(l); i++ {
+		if l[i].String() == l[k].String() {
+			continue
+		}
+		k++
+		if k < i {
+			l[k] = l[i]
+		}
+	}
+	return l[:k+1]
+}
+
 type nameProperties struct {
 	// The name of the module.  Must be unique across all modules.
 	Name *string
@@ -684,7 +733,7 @@ type commonProperties struct {
 	// Override of module name when reporting licenses
 	Effective_package_name *string `blueprint:"mutated"`
 	// Notice files
-	Effective_license_text Paths `blueprint:"mutated"`
+	Effective_license_text NamedPaths `blueprint:"mutated"`
 	// License names
 	Effective_license_kinds []string `blueprint:"mutated"`
 	// License conditions
@@ -1801,7 +1850,11 @@ func (m *ModuleBase) ExportedToMake() bool {
 }
 
 func (m *ModuleBase) EffectiveLicenseFiles() Paths {
-	return m.commonProperties.Effective_license_text
+	result := make(Paths, 0, len(m.commonProperties.Effective_license_text))
+	for _, p := range m.commonProperties.Effective_license_text {
+		result = append(result, p.Path)
+	}
+	return result
 }
 
 // computeInstallDeps finds the installed paths of all dependencies that have a dependency

+ 117 - 0
android/module_test.go

@@ -816,3 +816,120 @@ test {
 		})
 	}
 }
+
+func TestSortedUniqueNamedPaths(t *testing.T) {
+	type np struct {
+		path, name string
+	}
+	makePaths := func(l []np) NamedPaths {
+		result := make(NamedPaths, 0, len(l))
+		for _, p := range l {
+			result = append(result, NamedPath{PathForTesting(p.path), p.name})
+		}
+		return result
+	}
+
+	tests := []struct {
+		name        string
+		in          []np
+		expectedOut []np
+	}{
+		{
+			name:        "empty",
+			in:          []np{},
+			expectedOut: []np{},
+		},
+		{
+			name: "all_same",
+			in: []np{
+				{"a.txt", "A"},
+				{"a.txt", "A"},
+				{"a.txt", "A"},
+				{"a.txt", "A"},
+				{"a.txt", "A"},
+			},
+			expectedOut: []np{
+				{"a.txt", "A"},
+			},
+		},
+		{
+			name: "same_path_different_names",
+			in: []np{
+				{"a.txt", "C"},
+				{"a.txt", "A"},
+				{"a.txt", "D"},
+				{"a.txt", "B"},
+				{"a.txt", "E"},
+			},
+			expectedOut: []np{
+				{"a.txt", "A"},
+				{"a.txt", "B"},
+				{"a.txt", "C"},
+				{"a.txt", "D"},
+				{"a.txt", "E"},
+			},
+		},
+		{
+			name: "different_paths_same_name",
+			in: []np{
+				{"b/b.txt", "A"},
+				{"a/a.txt", "A"},
+				{"a/txt", "A"},
+				{"b", "A"},
+				{"a/b/d", "A"},
+			},
+			expectedOut: []np{
+				{"a/a.txt", "A"},
+				{"a/b/d", "A"},
+				{"a/txt", "A"},
+				{"b/b.txt", "A"},
+				{"b", "A"},
+			},
+		},
+		{
+			name: "all_different",
+			in: []np{
+				{"b/b.txt", "A"},
+				{"a/a.txt", "B"},
+				{"a/txt", "D"},
+				{"b", "C"},
+				{"a/b/d", "E"},
+			},
+			expectedOut: []np{
+				{"a/a.txt", "B"},
+				{"a/b/d", "E"},
+				{"a/txt", "D"},
+				{"b/b.txt", "A"},
+				{"b", "C"},
+			},
+		},
+		{
+			name: "some_different",
+			in: []np{
+				{"b/b.txt", "A"},
+				{"a/a.txt", "B"},
+				{"a/txt", "D"},
+				{"a/b/d", "E"},
+				{"b", "C"},
+				{"a/a.txt", "B"},
+				{"a/b/d", "E"},
+			},
+			expectedOut: []np{
+				{"a/a.txt", "B"},
+				{"a/b/d", "E"},
+				{"a/txt", "D"},
+				{"b/b.txt", "A"},
+				{"b", "C"},
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			actual := SortedUniqueNamedPaths(makePaths(tt.in))
+			expected := makePaths(tt.expectedOut)
+			t.Logf("actual: %v", actual)
+			t.Logf("expected: %v", expected)
+			AssertDeepEquals(t, "SortedUniqueNamedPaths ", expected, actual)
+		})
+	}
+}