VNDK APEX contains related *.libraries.txt files

These files were highly coupled with vndk version, so having them inside
the corresponding VNDK APEX is reasonable.

These files are used by linkerconfig and libnativeloader. In the future,
they reference these files from and VNDK APEX.

Bug: 141450808
Test: m com.android.vndk.current
Change-Id: I055a979d2636ddd8844a0afff81f6ba441f7965e
diff --git a/cc/vndk.go b/cc/vndk.go
index 0b65aca..f25861a 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -27,6 +27,34 @@
 	"android/soong/cc/config"
 )
 
+const (
+	llndkLibrariesTxt                = "llndk.libraries.txt"
+	vndkCoreLibrariesTxt             = "vndkcore.libraries.txt"
+	vndkSpLibrariesTxt               = "vndksp.libraries.txt"
+	vndkPrivateLibrariesTxt          = "vndkprivate.libraries.txt"
+	vndkUsingCoreVariantLibrariesTxt = "vndkcorevariant.libraries.txt"
+)
+
+func VndkLibrariesTxtModules(vndkVersion string) []string {
+	if vndkVersion == "current" {
+		return []string{
+			llndkLibrariesTxt,
+			vndkCoreLibrariesTxt,
+			vndkSpLibrariesTxt,
+			vndkPrivateLibrariesTxt,
+			vndkUsingCoreVariantLibrariesTxt,
+		}
+	}
+	// Snapshot vndks have their own *.libraries.VER.txt files.
+	// Note that snapshots don't have "vndkcorevariant.libraries.VER.txt"
+	return []string{
+		insertVndkVersion(llndkLibrariesTxt, vndkVersion),
+		insertVndkVersion(vndkCoreLibrariesTxt, vndkVersion),
+		insertVndkVersion(vndkSpLibrariesTxt, vndkVersion),
+		insertVndkVersion(vndkPrivateLibrariesTxt, vndkVersion),
+	}
+}
+
 type VndkProperties struct {
 	Vndk struct {
 		// declared as a VNDK or VNDK-SP module. The vendor variant
@@ -360,7 +388,7 @@
 }
 
 func init() {
-	android.RegisterModuleType("vndk_libraries_txt", VndkLibrariesTxt)
+	android.RegisterModuleType("vndk_libraries_txt", VndkLibrariesTxtFactory)
 	android.RegisterSingletonType("vndk-snapshot", VndkSnapshotSingleton)
 }
 
@@ -369,6 +397,9 @@
 	outputFile android.OutputPath
 }
 
+var _ android.PrebuiltEtcModule = &vndkLibrariesTxt{}
+var _ android.OutputFileProducer = &vndkLibrariesTxt{}
+
 // vndk_libraries_txt is a special kind of module type in that it name is one of
 // - llndk.libraries.txt
 // - vndkcore.libraries.txt
@@ -378,7 +409,7 @@
 // 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 {
+func VndkLibrariesTxtFactory() android.Module {
 	m := &vndkLibrariesTxt{}
 	android.InitAndroidModule(m)
 	return m
@@ -394,20 +425,20 @@
 func (txt *vndkLibrariesTxt) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	var list []string
 	switch txt.Name() {
-	case "llndk.libraries.txt":
+	case llndkLibrariesTxt:
 		for _, filename := range android.SortedStringMapValues(llndkLibraries(ctx.Config())) {
 			if strings.HasPrefix(filename, "libclang_rt.hwasan-") {
 				continue
 			}
 			list = append(list, filename)
 		}
-	case "vndkcore.libraries.txt":
+	case vndkCoreLibrariesTxt:
 		list = android.SortedStringMapValues(vndkCoreLibraries(ctx.Config()))
-	case "vndksp.libraries.txt":
+	case vndkSpLibrariesTxt:
 		list = android.SortedStringMapValues(vndkSpLibraries(ctx.Config()))
-	case "vndkprivate.libraries.txt":
+	case vndkPrivateLibrariesTxt:
 		list = android.SortedStringMapValues(vndkPrivateLibraries(ctx.Config()))
-	case "vndkcorevariant.libraries.txt":
+	case vndkUsingCoreVariantLibrariesTxt:
 		list = android.SortedStringMapValues(vndkUsingCoreVariantLibraries(ctx.Config()))
 	default:
 		ctx.ModuleErrorf("name(%s) is unknown.", txt.Name())
@@ -441,18 +472,25 @@
 	}
 }
 
+func (txt *vndkLibrariesTxt) OutputFile() android.OutputPath {
+	return txt.outputFile
+}
+
+func (txt *vndkLibrariesTxt) OutputFiles(tag string) (android.Paths, error) {
+	return android.Paths{txt.outputFile}, nil
+}
+
+func (txt *vndkLibrariesTxt) SubDir() string {
+	return ""
+}
+
 func VndkSnapshotSingleton() android.Singleton {
 	return &vndkSnapshotSingleton{}
 }
 
 type vndkSnapshotSingleton struct {
-	installedLlndkLibraries  []string
-	llndkLibrariesFile       android.Path
-	vndkSpLibrariesFile      android.Path
-	vndkCoreLibrariesFile    android.Path
-	vndkPrivateLibrariesFile android.Path
-	vndkLibrariesFile        android.Path
-	vndkSnapshotZipFile      android.OptionalPath
+	vndkLibrariesFile   android.OutputPath
+	vndkSnapshotZipFile android.OptionalPath
 }
 
 func (c *vndkSnapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) {
@@ -727,12 +765,14 @@
 		}
 	}
 
-	snapshotOutputs = append(snapshotOutputs,
-		installSnapshotFileFromPath(c.vndkCoreLibrariesFile, filepath.Join(configsDir, "vndkcore.libraries.txt")),
-		installSnapshotFileFromPath(c.vndkPrivateLibrariesFile, filepath.Join(configsDir, "vndkprivate.libraries.txt")),
-		installSnapshotFileFromPath(c.vndkSpLibrariesFile, filepath.Join(configsDir, "vndksp.libraries.txt")),
-		installSnapshotFileFromPath(c.llndkLibrariesFile, filepath.Join(configsDir, "llndk.libraries.txt")),
-	)
+	// install *.libraries.txt except vndkcorevariant.libraries.txt
+	ctx.VisitAllModules(func(module android.Module) {
+		m, ok := module.(*vndkLibrariesTxt)
+		if !ok || !m.Enabled() || m.Name() == vndkUsingCoreVariantLibrariesTxt {
+			return
+		}
+		snapshotOutputs = append(snapshotOutputs, installSnapshotFileFromPath(m.OutputFile(), filepath.Join(configsDir, m.Name())))
+	})
 
 	/*
 		Dump a map to a list file as:
@@ -814,43 +854,11 @@
 }
 
 func (c *vndkSnapshotSingleton) buildVndkLibrariesTxtFiles(ctx android.SingletonContext) {
-	// Make uses LLNDK_LIBRARIES to determine which libraries to install.
-	// HWASAN is only part of the LL-NDK in builds in which libc depends on HWASAN.
-	// Therefore, by removing the library here, we cause it to only be installed if libc
-	// depends on it.
-	installedLlndkLibraries := make(map[string]string)
-	for lib, filename := range llndkLibraries(ctx.Config()) {
-		if strings.HasPrefix(lib, "libclang_rt.hwasan-") {
-			continue
-		}
-		installedLlndkLibraries[lib] = filename
-	}
-
-	installListFile := func(list []string, fileName string) android.Path {
-		out := android.PathForOutput(ctx, "vndk", fileName)
-		ctx.Build(pctx, android.BuildParams{
-			Rule:        android.WriteFile,
-			Output:      out,
-			Description: "Writing " + out.String(),
-			Args: map[string]string{
-				"content": strings.Join(list, "\\n"),
-			},
-		})
-		return out
-	}
-
-	c.installedLlndkLibraries = android.SortedStringKeys(installedLlndkLibraries)
-
-	llndk := android.SortedStringMapValues(installedLlndkLibraries)
+	llndk := android.SortedStringMapValues(llndkLibraries(ctx.Config()))
 	vndkcore := android.SortedStringMapValues(vndkCoreLibraries(ctx.Config()))
 	vndksp := android.SortedStringMapValues(vndkSpLibraries(ctx.Config()))
 	vndkprivate := android.SortedStringMapValues(vndkPrivateLibraries(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")
-
 	// 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
@@ -867,21 +875,43 @@
 	merged = append(merged, addPrefix(vndksp, "VNDK-SP: ")...)
 	merged = append(merged, addPrefix(filterOutLibClangRt(vndkcore), "VNDK-core: ")...)
 	merged = append(merged, addPrefix(vndkprivate, "VNDK-private: ")...)
-	c.vndkLibrariesFile = installListFile(merged, "vndk.libraries.txt")
+	c.vndkLibrariesFile = android.PathForOutput(ctx, "vndk", "vndk.libraries.txt")
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        android.WriteFile,
+		Output:      c.vndkLibrariesFile,
+		Description: "Writing " + c.vndkLibrariesFile.String(),
+		Args: map[string]string{
+			"content": strings.Join(merged, "\\n"),
+		},
+	})
 }
 
 func (c *vndkSnapshotSingleton) MakeVars(ctx android.MakeVarsContext) {
 	// Make uses LLNDK_MOVED_TO_APEX_LIBRARIES to avoid installing libraries on /system if
 	// they been moved to an apex.
 	movedToApexLlndkLibraries := []string{}
-	for _, lib := range c.installedLlndkLibraries {
+	for lib := range llndkLibraries(ctx.Config()) {
 		// Skip bionic libs, they are handled in different manner
 		if android.DirectlyInAnyApex(&notOnHostContext{}, lib) && !isBionic(lib) {
 			movedToApexLlndkLibraries = append(movedToApexLlndkLibraries, lib)
 		}
 	}
 	ctx.Strict("LLNDK_MOVED_TO_APEX_LIBRARIES", strings.Join(movedToApexLlndkLibraries, " "))
-	ctx.Strict("LLNDK_LIBRARIES", strings.Join(c.installedLlndkLibraries, " "))
+
+	// Make uses LLNDK_LIBRARIES to determine which libraries to install.
+	// HWASAN is only part of the LL-NDK in builds in which libc depends on HWASAN.
+	// Therefore, by removing the library here, we cause it to only be installed if libc
+	// depends on it.
+	installedLlndkLibraries := []string{}
+	for lib := range llndkLibraries(ctx.Config()) {
+		if strings.HasPrefix(lib, "libclang_rt.hwasan-") {
+			continue
+		}
+		installedLlndkLibraries = append(installedLlndkLibraries, lib)
+	}
+	sort.Strings(installedLlndkLibraries)
+	ctx.Strict("LLNDK_LIBRARIES", strings.Join(installedLlndkLibraries, " "))
+
 	ctx.Strict("VNDK_CORE_LIBRARIES", strings.Join(android.SortedStringKeys(vndkCoreLibraries(ctx.Config())), " "))
 	ctx.Strict("VNDK_SAMEPROCESS_LIBRARIES", strings.Join(android.SortedStringKeys(vndkSpLibraries(ctx.Config())), " "))
 	ctx.Strict("VNDK_PRIVATE_LIBRARIES", strings.Join(android.SortedStringKeys(vndkPrivateLibraries(ctx.Config())), " "))