Browse Source

Mixed builds support for prebuilt_* targets

These targets do not have any build actions per se, but return a
PrebuiltFileInfo provider. Parse this info from cquery and generate the
appropriate installation rules and androidmk entries

Details
- Support the bp2build available properties. Not all properties have
  been converted by bp2build yet, and those are being tracked in b/207489266
- Create a addInstallRules helper function to reduce duplication between
  GenerateAndroidBuildActions and ProcessBazelQueryResponse

Test: unit test
Bug: 280094612
Change-Id: Ia67986af1dd2ff4712586dbec86ee9fda380f726
Spandan Das 11 months ago
parent
commit
756d3400d6
2 changed files with 104 additions and 9 deletions
  1. 65 9
      etc/prebuilt_etc.go
  2. 39 0
      etc/prebuilt_etc_test.go

+ 65 - 9
etc/prebuilt_etc.go

@@ -38,6 +38,7 @@ import (
 
 	"android/soong/android"
 	"android/soong/bazel"
+	"android/soong/bazel/cquery"
 	"android/soong/snapshot"
 )
 
@@ -329,7 +330,6 @@ func (p *PrebuiltEtc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 		ctx.PropertyErrorf("src", "missing prebuilt source file")
 		return
 	}
-	p.outputFilePath = android.PathForModuleOut(ctx, filename).OutputPath
 
 	if strings.Contains(filename, "/") {
 		ctx.PropertyErrorf("filename", "filename cannot contain separator '/'")
@@ -349,21 +349,42 @@ func (p *PrebuiltEtc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	}
 	p.installDirPath = android.PathForModuleInstall(ctx, installBaseDir, p.SubDir())
 
+	// Call InstallFile even when uninstallable to make the module included in the package
+	ip := installProperties{
+		installable:    p.Installable(),
+		filename:       filename,
+		sourceFilePath: p.sourceFilePath,
+		symlinks:       p.properties.Symlinks,
+	}
+	p.addInstallRules(ctx, ip)
+}
+
+type installProperties struct {
+	installable    bool
+	filename       string
+	sourceFilePath android.Path
+	symlinks       []string
+}
+
+// utility function to add install rules to the build graph.
+// Reduces code duplication between Soong and Mixed build analysis
+func (p *PrebuiltEtc) addInstallRules(ctx android.ModuleContext, ip installProperties) {
+	if !ip.installable {
+		p.SkipInstall()
+	}
+
+	// Copy the file from src to a location in out/ with the correct `filename`
 	// This ensures that outputFilePath has the correct name for others to
 	// use, as the source file may have a different name.
+	p.outputFilePath = android.PathForModuleOut(ctx, ip.filename).OutputPath
 	ctx.Build(pctx, android.BuildParams{
 		Rule:   android.Cp,
 		Output: p.outputFilePath,
-		Input:  p.sourceFilePath,
+		Input:  ip.sourceFilePath,
 	})
 
-	if !p.Installable() {
-		p.SkipInstall()
-	}
-
-	// Call InstallFile even when uninstallable to make the module included in the package
-	installPath := ctx.InstallFile(p.installDirPath, p.outputFilePath.Base(), p.outputFilePath)
-	for _, sl := range p.properties.Symlinks {
+	installPath := ctx.InstallFile(p.installDirPath, ip.filename, p.outputFilePath)
+	for _, sl := range ip.symlinks {
 		ctx.InstallSymlink(p.installDirPath, sl, installPath)
 	}
 }
@@ -781,3 +802,38 @@ func (module *PrebuiltEtc) ConvertWithBp2build(ctx android.TopDownMutatorContext
 
 	ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: module.Name()}, attrs)
 }
+
+var _ android.MixedBuildBuildable = (*PrebuiltEtc)(nil)
+
+func (pe *PrebuiltEtc) IsMixedBuildSupported(ctx android.BaseModuleContext) bool {
+	return true
+}
+
+func (pe *PrebuiltEtc) QueueBazelCall(ctx android.BaseModuleContext) {
+	ctx.Config().BazelContext.QueueBazelRequest(
+		pe.GetBazelLabel(ctx, pe),
+		cquery.GetPrebuiltFileInfo,
+		android.GetConfigKey(ctx),
+	)
+}
+
+func (pe *PrebuiltEtc) ProcessBazelQueryResponse(ctx android.ModuleContext) {
+	bazelCtx := ctx.Config().BazelContext
+	pfi, err := bazelCtx.GetPrebuiltFileInfo(pe.GetBazelLabel(ctx, pe), android.GetConfigKey(ctx))
+	if err != nil {
+		ctx.ModuleErrorf(err.Error())
+		return
+	}
+
+	// Set properties for androidmk
+	pe.installDirPath = android.PathForModuleInstall(ctx, pfi.Dir)
+
+	// Installation rules
+	ip := installProperties{
+		installable:    pfi.Installable,
+		filename:       pfi.Filename,
+		sourceFilePath: android.PathForSource(ctx, pfi.Src),
+		// symlinks: pe.properties.Symlinks, // TODO: b/207489266 - Fully support all properties in prebuilt_file
+	}
+	pe.addInstallRules(ctx, ip)
+}

+ 39 - 0
etc/prebuilt_etc_test.go

@@ -23,6 +23,7 @@ import (
 	"github.com/google/blueprint/proptools"
 
 	"android/soong/android"
+	"android/soong/bazel/cquery"
 	"android/soong/snapshot"
 )
 
@@ -494,3 +495,41 @@ func TestPrebuiltTakeSnapshot(t *testing.T) {
 		checkIfSnapshotNotTaken(t, result, "recovery", "prebuilt_recovery_indirect")
 	})
 }
+
+func TestPrebuiltEtcAndroidMkEntriesWithBazel(t *testing.T) {
+	t.Parallel()
+	bp := `
+prebuilt_etc {
+	name: "myetc",
+	src: "prebuilt_etc.rc", // filename in src tree
+	filename: "init.rc", // target filename on device
+	sub_dir: "subdir", // relative subdir for installation
+	bazel_module: { label: "//foo/bar:myetc" },
+}
+`
+	res := android.GroupFixturePreparers(
+		prepareForPrebuiltEtcTest,
+		android.FixtureModifyConfig(func(cfg android.Config) {
+			cfg.BazelContext = android.MockBazelContext{
+				LabelToPrebuiltFileInfo: map[string]cquery.PrebuiltFileInfo{
+					"//foo/bar:myetc": cquery.PrebuiltFileInfo{
+						Src:         "foo/bar/prebuilt_etc.rc",
+						Dir:         "etc/subdir",
+						Filename:    "init.rc",
+						Installable: true,
+					},
+				},
+			}
+		}),
+	).RunTestWithBp(t, bp)
+	ctx := res.ModuleForTests("myetc", "android_arm64_armv8-a")
+	mod := ctx.Module()
+	entries := android.AndroidMkEntriesForTest(t, res.TestContext, mod)[0]
+	// verify androidmk entries
+	android.AssertStringDoesContain(t, "LOCAL_MODULE_PATH should contain", entries.EntryMap["LOCAL_MODULE_PATH"][0], "etc/subdir")
+	android.AssertStringEquals(t, "LOCAL_INSTALLED_MODULE_STEM is incorrect", "init.rc", entries.EntryMap["LOCAL_INSTALLED_MODULE_STEM"][0])
+	// verify installation rules
+	install := ctx.Description("install")
+	android.AssertStringEquals(t, "Source location of prebuilt_etc installation", "out/soong/.intermediates/myetc/android_arm64_armv8-a/init.rc", install.Input.String())
+	android.AssertStringEquals(t, "Target location of prebuilt_etc installation", "out/soong/target/product/test_device/system/etc/subdir/init.rc", install.Output.String())
+}