xref: /aosp_15_r20/build/soong/android/sbom.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1// Copyright 2024 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package android
16
17import (
18	"path/filepath"
19
20	"github.com/google/blueprint"
21)
22
23var (
24	// Command line tool to generate SBOM in Soong
25	genSbom = pctx.HostBinToolVariable("genSbom", "gen_sbom")
26
27	// Command to generate SBOM in Soong.
28	genSbomRule = pctx.AndroidStaticRule("genSbomRule", blueprint.RuleParams{
29		Command:     "rm -rf $out && ${genSbom} --output_file ${out} --metadata ${in} --product_out ${productOut} --soong_out ${soongOut} --build_version \"$$(cat ${buildFingerprintFile})\" --product_mfr \"${productManufacturer}\" --json",
30		CommandDeps: []string{"${genSbom}"},
31	}, "productOut", "soongOut", "buildFingerprintFile", "productManufacturer")
32)
33
34func init() {
35	RegisterSbomSingleton(InitRegistrationContext)
36}
37
38func RegisterSbomSingleton(ctx RegistrationContext) {
39	ctx.RegisterParallelSingletonType("sbom_singleton", sbomSingletonFactory)
40}
41
42// sbomSingleton is used to generate build actions of generating SBOM of products.
43type sbomSingleton struct {
44	sbomFile OutputPath
45}
46
47func sbomSingletonFactory() Singleton {
48	return &sbomSingleton{}
49}
50
51// Generates SBOM of products
52func (this *sbomSingleton) GenerateBuildActions(ctx SingletonContext) {
53	if !ctx.Config().HasDeviceProduct() {
54		return
55	}
56	implicits := []Path{}
57	prodVars := ctx.Config().productVariables
58	buildFingerprintFile := PathForArbitraryOutput(ctx, "target", "product", String(prodVars.DeviceName), "build_fingerprint.txt")
59	implicits = append(implicits, buildFingerprintFile)
60
61	// Add installed_files.stamp as implicit input, which depends on all installed files of the product.
62	installedFilesStamp := PathForOutput(ctx, "compliance-metadata", ctx.Config().DeviceProduct(), "installed_files.stamp")
63	implicits = append(implicits, installedFilesStamp)
64
65	metadataDb := PathForOutput(ctx, "compliance-metadata", ctx.Config().DeviceProduct(), "compliance-metadata.db")
66	this.sbomFile = PathForOutput(ctx, "sbom", ctx.Config().DeviceProduct(), "sbom.spdx.json")
67	ctx.Build(pctx, BuildParams{
68		Rule:      genSbomRule,
69		Input:     metadataDb,
70		Implicits: implicits,
71		Output:    this.sbomFile,
72		Args: map[string]string{
73			"productOut":           filepath.Join(ctx.Config().OutDir(), "target", "product", String(prodVars.DeviceName)),
74			"soongOut":             ctx.Config().soongOutDir,
75			"buildFingerprintFile": buildFingerprintFile.String(),
76			"productManufacturer":  ctx.Config().ProductVariables().ProductManufacturer,
77		},
78	})
79
80	if !ctx.Config().UnbundledBuildApps() {
81		// When building SBOM of products, phony rule "sbom" is for generating product SBOM in Soong.
82		ctx.Build(pctx, BuildParams{
83			Rule:   blueprint.Phony,
84			Inputs: []Path{this.sbomFile},
85			Output: PathForPhony(ctx, "sbom"),
86		})
87	}
88}
89
90func (this *sbomSingleton) MakeVars(ctx MakeVarsContext) {
91	// When building SBOM of products
92	if !ctx.Config().UnbundledBuildApps() {
93		ctx.DistForGoalWithFilename("droid", this.sbomFile, "sbom/sbom.spdx.json")
94	}
95}
96