diff --git a/android/makevars.go b/android/makevars.go index d4cfd299e..4039e7edb 100644 --- a/android/makevars.go +++ b/android/makevars.go @@ -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() } diff --git a/android/module.go b/android/module.go index 1100feed1..328b38373 100644 --- a/android/module.go +++ b/android/module.go @@ -839,8 +839,12 @@ 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 - katiSymlinks katiInstalls - testData []DataPath + // 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 // The files to copy to the dist as explicitly specified in the .bp file. distFiles TaggedDistFiles @@ -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