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

Commit d571a52d authored by Roland Levillain's avatar Roland Levillain Committed by android-build-merger
Browse files

Merge "Handle `test_per_src` modules as indirect dependencies in APEXes."

am: cadffcdd

Change-Id: I6e420de099250d40069a188b4eef618b0b403591
parents 7830315f cadffcdd
Loading
Loading
Loading
Loading
+52 −45
Original line number Diff line number Diff line
@@ -694,12 +694,6 @@ func getCopyManifestForExecutable(cc *cc.Module) (fileToCopy android.Path, dirIn
	return
}

func getCopyManifestForTestPerSrcExecutables(cc *cc.Module) (filesToCopy []android.Path, dirInApex string) {
	dirInApex = filepath.Join("bin", cc.RelativeInstallPath())
	filesToCopy = cc.TestPerSrcOutputFiles()
	return
}

func getCopyManifestForPyBinary(py *python.Module) (fileToCopy android.Path, dirInApex string) {
	dirInApex = "bin"
	fileToCopy = py.HostToolPath().Path()
@@ -780,10 +774,10 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
	})

	ctx.WalkDepsBlueprint(func(child, parent blueprint.Module) bool {
		if _, ok := parent.(*apexBundle); ok {
			// direct dependencies
		depTag := ctx.OtherModuleDependencyTag(child)
		depName := ctx.OtherModuleName(child)
		if _, ok := parent.(*apexBundle); ok {
			// direct dependencies
			switch depTag {
			case sharedLibTag:
				if cc, ok := child.(*cc.Module); ok {
@@ -834,22 +828,19 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
					ctx.PropertyErrorf("prebuilts", "%q is not a prebuilt_etc module", depName)
				}
			case testTag:
				if cc, ok := child.(*cc.Module); ok {
					if cc.TestPerSrcOutputFiles() != nil {
						// Multiple-output test module (using `test_per_src`).
						filesToCopy, dirInApex := getCopyManifestForTestPerSrcExecutables(cc)
						for _, fileToCopy := range filesToCopy {
							// Handle modules created as `test_per_src` variations of a single test module:
							// replace the name of the original test module (`depName`, shared by all
							// `test_per_src` variants of that module) with the name of the generated test
							// binary.
							moduleName := filepath.Base(fileToCopy.String())
							filesInfo = append(filesInfo, apexFile{fileToCopy, moduleName, dirInApex, nativeTest, cc, nil})
						}
				if ccTest, ok := child.(*cc.Module); ok {
					if ccTest.IsTestPerSrcAllTestsVariation() {
						// Multiple-output test module (where `test_per_src: true`).
						//
						// `ccTest` is the "" ("all tests") variation of a `test_per_src` module.
						// We do not add this variation to `filesInfo`, as it has no output;
						// however, we do add the other variations of this module as indirect
						// dependencies (see below).
						return true
					} else {
						// Single-output test module (not using `test_per_src`).
						fileToCopy, dirInApex := getCopyManifestForExecutable(cc)
						filesInfo = append(filesInfo, apexFile{fileToCopy, depName, dirInApex, nativeTest, cc, nil})
						// Single-output test module (where `test_per_src: false`).
						fileToCopy, dirInApex := getCopyManifestForExecutable(ccTest)
						filesInfo = append(filesInfo, apexFile{fileToCopy, depName, dirInApex, nativeTest, ccTest, nil})
					}
					return true
				} else {
@@ -875,6 +866,9 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
		} else {
			// indirect dependencies
			if am, ok := child.(android.ApexModule); ok && am.CanHaveApexVariants() && am.IsInstallableToApex() {
				// We cannot use a switch statement on `depTag` here as the checked
				// tags used below are private (e.g. `cc.sharedDepTag`).
				if cc.IsSharedDepTag(depTag) || cc.IsRuntimeDepTag(depTag) {
					if cc, ok := child.(*cc.Module); ok {
						if android.InList(cc.Name(), providedNativeSharedLibs) {
							// If we're using a shared library which is provided from other APEX,
@@ -895,11 +889,24 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
							// Don't track further
							return false
						}
					depName := ctx.OtherModuleName(child)
						fileToCopy, dirInApex := getCopyManifestForNativeLibrary(cc, handleSpecialLibs)
						filesInfo = append(filesInfo, apexFile{fileToCopy, depName, dirInApex, nativeSharedLib, cc, nil})
						return true
					}
				} else if cc.IsTestPerSrcDepTag(depTag) {
					if cc, ok := child.(*cc.Module); ok {
						fileToCopy, dirInApex := getCopyManifestForExecutable(cc)
						// Handle modules created as `test_per_src` variations of a single test module:
						// use the name of the generated test binary (`fileToCopy`) instead of the name
						// of the original test module (`depName`, shared by all `test_per_src`
						// variations of that module).
						moduleName := filepath.Base(fileToCopy.String())
						filesInfo = append(filesInfo, apexFile{fileToCopy, moduleName, dirInApex, nativeTest, cc, nil})
						return true
					}
				} else {
					ctx.ModuleErrorf("unexpected tag %q for indirect dependency %q", depTag, depName)
				}
			}
		}
		return false
+17 −1
Original line number Diff line number Diff line
@@ -1393,7 +1393,7 @@ func TestPrebuiltOverrides(t *testing.T) {
}

func TestApexWithTests(t *testing.T) {
	ctx, _ := testApex(t, `
	ctx, config := testApex(t, `
		apex_test {
			name: "myapex",
			key: "myapex.key",
@@ -1445,6 +1445,22 @@ func TestApexWithTests(t *testing.T) {
	ensureContains(t, copyCmds, "image.apex/bin/test/mytest1")
	ensureContains(t, copyCmds, "image.apex/bin/test/mytest2")
	ensureContains(t, copyCmds, "image.apex/bin/test/mytest3")

	// Ensure the module is correctly translated.
	apexBundle := ctx.ModuleForTests("myapex", "android_common_myapex").Module().(*apexBundle)
	data := android.AndroidMkDataForTest(t, config, "", apexBundle)
	name := apexBundle.BaseModuleName()
	prefix := "TARGET_"
	var builder strings.Builder
	data.Custom(&builder, name, prefix, "", data)
	androidMk := builder.String()
	ensureContains(t, androidMk, "LOCAL_MODULE := myapex.mytest\n")
	ensureContains(t, androidMk, "LOCAL_MODULE := myapex.mytest1\n")
	ensureContains(t, androidMk, "LOCAL_MODULE := myapex.mytest2\n")
	ensureContains(t, androidMk, "LOCAL_MODULE := myapex.mytest3\n")
	ensureContains(t, androidMk, "LOCAL_MODULE := myapex.apex_manifest.json\n")
	ensureContains(t, androidMk, "LOCAL_MODULE := myapex.apex_pubkey\n")
	ensureContains(t, androidMk, "LOCAL_MODULE := myapex\n")
}

func TestApexUsesOtherApex(t *testing.T) {
+35 −32
Original line number Diff line number Diff line
@@ -342,6 +342,7 @@ type dependencyTag struct {
	blueprint.BaseDependencyTag
	name    string
	library bool
	shared  bool

	reexportFlags bool

@@ -353,10 +354,10 @@ type xref interface {
}

var (
	sharedDepTag          = dependencyTag{name: "shared", library: true}
	sharedExportDepTag    = dependencyTag{name: "shared", library: true, reexportFlags: true}
	earlySharedDepTag     = dependencyTag{name: "early_shared", library: true}
	lateSharedDepTag      = dependencyTag{name: "late shared", library: true}
	sharedDepTag          = dependencyTag{name: "shared", library: true, shared: true}
	sharedExportDepTag    = dependencyTag{name: "shared", library: true, shared: true, reexportFlags: true}
	earlySharedDepTag     = dependencyTag{name: "early_shared", library: true, shared: true}
	lateSharedDepTag      = dependencyTag{name: "late shared", library: true, shared: true}
	staticDepTag          = dependencyTag{name: "static", library: true}
	staticExportDepTag    = dependencyTag{name: "static", library: true, reexportFlags: true}
	lateStaticDepTag      = dependencyTag{name: "late static", library: true}
@@ -381,6 +382,21 @@ var (
	testPerSrcDepTag      = dependencyTag{name: "test_per_src"}
)

func IsSharedDepTag(depTag blueprint.DependencyTag) bool {
	ccDepTag, ok := depTag.(dependencyTag)
	return ok && ccDepTag.shared
}

func IsRuntimeDepTag(depTag blueprint.DependencyTag) bool {
	ccDepTag, ok := depTag.(dependencyTag)
	return ok && ccDepTag == runtimeDepTag
}

func IsTestPerSrcDepTag(depTag blueprint.DependencyTag) bool {
	ccDepTag, ok := depTag.(dependencyTag)
	return ok && ccDepTag == testPerSrcDepTag
}

// Module contains the properties and members used by all C/C++ module types, and implements
// the blueprint.Module interface.  It delegates to compiler, linker, and installer interfaces
// to construct the output file.  Behavior can be customized with a Customizer interface
@@ -414,9 +430,6 @@ type Module struct {

	outputFile android.OptionalPath

	// Test output files, in the case of a test module using `test_per_src`.
	testPerSrcOutputFiles []android.Path

	cachedToolchain config.Toolchain

	subAndroidMkOnce map[subAndroidMkProvider]bool
@@ -441,10 +454,6 @@ func (c *Module) OutputFile() android.OptionalPath {
	return c.outputFile
}

func (c *Module) TestPerSrcOutputFiles() []android.Path {
	return c.testPerSrcOutputFiles
}

func (c *Module) UnstrippedOutputFile() android.Path {
	if c.linker != nil {
		return c.linker.unstrippedOutputFilePath()
@@ -962,29 +971,21 @@ func orderStaticModuleDeps(module *Module, staticDeps []*Module, sharedDeps []*M
	return results
}

func (c *Module) IsTestPerSrcAllTestsVariation() bool {
	test, ok := c.linker.(testPerSrc)
	return ok && test.isAllTestsVariation()
}

func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
	// Handle the case of a test module split by `test_per_src` mutator.
	if test, ok := c.linker.(testPerSrc); ok {
		// The `test_per_src` mutator adds an extra variant named "", depending on all the
		// other `test_per_src` variants of the test module. Collect the output files of
		// these dependencies and record them in the `testPerSrcOutputFiles` for later use
		// (see e.g. `apexBundle.GenerateAndroidBuildActions`).
		if test.isAllTestsVariation() {
			var testPerSrcOutputFiles []android.Path
			for _, dep := range actx.GetDirectDepsWithTag(testPerSrcDepTag) {
				if ccDep, ok := dep.(*Module); ok {
					depOutputFile := ccDep.OutputFile().Path()
					testPerSrcOutputFiles =
						append(testPerSrcOutputFiles, depOutputFile)
				}
			}
			c.testPerSrcOutputFiles = testPerSrcOutputFiles
			// Set outputFile to an empty path, as this module does not produce an
			// output file per se.
	//
	// The `test_per_src` mutator adds an extra variation named "", depending on all the other
	// `test_per_src` variations of the test module. Set `outputFile` to an empty path for this
	// module and return early, as this module does not produce an output file per se.
	if c.IsTestPerSrcAllTestsVariation() {
		c.outputFile = android.OptionalPath{}
		return
	}
	}

	c.makeLinkType = c.getMakeLinkType(actx)

@@ -2064,12 +2065,14 @@ func (c *Module) getMakeLinkType(actx android.ModuleContext) string {
}

// Overrides ApexModule.IsInstallabeToApex()
// Only shared libraries are installable to APEX.
// Only shared/runtime libraries and "test_per_src" tests are installable to APEX.
func (c *Module) IsInstallableToApex() bool {
	if shared, ok := c.linker.(interface {
		shared() bool
	}); ok {
		return shared.shared()
	} else if _, ok := c.linker.(testPerSrc); ok {
		return true
	}
	return false
}