blob: 0b459965ced7f1e30fc4287ced86272cf468f29c [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"
Kevin Dagostino60f562a2022-09-20 03:54:47 +000012
Chris Parsons492bd912022-01-20 12:55:05 -050013 "github.com/google/blueprint"
Jingwen Chen164e0862021-02-19 00:48:40 -050014)
15
16// Simple metrics struct to collect information about a Blueprint to BUILD
17// conversion process.
18type CodegenMetrics struct {
Jingwen Chen310bc8f2021-09-20 10:54:27 +000019 // 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 -050020 generatedModuleCount uint64
Jingwen Chen310bc8f2021-09-20 10:54:27 +000021
22 // 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 -050023 handCraftedModuleCount uint64
Jingwen Chen310bc8f2021-09-20 10:54:27 +000024
25 // Total number of unconverted Soong modules
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -050026 unconvertedModuleCount uint64
Jingwen Chen164e0862021-02-19 00:48:40 -050027
28 // 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 -050029 ruleClassCount map[string]uint64
Liz Kammer6eff3232021-08-26 08:37:59 -040030
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -050031 // List of modules with unconverted deps
32 // NOTE: NOT in the .proto
Liz Kammer6eff3232021-08-26 08:37:59 -040033 moduleWithUnconvertedDepsMsgs []string
Jingwen Chen61174502021-09-17 08:40:45 +000034
Liz Kammerdaa09ef2021-12-15 15:35:38 -050035 // List of modules with missing deps
36 // NOTE: NOT in the .proto
37 moduleWithMissingDepsMsgs []string
38
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -050039 // List of converted modules
Jingwen Chen61174502021-09-17 08:40:45 +000040 convertedModules []string
Chris Parsons492bd912022-01-20 12:55:05 -050041
Kevin Dagostino60f562a2022-09-20 03:54:47 +000042 // Map of converted modules and paths to call
43 convertedModulePathMap map[string]string
44
Chris Parsons492bd912022-01-20 12:55:05 -050045 // Counts of converted modules by module type.
46 convertedModuleTypeCount map[string]uint64
47
48 // Counts of total modules by module type.
49 totalModuleTypeCount map[string]uint64
Chris Parsons715b08f2022-03-22 19:23:40 -040050
51 Events []*bp2build_metrics_proto.Event
Jingwen Chen164e0862021-02-19 00:48:40 -050052}
53
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -050054// Serialize returns the protoized version of CodegenMetrics: bp2build_metrics_proto.Bp2BuildMetrics
55func (metrics *CodegenMetrics) Serialize() bp2build_metrics_proto.Bp2BuildMetrics {
56 return bp2build_metrics_proto.Bp2BuildMetrics{
Chris Parsons492bd912022-01-20 12:55:05 -050057 GeneratedModuleCount: metrics.generatedModuleCount,
58 HandCraftedModuleCount: metrics.handCraftedModuleCount,
59 UnconvertedModuleCount: metrics.unconvertedModuleCount,
60 RuleClassCount: metrics.ruleClassCount,
61 ConvertedModules: metrics.convertedModules,
62 ConvertedModuleTypeCount: metrics.convertedModuleTypeCount,
63 TotalModuleTypeCount: metrics.totalModuleTypeCount,
Chris Parsons715b08f2022-03-22 19:23:40 -040064 Events: metrics.Events,
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -050065 }
66}
67
Jingwen Chen164e0862021-02-19 00:48:40 -050068// Print the codegen metrics to stdout.
Jingwen Chenafb84bd2021-09-20 10:31:46 +000069func (metrics *CodegenMetrics) Print() {
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -050070 generatedTargetCount := uint64(0)
Jingwen Chen310bc8f2021-09-20 10:54:27 +000071 for _, ruleClass := range android.SortedStringKeys(metrics.ruleClassCount) {
72 count := metrics.ruleClassCount[ruleClass]
Jingwen Chen164e0862021-02-19 00:48:40 -050073 fmt.Printf("[bp2build] %s: %d targets\n", ruleClass, count)
74 generatedTargetCount += count
75 }
76 fmt.Printf(
Liz Kammerdaa09ef2021-12-15 15:35:38 -050077 `[bp2build] Converted %d Android.bp modules to %d total generated BUILD targets. Included %d handcrafted BUILD targets. There are %d total Android.bp modules.
78%d converted modules have unconverted deps:
79 %s
80%d converted modules have missing deps:
81 %s
82`,
Chris Parsons91b81f02021-12-08 11:19:06 -050083 metrics.generatedModuleCount,
Jingwen Chen164e0862021-02-19 00:48:40 -050084 generatedTargetCount,
Jingwen Chen310bc8f2021-09-20 10:54:27 +000085 metrics.handCraftedModuleCount,
86 metrics.TotalModuleCount(),
Liz Kammer6eff3232021-08-26 08:37:59 -040087 len(metrics.moduleWithUnconvertedDepsMsgs),
Liz Kammerdaa09ef2021-12-15 15:35:38 -050088 strings.Join(metrics.moduleWithUnconvertedDepsMsgs, "\n\t"),
89 len(metrics.moduleWithMissingDepsMsgs),
90 strings.Join(metrics.moduleWithMissingDepsMsgs, "\n\t"),
91 )
Jingwen Chen164e0862021-02-19 00:48:40 -050092}
Jingwen Chen61174502021-09-17 08:40:45 +000093
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -050094const bp2buildMetricsFilename = "bp2build_metrics.pb"
95
96// fail prints $PWD to stderr, followed by the given printf string and args (vals),
97// then the given alert, and then exits with 1 for failure
98func fail(err error, alertFmt string, vals ...interface{}) {
99 cwd, wderr := os.Getwd()
100 if wderr != nil {
101 cwd = "FAILED TO GET $PWD: " + wderr.Error()
102 }
103 fmt.Fprintf(os.Stderr, "\nIn "+cwd+":\n"+alertFmt+"\n"+err.Error()+"\n", vals...)
104 os.Exit(1)
105}
106
107// Write the bp2build-protoized codegen metrics into the given directory
108func (metrics *CodegenMetrics) Write(dir string) {
109 if _, err := os.Stat(dir); os.IsNotExist(err) {
110 // The metrics dir doesn't already exist, so create it (and parents)
111 if err := os.MkdirAll(dir, 0755); err != nil { // rx for all; w for user
112 fail(err, "Failed to `mkdir -p` %s", dir)
113 }
114 } else if err != nil {
115 fail(err, "Failed to `stat` %s", dir)
116 }
117 metricsFile := filepath.Join(dir, bp2buildMetricsFilename)
118 if err := metrics.dump(metricsFile); err != nil {
119 fail(err, "Error outputting %s", metricsFile)
120 }
121 if _, err := os.Stat(metricsFile); err != nil {
122 fail(err, "MISSING BP2BUILD METRICS OUTPUT: Failed to `stat` %s", metricsFile)
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -0500123 }
124}
125
Jingwen Chen310bc8f2021-09-20 10:54:27 +0000126func (metrics *CodegenMetrics) IncrementRuleClassCount(ruleClass string) {
127 metrics.ruleClassCount[ruleClass] += 1
128}
129
Chris Parsons492bd912022-01-20 12:55:05 -0500130func (metrics *CodegenMetrics) AddUnconvertedModule(moduleType string) {
Jingwen Chen310bc8f2021-09-20 10:54:27 +0000131 metrics.unconvertedModuleCount += 1
Chris Parsons492bd912022-01-20 12:55:05 -0500132 metrics.totalModuleTypeCount[moduleType] += 1
Jingwen Chen310bc8f2021-09-20 10:54:27 +0000133}
134
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -0500135func (metrics *CodegenMetrics) TotalModuleCount() uint64 {
Jingwen Chen310bc8f2021-09-20 10:54:27 +0000136 return metrics.handCraftedModuleCount +
137 metrics.generatedModuleCount +
138 metrics.unconvertedModuleCount
139}
140
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -0500141// Dump serializes the metrics to the given filename
142func (metrics *CodegenMetrics) dump(filename string) (err error) {
143 ser := metrics.Serialize()
144 return shared.Save(&ser, filename)
145}
146
Jingwen Chen310bc8f2021-09-20 10:54:27 +0000147type ConversionType int
148
149const (
150 Generated ConversionType = iota
151 Handcrafted
152)
153
Kevin Dagostino60f562a2022-09-20 03:54:47 +0000154func (metrics *CodegenMetrics) AddConvertedModule(m blueprint.Module, moduleType string, dir string, conversionType ConversionType) {
Jingwen Chen61174502021-09-17 08:40:45 +0000155 // Undo prebuilt_ module name prefix modifications
Chris Parsons492bd912022-01-20 12:55:05 -0500156 moduleName := android.RemoveOptionalPrebuiltPrefix(m.Name())
Jingwen Chen61174502021-09-17 08:40:45 +0000157 metrics.convertedModules = append(metrics.convertedModules, moduleName)
Kevin Dagostino60f562a2022-09-20 03:54:47 +0000158 metrics.convertedModulePathMap[moduleName] = "//" + dir
Chris Parsons492bd912022-01-20 12:55:05 -0500159 metrics.convertedModuleTypeCount[moduleType] += 1
160 metrics.totalModuleTypeCount[moduleType] += 1
Jingwen Chen310bc8f2021-09-20 10:54:27 +0000161
162 if conversionType == Handcrafted {
163 metrics.handCraftedModuleCount += 1
164 } else if conversionType == Generated {
165 metrics.generatedModuleCount += 1
166 }
Jingwen Chen61174502021-09-17 08:40:45 +0000167}