license metadata html notice files
Introduce the below command-line tool:
htmlnotice outputs a NOTICE.html file constructed from the license
texts of the transitive closure of dependencies.
Bug: 68860345
Bug: 151177513
Bug: 151953481
Bug: 213388645
Bug: 210912771
Test: m all
Test: m systemlicense
Test: m htmlnotice; out/soong/host/linux-x85/htmlnotice ...
where ... is the path to the .meta_lic file for the system image. In my
case if
$ export PRODUCT=$(realpath $ANDROID_PRODUCT_OUT --relative-to=$PWD)
... can be expressed as:
${PRODUCT}/gen/META/lic_intermediates/${PRODUCT}/system.img.meta_lic
Change-Id: Idbbeb2939d8cbf497237516fe468004fcd2d72a1
diff --git a/tools/compliance/noticeindex.go b/tools/compliance/noticeindex.go
index 06c2627..5b7f376 100644
--- a/tools/compliance/noticeindex.go
+++ b/tools/compliance/noticeindex.go
@@ -54,8 +54,8 @@
text map[hash][]byte
// hashLibInstall maps hashes to libraries to install paths.
hashLibInstall map[hash]map[string]map[string]struct{}
- // installLibHash maps install paths to libraries to hashes.
- installLibHash map[string]map[string]map[hash]struct{}
+ // installHashLib maps install paths to libraries to hashes.
+ installHashLib map[string]map[hash]map[string]struct{}
// libHash maps libraries to hashes.
libHash map[string]map[hash]struct{}
// targetHash maps target nodes to hashes.
@@ -75,7 +75,7 @@
make(map[string]hash),
make(map[hash][]byte),
make(map[hash]map[string]map[string]struct{}),
- make(map[string]map[string]map[hash]struct{}),
+ make(map[string]map[hash]map[string]struct{}),
make(map[string]map[hash]struct{}),
make(map[*TargetNode]map[hash]struct{}),
make(map[string]string),
@@ -115,15 +115,15 @@
ni.libHash[libName][h] = struct{}{}
}
for _, installPath := range installPaths {
- if _, ok := ni.installLibHash[installPath]; !ok {
- ni.installLibHash[installPath] = make(map[string]map[hash]struct{})
- ni.installLibHash[installPath][libName] = make(map[hash]struct{})
- ni.installLibHash[installPath][libName][h] = struct{}{}
- } else if _, ok = ni.installLibHash[installPath][libName]; !ok {
- ni.installLibHash[installPath][libName] = make(map[hash]struct{})
- ni.installLibHash[installPath][libName][h] = struct{}{}
- } else if _, ok = ni.installLibHash[installPath][libName][h]; !ok {
- ni.installLibHash[installPath][libName][h] = struct{}{}
+ if _, ok := ni.installHashLib[installPath]; !ok {
+ ni.installHashLib[installPath] = make(map[hash]map[string]struct{})
+ ni.installHashLib[installPath][h] = make(map[string]struct{})
+ ni.installHashLib[installPath][h][libName] = struct{}{}
+ } else if _, ok = ni.installHashLib[installPath][h]; !ok {
+ ni.installHashLib[installPath][h] = make(map[string]struct{})
+ ni.installHashLib[installPath][h][libName] = struct{}{}
+ } else if _, ok = ni.installHashLib[installPath][h][libName]; !ok {
+ ni.installHashLib[installPath][h][libName] = struct{}{}
}
if _, ok := ni.hashLibInstall[h]; !ok {
ni.hashLibInstall[h] = make(map[string]map[string]struct{})
@@ -197,7 +197,7 @@
hl = append(hl, h)
}
if len(hl) > 0 {
- sort.Sort(hashList{ni, libName, &hl})
+ sort.Sort(hashList{ni, libName, "", &hl})
for _, h := range hl {
c <- h
}
@@ -230,6 +230,46 @@
return installs
}
+// InstallPaths returns the ordered channel of indexed install paths.
+func (ni *NoticeIndex) InstallPaths() chan string {
+ c := make(chan string)
+ go func() {
+ paths := make([]string, 0, len(ni.installHashLib))
+ for path := range ni.installHashLib {
+ paths = append(paths, path)
+ }
+ sort.Strings(paths)
+ for _, installPath := range paths {
+ c <- installPath
+ }
+ close(c)
+ }()
+ return c
+}
+
+// InstallHashes returns the ordered array of hashes attached to `installPath`.
+func (ni *NoticeIndex) InstallHashes(installPath string) []hash {
+ result := make([]hash, 0, len(ni.installHashLib[installPath]))
+ for h := range ni.installHashLib[installPath] {
+ result = append(result, h)
+ }
+ if len(result) > 0 {
+ sort.Sort(hashList{ni, "", installPath, &result})
+ }
+ return result
+}
+
+// InstallHashLibs returns the ordered array of library names attached to
+// `installPath` as hash `h`.
+func (ni *NoticeIndex) InstallHashLibs(installPath string, h hash) []string {
+ result := make([]string, 0, len(ni.installHashLib[installPath][h]))
+ for libName := range ni.installHashLib[installPath][h] {
+ result = append(result, libName)
+ }
+ sort.Strings(result)
+ return result
+}
+
// HashText returns the file content of the license text hashed as `h`.
func (ni *NoticeIndex) HashText(h hash) []byte {
return ni.text[h]
@@ -492,9 +532,10 @@
// hashList orders an array of hashes
type hashList struct {
- ni *NoticeIndex
- libName string
- hashes *[]hash
+ ni *NoticeIndex
+ libName string
+ installPath string
+ hashes *[]hash
}
// Len returns the count of elements in the slice.
@@ -511,6 +552,14 @@
if 0 < len(l.libName) {
insti = len(l.ni.hashLibInstall[(*l.hashes)[i]][l.libName])
instj = len(l.ni.hashLibInstall[(*l.hashes)[j]][l.libName])
+ } else {
+ libsi := l.ni.InstallHashLibs(l.installPath, (*l.hashes)[i])
+ libsj := l.ni.InstallHashLibs(l.installPath, (*l.hashes)[j])
+ libsis := strings.Join(libsi, " ")
+ libsjs := strings.Join(libsj, " ")
+ if libsis != libsjs {
+ return libsis < libsjs
+ }
}
if insti == instj {
leni := len(l.ni.text[(*l.hashes)[i]])