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

Commit 2b6dfb55 authored by Spandan Das's avatar Spandan Das
Browse files

Support mechanism to select a specific version of module sdk prebuilt

This CL is scoped to cc_* module types. With trunk stable, we will have
multiple prebuilts of the cc modules in
prebuilts/module_sdk/art/<v>/host-exports/, and this CL introduces a
mechanism to use apex_contributions to select a specific versioned
prebuilt when building.

If a soong module is selected using apex_contributions, all rdeps will
get that soong module, which includes
- rdep soong modules which might be depending on it via Android.bp
- Soong's rule builder HostToolPath API

Implementation details: Create a new source_module_name property to
identify the root module. rdeps referring to the root module will get
redirected if necessary. This property also
becomes the stem, if `stem` is not set explicitly.

Bug: 322175508

Test: Added a unit test

Change-Id: Ic8725602c81999621fcb33ce2a57fe4b9751baa8
parent 1f4475ce
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -84,6 +84,7 @@ func (c *Module) AndroidMkEntries() []android.AndroidMkEntries {
		// to be installed. And this is breaking some older devices (like marlin)
		// where system.img is small.
		Required:     c.Properties.AndroidMkRuntimeLibs,
		OverrideName: c.BaseModuleName(),
		Include:      "$(BUILD_SYSTEM)/soong_cc_rust_prebuilt.mk",

		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+13 −1
Original line number Diff line number Diff line
@@ -1744,7 +1744,7 @@ func (ctx *moduleContextImpl) useClangLld(actx ModuleContext) bool {
}

func (ctx *moduleContextImpl) baseModuleName() string {
	return ctx.mod.ModuleBase.BaseModuleName()
	return ctx.mod.BaseModuleName()
}

func (ctx *moduleContextImpl) getVndkExtendsModuleName() string {
@@ -4173,6 +4173,18 @@ func (c *Module) Partition() string {
	return ""
}

type sourceModuleName interface {
	sourceModuleName() string
}

func (c *Module) BaseModuleName() string {
	if smn, ok := c.linker.(sourceModuleName); ok && smn.sourceModuleName() != "" {
		// if the prebuilt module sets a source_module_name in Android.bp, use that
		return smn.sourceModuleName()
	}
	return c.ModuleBase.BaseModuleName()
}

var Bool = proptools.Bool
var BoolDefault = proptools.BoolDefault
var BoolPtr = proptools.BoolPtr
+21 −1
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@ package cc
import (
	"path/filepath"

	"github.com/google/blueprint/proptools"

	"android/soong/android"
)

@@ -36,9 +38,15 @@ func RegisterPrebuiltBuildComponents(ctx android.RegistrationContext) {
type prebuiltLinkerInterface interface {
	Name(string) string
	prebuilt() *android.Prebuilt
	sourceModuleName() string
}

type prebuiltLinkerProperties struct {
	// Name of the source soong module that gets shadowed by this prebuilt
	// If unspecified, follows the naming convention that the source module of
	// the prebuilt is Name() without "prebuilt_" prefix
	Source_module_name *string

	// a prebuilt library or binary. Can reference a genrule module that generates an executable file.
	Srcs []string `android:"path,arch_variant"`

@@ -337,6 +345,10 @@ func NewPrebuiltStaticLibrary(hod android.HostOrDeviceSupported) (*Module, *libr
}

type prebuiltObjectProperties struct {
	// Name of the source soong module that gets shadowed by this prebuilt
	// If unspecified, follows the naming convention that the source module of
	// the prebuilt is Name() without "prebuilt_" prefix
	Source_module_name *string
	Srcs               []string `android:"path,arch_variant"`
}

@@ -351,6 +363,10 @@ func (p *prebuiltObjectLinker) prebuilt() *android.Prebuilt {
	return &p.Prebuilt
}

func (p *prebuiltObjectLinker) sourceModuleName() string {
	return proptools.String(p.properties.Source_module_name)
}

var _ prebuiltLinkerInterface = (*prebuiltObjectLinker)(nil)

func (p *prebuiltObjectLinker) link(ctx ModuleContext,
@@ -520,3 +536,7 @@ func srcsForSanitizer(sanitize *sanitize, sanitized Sanitized) []string {
	}
	return sanitized.None.Srcs
}

func (p *prebuiltLinker) sourceModuleName() string {
	return proptools.String(p.properties.Source_module_name)
}
+98 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
package cc

import (
	"fmt"
	"runtime"
	"testing"

@@ -509,3 +510,100 @@ cc_prebuilt_binary {
}`
	testCcError(t, `Android.bp:4:6: module "bintest" variant "android_arm64_armv8-a": srcs: multiple prebuilt source files`, bp)
}

func TestMultiplePrebuilts(t *testing.T) {
	bp := `
		// an rdep
		cc_library {
			name: "libfoo",
			shared_libs: ["libbar"],
		}

		// multiple variations of dep
		// source
		cc_library {
			name: "libbar",
		}
		// prebuilt "v1"
		cc_prebuilt_library_shared {
			name: "libbar",
			srcs: ["libbar.so"],
		}
		// prebuilt "v2"
		cc_prebuilt_library_shared {
			name: "libbar.v2",
			stem: "libbar",
			source_module_name: "libbar",
			srcs: ["libbar.so"],
		}

		// selectors
		apex_contributions {
			name: "myapex_contributions",
			contents: ["%v"],
		}
		all_apex_contributions {name: "all_apex_contributions"}
	`
	hasDep := func(ctx *android.TestContext, m android.Module, wantDep android.Module) bool {
		t.Helper()
		var found bool
		ctx.VisitDirectDeps(m, func(dep blueprint.Module) {
			if dep == wantDep {
				found = true
			}
		})
		return found
	}

	testCases := []struct {
		desc                   string
		selectedDependencyName string
		expectedDependencyName string
	}{
		{
			desc:                   "Source library is selected using apex_contributions",
			selectedDependencyName: "libbar",
			expectedDependencyName: "libbar",
		},
		{
			desc:                   "Prebuilt library v1 is selected using apex_contributions",
			selectedDependencyName: "prebuilt_libbar",
			expectedDependencyName: "prebuilt_libbar",
		},
		{
			desc:                   "Prebuilt library v2 is selected using apex_contributions",
			selectedDependencyName: "prebuilt_libbar.v2",
			expectedDependencyName: "prebuilt_libbar.v2",
		},
	}

	for _, tc := range testCases {
		preparer := android.GroupFixturePreparers(
			android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
				android.RegisterApexContributionsBuildComponents(ctx)
			}),
			android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
				variables.BuildFlags = map[string]string{
					"RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "myapex_contributions",
				}
			}),
		)
		ctx := testPrebuilt(t, fmt.Sprintf(bp, tc.selectedDependencyName), map[string][]byte{
			"libbar.so": nil,
			"crtx.o":    nil,
		}, preparer)
		libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
		expectedDependency := ctx.ModuleForTests(tc.expectedDependencyName, "android_arm64_armv8-a_shared").Module()
		android.AssertBoolEquals(t, fmt.Sprintf("expected dependency from %s to %s\n", libfoo.Name(), tc.expectedDependencyName), true, hasDep(ctx, libfoo, expectedDependency))

		// check installation rules
		// the selected soong module should be exported to make
		libbar := ctx.ModuleForTests(tc.expectedDependencyName, "android_arm64_armv8-a_shared").Module()
		android.AssertBoolEquals(t, fmt.Sprintf("dependency %s should be exported to make\n", expectedDependency), true, !libbar.IsHideFromMake())

		// check LOCAL_MODULE of the selected module name
		// the prebuilt should have the same LOCAL_MODULE when exported to make
		entries := android.AndroidMkEntriesForTest(t, ctx, libbar)[0]
		android.AssertStringEquals(t, "unexpected LOCAL_MODULE", "libbar", entries.EntryMap["LOCAL_MODULE"][0])
	}
}