aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTreeHugger Robot <treehugger-gerrit@google.com>2022-06-10 19:46:31 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2022-06-10 19:46:31 +0000
commitfd2daf0913836b8c3bfa3491270014011948c8a7 (patch)
treef33c0c10b70844b9bad6c623c5f5483d0e612aa2
parent036446090018299e82a3f17562ad6659e5a8e933 (diff)
parent99b87147ece96c9b214a976c657beff0acd0a568 (diff)
downloadbuild-fd2daf0913836b8c3bfa3491270014011948c8a7.tar.gz
Merge "Improve flags for compliance tools." into tm-dev am: 99b87147ec
Original change: https://googleplex-android-review.googlesource.com/c/platform/build/+/18821066 Change-Id: I1d92e1c3e6fb793c4b4928fff709a782fb6611ab Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--tools/compliance/Android.bp33
-rw-r--r--tools/compliance/cmd/bom/bom.go68
-rw-r--r--tools/compliance/cmd/checkshare/checkshare.go109
-rw-r--r--tools/compliance/cmd/dumpgraph/dumpgraph.go112
-rw-r--r--tools/compliance/cmd/dumpresolutions/dumpresolutions.go114
-rw-r--r--tools/compliance/cmd/htmlnotice/htmlnotice.go78
-rw-r--r--tools/compliance/cmd/listshare/listshare.go91
-rw-r--r--tools/compliance/cmd/rtrace/rtrace.go120
-rw-r--r--tools/compliance/cmd/shippedlibs/shippedlibs.go3
-rw-r--r--tools/compliance/cmd/textnotice/textnotice.go74
-rw-r--r--tools/compliance/cmd/xmlnotice/xmlnotice.go76
11 files changed, 644 insertions, 234 deletions
diff --git a/tools/compliance/Android.bp b/tools/compliance/Android.bp
index 7a6c4ba4c0..225f3a578b 100644
--- a/tools/compliance/Android.bp
+++ b/tools/compliance/Android.bp
@@ -20,14 +20,20 @@ package {
blueprint_go_binary {
name: "compliance_checkshare",
srcs: ["cmd/checkshare/checkshare.go"],
- deps: ["compliance-module"],
+ deps: [
+ "compliance-module",
+ "soong-response",
+ ],
testSrcs: ["cmd/checkshare/checkshare_test.go"],
}
blueprint_go_binary {
name: "compliancenotice_bom",
srcs: ["cmd/bom/bom.go"],
- deps: ["compliance-module"],
+ deps: [
+ "compliance-module",
+ "soong-response",
+ ],
testSrcs: ["cmd/bom/bom_test.go"],
}
@@ -44,21 +50,30 @@ blueprint_go_binary {
blueprint_go_binary {
name: "compliance_listshare",
srcs: ["cmd/listshare/listshare.go"],
- deps: ["compliance-module"],
+ deps: [
+ "compliance-module",
+ "soong-response",
+ ],
testSrcs: ["cmd/listshare/listshare_test.go"],
}
blueprint_go_binary {
name: "compliance_dumpgraph",
srcs: ["cmd/dumpgraph/dumpgraph.go"],
- deps: ["compliance-module"],
+ deps: [
+ "compliance-module",
+ "soong-response",
+ ],
testSrcs: ["cmd/dumpgraph/dumpgraph_test.go"],
}
blueprint_go_binary {
name: "compliance_dumpresolutions",
srcs: ["cmd/dumpresolutions/dumpresolutions.go"],
- deps: ["compliance-module"],
+ deps: [
+ "compliance-module",
+ "soong-response",
+ ],
testSrcs: ["cmd/dumpresolutions/dumpresolutions_test.go"],
}
@@ -68,6 +83,7 @@ blueprint_go_binary {
deps: [
"compliance-module",
"blueprint-deptools",
+ "soong-response",
],
testSrcs: ["cmd/htmlnotice/htmlnotice_test.go"],
}
@@ -75,7 +91,10 @@ blueprint_go_binary {
blueprint_go_binary {
name: "compliance_rtrace",
srcs: ["cmd/rtrace/rtrace.go"],
- deps: ["compliance-module"],
+ deps: [
+ "compliance-module",
+ "soong-response",
+ ],
testSrcs: ["cmd/rtrace/rtrace_test.go"],
}
@@ -85,6 +104,7 @@ blueprint_go_binary {
deps: [
"compliance-module",
"blueprint-deptools",
+ "soong-response",
],
testSrcs: ["cmd/textnotice/textnotice_test.go"],
}
@@ -95,6 +115,7 @@ blueprint_go_binary {
deps: [
"compliance-module",
"blueprint-deptools",
+ "soong-response",
],
testSrcs: ["cmd/xmlnotice/xmlnotice_test.go"],
}
diff --git a/tools/compliance/cmd/bom/bom.go b/tools/compliance/cmd/bom/bom.go
index b613a1f9ff..187f828057 100644
--- a/tools/compliance/cmd/bom/bom.go
+++ b/tools/compliance/cmd/bom/bom.go
@@ -24,13 +24,11 @@ import (
"path/filepath"
"strings"
+ "android/soong/response"
"android/soong/tools/compliance"
)
var (
- outputFile = flag.String("o", "-", "Where to write the bill of materials. (default stdout)")
- stripPrefix = newMultiString("strip_prefix", "Prefix to remove from paths. i.e. path to root (multiple allowed)")
-
failNoneRequested = fmt.Errorf("\nNo license metadata files requested")
failNoLicenses = fmt.Errorf("No licenses found")
)
@@ -55,22 +53,10 @@ func (ctx context) strip(installPath string) string {
return installPath
}
-func init() {
- flag.Usage = func() {
- fmt.Fprintf(os.Stderr, `Usage: %s {options} file.meta_lic {file.meta_lic...}
-
-Outputs a bill of materials. i.e. the list of installed paths.
-
-Options:
-`, filepath.Base(os.Args[0]))
- flag.PrintDefaults()
- }
-}
-
// newMultiString creates a flag that allows multiple values in an array.
-func newMultiString(name, usage string) *multiString {
+func newMultiString(flags *flag.FlagSet, name, usage string) *multiString {
var f multiString
- flag.Var(&f, name, usage)
+ flags.Var(&f, name, usage)
return &f
}
@@ -81,16 +67,52 @@ func (ms *multiString) String() string { return strings.Join(*ms, ", ") }
func (ms *multiString) Set(s string) error { *ms = append(*ms, s); return nil }
func main() {
- flag.Parse()
+ var expandedArgs []string
+ for _, arg := range os.Args[1:] {
+ if strings.HasPrefix(arg, "@") {
+ f, err := os.Open(strings.TrimPrefix(arg, "@"))
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err.Error())
+ os.Exit(1)
+ }
+
+ respArgs, err := response.ReadRspFile(f)
+ f.Close()
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err.Error())
+ os.Exit(1)
+ }
+ expandedArgs = append(expandedArgs, respArgs...)
+ } else {
+ expandedArgs = append(expandedArgs, arg)
+ }
+ }
+
+ flags := flag.NewFlagSet("flags", flag.ExitOnError)
+
+ flags.Usage = func() {
+ fmt.Fprintf(os.Stderr, `Usage: %s {options} file.meta_lic {file.meta_lic...}
+
+Outputs a bill of materials. i.e. the list of installed paths.
+
+Options:
+`, filepath.Base(os.Args[0]))
+ flags.PrintDefaults()
+ }
+
+ outputFile := flags.String("o", "-", "Where to write the bill of materials. (default stdout)")
+ stripPrefix := newMultiString(flags, "strip_prefix", "Prefix to remove from paths. i.e. path to root (multiple allowed)")
+
+ flags.Parse(expandedArgs)
// Must specify at least one root target.
- if flag.NArg() == 0 {
- flag.Usage()
+ if flags.NArg() == 0 {
+ flags.Usage()
os.Exit(2)
}
if len(*outputFile) == 0 {
- flag.Usage()
+ flags.Usage()
fmt.Fprintf(os.Stderr, "must specify file for -o; use - for stdout\n")
os.Exit(2)
} else {
@@ -118,10 +140,10 @@ func main() {
ctx := &context{ofile, os.Stderr, compliance.FS, *stripPrefix}
- err := billOfMaterials(ctx, flag.Args()...)
+ err := billOfMaterials(ctx, flags.Args()...)
if err != nil {
if err == failNoneRequested {
- flag.Usage()
+ flags.Usage()
}
fmt.Fprintf(os.Stderr, "%s\n", err.Error())
os.Exit(1)
diff --git a/tools/compliance/cmd/checkshare/checkshare.go b/tools/compliance/cmd/checkshare/checkshare.go
index 73bdcb5679..f7b4cd2e39 100644
--- a/tools/compliance/cmd/checkshare/checkshare.go
+++ b/tools/compliance/cmd/checkshare/checkshare.go
@@ -15,6 +15,7 @@
package main
import (
+ "bytes"
"flag"
"fmt"
"io"
@@ -22,13 +23,51 @@ import (
"os"
"path/filepath"
"sort"
+ "strings"
+ "android/soong/response"
"android/soong/tools/compliance"
)
-func init() {
- flag.Usage = func() {
- fmt.Fprintf(os.Stderr, `Usage: %s file.meta_lic {file.meta_lic...}
+var (
+ failConflicts = fmt.Errorf("conflicts")
+ failNoneRequested = fmt.Errorf("\nNo metadata files requested")
+ failNoLicenses = fmt.Errorf("No licenses")
+)
+
+// byError orders conflicts by error string
+type byError []compliance.SourceSharePrivacyConflict
+
+func (l byError) Len() int { return len(l) }
+func (l byError) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
+func (l byError) Less(i, j int) bool { return l[i].Error() < l[j].Error() }
+
+func main() {
+ var expandedArgs []string
+ for _, arg := range os.Args[1:] {
+ if strings.HasPrefix(arg, "@") {
+ f, err := os.Open(strings.TrimPrefix(arg, "@"))
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err.Error())
+ os.Exit(1)
+ }
+
+ respArgs, err := response.ReadRspFile(f)
+ f.Close()
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err.Error())
+ os.Exit(1)
+ }
+ expandedArgs = append(expandedArgs, respArgs...)
+ } else {
+ expandedArgs = append(expandedArgs, arg)
+ }
+ }
+
+ flags := flag.NewFlagSet("flags", flag.ExitOnError)
+
+ flags.Usage = func() {
+ fmt.Fprintf(os.Stderr, `Usage: %s {-o outfile} file.meta_lic {file.meta_lic...}
Reports on stderr any targets where policy says that the source both
must and must not be shared. The error report indicates the target, the
@@ -44,41 +83,65 @@ outputs "PASS" to stdout and exits with status 0.
If policy says any source must both be shared and not be shared,
outputs "FAIL" to stdout and exits with status 1.
`, filepath.Base(os.Args[0]))
+ flags.PrintDefaults()
}
-}
-var (
- failConflicts = fmt.Errorf("conflicts")
- failNoneRequested = fmt.Errorf("\nNo metadata files requested")
- failNoLicenses = fmt.Errorf("No licenses")
-)
-
-// byError orders conflicts by error string
-type byError []compliance.SourceSharePrivacyConflict
-
-func (l byError) Len() int { return len(l) }
-func (l byError) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
-func (l byError) Less(i, j int) bool { return l[i].Error() < l[j].Error() }
+ outputFile := flags.String("o", "-", "Where to write the output. (default stdout)")
-func main() {
- flag.Parse()
+ flags.Parse(expandedArgs)
// Must specify at least one root target.
- if flag.NArg() == 0 {
- flag.Usage()
+ if flags.NArg() == 0 {
+ flags.Usage()
os.Exit(2)
}
- err := checkShare(os.Stdout, os.Stderr, compliance.FS, flag.Args()...)
+ if len(*outputFile) == 0 {
+ flags.Usage()
+ fmt.Fprintf(os.Stderr, "must specify file for -o; use - for stdout\n")
+ os.Exit(2)
+ } else {
+ dir, err := filepath.Abs(filepath.Dir(*outputFile))
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "cannot determine path to %q: %s\n", *outputFile, err)
+ os.Exit(1)
+ }
+ fi, err := os.Stat(dir)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "cannot read directory %q of %q: %s\n", dir, *outputFile, err)
+ os.Exit(1)
+ }
+ if !fi.IsDir() {
+ fmt.Fprintf(os.Stderr, "parent %q of %q is not a directory\n", dir, *outputFile)
+ os.Exit(1)
+ }
+ }
+
+ var ofile io.Writer
+ ofile = os.Stdout
+ var obuf *bytes.Buffer
+ if *outputFile != "-" {
+ obuf = &bytes.Buffer{}
+ ofile = obuf
+ }
+
+ err := checkShare(ofile, os.Stderr, compliance.FS, flags.Args()...)
if err != nil {
if err != failConflicts {
if err == failNoneRequested {
- flag.Usage()
+ flags.Usage()
}
fmt.Fprintf(os.Stderr, "%s\n", err.Error())
}
os.Exit(1)
}
+ if *outputFile != "-" {
+ err := os.WriteFile(*outputFile, obuf.Bytes(), 0666)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "could not write output to %q from %q: %s\n", *outputFile, os.Getenv("PWD"), err)
+ os.Exit(1)
+ }
+ }
os.Exit(0)
}
@@ -92,7 +155,7 @@ func checkShare(stdout, stderr io.Writer, rootFS fs.FS, files ...string) error {
// Read the license graph from the license metadata files (*.meta_lic).
licenseGraph, err := compliance.ReadLicenseGraph(rootFS, stderr, files)
if err != nil {
- return fmt.Errorf("Unable to read license metadata file(s) %q: %w\n", files, err)
+ return fmt.Errorf("Unable to read license metadata file(s) %q from %q: %w\n", files, os.Getenv("PWD"), err)
}
if licenseGraph == nil {
return failNoLicenses
diff --git a/tools/compliance/cmd/dumpgraph/dumpgraph.go b/tools/compliance/cmd/dumpgraph/dumpgraph.go
index 32a3fc44cf..56257794a4 100644
--- a/tools/compliance/cmd/dumpgraph/dumpgraph.go
+++ b/tools/compliance/cmd/dumpgraph/dumpgraph.go
@@ -15,6 +15,7 @@
package main
import (
+ "bytes"
"flag"
"fmt"
"io"
@@ -24,14 +25,11 @@ import (
"sort"
"strings"
+ "android/soong/response"
"android/soong/tools/compliance"
)
var (
- graphViz = flag.Bool("dot", false, "Whether to output graphviz (i.e. dot) format.")
- labelConditions = flag.Bool("label_conditions", false, "Whether to label target nodes with conditions.")
- stripPrefix = newMultiString("strip_prefix", "Prefix to remove from paths. i.e. path to root (multiple allowed)")
-
failNoneRequested = fmt.Errorf("\nNo license metadata files requested")
failNoLicenses = fmt.Errorf("No licenses found")
)
@@ -55,8 +53,44 @@ func (ctx context) strip(installPath string) string {
return installPath
}
-func init() {
- flag.Usage = func() {
+// newMultiString creates a flag that allows multiple values in an array.
+func newMultiString(flags *flag.FlagSet, name, usage string) *multiString {
+ var f multiString
+ flags.Var(&f, name, usage)
+ return &f
+}
+
+// multiString implements the flag `Value` interface for multiple strings.
+type multiString []string
+
+func (ms *multiString) String() string { return strings.Join(*ms, ", ") }
+func (ms *multiString) Set(s string) error { *ms = append(*ms, s); return nil }
+
+func main() {
+ var expandedArgs []string
+ for _, arg := range os.Args[1:] {
+ if strings.HasPrefix(arg, "@") {
+ f, err := os.Open(strings.TrimPrefix(arg, "@"))
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err.Error())
+ os.Exit(1)
+ }
+
+ respArgs, err := response.ReadRspFile(f)
+ f.Close()
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err.Error())
+ os.Exit(1)
+ }
+ expandedArgs = append(expandedArgs, respArgs...)
+ } else {
+ expandedArgs = append(expandedArgs, arg)
+ }
+ }
+
+ flags := flag.NewFlagSet("flags", flag.ExitOnError)
+
+ flags.Usage = func() {
fmt.Fprintf(os.Stderr, `Usage: %s {options} file.meta_lic {file.meta_lic...}
Outputs space-separated Target Dependency Annotations tuples for each
@@ -70,42 +104,68 @@ target:condition1:condition2 etc.
Options:
`, filepath.Base(os.Args[0]))
- flag.PrintDefaults()
+ flags.PrintDefaults()
}
-}
-// newMultiString creates a flag that allows multiple values in an array.
-func newMultiString(name, usage string) *multiString {
- var f multiString
- flag.Var(&f, name, usage)
- return &f
-}
+ graphViz := flags.Bool("dot", false, "Whether to output graphviz (i.e. dot) format.")
+ labelConditions := flags.Bool("label_conditions", false, "Whether to label target nodes with conditions.")
+ outputFile := flags.String("o", "-", "Where to write the output. (default stdout)")
+ stripPrefix := newMultiString(flags, "strip_prefix", "Prefix to remove from paths. i.e. path to root (multiple allowed)")
-// multiString implements the flag `Value` interface for multiple strings.
-type multiString []string
-
-func (ms *multiString) String() string { return strings.Join(*ms, ", ") }
-func (ms *multiString) Set(s string) error { *ms = append(*ms, s); return nil }
-
-func main() {
- flag.Parse()
+ flags.Parse(expandedArgs)
// Must specify at least one root target.
- if flag.NArg() == 0 {
- flag.Usage()
+ if flags.NArg() == 0 {
+ flags.Usage()
os.Exit(2)
}
+ if len(*outputFile) == 0 {
+ flags.Usage()
+ fmt.Fprintf(os.Stderr, "must specify file for -o; use - for stdout\n")
+ os.Exit(2)
+ } else {
+ dir, err := filepath.Abs(filepath.Dir(*outputFile))
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "cannot determine path to %q: %s\n", *outputFile, err)
+ os.Exit(1)
+ }
+ fi, err := os.Stat(dir)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "cannot read directory %q of %q: %s\n", dir, *outputFile, err)
+ os.Exit(1)
+ }
+ if !fi.IsDir() {
+ fmt.Fprintf(os.Stderr, "parent %q of %q is not a directory\n", dir, *outputFile)
+ os.Exit(1)
+ }
+ }
+
+ var ofile io.Writer
+ ofile = os.Stdout
+ var obuf *bytes.Buffer
+ if *outputFile != "-" {
+ obuf = &bytes.Buffer{}
+ ofile = obuf
+ }
+
ctx := &context{*graphViz, *labelConditions, *stripPrefix}
- err := dumpGraph(ctx, os.Stdout, os.Stderr, compliance.FS, flag.Args()...)
+ err := dumpGraph(ctx, ofile, os.Stderr, compliance.FS, flags.Args()...)
if err != nil {
if err == failNoneRequested {
- flag.Usage()
+ flags.Usage()
}
fmt.Fprintf(os.Stderr, "%s\n", err.Error())
os.Exit(1)
}
+ if *outputFile != "-" {
+ err := os.WriteFile(*outputFile, obuf.Bytes(), 0666)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "could not write output to %q from %q: %s\n", *outputFile, os.Getenv("PWD"), err)
+ os.Exit(1)
+ }
+ }
os.Exit(0)
}
diff --git a/tools/compliance/cmd/dumpresolutions/dumpresolutions.go b/tools/compliance/cmd/dumpresolutions/dumpresolutions.go
index d02c238846..dc0cf884f5 100644
--- a/tools/compliance/cmd/dumpresolutions/dumpresolutions.go
+++ b/tools/compliance/cmd/dumpresolutions/dumpresolutions.go
@@ -15,6 +15,7 @@
package main
import (
+ "bytes"
"flag"
"fmt"
"io"
@@ -24,15 +25,11 @@ import (
"sort"
"strings"
+ "android/soong/response"
"android/soong/tools/compliance"
)
var (
- conditions = newMultiString("c", "License condition to resolve. (may be given multiple times)")
- graphViz = flag.Bool("dot", false, "Whether to output graphviz (i.e. dot) format.")
- labelConditions = flag.Bool("label_conditions", false, "Whether to label target nodes with conditions.")
- stripPrefix = newMultiString("strip_prefix", "Prefix to remove from paths. i.e. path to root (multiple allowed)")
-
failNoneRequested = fmt.Errorf("\nNo license metadata files requested")
failNoLicenses = fmt.Errorf("No licenses found")
)
@@ -57,8 +54,44 @@ func (ctx context) strip(installPath string) string {
return installPath
}
-func init() {
- flag.Usage = func() {
+// newMultiString creates a flag that allows multiple values in an array.
+func newMultiString(flags *flag.FlagSet, name, usage string) *multiString {
+ var f multiString
+ flags.Var(&f, name, usage)
+ return &f
+}
+
+// multiString implements the flag `Value` interface for multiple strings.
+type multiString []string
+
+func (ms *multiString) String() string { return strings.Join(*ms, ", ") }
+func (ms *multiString) Set(s string) error { *ms = append(*ms, s); return nil }
+
+func main() {
+ var expandedArgs []string
+ for _, arg := range os.Args[1:] {
+ if strings.HasPrefix(arg, "@") {
+ f, err := os.Open(strings.TrimPrefix(arg, "@"))
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err.Error())
+ os.Exit(1)
+ }
+
+ respArgs, err := response.ReadRspFile(f)
+ f.Close()
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err.Error())
+ os.Exit(1)
+ }
+ expandedArgs = append(expandedArgs, respArgs...)
+ } else {
+ expandedArgs = append(expandedArgs, arg)
+ }
+ }
+
+ flags := flag.NewFlagSet("flags", flag.ExitOnError)
+
+ flags.Usage = func() {
fmt.Fprintf(os.Stderr, `Usage: %s {options} file.meta_lic {file.meta_lic...}
Outputs a space-separated Target ActsOn Origin Condition tuple for each
@@ -75,32 +108,52 @@ i.e. target:condition1:condition2 etc.
Options:
`, filepath.Base(os.Args[0]))
- flag.PrintDefaults()
+ flags.PrintDefaults()
}
-}
-// newMultiString creates a flag that allows multiple values in an array.
-func newMultiString(name, usage string) *multiString {
- var f multiString
- flag.Var(&f, name, usage)
- return &f
-}
+ conditions := newMultiString(flags, "c", "License condition to resolve. (may be given multiple times)")
+ graphViz := flags.Bool("dot", false, "Whether to output graphviz (i.e. dot) format.")
+ labelConditions := flags.Bool("label_conditions", false, "Whether to label target nodes with conditions.")
+ outputFile := flags.String("o", "-", "Where to write the output. (default stdout)")
+ stripPrefix := newMultiString(flags, "strip_prefix", "Prefix to remove from paths. i.e. path to root (multiple allowed)")
-// multiString implements the flag `Value` interface for multiple strings.
-type multiString []string
-
-func (ms *multiString) String() string { return strings.Join(*ms, ", ") }
-func (ms *multiString) Set(s string) error { *ms = append(*ms, s); return nil }
-
-func main() {
- flag.Parse()
+ flags.Parse(expandedArgs)
// Must specify at least one root target.
- if flag.NArg() == 0 {
- flag.Usage()
+ if flags.NArg() == 0 {
+ flags.Usage()
os.Exit(2)
}
+ if len(*outputFile) == 0 {
+ flags.Usage()
+ fmt.Fprintf(os.Stderr, "must specify file for -o; use - for stdout\n")
+ os.Exit(2)
+ } else {
+ dir, err := filepath.Abs(filepath.Dir(*outputFile))
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "cannot determine path to %q: %s\n", *outputFile, err)
+ os.Exit(1)
+ }
+ fi, err := os.Stat(dir)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "cannot read directory %q of %q: %s\n", dir, *outputFile, err)
+ os.Exit(1)
+ }
+ if !fi.IsDir() {
+ fmt.Fprintf(os.Stderr, "parent %q of %q is not a directory\n", dir, *outputFile)
+ os.Exit(1)
+ }
+ }
+
+ var ofile io.Writer
+ ofile = os.Stdout
+ var obuf *bytes.Buffer
+ if *outputFile != "-" {
+ obuf = &bytes.Buffer{}
+ ofile = obuf
+ }
+
lcs := make([]compliance.LicenseCondition, 0, len(*conditions))
for _, name := range *conditions {
lcs = append(lcs, compliance.RecognizedConditionNames[name])
@@ -111,14 +164,21 @@ func main() {
labelConditions: *labelConditions,
stripPrefix: *stripPrefix,
}
- _, err := dumpResolutions(ctx, os.Stdout, os.Stderr, compliance.FS, flag.Args()...)
+ _, err := dumpResolutions(ctx, ofile, os.Stderr, compliance.FS, flags.Args()...)
if err != nil {
if err == failNoneRequested {
- flag.Usage()
+ flags.Usage()
}
fmt.Fprintf(os.Stderr, "%s\n", err.Error())
os.Exit(1)
}
+ if *outputFile != "-" {
+ err := os.WriteFile(*outputFile, obuf.Bytes(), 0666)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "could not write output to %q from %q: %s\n", *outputFile, os.Getenv("PWD"), err)
+ os.Exit(1)
+ }
+ }
os.Exit(0)
}
diff --git a/tools/compliance/cmd/htmlnotice/htmlnotice.go b/tools/compliance/cmd/htmlnotice/htmlnotice.go
index e98b27222a..1a4961020e 100644
--- a/tools/compliance/cmd/htmlnotice/htmlnotice.go
+++ b/tools/compliance/cmd/htmlnotice/htmlnotice.go
@@ -26,19 +26,13 @@ import (
"path/filepath"
"strings"
+ "android/soong/response"
"android/soong/tools/compliance"
"github.com/google/blueprint/deptools"
)
var (
- outputFile = flag.String("o", "-", "Where to write the NOTICE text file. (default stdout)")
- depsFile = flag.String("d", "", "Where to write the deps file")
- includeTOC = flag.Bool("toc", true, "Whether to include a table of contents.")
- product = flag.String("product", "", "The name of the product for which the notice is generated.")
- stripPrefix = newMultiString("strip_prefix", "Prefix to remove from paths. i.e. path to root (multiple allowed)")
- title = flag.String("title", "", "The title of the notice file.")
-
failNoneRequested = fmt.Errorf("\nNo license metadata files requested")
failNoLicenses = fmt.Errorf("No licenses found")
)
@@ -70,23 +64,10 @@ func (ctx context) strip(installPath string) string {
return installPath
}
-func init() {
- flag.Usage = func() {
- fmt.Fprintf(os.Stderr, `Usage: %s {options} file.meta_lic {file.meta_lic...}
-
-Outputs an html NOTICE.html or gzipped NOTICE.html.gz file if the -o filename
-ends with ".gz".
-
-Options:
-`, filepath.Base(os.Args[0]))
- flag.PrintDefaults()
- }
-}
-
// newMultiString creates a flag that allows multiple values in an array.
-func newMultiString(name, usage string) *multiString {
+func newMultiString(flags *flag.FlagSet, name, usage string) *multiString {
var f multiString
- flag.Var(&f, name, usage)
+ flags.Var(&f, name, usage)
return &f
}
@@ -97,16 +78,57 @@ func (ms *multiString) String() string { return strings.Join(*ms, ", ") }
func (ms *multiString) Set(s string) error { *ms = append(*ms, s); return nil }
func main() {
- flag.Parse()
+ var expandedArgs []string
+ for _, arg := range os.Args[1:] {
+ if strings.HasPrefix(arg, "@") {
+ f, err := os.Open(strings.TrimPrefix(arg, "@"))
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err.Error())
+ os.Exit(1)
+ }
+
+ respArgs, err := response.ReadRspFile(f)
+ f.Close()
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err.Error())
+ os.Exit(1)
+ }
+ expandedArgs = append(expandedArgs, respArgs...)
+ } else {
+ expandedArgs = append(expandedArgs, arg)
+ }
+ }
+
+ flags := flag.NewFlagSet("flags", flag.ExitOnError)
+
+ flags.Usage = func() {
+ fmt.Fprintf(os.Stderr, `Usage: %s {options} file.meta_lic {file.meta_lic...}
+
+Outputs an html NOTICE.html or gzipped NOTICE.html.gz file if the -o filename
+ends with ".gz".
+
+Options:
+`, filepath.Base(os.Args[0]))
+ flags.PrintDefaults()
+ }
+
+ outputFile := flags.String("o", "-", "Where to write the NOTICE text file. (default stdout)")
+ depsFile := flags.String("d", "", "Where to write the deps file")
+ includeTOC := flags.Bool("toc", true, "Whether to include a table of contents.")
+ product := flags.String("product", "", "The name of the product for which the notice is generated.")
+ stripPrefix := newMultiString(flags, "strip_prefix", "Prefix to remove from paths. i.e. path to root (multiple allowed)")
+ title := flags.String("title", "", "The title of the notice file.")
+
+ flags.Parse(expandedArgs)
// Must specify at least one root target.
- if flag.NArg() == 0 {
- flag.Usage()
+ if flags.NArg() == 0 {
+ flags.Usage()
os.Exit(2)
}
if len(*outputFile) == 0 {
- flag.Usage()
+ flags.Usage()
fmt.Fprintf(os.Stderr, "must specify file for -o; use - for stdout\n")
os.Exit(2)
} else {
@@ -143,10 +165,10 @@ func main() {
ctx := &context{ofile, os.Stderr, compliance.FS, *includeTOC, *product, *stripPrefix, *title, &deps}
- err := htmlNotice(ctx, flag.Args()...)
+ err := htmlNotice(ctx, flags.Args()...)
if err != nil {
if err == failNoneRequested {
- flag.Usage()
+ flags.Usage()
}
fmt.Fprintf(os.Stderr, "%s\n", err.Error())
os.Exit(1)
diff --git a/tools/compliance/cmd/listshare/listshare.go b/tools/compliance/cmd/listshare/listshare.go
index 7f4038b6c5..31bd1b22ac 100644
--- a/tools/compliance/cmd/listshare/listshare.go
+++ b/tools/compliance/cmd/listshare/listshare.go
@@ -15,6 +15,7 @@
package main
import (
+ "bytes"
"flag"
"fmt"
"io"
@@ -24,12 +25,41 @@ import (
"sort"
"strings"
+ "android/soong/response"
"android/soong/tools/compliance"
)
-func init() {
- flag.Usage = func() {
- fmt.Fprintf(os.Stderr, `Usage: %s file.meta_lic {file.meta_lic...}
+var (
+ failNoneRequested = fmt.Errorf("\nNo license metadata files requested")
+ failNoLicenses = fmt.Errorf("No licenses found")
+)
+
+func main() {
+ var expandedArgs []string
+ for _, arg := range os.Args[1:] {
+ if strings.HasPrefix(arg, "@") {
+ f, err := os.Open(strings.TrimPrefix(arg, "@"))
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err.Error())
+ os.Exit(1)
+ }
+
+ respArgs, err := response.ReadRspFile(f)
+ f.Close()
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err.Error())
+ os.Exit(1)
+ }
+ expandedArgs = append(expandedArgs, respArgs...)
+ } else {
+ expandedArgs = append(expandedArgs, arg)
+ }
+ }
+
+ flags := flag.NewFlagSet("flags", flag.ExitOnError)
+
+ flags.Usage = func() {
+ fmt.Fprintf(os.Stderr, `Usage: %s {-o outfile} file.meta_lic {file.meta_lic...}
Outputs a csv file with 1 project per line in the first field followed
by target:condition pairs describing why the project must be shared.
@@ -39,30 +69,61 @@ Soong module or Make target, and the license condition is either
restricted (e.g. GPL) or reciprocal (e.g. MPL).
`, filepath.Base(os.Args[0]))
}
-}
-var (
- failNoneRequested = fmt.Errorf("\nNo license metadata files requested")
- failNoLicenses = fmt.Errorf("No licenses found")
-)
+ outputFile := flags.String("o", "-", "Where to write the list of projects to share. (default stdout)")
-func main() {
- flag.Parse()
+ flags.Parse(expandedArgs)
// Must specify at least one root target.
- if flag.NArg() == 0 {
- flag.Usage()
+ if flags.NArg() == 0 {
+ flags.Usage()
os.Exit(2)
}
- err := listShare(os.Stdout, os.Stderr, compliance.FS, flag.Args()...)
+ if len(*outputFile) == 0 {
+ flags.Usage()
+ fmt.Fprintf(os.Stderr, "must specify file for -o; use - for stdout\n")
+ os.Exit(2)
+ } else {
+ dir, err := filepath.Abs(filepath.Dir(*outputFile))
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "cannot determine path to %q: %s\n", *outputFile, err)
+ os.Exit(1)
+ }
+ fi, err := os.Stat(dir)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "cannot read directory %q of %q: %s\n", dir, *outputFile, err)
+ os.Exit(1)
+ }
+ if !fi.IsDir() {
+ fmt.Fprintf(os.Stderr, "parent %q of %q is not a directory\n", dir, *outputFile)
+ os.Exit(1)
+ }
+ }
+
+ var ofile io.Writer
+ ofile = os.Stdout
+ var obuf *bytes.Buffer
+ if *outputFile != "-" {
+ obuf = &bytes.Buffer{}
+ ofile = obuf
+ }
+
+ err := listShare(ofile, os.Stderr, compliance.FS, flags.Args()...)
if err != nil {
if err == failNoneRequested {
- flag.Usage()
+ flags.Usage()
}
fmt.Fprintf(os.Stderr, "%s\n", err.Error())
os.Exit(1)
}
+ if *outputFile != "-" {
+ err := os.WriteFile(*outputFile, obuf.Bytes(), 0666)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "could not write output to %q from %q: %s\n", *outputFile, os.Getenv("PWD"), err)
+ os.Exit(1)
+ }
+ }
os.Exit(0)
}
@@ -76,7 +137,7 @@ func listShare(stdout, stderr io.Writer, rootFS fs.FS, files ...string) error {
// Read the license graph from the license metadata files (*.meta_lic).
licenseGraph, err := compliance.ReadLicenseGraph(rootFS, stderr, files)
if err != nil {
- return fmt.Errorf("Unable to read license metadata file(s) %q: %v\n", files, err)
+ return fmt.Errorf("Unable to read license metadata file(s) %q from %q: %v\n", files, os.Getenv("PWD"), err)
}
if licenseGraph == nil {
return failNoLicenses
diff --git a/tools/compliance/cmd/rtrace/rtrace.go b/tools/compliance/cmd/rtrace/rtrace.go
index 91171c42e7..667cdcea87 100644
--- a/tools/compliance/cmd/rtrace/rtrace.go
+++ b/tools/compliance/cmd/rtrace/rtrace.go
@@ -15,6 +15,7 @@
package main
import (
+ "bytes"
"flag"
"fmt"
"io"
@@ -24,21 +25,19 @@ import (
"sort"
"strings"
+ "android/soong/response"
"android/soong/tools/compliance"
)
var (
- sources = newMultiString("rtrace", "Projects or metadata files to trace back from. (required; multiple allowed)")
- stripPrefix = newMultiString("strip_prefix", "Prefix to remove from paths. i.e. path to root (multiple allowed)")
-
failNoneRequested = fmt.Errorf("\nNo license metadata files requested")
failNoSources = fmt.Errorf("\nNo projects or metadata files to trace back from")
failNoLicenses = fmt.Errorf("No licenses found")
)
type context struct {
- sources []string
- stripPrefix []string
+ sources []string
+ stripPrefix []string
}
func (ctx context) strip(installPath string) string {
@@ -54,8 +53,44 @@ func (ctx context) strip(installPath string) string {
return installPath
}
-func init() {
- flag.Usage = func() {
+// newMultiString creates a flag that allows multiple values in an array.
+func newMultiString(flags *flag.FlagSet, name, usage string) *multiString {
+ var f multiString
+ flags.Var(&f, name, usage)
+ return &f
+}
+
+// multiString implements the flag `Value` interface for multiple strings.
+type multiString []string
+
+func (ms *multiString) String() string { return strings.Join(*ms, ", ") }
+func (ms *multiString) Set(s string) error { *ms = append(*ms, s); return nil }
+
+func main() {
+ var expandedArgs []string
+ for _, arg := range os.Args[1:] {
+ if strings.HasPrefix(arg, "@") {
+ f, err := os.Open(strings.TrimPrefix(arg, "@"))
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err.Error())
+ os.Exit(1)
+ }
+
+ respArgs, err := response.ReadRspFile(f)
+ f.Close()
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err.Error())
+ os.Exit(1)
+ }
+ expandedArgs = append(expandedArgs, respArgs...)
+ } else {
+ expandedArgs = append(expandedArgs, arg)
+ }
+ }
+
+ flags := flag.NewFlagSet("flags", flag.ExitOnError)
+
+ flags.Usage = func() {
fmt.Fprintf(os.Stderr, `Usage: %s {options} file.meta_lic {file.meta_lic...}
Outputs a space-separated Target ActsOn Origin Condition tuple for each
@@ -72,50 +107,75 @@ i.e. target:condition1:condition2 etc.
Options:
`, filepath.Base(os.Args[0]))
- flag.PrintDefaults()
+ flags.PrintDefaults()
}
-}
-// newMultiString creates a flag that allows multiple values in an array.
-func newMultiString(name, usage string) *multiString {
- var f multiString
- flag.Var(&f, name, usage)
- return &f
-}
+ outputFile := flags.String("o", "-", "Where to write the output. (default stdout)")
+ sources := newMultiString(flags, "rtrace", "Projects or metadata files to trace back from. (required; multiple allowed)")
+ stripPrefix := newMultiString(flags, "strip_prefix", "Prefix to remove from paths. i.e. path to root (multiple allowed)")
-// multiString implements the flag `Value` interface for multiple strings.
-type multiString []string
-
-func (ms *multiString) String() string { return strings.Join(*ms, ", ") }
-func (ms *multiString) Set(s string) error { *ms = append(*ms, s); return nil }
-
-func main() {
- flag.Parse()
+ flags.Parse(expandedArgs)
// Must specify at least one root target.
- if flag.NArg() == 0 {
- flag.Usage()
+ if flags.NArg() == 0 {
+ flags.Usage()
os.Exit(2)
}
if len(*sources) == 0 {
- flag.Usage()
+ flags.Usage()
fmt.Fprintf(os.Stderr, "\nMust specify at least 1 --rtrace source.\n")
os.Exit(2)
}
+ if len(*outputFile) == 0 {
+ flags.Usage()
+ fmt.Fprintf(os.Stderr, "must specify file for -o; use - for stdout\n")
+ os.Exit(2)
+ } else {
+ dir, err := filepath.Abs(filepath.Dir(*outputFile))
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "cannot determine path to %q: %s\n", *outputFile, err)
+ os.Exit(1)
+ }
+ fi, err := os.Stat(dir)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "cannot read directory %q of %q: %s\n", dir, *outputFile, err)
+ os.Exit(1)
+ }
+ if !fi.IsDir() {
+ fmt.Fprintf(os.Stderr, "parent %q of %q is not a directory\n", dir, *outputFile)
+ os.Exit(1)
+ }
+ }
+
+ var ofile io.Writer
+ ofile = os.Stdout
+ var obuf *bytes.Buffer
+ if *outputFile != "-" {
+ obuf = &bytes.Buffer{}
+ ofile = obuf
+ }
+
ctx := &context{
- sources: *sources,
- stripPrefix: *stripPrefix,
+ sources: *sources,
+ stripPrefix: *stripPrefix,
}
- _, err := traceRestricted(ctx, os.Stdout, os.Stderr, compliance.FS, flag.Args()...)
+ _, err := traceRestricted(ctx, ofile, os.Stderr, compliance.FS, flags.Args()...)
if err != nil {
if err == failNoneRequested {
- flag.Usage()
+ flags.Usage()
}
fmt.Fprintf(os.Stderr, "%s\n", err.Error())
os.Exit(1)
}
+ if *outputFile != "-" {
+ err := os.WriteFile(*outputFile, obuf.Bytes(), 0666)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "could not write output to %q from %q: %s\n", *outputFile, os.Getenv("PWD"), err)
+ os.Exit(1)
+ }
+ }
os.Exit(0)
}
diff --git a/tools/compliance/cmd/shippedlibs/shippedlibs.go b/tools/compliance/cmd/shippedlibs/shippedlibs.go
index 9d25dd3de9..add6dd63e8 100644
--- a/tools/compliance/cmd/shippedlibs/shippedlibs.go
+++ b/tools/compliance/cmd/shippedlibs/shippedlibs.go
@@ -39,9 +39,6 @@ type context struct {
rootFS fs.FS
}
-func init() {
-}
-
func main() {
var expandedArgs []string
for _, arg := range os.Args[1:] {
diff --git a/tools/compliance/cmd/textnotice/textnotice.go b/tools/compliance/cmd/textnotice/textnotice.go
index cfa0859a2a..9beaf58ad1 100644
--- a/tools/compliance/cmd/textnotice/textnotice.go
+++ b/tools/compliance/cmd/textnotice/textnotice.go
@@ -25,18 +25,13 @@ import (
"path/filepath"
"strings"
+ "android/soong/response"
"android/soong/tools/compliance"
"github.com/google/blueprint/deptools"
)
var (
- outputFile = flag.String("o", "-", "Where to write the NOTICE text file. (default stdout)")
- depsFile = flag.String("d", "", "Where to write the deps file")
- product = flag.String("product", "", "The name of the product for which the notice is generated.")
- stripPrefix = newMultiString("strip_prefix", "Prefix to remove from paths. i.e. path to root (multiple allowed)")
- title = flag.String("title", "", "The title of the notice file.")
-
failNoneRequested = fmt.Errorf("\nNo license metadata files requested")
failNoLicenses = fmt.Errorf("No licenses found")
)
@@ -67,22 +62,10 @@ func (ctx context) strip(installPath string) string {
return installPath
}
-func init() {
- flag.Usage = func() {
- fmt.Fprintf(os.Stderr, `Usage: %s {options} file.meta_lic {file.meta_lic...}
-
-Outputs a text NOTICE file.
-
-Options:
-`, filepath.Base(os.Args[0]))
- flag.PrintDefaults()
- }
-}
-
// newMultiString creates a flag that allows multiple values in an array.
-func newMultiString(name, usage string) *multiString {
+func newMultiString(flags *flag.FlagSet, name, usage string) *multiString {
var f multiString
- flag.Var(&f, name, usage)
+ flags.Var(&f, name, usage)
return &f
}
@@ -93,16 +76,55 @@ func (ms *multiString) String() string { return strings.Join(*ms, ", ") }
func (ms *multiString) Set(s string) error { *ms = append(*ms, s); return nil }
func main() {
- flag.Parse()
+ var expandedArgs []string
+ for _, arg := range os.Args[1:] {
+ if strings.HasPrefix(arg, "@") {
+ f, err := os.Open(strings.TrimPrefix(arg, "@"))
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err.Error())
+ os.Exit(1)
+ }
+
+ respArgs, err := response.ReadRspFile(f)
+ f.Close()
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err.Error())
+ os.Exit(1)
+ }
+ expandedArgs = append(expandedArgs, respArgs...)
+ } else {
+ expandedArgs = append(expandedArgs, arg)
+ }
+ }
+
+ flags := flag.NewFlagSet("flags", flag.ExitOnError)
+
+ flags.Usage = func() {
+ fmt.Fprintf(os.Stderr, `Usage: %s {options} file.meta_lic {file.meta_lic...}
+
+Outputs a text NOTICE file.
+
+Options:
+`, filepath.Base(os.Args[0]))
+ flags.PrintDefaults()
+ }
+
+ outputFile := flags.String("o", "-", "Where to write the NOTICE text file. (default stdout)")
+ depsFile := flags.String("d", "", "Where to write the deps file")
+ product := flags.String("product", "", "The name of the product for which the notice is generated.")
+ stripPrefix := newMultiString(flags, "strip_prefix", "Prefix to remove from paths. i.e. path to root (multiple allowed)")
+ title := flags.String("title", "", "The title of the notice file.")
+
+ flags.Parse(expandedArgs)
// Must specify at least one root target.
- if flag.NArg() == 0 {
- flag.Usage()
+ if flags.NArg() == 0 {
+ flags.Usage()
os.Exit(2)
}
if len(*outputFile) == 0 {
- flag.Usage()
+ flags.Usage()
fmt.Fprintf(os.Stderr, "must specify file for -o; use - for stdout\n")
os.Exit(2)
} else {
@@ -139,10 +161,10 @@ func main() {
ctx := &context{ofile, os.Stderr, compliance.FS, *product, *stripPrefix, *title, &deps}
- err := textNotice(ctx, flag.Args()...)
+ err := textNotice(ctx, flags.Args()...)
if err != nil {
if err == failNoneRequested {
- flag.Usage()
+ flags.Usage()
}
fmt.Fprintf(os.Stderr, "%s\n", err.Error())
os.Exit(1)
diff --git a/tools/compliance/cmd/xmlnotice/xmlnotice.go b/tools/compliance/cmd/xmlnotice/xmlnotice.go
index 84859d738a..2097b7c5e1 100644
--- a/tools/compliance/cmd/xmlnotice/xmlnotice.go
+++ b/tools/compliance/cmd/xmlnotice/xmlnotice.go
@@ -26,18 +26,13 @@ import (
"path/filepath"
"strings"
+ "android/soong/response"
"android/soong/tools/compliance"
"github.com/google/blueprint/deptools"
)
var (
- outputFile = flag.String("o", "-", "Where to write the NOTICE xml or xml.gz file. (default stdout)")
- depsFile = flag.String("d", "", "Where to write the deps file")
- product = flag.String("product", "", "The name of the product for which the notice is generated.")
- stripPrefix = newMultiString("strip_prefix", "Prefix to remove from paths. i.e. path to root (multiple allowed)")
- title = flag.String("title", "", "The title of the notice file.")
-
failNoneRequested = fmt.Errorf("\nNo license metadata files requested")
failNoLicenses = fmt.Errorf("No licenses found")
)
@@ -68,23 +63,10 @@ func (ctx context) strip(installPath string) string {
return installPath
}
-func init() {
- flag.Usage = func() {
- fmt.Fprintf(os.Stderr, `Usage: %s {options} file.meta_lic {file.meta_lic...}
-
-Outputs an xml NOTICE.xml or gzipped NOTICE.xml.gz file if the -o filename ends
-with ".gz".
-
-Options:
-`, filepath.Base(os.Args[0]))
- flag.PrintDefaults()
- }
-}
-
// newMultiString creates a flag that allows multiple values in an array.
-func newMultiString(name, usage string) *multiString {
+func newMultiString(flags *flag.FlagSet, name, usage string) *multiString {
var f multiString
- flag.Var(&f, name, usage)
+ flags.Var(&f, name, usage)
return &f
}
@@ -95,16 +77,56 @@ func (ms *multiString) String() string { return strings.Join(*ms, ", ") }
func (ms *multiString) Set(s string) error { *ms = append(*ms, s); return nil }
func main() {
- flag.Parse()
+ var expandedArgs []string
+ for _, arg := range os.Args[1:] {
+ if strings.HasPrefix(arg, "@") {
+ f, err := os.Open(strings.TrimPrefix(arg, "@"))
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err.Error())
+ os.Exit(1)
+ }
+
+ respArgs, err := response.ReadRspFile(f)
+ f.Close()
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err.Error())
+ os.Exit(1)
+ }
+ expandedArgs = append(expandedArgs, respArgs...)
+ } else {
+ expandedArgs = append(expandedArgs, arg)
+ }
+ }
+
+ flags := flag.NewFlagSet("flags", flag.ExitOnError)
+
+ flags.Usage = func() {
+ fmt.Fprintf(os.Stderr, `Usage: %s {options} file.meta_lic {file.meta_lic...}
+
+Outputs an xml NOTICE.xml or gzipped NOTICE.xml.gz file if the -o filename ends
+with ".gz".
+
+Options:
+`, filepath.Base(os.Args[0]))
+ flags.PrintDefaults()
+ }
+
+ outputFile := flags.String("o", "-", "Where to write the NOTICE xml or xml.gz file. (default stdout)")
+ depsFile := flags.String("d", "", "Where to write the deps file")
+ product := flags.String("product", "", "The name of the product for which the notice is generated.")
+ stripPrefix := newMultiString(flags, "strip_prefix", "Prefix to remove from paths. i.e. path to root (multiple allowed)")
+ title := flags.String("title", "", "The title of the notice file.")
+
+ flags.Parse(expandedArgs)
// Must specify at least one root target.
- if flag.NArg() == 0 {
- flag.Usage()
+ if flags.NArg() == 0 {
+ flags.Usage()
os.Exit(2)
}
if len(*outputFile) == 0 {
- flag.Usage()
+ flags.Usage()
fmt.Fprintf(os.Stderr, "must specify file for -o; use - for stdout\n")
os.Exit(2)
} else {
@@ -141,10 +163,10 @@ func main() {
ctx := &context{ofile, os.Stderr, compliance.FS, *product, *stripPrefix, *title, &deps}
- err := xmlNotice(ctx, flag.Args()...)
+ err := xmlNotice(ctx, flags.Args()...)
if err != nil {
if err == failNoneRequested {
- flag.Usage()
+ flags.Usage()
}
fmt.Fprintf(os.Stderr, "%s\n", err.Error())
os.Exit(1)