Make vndk*.libraries.txt as soong modules

Migrating from Make to Soong.

These files are generated by singleton and had to be defined as PREBUILT
modules in Make (system/core/rootdir/Android.mk)

Now, they are converted as soong modules.

To make things easier, a special kind of module 'vndk_libraries_txt' is
added which works like prebuilt_etc but its src file is generated by
soong.

Bug: 141450808
Test: m llndk.libraries.txt
Change-Id: Ia77e6af73f760fcd77020218c5bc37892b2cda1f
diff --git a/cc/vndk.go b/cc/vndk.go
index bb4aafc..0b65aca 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -360,22 +360,99 @@
 }
 
 func init() {
+	android.RegisterModuleType("vndk_libraries_txt", VndkLibrariesTxt)
 	android.RegisterSingletonType("vndk-snapshot", VndkSnapshotSingleton)
 }
 
+type vndkLibrariesTxt struct {
+	android.ModuleBase
+	outputFile android.OutputPath
+}
+
+// vndk_libraries_txt is a special kind of module type in that it name is one of
+// - llndk.libraries.txt
+// - vndkcore.libraries.txt
+// - vndksp.libraries.txt
+// - vndkprivate.libraries.txt
+// - vndkcorevariant.libraries.txt
+// A module behaves like a prebuilt_etc but its content is generated by soong.
+// By being a soong module, these files can be referenced by other soong modules.
+// For example, apex_vndk can depend on these files as prebuilt.
+func VndkLibrariesTxt() android.Module {
+	m := &vndkLibrariesTxt{}
+	android.InitAndroidModule(m)
+	return m
+}
+
+func insertVndkVersion(filename string, vndkVersion string) string {
+	if index := strings.LastIndex(filename, "."); index != -1 {
+		return filename[:index] + "." + vndkVersion + filename[index:]
+	}
+	return filename
+}
+
+func (txt *vndkLibrariesTxt) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	var list []string
+	switch txt.Name() {
+	case "llndk.libraries.txt":
+		for _, filename := range android.SortedStringMapValues(llndkLibraries(ctx.Config())) {
+			if strings.HasPrefix(filename, "libclang_rt.hwasan-") {
+				continue
+			}
+			list = append(list, filename)
+		}
+	case "vndkcore.libraries.txt":
+		list = android.SortedStringMapValues(vndkCoreLibraries(ctx.Config()))
+	case "vndksp.libraries.txt":
+		list = android.SortedStringMapValues(vndkSpLibraries(ctx.Config()))
+	case "vndkprivate.libraries.txt":
+		list = android.SortedStringMapValues(vndkPrivateLibraries(ctx.Config()))
+	case "vndkcorevariant.libraries.txt":
+		list = android.SortedStringMapValues(vndkUsingCoreVariantLibraries(ctx.Config()))
+	default:
+		ctx.ModuleErrorf("name(%s) is unknown.", txt.Name())
+		return
+	}
+
+	filename := insertVndkVersion(txt.Name(), ctx.DeviceConfig().PlatformVndkVersion())
+	txt.outputFile = android.PathForModuleOut(ctx, filename).OutputPath
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        android.WriteFile,
+		Output:      txt.outputFile,
+		Description: "Writing " + txt.outputFile.String(),
+		Args: map[string]string{
+			"content": strings.Join(list, "\\n"),
+		},
+	})
+
+	installPath := android.PathForModuleInstall(ctx, "etc")
+	ctx.InstallFile(installPath, filename, txt.outputFile)
+}
+
+func (txt *vndkLibrariesTxt) AndroidMkEntries() android.AndroidMkEntries {
+	return android.AndroidMkEntries{
+		Class:      "ETC",
+		OutputFile: android.OptionalPathForPath(txt.outputFile),
+		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+			func(entries *android.AndroidMkEntries) {
+				entries.SetString("LOCAL_MODULE_STEM", txt.outputFile.Base())
+			},
+		},
+	}
+}
+
 func VndkSnapshotSingleton() android.Singleton {
 	return &vndkSnapshotSingleton{}
 }
 
 type vndkSnapshotSingleton struct {
-	installedLlndkLibraries      []string
-	llndkLibrariesFile           android.Path
-	vndkSpLibrariesFile          android.Path
-	vndkCoreLibrariesFile        android.Path
-	vndkPrivateLibrariesFile     android.Path
-	vndkCoreVariantLibrariesFile android.Path
-	vndkLibrariesFile            android.Path
-	vndkSnapshotZipFile          android.OptionalPath
+	installedLlndkLibraries  []string
+	llndkLibrariesFile       android.Path
+	vndkSpLibrariesFile      android.Path
+	vndkCoreLibrariesFile    android.Path
+	vndkPrivateLibrariesFile android.Path
+	vndkLibrariesFile        android.Path
+	vndkSnapshotZipFile      android.OptionalPath
 }
 
 func (c *vndkSnapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) {
@@ -768,15 +845,13 @@
 	vndkcore := android.SortedStringMapValues(vndkCoreLibraries(ctx.Config()))
 	vndksp := android.SortedStringMapValues(vndkSpLibraries(ctx.Config()))
 	vndkprivate := android.SortedStringMapValues(vndkPrivateLibraries(ctx.Config()))
-	vndkcorevariant := android.SortedStringMapValues(vndkUsingCoreVariantLibraries(ctx.Config()))
 
 	c.llndkLibrariesFile = installListFile(llndk, "llndk.libraries.txt")
 	c.vndkCoreLibrariesFile = installListFile(vndkcore, "vndkcore.libraries.txt")
 	c.vndkSpLibrariesFile = installListFile(vndksp, "vndksp.libraries.txt")
 	c.vndkPrivateLibrariesFile = installListFile(vndkprivate, "vndkprivate.libraries.txt")
-	c.vndkCoreVariantLibrariesFile = installListFile(vndkcorevariant, "vndkcorevariant.libraries.txt")
 
-	// merged & tagged & filtered-out(libclang_rt)
+	// Build list of vndk libs as merged & tagged & filter-out(libclang_rt):
 	// Since each target have different set of libclang_rt.* files,
 	// keep the common set of files in vndk.libraries.txt
 	var merged []string
@@ -812,12 +887,6 @@
 	ctx.Strict("VNDK_PRIVATE_LIBRARIES", strings.Join(android.SortedStringKeys(vndkPrivateLibraries(ctx.Config())), " "))
 	ctx.Strict("VNDK_USING_CORE_VARIANT_LIBRARIES", strings.Join(android.SortedStringKeys(vndkUsingCoreVariantLibraries(ctx.Config())), " "))
 
-	ctx.Strict("LLNDK_LIBRARIES_FILE", c.llndkLibrariesFile.String())
-	ctx.Strict("VNDKCORE_LIBRARIES_FILE", c.vndkCoreLibrariesFile.String())
-	ctx.Strict("VNDKSP_LIBRARIES_FILE", c.vndkSpLibrariesFile.String())
-	ctx.Strict("VNDKPRIVATE_LIBRARIES_FILE", c.vndkPrivateLibrariesFile.String())
-	ctx.Strict("VNDKCOREVARIANT_LIBRARIES_FILE", c.vndkCoreVariantLibrariesFile.String())
-
 	ctx.Strict("VNDK_LIBRARIES_FILE", c.vndkLibrariesFile.String())
 	ctx.Strict("SOONG_VNDK_SNAPSHOT_ZIP", c.vndkSnapshotZipFile.String())
 }