Implement fake vendor snapshot

A fake vendor snapshot is a vendor snapshot whose prebuilt binaries and
captured headers are all empty. It's much faster to be built than the
real vendor snapshot, so users can exploit the fake vendor snapshot to
reduce the size of vendor snapshot they need, by installing the fake
snapshot and then inspecting the ninja dependencies.

Bug: 157967325
Test: m dist vendor-fake-snapshot
Change-Id: I5e16e8dbbf9dd5e753cdd471ca73d06984a6cb2c
This commit is contained in:
Inseob Kim
2021-01-05 20:03:22 +09:00
parent 77dcb9d768
commit e9aec6aaca
4 changed files with 58 additions and 8 deletions

View File

@@ -1245,6 +1245,15 @@ func TestVendorSnapshotCapture(t *testing.T) {
t.Errorf("%q expected but not found", jsonFile)
}
}
// fake snapshot should have all outputs in the normal snapshot.
fakeSnapshotSingleton := ctx.SingletonForTests("vendor-fake-snapshot")
for _, output := range snapshotSingleton.AllOutputs() {
fakeOutput := strings.Replace(output, "/vendor-snapshot/", "/fake/vendor-snapshot/", 1)
if fakeSnapshotSingleton.MaybeOutput(fakeOutput).Rule == nil {
t.Errorf("%q expected but not found", fakeOutput)
}
}
}
func TestVendorSnapshotUse(t *testing.T) {
@@ -1676,6 +1685,8 @@ func TestVendorSnapshotExcludeInVendorProprietaryPathErrors(t *testing.T) {
`module "libvendor\{.+,image:vendor.+,arch:arm_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
`module "libvendor\{.+,image:vendor.+,arch:arm64_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
`module "libvendor\{.+,image:vendor.+,arch:arm_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
`module "libvendor\{.+,image:vendor.+,arch:arm64_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
`module "libvendor\{.+,image:vendor.+,arch:arm_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
})
}
@@ -1719,6 +1730,10 @@ func TestVendorSnapshotExcludeWithVendorAvailable(t *testing.T) {
`module "libinclude\{.+,image:,arch:arm_.+\}" may not use both "vendor_available: true" and "exclude_from_vendor_snapshot: true"`,
`module "libinclude\{.+,image:vendor.+,arch:arm64_.+\}" may not use both "vendor_available: true" and "exclude_from_vendor_snapshot: true"`,
`module "libinclude\{.+,image:vendor.+,arch:arm_.+\}" may not use both "vendor_available: true" and "exclude_from_vendor_snapshot: true"`,
`module "libinclude\{.+,image:,arch:arm64_.+\}" may not use both "vendor_available: true" and "exclude_from_vendor_snapshot: true"`,
`module "libinclude\{.+,image:,arch:arm_.+\}" may not use both "vendor_available: true" and "exclude_from_vendor_snapshot: true"`,
`module "libinclude\{.+,image:vendor.+,arch:arm64_.+\}" may not use both "vendor_available: true" and "exclude_from_vendor_snapshot: true"`,
`module "libinclude\{.+,image:vendor.+,arch:arm_.+\}" may not use both "vendor_available: true" and "exclude_from_vendor_snapshot: true"`,
})
}

View File

@@ -94,6 +94,8 @@ func (vendorSnapshotImage) init() {
android.RegisterModuleType("vendor_snapshot_header", VendorSnapshotHeaderFactory)
android.RegisterModuleType("vendor_snapshot_binary", VendorSnapshotBinaryFactory)
android.RegisterModuleType("vendor_snapshot_object", VendorSnapshotObjectFactory)
android.RegisterSingletonType("vendor-fake-snapshot", VendorFakeSnapshotSingleton)
}
func (vendorSnapshotImage) shouldGenerateSnapshot(ctx android.SingletonContext) bool {

View File

@@ -577,6 +577,7 @@ func CreateTestContext(config android.Config) *android.TestContext {
RegisterRequiredBuildComponentsForTest(ctx)
ctx.RegisterSingletonType("vndk-snapshot", VndkSnapshotSingleton)
ctx.RegisterSingletonType("vendor-snapshot", VendorSnapshotSingleton)
ctx.RegisterSingletonType("vendor-fake-snapshot", VendorFakeSnapshotSingleton)
ctx.RegisterSingletonType("recovery-snapshot", RecoverySnapshotSingleton)
return ctx

View File

@@ -34,6 +34,16 @@ var vendorSnapshotSingleton = snapshotSingleton{
android.OptionalPath{},
true,
vendorSnapshotImageSingleton,
false, /* fake */
}
var vendorFakeSnapshotSingleton = snapshotSingleton{
"vendor",
"SOONG_VENDOR_FAKE_SNAPSHOT_ZIP",
android.OptionalPath{},
true,
vendorSnapshotImageSingleton,
true, /* fake */
}
var recoverySnapshotSingleton = snapshotSingleton{
@@ -42,12 +52,17 @@ var recoverySnapshotSingleton = snapshotSingleton{
android.OptionalPath{},
false,
recoverySnapshotImageSingleton,
false, /* fake */
}
func VendorSnapshotSingleton() android.Singleton {
return &vendorSnapshotSingleton
}
func VendorFakeSnapshotSingleton() android.Singleton {
return &vendorFakeSnapshotSingleton
}
func RecoverySnapshotSingleton() android.Singleton {
return &recoverySnapshotSingleton
}
@@ -70,6 +85,11 @@ type snapshotSingleton struct {
// 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
}
var (
@@ -351,6 +371,11 @@ func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) {
*/
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())
includeDir := filepath.Join(snapshotArchDir, "include")
@@ -362,6 +387,15 @@ func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) {
var headers android.Paths
copyFile := copyFileRule
if c.fake {
// All prebuilt binaries and headers are installed by copyFile function. This makes a fake
// snapshot just touch prebuilts and headers, rather than installing real files.
copyFile = func(ctx android.SingletonContext, path android.Path, out string) android.OutputPath {
return writeStringToFileRule(ctx, "", out)
}
}
// installSnapshot function copies prebuilt file (.so, .a, or executable) and json flag file.
// For executables, init_rc and vintf_fragments files are also copied.
installSnapshot := func(m *Module) android.Paths {
@@ -400,7 +434,7 @@ func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) {
out := filepath.Join(configsDir, path.Base())
if !installedConfigs[out] {
installedConfigs[out] = true
ret = append(ret, copyFileRule(ctx, path, out))
ret = append(ret, copyFile(ctx, path, out))
}
}
@@ -451,7 +485,7 @@ func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) {
prop.ModuleName += ".cfi"
}
snapshotLibOut := filepath.Join(snapshotArchDir, targetArch, libType, stem)
ret = append(ret, copyFileRule(ctx, libPath, snapshotLibOut))
ret = append(ret, copyFile(ctx, libPath, snapshotLibOut))
} else {
stem = ctx.ModuleName(m)
}
@@ -465,7 +499,7 @@ func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) {
// install bin
binPath := m.outputFile.Path()
snapshotBinOut := filepath.Join(snapshotArchDir, targetArch, "binary", binPath.Base())
ret = append(ret, copyFileRule(ctx, binPath, snapshotBinOut))
ret = append(ret, copyFile(ctx, binPath, snapshotBinOut))
propOut = snapshotBinOut + ".json"
} else if m.object() {
// object files aren't installed to the device, so their names can conflict.
@@ -473,7 +507,7 @@ func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) {
objPath := m.outputFile.Path()
snapshotObjOut := filepath.Join(snapshotArchDir, targetArch, "object",
ctx.ModuleName(m)+filepath.Ext(objPath.Base()))
ret = append(ret, copyFileRule(ctx, objPath, snapshotObjOut))
ret = append(ret, copyFile(ctx, objPath, snapshotObjOut))
propOut = snapshotObjOut + ".json"
} else {
ctx.Errorf("unknown module %q in vendor snapshot", m.String())
@@ -538,16 +572,14 @@ func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) {
// skip already copied notice file
if !installedNotices[noticeOut] {
installedNotices[noticeOut] = true
snapshotOutputs = append(snapshotOutputs, combineNoticesRule(
ctx, m.NoticeFiles(), noticeOut))
snapshotOutputs = append(snapshotOutputs, combineNoticesRule(ctx, m.NoticeFiles(), noticeOut))
}
}
})
// install all headers after removing duplicates
for _, header := range android.FirstUniquePaths(headers) {
snapshotOutputs = append(snapshotOutputs, copyFileRule(
ctx, header, filepath.Join(includeDir, header.String())))
snapshotOutputs = append(snapshotOutputs, copyFile(ctx, header, filepath.Join(includeDir, header.String())))
}
// All artifacts are ready. Sort them to normalize ninja and then zip.