| // Copyright 2024 Google Inc. All rights reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package android |
| |
| import ( |
| "path/filepath" |
| |
| "github.com/google/blueprint" |
| ) |
| |
| var ( |
| // Command line tool to generate SBOM in Soong |
| genSbom = pctx.HostBinToolVariable("genSbom", "gen_sbom") |
| |
| // Command to generate SBOM in Soong. |
| genSbomRule = pctx.AndroidStaticRule("genSbomRule", blueprint.RuleParams{ |
| Command: "rm -rf $out && ${genSbom} --output_file ${out} --metadata ${in} --product_out ${productOut} --soong_out ${soongOut} --build_version \"$$(cat ${buildFingerprintFile})\" --product_mfr \"${productManufacturer}\" --json", |
| CommandDeps: []string{"${genSbom}"}, |
| }, "productOut", "soongOut", "buildFingerprintFile", "productManufacturer") |
| ) |
| |
| func init() { |
| RegisterSbomSingleton(InitRegistrationContext) |
| } |
| |
| func RegisterSbomSingleton(ctx RegistrationContext) { |
| ctx.RegisterParallelSingletonType("sbom_singleton", sbomSingletonFactory) |
| } |
| |
| // sbomSingleton is used to generate build actions of generating SBOM of products. |
| type sbomSingleton struct { |
| sbomFile OutputPath |
| } |
| |
| func sbomSingletonFactory() Singleton { |
| return &sbomSingleton{} |
| } |
| |
| // Generates SBOM of products |
| func (this *sbomSingleton) GenerateBuildActions(ctx SingletonContext) { |
| if !ctx.Config().HasDeviceProduct() { |
| return |
| } |
| implicits := []Path{} |
| prodVars := ctx.Config().productVariables |
| buildFingerprintFile := PathForArbitraryOutput(ctx, "target", "product", String(prodVars.DeviceName), "build_fingerprint.txt") |
| implicits = append(implicits, buildFingerprintFile) |
| |
| // Add installed_files.stamp as implicit input, which depends on all installed files of the product. |
| installedFilesStamp := PathForOutput(ctx, "compliance-metadata", ctx.Config().DeviceProduct(), "installed_files.stamp") |
| implicits = append(implicits, installedFilesStamp) |
| |
| metadataDb := PathForOutput(ctx, "compliance-metadata", ctx.Config().DeviceProduct(), "compliance-metadata.db") |
| this.sbomFile = PathForOutput(ctx, "sbom", ctx.Config().DeviceProduct(), "sbom.spdx.json") |
| ctx.Build(pctx, BuildParams{ |
| Rule: genSbomRule, |
| Input: metadataDb, |
| Implicits: implicits, |
| Output: this.sbomFile, |
| Args: map[string]string{ |
| "productOut": filepath.Join(ctx.Config().OutDir(), "target", "product", String(prodVars.DeviceName)), |
| "soongOut": ctx.Config().soongOutDir, |
| "buildFingerprintFile": buildFingerprintFile.String(), |
| "productManufacturer": ctx.Config().ProductVariables().ProductManufacturer, |
| }, |
| }) |
| |
| if !ctx.Config().UnbundledBuildApps() { |
| // When building SBOM of products, phony rule "sbom" is for generating product SBOM in Soong. |
| ctx.Build(pctx, BuildParams{ |
| Rule: blueprint.Phony, |
| Inputs: []Path{this.sbomFile}, |
| Output: PathForPhony(ctx, "sbom"), |
| }) |
| } |
| } |
| |
| func (this *sbomSingleton) MakeVars(ctx MakeVarsContext) { |
| // When building SBOM of products |
| if !ctx.Config().UnbundledBuildApps() { |
| ctx.DistForGoalWithFilename("droid", this.sbomFile, "sbom/sbom.spdx.json") |
| } |
| } |