xref: /aosp_15_r20/build/soong/android/compliance_metadata.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1*333d2b36SAndroid Build Coastguard Worker// Copyright 2024 Google Inc. All rights reserved.
2*333d2b36SAndroid Build Coastguard Worker//
3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License");
4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License.
5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at
6*333d2b36SAndroid Build Coastguard Worker//
7*333d2b36SAndroid Build Coastguard Worker//	http://www.apache.org/licenses/LICENSE-2.0
8*333d2b36SAndroid Build Coastguard Worker//
9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software
10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS,
11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and
13*333d2b36SAndroid Build Coastguard Worker// limitations under the License.
14*333d2b36SAndroid Build Coastguard Worker
15*333d2b36SAndroid Build Coastguard Workerpackage android
16*333d2b36SAndroid Build Coastguard Worker
17*333d2b36SAndroid Build Coastguard Workerimport (
18*333d2b36SAndroid Build Coastguard Worker	"bytes"
19*333d2b36SAndroid Build Coastguard Worker	"encoding/csv"
20*333d2b36SAndroid Build Coastguard Worker	"fmt"
21*333d2b36SAndroid Build Coastguard Worker	"slices"
22*333d2b36SAndroid Build Coastguard Worker	"strconv"
23*333d2b36SAndroid Build Coastguard Worker	"strings"
24*333d2b36SAndroid Build Coastguard Worker
25*333d2b36SAndroid Build Coastguard Worker	"github.com/google/blueprint"
26*333d2b36SAndroid Build Coastguard Worker	"github.com/google/blueprint/gobtools"
27*333d2b36SAndroid Build Coastguard Worker)
28*333d2b36SAndroid Build Coastguard Worker
29*333d2b36SAndroid Build Coastguard Workervar (
30*333d2b36SAndroid Build Coastguard Worker	// Constants of property names used in compliance metadata of modules
31*333d2b36SAndroid Build Coastguard Worker	ComplianceMetadataProp = struct {
32*333d2b36SAndroid Build Coastguard Worker		NAME                   string
33*333d2b36SAndroid Build Coastguard Worker		PACKAGE                string
34*333d2b36SAndroid Build Coastguard Worker		MODULE_TYPE            string
35*333d2b36SAndroid Build Coastguard Worker		OS                     string
36*333d2b36SAndroid Build Coastguard Worker		ARCH                   string
37*333d2b36SAndroid Build Coastguard Worker		IS_PRIMARY_ARCH        string
38*333d2b36SAndroid Build Coastguard Worker		VARIANT                string
39*333d2b36SAndroid Build Coastguard Worker		IS_STATIC_LIB          string
40*333d2b36SAndroid Build Coastguard Worker		INSTALLED_FILES        string
41*333d2b36SAndroid Build Coastguard Worker		BUILT_FILES            string
42*333d2b36SAndroid Build Coastguard Worker		STATIC_DEPS            string
43*333d2b36SAndroid Build Coastguard Worker		STATIC_DEP_FILES       string
44*333d2b36SAndroid Build Coastguard Worker		WHOLE_STATIC_DEPS      string
45*333d2b36SAndroid Build Coastguard Worker		WHOLE_STATIC_DEP_FILES string
46*333d2b36SAndroid Build Coastguard Worker		LICENSES               string
47*333d2b36SAndroid Build Coastguard Worker
48*333d2b36SAndroid Build Coastguard Worker		// module_type=package
49*333d2b36SAndroid Build Coastguard Worker		PKG_DEFAULT_APPLICABLE_LICENSES string
50*333d2b36SAndroid Build Coastguard Worker
51*333d2b36SAndroid Build Coastguard Worker		// module_type=license
52*333d2b36SAndroid Build Coastguard Worker		LIC_LICENSE_KINDS string
53*333d2b36SAndroid Build Coastguard Worker		LIC_LICENSE_TEXT  string
54*333d2b36SAndroid Build Coastguard Worker		LIC_PACKAGE_NAME  string
55*333d2b36SAndroid Build Coastguard Worker
56*333d2b36SAndroid Build Coastguard Worker		// module_type=license_kind
57*333d2b36SAndroid Build Coastguard Worker		LK_CONDITIONS string
58*333d2b36SAndroid Build Coastguard Worker		LK_URL        string
59*333d2b36SAndroid Build Coastguard Worker	}{
60*333d2b36SAndroid Build Coastguard Worker		"name",
61*333d2b36SAndroid Build Coastguard Worker		"package",
62*333d2b36SAndroid Build Coastguard Worker		"module_type",
63*333d2b36SAndroid Build Coastguard Worker		"os",
64*333d2b36SAndroid Build Coastguard Worker		"arch",
65*333d2b36SAndroid Build Coastguard Worker		"is_primary_arch",
66*333d2b36SAndroid Build Coastguard Worker		"variant",
67*333d2b36SAndroid Build Coastguard Worker		"is_static_lib",
68*333d2b36SAndroid Build Coastguard Worker		"installed_files",
69*333d2b36SAndroid Build Coastguard Worker		"built_files",
70*333d2b36SAndroid Build Coastguard Worker		"static_deps",
71*333d2b36SAndroid Build Coastguard Worker		"static_dep_files",
72*333d2b36SAndroid Build Coastguard Worker		"whole_static_deps",
73*333d2b36SAndroid Build Coastguard Worker		"whole_static_dep_files",
74*333d2b36SAndroid Build Coastguard Worker		"licenses",
75*333d2b36SAndroid Build Coastguard Worker
76*333d2b36SAndroid Build Coastguard Worker		"pkg_default_applicable_licenses",
77*333d2b36SAndroid Build Coastguard Worker
78*333d2b36SAndroid Build Coastguard Worker		"lic_license_kinds",
79*333d2b36SAndroid Build Coastguard Worker		"lic_license_text",
80*333d2b36SAndroid Build Coastguard Worker		"lic_package_name",
81*333d2b36SAndroid Build Coastguard Worker
82*333d2b36SAndroid Build Coastguard Worker		"lk_conditions",
83*333d2b36SAndroid Build Coastguard Worker		"lk_url",
84*333d2b36SAndroid Build Coastguard Worker	}
85*333d2b36SAndroid Build Coastguard Worker
86*333d2b36SAndroid Build Coastguard Worker	// A constant list of all property names in compliance metadata
87*333d2b36SAndroid Build Coastguard Worker	// Order of properties here is the order of columns in the exported CSV file.
88*333d2b36SAndroid Build Coastguard Worker	COMPLIANCE_METADATA_PROPS = []string{
89*333d2b36SAndroid Build Coastguard Worker		ComplianceMetadataProp.NAME,
90*333d2b36SAndroid Build Coastguard Worker		ComplianceMetadataProp.PACKAGE,
91*333d2b36SAndroid Build Coastguard Worker		ComplianceMetadataProp.MODULE_TYPE,
92*333d2b36SAndroid Build Coastguard Worker		ComplianceMetadataProp.OS,
93*333d2b36SAndroid Build Coastguard Worker		ComplianceMetadataProp.ARCH,
94*333d2b36SAndroid Build Coastguard Worker		ComplianceMetadataProp.VARIANT,
95*333d2b36SAndroid Build Coastguard Worker		ComplianceMetadataProp.IS_STATIC_LIB,
96*333d2b36SAndroid Build Coastguard Worker		ComplianceMetadataProp.IS_PRIMARY_ARCH,
97*333d2b36SAndroid Build Coastguard Worker		// Space separated installed files
98*333d2b36SAndroid Build Coastguard Worker		ComplianceMetadataProp.INSTALLED_FILES,
99*333d2b36SAndroid Build Coastguard Worker		// Space separated built files
100*333d2b36SAndroid Build Coastguard Worker		ComplianceMetadataProp.BUILT_FILES,
101*333d2b36SAndroid Build Coastguard Worker		// Space separated module names of static dependencies
102*333d2b36SAndroid Build Coastguard Worker		ComplianceMetadataProp.STATIC_DEPS,
103*333d2b36SAndroid Build Coastguard Worker		// Space separated file paths of static dependencies
104*333d2b36SAndroid Build Coastguard Worker		ComplianceMetadataProp.STATIC_DEP_FILES,
105*333d2b36SAndroid Build Coastguard Worker		// Space separated module names of whole static dependencies
106*333d2b36SAndroid Build Coastguard Worker		ComplianceMetadataProp.WHOLE_STATIC_DEPS,
107*333d2b36SAndroid Build Coastguard Worker		// Space separated file paths of whole static dependencies
108*333d2b36SAndroid Build Coastguard Worker		ComplianceMetadataProp.WHOLE_STATIC_DEP_FILES,
109*333d2b36SAndroid Build Coastguard Worker		ComplianceMetadataProp.LICENSES,
110*333d2b36SAndroid Build Coastguard Worker		// module_type=package
111*333d2b36SAndroid Build Coastguard Worker		ComplianceMetadataProp.PKG_DEFAULT_APPLICABLE_LICENSES,
112*333d2b36SAndroid Build Coastguard Worker		// module_type=license
113*333d2b36SAndroid Build Coastguard Worker		ComplianceMetadataProp.LIC_LICENSE_KINDS,
114*333d2b36SAndroid Build Coastguard Worker		ComplianceMetadataProp.LIC_LICENSE_TEXT, // resolve to file paths
115*333d2b36SAndroid Build Coastguard Worker		ComplianceMetadataProp.LIC_PACKAGE_NAME,
116*333d2b36SAndroid Build Coastguard Worker		// module_type=license_kind
117*333d2b36SAndroid Build Coastguard Worker		ComplianceMetadataProp.LK_CONDITIONS,
118*333d2b36SAndroid Build Coastguard Worker		ComplianceMetadataProp.LK_URL,
119*333d2b36SAndroid Build Coastguard Worker	}
120*333d2b36SAndroid Build Coastguard Worker)
121*333d2b36SAndroid Build Coastguard Worker
122*333d2b36SAndroid Build Coastguard Worker// ComplianceMetadataInfo provides all metadata of a module, e.g. name, module type, package, license,
123*333d2b36SAndroid Build Coastguard Worker// dependencies, built/installed files, etc. It is a wrapper on a map[string]string with some utility
124*333d2b36SAndroid Build Coastguard Worker// methods to get/set properties' values.
125*333d2b36SAndroid Build Coastguard Workertype ComplianceMetadataInfo struct {
126*333d2b36SAndroid Build Coastguard Worker	properties map[string]string
127*333d2b36SAndroid Build Coastguard Worker}
128*333d2b36SAndroid Build Coastguard Worker
129*333d2b36SAndroid Build Coastguard Workertype complianceMetadataInfoGob struct {
130*333d2b36SAndroid Build Coastguard Worker	Properties map[string]string
131*333d2b36SAndroid Build Coastguard Worker}
132*333d2b36SAndroid Build Coastguard Worker
133*333d2b36SAndroid Build Coastguard Workerfunc NewComplianceMetadataInfo() *ComplianceMetadataInfo {
134*333d2b36SAndroid Build Coastguard Worker	return &ComplianceMetadataInfo{
135*333d2b36SAndroid Build Coastguard Worker		properties: map[string]string{},
136*333d2b36SAndroid Build Coastguard Worker	}
137*333d2b36SAndroid Build Coastguard Worker}
138*333d2b36SAndroid Build Coastguard Worker
139*333d2b36SAndroid Build Coastguard Workerfunc (m *ComplianceMetadataInfo) ToGob() *complianceMetadataInfoGob {
140*333d2b36SAndroid Build Coastguard Worker	return &complianceMetadataInfoGob{
141*333d2b36SAndroid Build Coastguard Worker		Properties: m.properties,
142*333d2b36SAndroid Build Coastguard Worker	}
143*333d2b36SAndroid Build Coastguard Worker}
144*333d2b36SAndroid Build Coastguard Worker
145*333d2b36SAndroid Build Coastguard Workerfunc (m *ComplianceMetadataInfo) FromGob(data *complianceMetadataInfoGob) {
146*333d2b36SAndroid Build Coastguard Worker	m.properties = data.Properties
147*333d2b36SAndroid Build Coastguard Worker}
148*333d2b36SAndroid Build Coastguard Worker
149*333d2b36SAndroid Build Coastguard Workerfunc (c *ComplianceMetadataInfo) GobEncode() ([]byte, error) {
150*333d2b36SAndroid Build Coastguard Worker	return gobtools.CustomGobEncode[complianceMetadataInfoGob](c)
151*333d2b36SAndroid Build Coastguard Worker}
152*333d2b36SAndroid Build Coastguard Worker
153*333d2b36SAndroid Build Coastguard Workerfunc (c *ComplianceMetadataInfo) GobDecode(data []byte) error {
154*333d2b36SAndroid Build Coastguard Worker	return gobtools.CustomGobDecode[complianceMetadataInfoGob](data, c)
155*333d2b36SAndroid Build Coastguard Worker}
156*333d2b36SAndroid Build Coastguard Worker
157*333d2b36SAndroid Build Coastguard Workerfunc (c *ComplianceMetadataInfo) SetStringValue(propertyName string, value string) {
158*333d2b36SAndroid Build Coastguard Worker	if !slices.Contains(COMPLIANCE_METADATA_PROPS, propertyName) {
159*333d2b36SAndroid Build Coastguard Worker		panic(fmt.Errorf("Unknown metadata property: %s.", propertyName))
160*333d2b36SAndroid Build Coastguard Worker	}
161*333d2b36SAndroid Build Coastguard Worker	c.properties[propertyName] = value
162*333d2b36SAndroid Build Coastguard Worker}
163*333d2b36SAndroid Build Coastguard Worker
164*333d2b36SAndroid Build Coastguard Workerfunc (c *ComplianceMetadataInfo) SetListValue(propertyName string, value []string) {
165*333d2b36SAndroid Build Coastguard Worker	c.SetStringValue(propertyName, strings.TrimSpace(strings.Join(value, " ")))
166*333d2b36SAndroid Build Coastguard Worker}
167*333d2b36SAndroid Build Coastguard Worker
168*333d2b36SAndroid Build Coastguard Workerfunc (c *ComplianceMetadataInfo) getStringValue(propertyName string) string {
169*333d2b36SAndroid Build Coastguard Worker	if !slices.Contains(COMPLIANCE_METADATA_PROPS, propertyName) {
170*333d2b36SAndroid Build Coastguard Worker		panic(fmt.Errorf("Unknown metadata property: %s.", propertyName))
171*333d2b36SAndroid Build Coastguard Worker	}
172*333d2b36SAndroid Build Coastguard Worker	return c.properties[propertyName]
173*333d2b36SAndroid Build Coastguard Worker}
174*333d2b36SAndroid Build Coastguard Worker
175*333d2b36SAndroid Build Coastguard Workerfunc (c *ComplianceMetadataInfo) getAllValues() map[string]string {
176*333d2b36SAndroid Build Coastguard Worker	return c.properties
177*333d2b36SAndroid Build Coastguard Worker}
178*333d2b36SAndroid Build Coastguard Worker
179*333d2b36SAndroid Build Coastguard Workervar (
180*333d2b36SAndroid Build Coastguard Worker	ComplianceMetadataProvider = blueprint.NewProvider[*ComplianceMetadataInfo]()
181*333d2b36SAndroid Build Coastguard Worker)
182*333d2b36SAndroid Build Coastguard Worker
183*333d2b36SAndroid Build Coastguard Worker// buildComplianceMetadataProvider starts with the ModuleContext.ComplianceMetadataInfo() and fills in more common metadata
184*333d2b36SAndroid Build Coastguard Worker// for different module types without accessing their private fields but through android.Module interface
185*333d2b36SAndroid Build Coastguard Worker// and public/private fields of package android. The final metadata is stored to a module's ComplianceMetadataProvider.
186*333d2b36SAndroid Build Coastguard Workerfunc buildComplianceMetadataProvider(ctx *moduleContext, m *ModuleBase) {
187*333d2b36SAndroid Build Coastguard Worker	complianceMetadataInfo := ctx.ComplianceMetadataInfo()
188*333d2b36SAndroid Build Coastguard Worker	complianceMetadataInfo.SetStringValue(ComplianceMetadataProp.NAME, m.Name())
189*333d2b36SAndroid Build Coastguard Worker	complianceMetadataInfo.SetStringValue(ComplianceMetadataProp.PACKAGE, ctx.ModuleDir())
190*333d2b36SAndroid Build Coastguard Worker	complianceMetadataInfo.SetStringValue(ComplianceMetadataProp.MODULE_TYPE, ctx.ModuleType())
191*333d2b36SAndroid Build Coastguard Worker
192*333d2b36SAndroid Build Coastguard Worker	switch ctx.ModuleType() {
193*333d2b36SAndroid Build Coastguard Worker	case "license":
194*333d2b36SAndroid Build Coastguard Worker		licenseModule := m.module.(*licenseModule)
195*333d2b36SAndroid Build Coastguard Worker		complianceMetadataInfo.SetListValue(ComplianceMetadataProp.LIC_LICENSE_KINDS, licenseModule.properties.License_kinds)
196*333d2b36SAndroid Build Coastguard Worker		complianceMetadataInfo.SetListValue(ComplianceMetadataProp.LIC_LICENSE_TEXT, PathsForModuleSrc(ctx, licenseModule.properties.License_text).Strings())
197*333d2b36SAndroid Build Coastguard Worker		complianceMetadataInfo.SetStringValue(ComplianceMetadataProp.LIC_PACKAGE_NAME, String(licenseModule.properties.Package_name))
198*333d2b36SAndroid Build Coastguard Worker	case "license_kind":
199*333d2b36SAndroid Build Coastguard Worker		licenseKindModule := m.module.(*licenseKindModule)
200*333d2b36SAndroid Build Coastguard Worker		complianceMetadataInfo.SetListValue(ComplianceMetadataProp.LK_CONDITIONS, licenseKindModule.properties.Conditions)
201*333d2b36SAndroid Build Coastguard Worker		complianceMetadataInfo.SetStringValue(ComplianceMetadataProp.LK_URL, licenseKindModule.properties.Url)
202*333d2b36SAndroid Build Coastguard Worker	default:
203*333d2b36SAndroid Build Coastguard Worker		complianceMetadataInfo.SetStringValue(ComplianceMetadataProp.OS, ctx.Os().String())
204*333d2b36SAndroid Build Coastguard Worker		complianceMetadataInfo.SetStringValue(ComplianceMetadataProp.ARCH, ctx.Arch().String())
205*333d2b36SAndroid Build Coastguard Worker		complianceMetadataInfo.SetStringValue(ComplianceMetadataProp.IS_PRIMARY_ARCH, strconv.FormatBool(ctx.PrimaryArch()))
206*333d2b36SAndroid Build Coastguard Worker		complianceMetadataInfo.SetStringValue(ComplianceMetadataProp.VARIANT, ctx.ModuleSubDir())
207*333d2b36SAndroid Build Coastguard Worker		if m.primaryLicensesProperty != nil && m.primaryLicensesProperty.getName() == "licenses" {
208*333d2b36SAndroid Build Coastguard Worker			complianceMetadataInfo.SetListValue(ComplianceMetadataProp.LICENSES, m.primaryLicensesProperty.getStrings())
209*333d2b36SAndroid Build Coastguard Worker		}
210*333d2b36SAndroid Build Coastguard Worker
211*333d2b36SAndroid Build Coastguard Worker		var installed InstallPaths
212*333d2b36SAndroid Build Coastguard Worker		installed = append(installed, ctx.installFiles...)
213*333d2b36SAndroid Build Coastguard Worker		installed = append(installed, ctx.katiInstalls.InstallPaths()...)
214*333d2b36SAndroid Build Coastguard Worker		installed = append(installed, ctx.katiSymlinks.InstallPaths()...)
215*333d2b36SAndroid Build Coastguard Worker		installed = append(installed, ctx.katiInitRcInstalls.InstallPaths()...)
216*333d2b36SAndroid Build Coastguard Worker		installed = append(installed, ctx.katiVintfInstalls.InstallPaths()...)
217*333d2b36SAndroid Build Coastguard Worker		complianceMetadataInfo.SetListValue(ComplianceMetadataProp.INSTALLED_FILES, FirstUniqueStrings(installed.Strings()))
218*333d2b36SAndroid Build Coastguard Worker	}
219*333d2b36SAndroid Build Coastguard Worker	ctx.setProvider(ComplianceMetadataProvider, complianceMetadataInfo)
220*333d2b36SAndroid Build Coastguard Worker}
221*333d2b36SAndroid Build Coastguard Worker
222*333d2b36SAndroid Build Coastguard Workerfunc init() {
223*333d2b36SAndroid Build Coastguard Worker	RegisterComplianceMetadataSingleton(InitRegistrationContext)
224*333d2b36SAndroid Build Coastguard Worker}
225*333d2b36SAndroid Build Coastguard Worker
226*333d2b36SAndroid Build Coastguard Workerfunc RegisterComplianceMetadataSingleton(ctx RegistrationContext) {
227*333d2b36SAndroid Build Coastguard Worker	ctx.RegisterParallelSingletonType("compliance_metadata_singleton", complianceMetadataSingletonFactory)
228*333d2b36SAndroid Build Coastguard Worker}
229*333d2b36SAndroid Build Coastguard Worker
230*333d2b36SAndroid Build Coastguard Workervar (
231*333d2b36SAndroid Build Coastguard Worker	// sqlite3 command line tool
232*333d2b36SAndroid Build Coastguard Worker	sqlite3 = pctx.HostBinToolVariable("sqlite3", "sqlite3")
233*333d2b36SAndroid Build Coastguard Worker
234*333d2b36SAndroid Build Coastguard Worker	// Command to import .csv files to sqlite3 database
235*333d2b36SAndroid Build Coastguard Worker	importCsv = pctx.AndroidStaticRule("importCsv",
236*333d2b36SAndroid Build Coastguard Worker		blueprint.RuleParams{
237*333d2b36SAndroid Build Coastguard Worker			Command: `rm -rf $out && ` +
238*333d2b36SAndroid Build Coastguard Worker				`${sqlite3} $out ".import --csv $in modules" && ` +
239*333d2b36SAndroid Build Coastguard Worker				`${sqlite3} $out ".import --csv ${make_metadata} make_metadata" && ` +
240*333d2b36SAndroid Build Coastguard Worker				`${sqlite3} $out ".import --csv ${make_modules} make_modules"`,
241*333d2b36SAndroid Build Coastguard Worker			CommandDeps: []string{"${sqlite3}"},
242*333d2b36SAndroid Build Coastguard Worker		}, "make_metadata", "make_modules")
243*333d2b36SAndroid Build Coastguard Worker)
244*333d2b36SAndroid Build Coastguard Worker
245*333d2b36SAndroid Build Coastguard Workerfunc complianceMetadataSingletonFactory() Singleton {
246*333d2b36SAndroid Build Coastguard Worker	return &complianceMetadataSingleton{}
247*333d2b36SAndroid Build Coastguard Worker}
248*333d2b36SAndroid Build Coastguard Worker
249*333d2b36SAndroid Build Coastguard Workertype complianceMetadataSingleton struct {
250*333d2b36SAndroid Build Coastguard Worker}
251*333d2b36SAndroid Build Coastguard Worker
252*333d2b36SAndroid Build Coastguard Workerfunc writerToCsv(csvWriter *csv.Writer, row []string) {
253*333d2b36SAndroid Build Coastguard Worker	err := csvWriter.Write(row)
254*333d2b36SAndroid Build Coastguard Worker	if err != nil {
255*333d2b36SAndroid Build Coastguard Worker		panic(err)
256*333d2b36SAndroid Build Coastguard Worker	}
257*333d2b36SAndroid Build Coastguard Worker}
258*333d2b36SAndroid Build Coastguard Worker
259*333d2b36SAndroid Build Coastguard Worker// Collect compliance metadata from all Soong modules, write to a CSV file and
260*333d2b36SAndroid Build Coastguard Worker// import compliance metadata from Make and Soong to a sqlite3 database.
261*333d2b36SAndroid Build Coastguard Workerfunc (c *complianceMetadataSingleton) GenerateBuildActions(ctx SingletonContext) {
262*333d2b36SAndroid Build Coastguard Worker	if !ctx.Config().HasDeviceProduct() {
263*333d2b36SAndroid Build Coastguard Worker		return
264*333d2b36SAndroid Build Coastguard Worker	}
265*333d2b36SAndroid Build Coastguard Worker	var buffer bytes.Buffer
266*333d2b36SAndroid Build Coastguard Worker	csvWriter := csv.NewWriter(&buffer)
267*333d2b36SAndroid Build Coastguard Worker
268*333d2b36SAndroid Build Coastguard Worker	// Collect compliance metadata of modules in Soong and write to out/soong/compliance-metadata/<product>/soong-modules.csv file.
269*333d2b36SAndroid Build Coastguard Worker	columnNames := []string{"id"}
270*333d2b36SAndroid Build Coastguard Worker	columnNames = append(columnNames, COMPLIANCE_METADATA_PROPS...)
271*333d2b36SAndroid Build Coastguard Worker	writerToCsv(csvWriter, columnNames)
272*333d2b36SAndroid Build Coastguard Worker
273*333d2b36SAndroid Build Coastguard Worker	rowId := -1
274*333d2b36SAndroid Build Coastguard Worker	ctx.VisitAllModules(func(module Module) {
275*333d2b36SAndroid Build Coastguard Worker		if !module.Enabled(ctx) {
276*333d2b36SAndroid Build Coastguard Worker			return
277*333d2b36SAndroid Build Coastguard Worker		}
278*333d2b36SAndroid Build Coastguard Worker		moduleType := ctx.ModuleType(module)
279*333d2b36SAndroid Build Coastguard Worker		if moduleType == "package" {
280*333d2b36SAndroid Build Coastguard Worker			metadataMap := map[string]string{
281*333d2b36SAndroid Build Coastguard Worker				ComplianceMetadataProp.NAME:                            ctx.ModuleName(module),
282*333d2b36SAndroid Build Coastguard Worker				ComplianceMetadataProp.MODULE_TYPE:                     ctx.ModuleType(module),
283*333d2b36SAndroid Build Coastguard Worker				ComplianceMetadataProp.PKG_DEFAULT_APPLICABLE_LICENSES: strings.Join(module.base().primaryLicensesProperty.getStrings(), " "),
284*333d2b36SAndroid Build Coastguard Worker			}
285*333d2b36SAndroid Build Coastguard Worker			rowId = rowId + 1
286*333d2b36SAndroid Build Coastguard Worker			metadata := []string{strconv.Itoa(rowId)}
287*333d2b36SAndroid Build Coastguard Worker			for _, propertyName := range COMPLIANCE_METADATA_PROPS {
288*333d2b36SAndroid Build Coastguard Worker				metadata = append(metadata, metadataMap[propertyName])
289*333d2b36SAndroid Build Coastguard Worker			}
290*333d2b36SAndroid Build Coastguard Worker			writerToCsv(csvWriter, metadata)
291*333d2b36SAndroid Build Coastguard Worker			return
292*333d2b36SAndroid Build Coastguard Worker		}
293*333d2b36SAndroid Build Coastguard Worker		if provider, ok := ctx.otherModuleProvider(module, ComplianceMetadataProvider); ok {
294*333d2b36SAndroid Build Coastguard Worker			metadataInfo := provider.(*ComplianceMetadataInfo)
295*333d2b36SAndroid Build Coastguard Worker			rowId = rowId + 1
296*333d2b36SAndroid Build Coastguard Worker			metadata := []string{strconv.Itoa(rowId)}
297*333d2b36SAndroid Build Coastguard Worker			for _, propertyName := range COMPLIANCE_METADATA_PROPS {
298*333d2b36SAndroid Build Coastguard Worker				metadata = append(metadata, metadataInfo.getStringValue(propertyName))
299*333d2b36SAndroid Build Coastguard Worker			}
300*333d2b36SAndroid Build Coastguard Worker			writerToCsv(csvWriter, metadata)
301*333d2b36SAndroid Build Coastguard Worker			return
302*333d2b36SAndroid Build Coastguard Worker		}
303*333d2b36SAndroid Build Coastguard Worker	})
304*333d2b36SAndroid Build Coastguard Worker	csvWriter.Flush()
305*333d2b36SAndroid Build Coastguard Worker
306*333d2b36SAndroid Build Coastguard Worker	deviceProduct := ctx.Config().DeviceProduct()
307*333d2b36SAndroid Build Coastguard Worker	modulesCsv := PathForOutput(ctx, "compliance-metadata", deviceProduct, "soong-modules.csv")
308*333d2b36SAndroid Build Coastguard Worker	WriteFileRuleVerbatim(ctx, modulesCsv, buffer.String())
309*333d2b36SAndroid Build Coastguard Worker
310*333d2b36SAndroid Build Coastguard Worker	// Metadata generated in Make
311*333d2b36SAndroid Build Coastguard Worker	makeMetadataCsv := PathForOutput(ctx, "compliance-metadata", deviceProduct, "make-metadata.csv")
312*333d2b36SAndroid Build Coastguard Worker	makeModulesCsv := PathForOutput(ctx, "compliance-metadata", deviceProduct, "make-modules.csv")
313*333d2b36SAndroid Build Coastguard Worker
314*333d2b36SAndroid Build Coastguard Worker	// Import metadata from Make and Soong to sqlite3 database
315*333d2b36SAndroid Build Coastguard Worker	complianceMetadataDb := PathForOutput(ctx, "compliance-metadata", deviceProduct, "compliance-metadata.db")
316*333d2b36SAndroid Build Coastguard Worker	ctx.Build(pctx, BuildParams{
317*333d2b36SAndroid Build Coastguard Worker		Rule:  importCsv,
318*333d2b36SAndroid Build Coastguard Worker		Input: modulesCsv,
319*333d2b36SAndroid Build Coastguard Worker		Implicits: []Path{
320*333d2b36SAndroid Build Coastguard Worker			makeMetadataCsv,
321*333d2b36SAndroid Build Coastguard Worker			makeModulesCsv,
322*333d2b36SAndroid Build Coastguard Worker		},
323*333d2b36SAndroid Build Coastguard Worker		Output: complianceMetadataDb,
324*333d2b36SAndroid Build Coastguard Worker		Args: map[string]string{
325*333d2b36SAndroid Build Coastguard Worker			"make_metadata": makeMetadataCsv.String(),
326*333d2b36SAndroid Build Coastguard Worker			"make_modules":  makeModulesCsv.String(),
327*333d2b36SAndroid Build Coastguard Worker		},
328*333d2b36SAndroid Build Coastguard Worker	})
329*333d2b36SAndroid Build Coastguard Worker
330*333d2b36SAndroid Build Coastguard Worker	// Phony rule "compliance-metadata.db". "m compliance-metadata.db" to create the compliance metadata database.
331*333d2b36SAndroid Build Coastguard Worker	ctx.Build(pctx, BuildParams{
332*333d2b36SAndroid Build Coastguard Worker		Rule:   blueprint.Phony,
333*333d2b36SAndroid Build Coastguard Worker		Inputs: []Path{complianceMetadataDb},
334*333d2b36SAndroid Build Coastguard Worker		Output: PathForPhony(ctx, "compliance-metadata.db"),
335*333d2b36SAndroid Build Coastguard Worker	})
336*333d2b36SAndroid Build Coastguard Worker
337*333d2b36SAndroid Build Coastguard Worker}
338