blob: dd2d2fa26c45e1120310012eee5792c8eeda799d [file] [log] [blame]
Wei Lib85a1782024-02-05 14:50:54 -08001// 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 "io"
19 "path/filepath"
20 "strings"
21
22 "github.com/google/blueprint"
23)
24
25var (
26 // Command line tool to generate SBOM in Soong
27 genSbom = pctx.HostBinToolVariable("genSbom", "gen_sbom")
28
29 // Command to generate SBOM in Soong.
30 genSbomRule = pctx.AndroidStaticRule("genSbomRule", blueprint.RuleParams{
31 Command: "rm -rf $out && ${genSbom} --output_file ${out} --metadata ${in} --product_out ${productOut} --soong_out ${soongOut} --build_version \"$$(cat ${buildFingerprintFile})\" --product_mfr \"${productManufacturer}\" --json",
32 CommandDeps: []string{"${genSbom}"},
33 }, "productOut", "soongOut", "buildFingerprintFile", "productManufacturer")
34)
35
36func init() {
37 RegisterSbomSingleton(InitRegistrationContext)
38}
39
40func RegisterSbomSingleton(ctx RegistrationContext) {
41 ctx.RegisterParallelSingletonType("sbom_singleton", sbomSingletonFactory)
42}
43
44// sbomSingleton is used to generate build actions of generating SBOM of products.
45type sbomSingleton struct{}
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 // Get all METADATA files and add them as implicit input
57 metadataFileListFile := PathForArbitraryOutput(ctx, ".module_paths", "METADATA.list")
58 f, err := ctx.Config().fs.Open(metadataFileListFile.String())
59 if err != nil {
60 panic(err)
61 }
62 b, err := io.ReadAll(f)
63 if err != nil {
64 panic(err)
65 }
66 allMetadataFiles := strings.Split(string(b), "\n")
67 implicits := []Path{metadataFileListFile}
68 for _, path := range allMetadataFiles {
69 implicits = append(implicits, PathForSource(ctx, path))
70 }
71 prodVars := ctx.Config().productVariables
72 buildFingerprintFile := PathForArbitraryOutput(ctx, "target", "product", String(prodVars.DeviceName), "build_fingerprint.txt")
73 implicits = append(implicits, buildFingerprintFile)
74
75 // Add installed_files.stamp as implicit input, which depends on all installed files of the product.
76 installedFilesStamp := PathForOutput(ctx, "compliance-metadata", ctx.Config().DeviceProduct(), "installed_files.stamp")
77 implicits = append(implicits, installedFilesStamp)
78
79 metadataDb := PathForOutput(ctx, "compliance-metadata", ctx.Config().DeviceProduct(), "compliance-metadata.db")
80 sbomFile := PathForOutput(ctx, "sbom", ctx.Config().DeviceProduct(), "sbom.spdx.json")
81 ctx.Build(pctx, BuildParams{
82 Rule: genSbomRule,
83 Input: metadataDb,
84 Implicits: implicits,
85 Output: sbomFile,
86 Args: map[string]string{
87 "productOut": filepath.Join(ctx.Config().OutDir(), "target", "product", String(prodVars.DeviceName)),
88 "soongOut": ctx.Config().soongOutDir,
89 "buildFingerprintFile": buildFingerprintFile.String(),
90 "productManufacturer": ctx.Config().ProductVariables().ProductManufacturer,
91 },
92 })
93
94 // Phony rule "soong-sbom". "m soong-sbom" to generate product SBOM in Soong.
95 ctx.Build(pctx, BuildParams{
96 Rule: blueprint.Phony,
97 Inputs: []Path{sbomFile},
98 Output: PathForPhony(ctx, "soong-sbom"),
99 })
100}