Joe Onorato | d6a2999 | 2024-12-06 12:55:41 -0800 | [diff] [blame] | 1 | package build |
| 2 | |
| 3 | import ( |
| 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 | |
| 15 | func 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 | |
| 24 | func 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 | |
| 34 | func 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. |
| 46 | func 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 | } |