Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e9aec6aa authored by Inseob Kim's avatar Inseob Kim
Browse files

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
parent 77dcb9d7
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -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"`,
	})
}

+2 −0
Original line number Diff line number Diff line
@@ -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 {
+1 −0
Original line number Diff line number Diff line
@@ -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
+40 −8
Original line number Diff line number Diff line
@@ -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.