blob: 557ea994cffca1e79089d59fc84340b2fa9c155c [file] [log] [blame]
Jingwen Chen164e0862021-02-19 00:48:40 -05001package bp2build
2
3import (
Jingwen Chen164e0862021-02-19 00:48:40 -05004 "fmt"
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -05005 "os"
6 "path/filepath"
Liz Kammer6eff3232021-08-26 08:37:59 -04007 "strings"
Chris Parsons91b81f02021-12-08 11:19:06 -05008
9 "android/soong/android"
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -050010 "android/soong/shared"
11 "android/soong/ui/metrics/bp2build_metrics_proto"
Jingwen Chen164e0862021-02-19 00:48:40 -050012)
13
14// Simple metrics struct to collect information about a Blueprint to BUILD
15// conversion process.
16type CodegenMetrics struct {
Jingwen Chen310bc8f2021-09-20 10:54:27 +000017 // Total number of Soong modules converted to generated targets
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -050018 generatedModuleCount uint64
Jingwen Chen310bc8f2021-09-20 10:54:27 +000019
20 // Total number of Soong modules converted to handcrafted targets
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -050021 handCraftedModuleCount uint64
Jingwen Chen310bc8f2021-09-20 10:54:27 +000022
23 // Total number of unconverted Soong modules
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -050024 unconvertedModuleCount uint64
Jingwen Chen164e0862021-02-19 00:48:40 -050025
26 // Counts of generated Bazel targets per Bazel rule class
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -050027 ruleClassCount map[string]uint64
Liz Kammer6eff3232021-08-26 08:37:59 -040028
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -050029 // List of modules with unconverted deps
30 // NOTE: NOT in the .proto
Liz Kammer6eff3232021-08-26 08:37:59 -040031 moduleWithUnconvertedDepsMsgs []string
Jingwen Chen61174502021-09-17 08:40:45 +000032
Liz Kammerdaa09ef2021-12-15 15:35:38 -050033 // List of modules with missing deps
34 // NOTE: NOT in the .proto
35 moduleWithMissingDepsMsgs []string
36
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -050037 // List of converted modules
Jingwen Chen61174502021-09-17 08:40:45 +000038 convertedModules []string
Jingwen Chen164e0862021-02-19 00:48:40 -050039}
40
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -050041// Serialize returns the protoized version of CodegenMetrics: bp2build_metrics_proto.Bp2BuildMetrics
42func (metrics *CodegenMetrics) Serialize() bp2build_metrics_proto.Bp2BuildMetrics {
43 return bp2build_metrics_proto.Bp2BuildMetrics{
44 GeneratedModuleCount: metrics.generatedModuleCount,
45 HandCraftedModuleCount: metrics.handCraftedModuleCount,
46 UnconvertedModuleCount: metrics.unconvertedModuleCount,
47 RuleClassCount: metrics.ruleClassCount,
48 ConvertedModules: metrics.convertedModules,
49 }
50}
51
Jingwen Chen164e0862021-02-19 00:48:40 -050052// Print the codegen metrics to stdout.
Jingwen Chenafb84bd2021-09-20 10:31:46 +000053func (metrics *CodegenMetrics) Print() {
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -050054 generatedTargetCount := uint64(0)
Jingwen Chen310bc8f2021-09-20 10:54:27 +000055 for _, ruleClass := range android.SortedStringKeys(metrics.ruleClassCount) {
56 count := metrics.ruleClassCount[ruleClass]
Jingwen Chen164e0862021-02-19 00:48:40 -050057 fmt.Printf("[bp2build] %s: %d targets\n", ruleClass, count)
58 generatedTargetCount += count
59 }
60 fmt.Printf(
Liz Kammerdaa09ef2021-12-15 15:35:38 -050061 `[bp2build] Converted %d Android.bp modules to %d total generated BUILD targets. Included %d handcrafted BUILD targets. There are %d total Android.bp modules.
62%d converted modules have unconverted deps:
63 %s
64%d converted modules have missing deps:
65 %s
66`,
Chris Parsons91b81f02021-12-08 11:19:06 -050067 metrics.generatedModuleCount,
Jingwen Chen164e0862021-02-19 00:48:40 -050068 generatedTargetCount,
Jingwen Chen310bc8f2021-09-20 10:54:27 +000069 metrics.handCraftedModuleCount,
70 metrics.TotalModuleCount(),
Liz Kammer6eff3232021-08-26 08:37:59 -040071 len(metrics.moduleWithUnconvertedDepsMsgs),
Liz Kammerdaa09ef2021-12-15 15:35:38 -050072 strings.Join(metrics.moduleWithUnconvertedDepsMsgs, "\n\t"),
73 len(metrics.moduleWithMissingDepsMsgs),
74 strings.Join(metrics.moduleWithMissingDepsMsgs, "\n\t"),
75 )
Jingwen Chen164e0862021-02-19 00:48:40 -050076}
Jingwen Chen61174502021-09-17 08:40:45 +000077
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -050078const bp2buildMetricsFilename = "bp2build_metrics.pb"
79
80// fail prints $PWD to stderr, followed by the given printf string and args (vals),
81// then the given alert, and then exits with 1 for failure
82func fail(err error, alertFmt string, vals ...interface{}) {
83 cwd, wderr := os.Getwd()
84 if wderr != nil {
85 cwd = "FAILED TO GET $PWD: " + wderr.Error()
86 }
87 fmt.Fprintf(os.Stderr, "\nIn "+cwd+":\n"+alertFmt+"\n"+err.Error()+"\n", vals...)
88 os.Exit(1)
89}
90
91// Write the bp2build-protoized codegen metrics into the given directory
92func (metrics *CodegenMetrics) Write(dir string) {
93 if _, err := os.Stat(dir); os.IsNotExist(err) {
94 // The metrics dir doesn't already exist, so create it (and parents)
95 if err := os.MkdirAll(dir, 0755); err != nil { // rx for all; w for user
96 fail(err, "Failed to `mkdir -p` %s", dir)
97 }
98 } else if err != nil {
99 fail(err, "Failed to `stat` %s", dir)
100 }
101 metricsFile := filepath.Join(dir, bp2buildMetricsFilename)
102 if err := metrics.dump(metricsFile); err != nil {
103 fail(err, "Error outputting %s", metricsFile)
104 }
105 if _, err := os.Stat(metricsFile); err != nil {
106 fail(err, "MISSING BP2BUILD METRICS OUTPUT: Failed to `stat` %s", metricsFile)
107 } else {
108 fmt.Printf("\nWrote bp2build metrics to: %s\n", metricsFile)
109 }
110}
111
Jingwen Chen310bc8f2021-09-20 10:54:27 +0000112func (metrics *CodegenMetrics) IncrementRuleClassCount(ruleClass string) {
113 metrics.ruleClassCount[ruleClass] += 1
114}
115
116func (metrics *CodegenMetrics) IncrementUnconvertedCount() {
117 metrics.unconvertedModuleCount += 1
118}
119
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -0500120func (metrics *CodegenMetrics) TotalModuleCount() uint64 {
Jingwen Chen310bc8f2021-09-20 10:54:27 +0000121 return metrics.handCraftedModuleCount +
122 metrics.generatedModuleCount +
123 metrics.unconvertedModuleCount
124}
125
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -0500126// Dump serializes the metrics to the given filename
127func (metrics *CodegenMetrics) dump(filename string) (err error) {
128 ser := metrics.Serialize()
129 return shared.Save(&ser, filename)
130}
131
Jingwen Chen310bc8f2021-09-20 10:54:27 +0000132type ConversionType int
133
134const (
135 Generated ConversionType = iota
136 Handcrafted
137)
138
139func (metrics *CodegenMetrics) AddConvertedModule(moduleName string, conversionType ConversionType) {
Jingwen Chen61174502021-09-17 08:40:45 +0000140 // Undo prebuilt_ module name prefix modifications
141 moduleName = android.RemoveOptionalPrebuiltPrefix(moduleName)
142 metrics.convertedModules = append(metrics.convertedModules, moduleName)
Jingwen Chen310bc8f2021-09-20 10:54:27 +0000143
144 if conversionType == Handcrafted {
145 metrics.handCraftedModuleCount += 1
146 } else if conversionType == Generated {
147 metrics.generatedModuleCount += 1
148 }
Jingwen Chen61174502021-09-17 08:40:45 +0000149}