blob: d1cc1a2c1e5bba38c5fc83c356f5e3a26495c81b [file] [log] [blame]
Joe Onoratod6a29992024-12-06 12:55:41 -08001package build
2
3import (
4 "compress/gzip"
5 "fmt"
6 "os"
7 "path/filepath"
8 "sort"
9 "strings"
10
11 "android/soong/shared"
12 "android/soong/ui/metrics"
13)
14
15func sortedStringSetKeys(m map[string]bool) []string {
16 result := make([]string, 0, len(m))
17 for key := range m {
18 result = append(result, key)
19 }
20 sort.Strings(result)
21 return result
22}
23
24func addSlash(str string) string {
25 if len(str) == 0 {
26 return ""
27 }
28 if str[len(str)-1] == '/' {
29 return str
30 }
31 return str + "/"
32}
33
34func hasPrefixStrings(str string, prefixes []string) bool {
35 for _, prefix := range prefixes {
36 if strings.HasPrefix(str, prefix) {
37 return true
38 }
39 }
40 return false
41}
42
43// Output DIST_DIR/source_inputs.txt.gz, which will contain a listing of the files
44// in the source tree (not including in the out directory) that were declared as ninja
45// inputs to the build that was just done.
46func runSourceInputs(ctx Context, config Config) {
47 ctx.BeginTrace(metrics.RunSoong, "runSourceInputs")
48 defer ctx.EndTrace()
49
50 success := false
51 outputFilename := shared.JoinPath(config.RealDistDir(), "source_inputs.txt.gz")
52
53 outputFile, err := os.Create(outputFilename)
54 if err != nil {
55 fmt.Fprintf(os.Stderr, "source_files_used: unable to open file for write: %s\n", outputFilename)
56 return
57 }
58 defer func() {
59 outputFile.Close()
60 if !success {
61 os.Remove(outputFilename)
62 }
63 }()
64
65 output := gzip.NewWriter(outputFile)
66 defer output.Close()
67
68 // Skip out dir, both absolute and relative. There are some files
69 // generated during analysis that ninja thinks are inputs not intermediates.
70 absOut, _ := filepath.Abs(config.OutDir())
71 excludes := []string{
72 addSlash(config.OutDir()),
73 addSlash(absOut),
74 }
75
76 goals := config.NinjaArgs()
77
78 result := make(map[string]bool)
79 for _, goal := range goals {
80 inputs, err := runNinjaInputs(ctx, config, goal)
81 if err != nil {
82 fmt.Fprintf(os.Stderr, "source_files_used: %v\n", err)
83 return
84 }
85
86 for _, filename := range inputs {
87 if !hasPrefixStrings(filename, excludes) {
88 result[filename] = true
89 }
90 }
91 }
92
93 for _, filename := range sortedStringSetKeys(result) {
94 output.Write([]byte(filename))
95 output.Write([]byte("\n"))
96 }
97
98 output.Flush()
99 success = true
100}