platform_build_soong/snapshot/snapshot.go
Justin Yun 1db9748805 Include license information for vendor and host snapshots
In addition to the license text files, include license kinds
information to json file. Also, use the original paths of license
text files that are copied to NOTICE_FILES directory.
This will be used when generating snapshots from the snapshot build.

Bug: 271539873
Test: m vendor-snapshot
Change-Id: I0c0427bb66f2c1fca322d5554aa66220a3b62fb3
2023-04-25 18:03:32 +09:00

146 lines
4.8 KiB
Go

// Copyright 2021 The Android Open Source Project
//
// 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 snapshot
import (
"path/filepath"
"sort"
"android/soong/android"
)
// This file contains singletons to capture snapshots. This singleton will generate snapshot of each target
// image, and capturing snapshot module will be delegated to each module which implements GenerateSnapshotAction
// function and register with RegisterSnapshotAction.
var pctx = android.NewPackageContext("android/soong/snapshot")
func init() {
pctx.Import("android/soong/android")
}
type SnapshotSingleton struct {
// Name, e.g., "vendor", "recovery", "ramdisk".
name string
// Make variable that points to the snapshot file, e.g.,
// "SOONG_RECOVERY_SNAPSHOT_ZIP".
makeVar string
// Path to the snapshot zip file.
snapshotZipFile android.OptionalPath
// Implementation of the image interface specific to the image
// associated with this snapshot (e.g., specific to the vendor image,
// recovery image, etc.).
Image SnapshotImage
// Whether this singleton is for fake snapshot or not.
// Fake snapshot is a snapshot whose prebuilt binaries and headers are empty.
// It is much faster to generate, and can be used to inspect dependencies.
Fake bool
}
// The output files to be included in the snapshot.
type SnapshotPaths struct {
// All files to be included in the snapshot
OutputFiles android.Paths
// Notice files of the snapshot output files
NoticeFiles android.Paths
}
// Interface of function to capture snapshot from each module
// Returns snapshot ouputs and notice files.
type GenerateSnapshotAction func(snapshot SnapshotSingleton, ctx android.SingletonContext, snapshotArchDir string) SnapshotPaths
var snapshotActionList []GenerateSnapshotAction
// Register GenerateSnapshotAction function so it can be called while generating snapshot
func RegisterSnapshotAction(x GenerateSnapshotAction) {
snapshotActionList = append(snapshotActionList, x)
}
func (c *SnapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) {
if !c.Image.shouldGenerateSnapshot(ctx) {
return
}
var snapshotOutputs android.Paths
// Snapshot zipped artifacts will be captured under {SNAPSHOT_ARCH} directory
snapshotDir := c.name + "-snapshot"
if c.Fake {
// If this is a fake snapshot singleton, place all files under fake/ subdirectory to avoid
// collision with real snapshot files
snapshotDir = filepath.Join("fake", snapshotDir)
}
snapshotArchDir := filepath.Join(snapshotDir, ctx.DeviceConfig().DeviceArch())
noticeDir := filepath.Join(snapshotArchDir, "NOTICE_FILES")
installedNotices := make(map[string]bool)
for _, f := range snapshotActionList {
snapshotPaths := f(*c, ctx, snapshotArchDir)
snapshotOutputs = append(snapshotOutputs, snapshotPaths.OutputFiles...)
for _, notice := range snapshotPaths.NoticeFiles {
if _, ok := installedNotices[notice.String()]; !ok {
installedNotices[notice.String()] = true
snapshotOutputs = append(snapshotOutputs, CopyFileRule(
pctx, ctx, notice, filepath.Join(noticeDir, notice.String())))
}
}
}
// All artifacts are ready. Sort them to normalize ninja and then zip.
sort.Slice(snapshotOutputs, func(i, j int) bool {
return snapshotOutputs[i].String() < snapshotOutputs[j].String()
})
zipPath := android.PathForOutput(
ctx,
snapshotDir,
c.name+"-"+ctx.Config().DeviceName()+".zip")
zipRule := android.NewRuleBuilder(pctx, ctx)
// filenames in rspfile from FlagWithRspFileInputList might be single-quoted. Remove it with tr
snapshotOutputList := android.PathForOutput(
ctx,
snapshotDir,
c.name+"-"+ctx.Config().DeviceName()+"_list")
rspFile := snapshotOutputList.ReplaceExtension(ctx, "rsp")
zipRule.Command().
Text("tr").
FlagWithArg("-d ", "\\'").
FlagWithRspFileInputList("< ", rspFile, snapshotOutputs).
FlagWithOutput("> ", snapshotOutputList)
zipRule.Temporary(snapshotOutputList)
zipRule.Command().
BuiltTool("soong_zip").
FlagWithOutput("-o ", zipPath).
FlagWithArg("-C ", android.PathForOutput(ctx, snapshotDir).String()).
FlagWithInput("-l ", snapshotOutputList)
zipRule.Build(zipPath.String(), c.name+" snapshot "+zipPath.String())
zipRule.DeleteTemporaryFiles()
c.snapshotZipFile = android.OptionalPathForPath(zipPath)
}
func (c *SnapshotSingleton) MakeVars(ctx android.MakeVarsContext) {
ctx.Strict(
c.makeVar,
c.snapshotZipFile.String())
}