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

Commit e1359af3 authored by Bill Peckham's avatar Bill Peckham Committed by Gerrit Code Review
Browse files

Merge "Add exclude_from_vendor_snapshot property, related logic"

parents 3f98d148 945441c0
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -280,6 +280,13 @@ type BaseProperties struct {
	// Set when both SDK and platform variants are exported to Make to trigger renaming the SDK
	// variant to have a ".sdk" suffix.
	SdkAndPlatformVariantVisibleToMake bool `blueprint:"mutated"`

	// Normally Soong uses the directory structure to decide which modules
	// should be included (framework) or excluded (non-framework) from the
	// vendor snapshot, but this property allows a partner to exclude a
	// module normally thought of as a framework module from the vendor
	// snapshot.
	Exclude_from_vendor_snapshot *bool
}

type VendorProperties struct {
@@ -1108,6 +1115,10 @@ func (c *Module) ExportedGeneratedHeaders() android.Paths {
	return nil
}

func (c *Module) ExcludeFromVendorSnapshot() bool {
	return Bool(c.Properties.Exclude_from_vendor_snapshot)
}

func isBionic(name string) bool {
	switch name {
	case "libc", "libm", "libdl", "libdl_android", "linker":
+217 −4
Original line number Diff line number Diff line
@@ -258,7 +258,8 @@ func checkVndkModule(t *testing.T, ctx *android.TestContext, name, subDir string
	}
}

func checkSnapshot(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string) {
func checkSnapshotIncludeExclude(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string, include bool) {
	t.Helper()
	mod, ok := ctx.ModuleForTests(moduleName, variant).Module().(android.OutputFileProducer)
	if !ok {
		t.Errorf("%q must have output\n", moduleName)
@@ -271,10 +272,25 @@ func checkSnapshot(t *testing.T, ctx *android.TestContext, singleton android.Tes
	}
	snapshotPath := filepath.Join(subDir, snapshotFilename)

	if include {
		out := singleton.Output(snapshotPath)
		if out.Input.String() != outputFiles[0].String() {
			t.Errorf("The input of snapshot %q must be %q, but %q", moduleName, out.Input.String(), outputFiles[0])
		}
	} else {
		out := singleton.MaybeOutput(snapshotPath)
		if out.Rule != nil {
			t.Errorf("There must be no rule for module %q output file %q", moduleName, outputFiles[0])
		}
	}
}

func checkSnapshot(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string) {
	checkSnapshotIncludeExclude(t, ctx, singleton, moduleName, snapshotFilename, subDir, variant, true)
}

func checkSnapshotExclude(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string) {
	checkSnapshotIncludeExclude(t, ctx, singleton, moduleName, snapshotFilename, subDir, variant, false)
}

func checkWriteFileOutput(t *testing.T, params android.TestingBuildParams, expected []string) {
@@ -1096,6 +1112,203 @@ func TestVendorSnapshotSanitizer(t *testing.T) {
	assertString(t, staticCfiModule.outputFile.Path().Base(), "libsnapshot.cfi.a")
}

func assertExcludeFromVendorSnapshotIs(t *testing.T, c *Module, expected bool) {
	t.Helper()
	if c.ExcludeFromVendorSnapshot() != expected {
		t.Errorf("expected %q ExcludeFromVendorSnapshot to be %t", c.String(), expected)
	}
}

func TestVendorSnapshotExclude(t *testing.T) {

	// This test verifies that the exclude_from_vendor_snapshot property
	// makes its way from the Android.bp source file into the module data
	// structure. It also verifies that modules are correctly included or
	// excluded in the vendor snapshot based on their path (framework or
	// vendor) and the exclude_from_vendor_snapshot property.

	frameworkBp := `
		cc_library_shared {
			name: "libinclude",
			srcs: ["src/include.cpp"],
			vendor_available: true,
		}
		cc_library_shared {
			name: "libexclude",
			srcs: ["src/exclude.cpp"],
			vendor: true,
			exclude_from_vendor_snapshot: true,
		}
	`

	vendorProprietaryBp := `
		cc_library_shared {
			name: "libvendor",
			srcs: ["vendor.cpp"],
			vendor: true,
		}
	`

	depsBp := GatherRequiredDepsForTest(android.Android)

	mockFS := map[string][]byte{
		"deps/Android.bp":       []byte(depsBp),
		"framework/Android.bp":  []byte(frameworkBp),
		"framework/include.cpp": nil,
		"framework/exclude.cpp": nil,
		"device/Android.bp":     []byte(vendorProprietaryBp),
		"device/vendor.cpp":     nil,
	}

	config := TestConfig(buildDir, android.Android, nil, "", mockFS)
	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
	config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
	ctx := CreateTestContext()
	ctx.Register(config)

	_, errs := ctx.ParseFileList(".", []string{"deps/Android.bp", "framework/Android.bp", "device/Android.bp"})
	android.FailIfErrored(t, errs)
	_, errs = ctx.PrepareBuildActions(config)
	android.FailIfErrored(t, errs)

	// Test an include and exclude framework module.
	assertExcludeFromVendorSnapshotIs(t, ctx.ModuleForTests("libinclude", coreVariant).Module().(*Module), false)
	assertExcludeFromVendorSnapshotIs(t, ctx.ModuleForTests("libinclude", vendorVariant).Module().(*Module), false)
	assertExcludeFromVendorSnapshotIs(t, ctx.ModuleForTests("libexclude", vendorVariant).Module().(*Module), true)

	// A vendor module is excluded, but by its path, not the
	// exclude_from_vendor_snapshot property.
	assertExcludeFromVendorSnapshotIs(t, ctx.ModuleForTests("libvendor", vendorVariant).Module().(*Module), false)

	// Verify the content of the vendor snapshot.

	snapshotDir := "vendor-snapshot"
	snapshotVariantPath := filepath.Join(buildDir, snapshotDir, "arm64")
	snapshotSingleton := ctx.SingletonForTests("vendor-snapshot")

	var includeJsonFiles []string
	var excludeJsonFiles []string

	for _, arch := range [][]string{
		[]string{"arm64", "armv8-a"},
		[]string{"arm", "armv7-a-neon"},
	} {
		archType := arch[0]
		archVariant := arch[1]
		archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)

		sharedVariant := fmt.Sprintf("android_vendor.VER_%s_%s_shared", archType, archVariant)
		sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")

		// Included modules
		checkSnapshot(t, ctx, snapshotSingleton, "libinclude", "libinclude.so", sharedDir, sharedVariant)
		includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libinclude.so.json"))

		// Excluded modules
		checkSnapshotExclude(t, ctx, snapshotSingleton, "libexclude", "libexclude.so", sharedDir, sharedVariant)
		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libexclude.so.json"))
		checkSnapshotExclude(t, ctx, snapshotSingleton, "libvendor", "libvendor.so", sharedDir, sharedVariant)
		excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libvendor.so.json"))
	}

	// Verify that each json file for an included module has a rule.
	for _, jsonFile := range includeJsonFiles {
		if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
			t.Errorf("include json file %q not found", jsonFile)
		}
	}

	// Verify that each json file for an excluded module has no rule.
	for _, jsonFile := range excludeJsonFiles {
		if snapshotSingleton.MaybeOutput(jsonFile).Rule != nil {
			t.Errorf("exclude json file %q found", jsonFile)
		}
	}
}

func TestVendorSnapshotExcludeInVendorProprietaryPathErrors(t *testing.T) {

	// This test verifies that using the exclude_from_vendor_snapshot
	// property on a module in a vendor proprietary path generates an
	// error. These modules are already excluded, so we prohibit using the
	// property in this way, which could add to confusion.

	vendorProprietaryBp := `
		cc_library_shared {
			name: "libvendor",
			srcs: ["vendor.cpp"],
			vendor: true,
			exclude_from_vendor_snapshot: true,
		}
	`

	depsBp := GatherRequiredDepsForTest(android.Android)

	mockFS := map[string][]byte{
		"deps/Android.bp":   []byte(depsBp),
		"device/Android.bp": []byte(vendorProprietaryBp),
		"device/vendor.cpp": nil,
	}

	config := TestConfig(buildDir, android.Android, nil, "", mockFS)
	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
	config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
	ctx := CreateTestContext()
	ctx.Register(config)

	_, errs := ctx.ParseFileList(".", []string{"deps/Android.bp", "device/Android.bp"})
	android.FailIfErrored(t, errs)

	_, errs = ctx.PrepareBuildActions(config)
	android.CheckErrorsAgainstExpectations(t, errs, []string{
		`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"`,
	})
}

func TestVendorSnapshotExcludeWithVendorAvailable(t *testing.T) {

	// This test verifies that using the exclude_from_vendor_snapshot
	// property on a module that is vendor available generates an error. A
	// vendor available module must be captured in the vendor snapshot and
	// must not built from source when building the vendor image against
	// the vendor snapshot.

	frameworkBp := `
		cc_library_shared {
			name: "libinclude",
			srcs: ["src/include.cpp"],
			vendor_available: true,
			exclude_from_vendor_snapshot: true,
		}
	`

	depsBp := GatherRequiredDepsForTest(android.Android)

	mockFS := map[string][]byte{
		"deps/Android.bp":       []byte(depsBp),
		"framework/Android.bp":  []byte(frameworkBp),
		"framework/include.cpp": nil,
	}

	config := TestConfig(buildDir, android.Android, nil, "", mockFS)
	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
	config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
	ctx := CreateTestContext()
	ctx.Register(config)

	_, errs := ctx.ParseFileList(".", []string{"deps/Android.bp", "framework/Android.bp"})
	android.FailIfErrored(t, errs)

	_, errs = ctx.PrepareBuildActions(config)
	android.CheckErrorsAgainstExpectations(t, errs, []string{
		`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"`,
	})
}

func TestDoubleLoadableDepError(t *testing.T) {
	// Check whether an error is emitted when a LLNDK depends on a non-double_loadable VNDK lib.
	testCcError(t, "module \".*\" variant \".*\": link.* \".*\" which is not LL-NDK, VNDK-SP, .*double_loadable", `
+1 −1
Original line number Diff line number Diff line
@@ -84,7 +84,7 @@ func (g *GenruleExtraProperties) ExtraImageVariations(ctx android.BaseModuleCont
		// If not, we assume modules under proprietary paths are compatible for
		// BOARD_VNDK_VERSION. The other modules are regarded as AOSP, that is
		// PLATFORM_VNDK_VERSION.
		if vndkVersion == "current" || !isVendorProprietaryPath(ctx.ModuleDir()) {
		if vndkVersion == "current" || !isVendorProprietaryModule(ctx) {
			variants = append(variants, VendorVariationPrefix+ctx.DeviceConfig().PlatformVndkVersion())
		} else {
			variants = append(variants, VendorVariationPrefix+vndkVersion)
+2 −2
Original line number Diff line number Diff line
@@ -223,7 +223,7 @@ func (m *Module) ImageMutatorBegin(mctx android.BaseModuleContext) {
		// We assume that modules under proprietary paths are compatible for
		// BOARD_VNDK_VERSION. The other modules are regarded as AOSP, or
		// PLATFORM_VNDK_VERSION.
		if isVendorProprietaryPath(mctx.ModuleDir()) {
		if isVendorProprietaryModule(mctx) {
			vendorVariants = append(vendorVariants, boardVndkVersion)
		} else {
			vendorVariants = append(vendorVariants, platformVndkVersion)
@@ -249,7 +249,7 @@ func (m *Module) ImageMutatorBegin(mctx android.BaseModuleContext) {
				platformVndkVersion,
				boardVndkVersion,
			)
		} else if isVendorProprietaryPath(mctx.ModuleDir()) {
		} else if isVendorProprietaryModule(mctx) {
			vendorVariants = append(vendorVariants, boardVndkVersion)
		} else {
			vendorVariants = append(vendorVariants, platformVndkVersion)
+1 −1
Original line number Diff line number Diff line
@@ -738,7 +738,7 @@ func isSanitizableDependencyTag(tag blueprint.DependencyTag) bool {
// as vendor snapshot. Such modules must create both cfi and non-cfi variants,
// except for ones which explicitly disable cfi.
func needsCfiForVendorSnapshot(mctx android.TopDownMutatorContext) bool {
	if isVendorProprietaryPath(mctx.ModuleDir()) {
	if isVendorProprietaryModule(mctx) {
		return false
	}

Loading