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