Install vintf fragments and init.rc files in Soong

Determine the install location of vintf fragments and init.rc files
in Soong so that they are available to Soong-generated module-info.json
entries.  Collect the vintf fragment and init.rc files requested by all Soong
modules, deduplicate the list, and install them in Soong.

Bug: 309006256
Test: Compare module-info.json
Change-Id: I491dc05a773d1a82e485475834d2669fc95cfa1e
This commit is contained in:
Colin Cross 2023-11-17 16:23:48 -08:00
parent ea30d85a65
commit d9bbf4b424
2 changed files with 90 additions and 20 deletions

View file

@ -16,9 +16,11 @@ package android
import (
"bytes"
"cmp"
"fmt"
"path/filepath"
"runtime"
"slices"
"sort"
"strings"
@ -242,6 +244,8 @@ func (s *makeVarsSingleton) GenerateBuildActions(ctx SingletonContext) {
var dists []dist
var phonies []phony
var katiInstalls []katiInstall
var katiInitRcInstalls []katiInstall
var katiVintfManifestInstalls []katiInstall
var katiSymlinks []katiInstall
providers := append([]makeVarsProvider(nil), makeVarsInitProviders...)
@ -275,10 +279,33 @@ func (s *makeVarsSingleton) GenerateBuildActions(ctx SingletonContext) {
if m.ExportedToMake() {
katiInstalls = append(katiInstalls, m.base().katiInstalls...)
katiInitRcInstalls = append(katiInitRcInstalls, m.base().katiInitRcInstalls...)
katiVintfManifestInstalls = append(katiVintfManifestInstalls, m.base().katiVintfInstalls...)
katiSymlinks = append(katiSymlinks, m.base().katiSymlinks...)
}
})
compareKatiInstalls := func(a, b katiInstall) int {
aTo, bTo := a.to.String(), b.to.String()
if cmpTo := cmp.Compare(aTo, bTo); cmpTo != 0 {
return cmpTo
}
aFrom, bFrom := a.from.String(), b.from.String()
return cmp.Compare(aFrom, bFrom)
}
slices.SortFunc(katiInitRcInstalls, compareKatiInstalls)
katiInitRcInstalls = slices.CompactFunc(katiInitRcInstalls, func(a, b katiInstall) bool {
return compareKatiInstalls(a, b) == 0
})
katiInstalls = append(katiInstalls, katiInitRcInstalls...)
slices.SortFunc(katiVintfManifestInstalls, compareKatiInstalls)
katiVintfManifestInstalls = slices.CompactFunc(katiVintfManifestInstalls, func(a, b katiInstall) bool {
return compareKatiInstalls(a, b) == 0
})
if ctx.Failed() {
return
}
@ -316,7 +343,7 @@ func (s *makeVarsSingleton) GenerateBuildActions(ctx SingletonContext) {
ctx.Errorf(err.Error())
}
installsBytes := s.writeInstalls(katiInstalls, katiSymlinks)
installsBytes := s.writeInstalls(katiInstalls, katiSymlinks, katiVintfManifestInstalls)
if err := pathtools.WriteFileIfChanged(installsFile, installsBytes, 0666); err != nil {
ctx.Errorf(err.Error())
}
@ -438,7 +465,7 @@ func (s *makeVarsSingleton) writeLate(phonies []phony, dists []dist) []byte {
// writeInstalls writes the list of install rules generated by Soong to a makefile. The rules
// are exported to Make instead of written directly to the ninja file so that main.mk can add
// the dependencies from the `required` property that are hard to resolve in Soong.
func (s *makeVarsSingleton) writeInstalls(installs, symlinks []katiInstall) []byte {
func (s *makeVarsSingleton) writeInstalls(installs, symlinks, katiVintfManifestInstalls []katiInstall) []byte {
buf := &bytes.Buffer{}
fmt.Fprint(buf, `# Autogenerated file
@ -486,9 +513,9 @@ func (s *makeVarsSingleton) writeInstalls(installs, symlinks []katiInstall) []by
for _, symlink := range symlinks {
fmt.Fprintf(buf, "%s:", symlink.to.String())
if symlink.from != nil {
// The symlink doesn't need updating when the target is modified, but we sometimes
// have a dependency on a symlink to a binary instead of to the binary directly, and
// the mtime of the symlink must be updated when the binary is modified, so use a
// The katiVintfManifestInstall doesn't need updating when the target is modified, but we sometimes
// have a dependency on a katiVintfManifestInstall to a binary instead of to the binary directly, and
// the mtime of the katiVintfManifestInstall must be updated when the binary is modified, so use a
// normal dependency here instead of an order-only dependency.
fmt.Fprintf(buf, " %s", symlink.from.String())
}
@ -507,7 +534,7 @@ func (s *makeVarsSingleton) writeInstalls(installs, symlinks []katiInstall) []by
if symlink.from != nil {
rel, err := filepath.Rel(filepath.Dir(symlink.to.String()), symlink.from.String())
if err != nil {
panic(fmt.Errorf("failed to find relative path for symlink from %q to %q: %w",
panic(fmt.Errorf("failed to find relative path for katiVintfManifestInstall from %q to %q: %w",
symlink.from.String(), symlink.to.String(), err))
}
fromStr = rel
@ -521,6 +548,19 @@ func (s *makeVarsSingleton) writeInstalls(installs, symlinks []katiInstall) []by
fmt.Fprintln(buf)
}
for _, install := range katiVintfManifestInstalls {
// Write a rule for each vintf install request that calls the copy-vintf-manifest-chedk make function.
fmt.Fprintf(buf, "$(eval $(call copy-vintf-manifest-checked, %s, %s))\n", install.from.String(), install.to.String())
if len(install.implicitDeps) > 0 {
panic(fmt.Errorf("unsupported implicitDeps %q in vintf install rule %q", install.implicitDeps, install.to))
}
if len(install.orderOnlyDeps) > 0 {
panic(fmt.Errorf("unsupported orderOnlyDeps %q in vintf install rule %q", install.orderOnlyDeps, install.to))
}
fmt.Fprintln(buf)
}
return buf.Bytes()
}

View file

@ -839,6 +839,10 @@ type ModuleBase struct {
// katiInstalls tracks the install rules that were created by Soong but are being exported
// to Make to convert to ninja rules so that Make can add additional dependencies.
katiInstalls katiInstalls
// katiInitRcInstalls and katiVintfInstalls track the install rules created by Soong that are
// allowed to have duplicates across modules and variants.
katiInitRcInstalls katiInstalls
katiVintfInstalls katiInstalls
katiSymlinks katiInstalls
testData []DataPath
@ -863,6 +867,9 @@ type ModuleBase struct {
initRcPaths Paths
vintfFragmentsPaths Paths
installedInitRcPaths InstallPaths
installedVintfFragmentsPaths InstallPaths
// set of dependency module:location mappings used to populate the license metadata for
// apex containers.
licenseInstallMap []string
@ -1684,6 +1691,41 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
}
})
if m.Device() {
// Handle any init.rc and vintf fragment files requested by the module. All files installed by this
// module will automatically have a dependency on the installed init.rc or vintf fragment file.
// The same init.rc or vintf fragment file may be requested by multiple modules or variants,
// so instead of installing them now just compute the install path and store it for later.
// The full list of all init.rc and vintf fragment install rules will be deduplicated later
// so only a single rule is created for each init.rc or vintf fragment file.
if !m.InVendorRamdisk() {
m.initRcPaths = PathsForModuleSrc(ctx, m.commonProperties.Init_rc)
rcDir := PathForModuleInstall(ctx, "etc", "init")
for _, src := range m.initRcPaths {
installedInitRc := rcDir.Join(ctx, src.Base())
m.katiInitRcInstalls = append(m.katiInitRcInstalls, katiInstall{
from: src,
to: installedInitRc,
})
ctx.PackageFile(rcDir, src.Base(), src)
m.installedInitRcPaths = append(m.installedInitRcPaths, installedInitRc)
}
}
m.vintfFragmentsPaths = PathsForModuleSrc(ctx, m.commonProperties.Vintf_fragments)
vintfDir := PathForModuleInstall(ctx, "etc", "vintf", "manifest")
for _, src := range m.vintfFragmentsPaths {
installedVintfFragment := vintfDir.Join(ctx, src.Base())
m.katiVintfInstalls = append(m.katiVintfInstalls, katiInstall{
from: src,
to: installedVintfFragment,
})
ctx.PackageFile(vintfDir, src.Base(), src)
m.installedVintfFragmentsPaths = append(m.installedVintfFragmentsPaths, installedVintfFragment)
}
}
licensesPropertyFlattener(ctx)
if ctx.Failed() {
return
@ -1694,18 +1736,6 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
return
}
m.initRcPaths = PathsForModuleSrc(ctx, m.commonProperties.Init_rc)
rcDir := PathForModuleInstall(ctx, "etc", "init")
for _, src := range m.initRcPaths {
ctx.PackageFile(rcDir, filepath.Base(src.String()), src)
}
m.vintfFragmentsPaths = PathsForModuleSrc(ctx, m.commonProperties.Vintf_fragments)
vintfDir := PathForModuleInstall(ctx, "etc", "vintf", "manifest")
for _, src := range m.vintfFragmentsPaths {
ctx.PackageFile(vintfDir, filepath.Base(src.String()), src)
}
// Create the set of tagged dist files after calling GenerateAndroidBuildActions
// as GenerateTaggedDistFiles() calls OutputFiles(tag) and so relies on the
// output paths being set which must be done before or during