Merge "Revert "Add BUILD_BROKEN_DONT_CHECK_SYSTEMSDK"" into main
diff --git a/OWNERS b/OWNERS
index 58edc89..01025fb 100644
--- a/OWNERS
+++ b/OWNERS
@@ -12,4 +12,6 @@
mrziwang@google.com
spandandas@google.com
weiwli@google.com
-yudiliu@google.com
\ No newline at end of file
+yudiliu@google.com
+
+per-file build/soong/ui/build/androidmk_denylist.go = joeo@google.com, weiwli@google.com
\ No newline at end of file
diff --git a/aconfig/codegen/cc_aconfig_library.go b/aconfig/codegen/cc_aconfig_library.go
index 12c2dea..8df353d 100644
--- a/aconfig/codegen/cc_aconfig_library.go
+++ b/aconfig/codegen/cc_aconfig_library.go
@@ -40,6 +40,7 @@
// default mode is "production", the other accepted modes are:
// "test": to generate test mode version of the library
// "exported": to generate exported mode version of the library
+ // "force-read-only": to generate force-read-only mode version of the library
// an error will be thrown if the mode is not supported
Mode *string
}
diff --git a/aconfig/codegen/cc_aconfig_library_test.go b/aconfig/codegen/cc_aconfig_library_test.go
index 3de4626..c5ff6a1 100644
--- a/aconfig/codegen/cc_aconfig_library_test.go
+++ b/aconfig/codegen/cc_aconfig_library_test.go
@@ -29,6 +29,7 @@
{"mode: `production`,", "production"},
{"mode: `test`,", "test"},
{"mode: `exported`,", "exported"},
+ {"mode: `force-read-only`,", "force-read-only"},
}
func TestCCCodegenMode(t *testing.T) {
diff --git a/aconfig/codegen/java_aconfig_library.go b/aconfig/codegen/java_aconfig_library.go
index c027815..e6817e0 100644
--- a/aconfig/codegen/java_aconfig_library.go
+++ b/aconfig/codegen/java_aconfig_library.go
@@ -30,7 +30,7 @@
var declarationsTag = declarationsTagType{}
-var aconfigSupportedModes = []string{"production", "test", "exported"}
+var aconfigSupportedModes = []string{"production", "test", "exported", "force-read-only"}
type JavaAconfigDeclarationsLibraryProperties struct {
// name of the aconfig_declarations module to generate a library for
@@ -39,6 +39,7 @@
// default mode is "production", the other accepted modes are:
// "test": to generate test mode version of the library
// "exported": to generate exported mode version of the library
+ // "force-read-only": to generate force-read-only mode version of the library
// an error will be thrown if the mode is not supported
Mode *string
}
diff --git a/aconfig/codegen/java_aconfig_library_test.go b/aconfig/codegen/java_aconfig_library_test.go
index 2523abc..8d54b5b 100644
--- a/aconfig/codegen/java_aconfig_library_test.go
+++ b/aconfig/codegen/java_aconfig_library_test.go
@@ -227,6 +227,10 @@
testCodegenMode(t, "mode: `exported`,", "exported")
}
+func TestForceReadOnlyMode(t *testing.T) {
+ testCodegenMode(t, "mode: `force-read-only`,", "force-read-only")
+}
+
func TestUnsupportedMode(t *testing.T) {
testCodegenModeWithError(t, "mode: `unsupported`,", "mode: \"unsupported\" is not a supported mode")
}
diff --git a/aconfig/codegen/rust_aconfig_library.go b/aconfig/codegen/rust_aconfig_library.go
index 73b6fec..2ab54b6 100644
--- a/aconfig/codegen/rust_aconfig_library.go
+++ b/aconfig/codegen/rust_aconfig_library.go
@@ -23,6 +23,7 @@
// default mode is "production", the other accepted modes are:
// "test": to generate test mode version of the library
// "exported": to generate exported mode version of the library
+ // "force-read-only": to generate force-read-only mode version of the library
// an error will be thrown if the mode is not supported
Mode *string
}
diff --git a/aconfig/codegen/rust_aconfig_library_test.go b/aconfig/codegen/rust_aconfig_library_test.go
index c09f701..60bc9f7 100644
--- a/aconfig/codegen/rust_aconfig_library_test.go
+++ b/aconfig/codegen/rust_aconfig_library_test.go
@@ -72,6 +72,7 @@
{"mode: `production`,", "production"},
{"mode: `test`,", "test"},
{"mode: `exported`,", "exported"},
+ {"mode: `force-read-only`,", "force-read-only"},
}
func TestRustCodegenMode(t *testing.T) {
diff --git a/android/Android.bp b/android/Android.bp
index f71f34f..e40e462 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -63,6 +63,7 @@
"metrics.go",
"module.go",
"module_context.go",
+ "module_info_json.go",
"mutator.go",
"namespace.go",
"neverallow.go",
diff --git a/android/androidmk.go b/android/androidmk.go
index 004ae9e..f65e084 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -30,6 +30,7 @@
"reflect"
"runtime"
"sort"
+ "strconv"
"strings"
"github.com/google/blueprint"
@@ -626,6 +627,10 @@
a.SetPath("LOCAL_SOONG_LICENSE_METADATA", licenseMetadata.LicenseMetadataPath)
}
+ if _, ok := SingletonModuleProvider(ctx, mod, ModuleInfoJSONProvider); ok {
+ a.SetBool("LOCAL_SOONG_MODULE_INFO_JSON", true)
+ }
+
extraCtx := &androidMkExtraEntriesContext{
ctx: ctx,
mod: mod,
@@ -643,14 +648,14 @@
}
}
+func (a *AndroidMkEntries) disabled() bool {
+ return a.Disabled || !a.OutputFile.Valid()
+}
+
// write flushes the AndroidMkEntries's in-struct data populated by AndroidMkEntries into the
// given Writer object.
func (a *AndroidMkEntries) write(w io.Writer) {
- if a.Disabled {
- return
- }
-
- if !a.OutputFile.Valid() {
+ if a.disabled() {
return
}
@@ -696,7 +701,9 @@
return
}
- err := translateAndroidMk(ctx, absolutePath(transMk.String()), androidMkModulesList)
+ moduleInfoJSON := PathForOutput(ctx, "module-info"+String(ctx.Config().productVariables.Make_suffix)+".json")
+
+ err := translateAndroidMk(ctx, absolutePath(transMk.String()), moduleInfoJSON, androidMkModulesList)
if err != nil {
ctx.Errorf(err.Error())
}
@@ -707,14 +714,16 @@
})
}
-func translateAndroidMk(ctx SingletonContext, absMkFile string, mods []blueprint.Module) error {
+func translateAndroidMk(ctx SingletonContext, absMkFile string, moduleInfoJSONPath WritablePath, mods []blueprint.Module) error {
buf := &bytes.Buffer{}
+ var moduleInfoJSONs []*ModuleInfoJSON
+
fmt.Fprintln(buf, "LOCAL_MODULE_MAKEFILE := $(lastword $(MAKEFILE_LIST))")
typeStats := make(map[string]int)
for _, mod := range mods {
- err := translateAndroidMkModule(ctx, buf, mod)
+ err := translateAndroidMkModule(ctx, buf, &moduleInfoJSONs, mod)
if err != nil {
os.Remove(absMkFile)
return err
@@ -736,10 +745,36 @@
fmt.Fprintf(buf, "STATS.SOONG_MODULE_TYPE.%s := %d\n", mod_type, typeStats[mod_type])
}
- return pathtools.WriteFileIfChanged(absMkFile, buf.Bytes(), 0666)
+ err := pathtools.WriteFileIfChanged(absMkFile, buf.Bytes(), 0666)
+ if err != nil {
+ return err
+ }
+
+ return writeModuleInfoJSON(ctx, moduleInfoJSONs, moduleInfoJSONPath)
}
-func translateAndroidMkModule(ctx SingletonContext, w io.Writer, mod blueprint.Module) error {
+func writeModuleInfoJSON(ctx SingletonContext, moduleInfoJSONs []*ModuleInfoJSON, moduleInfoJSONPath WritablePath) error {
+ moduleInfoJSONBuf := &strings.Builder{}
+ moduleInfoJSONBuf.WriteString("[")
+ for i, moduleInfoJSON := range moduleInfoJSONs {
+ if i != 0 {
+ moduleInfoJSONBuf.WriteString(",\n")
+ }
+ moduleInfoJSONBuf.WriteString("{")
+ moduleInfoJSONBuf.WriteString(strconv.Quote(moduleInfoJSON.core.RegisterName))
+ moduleInfoJSONBuf.WriteString(":")
+ err := encodeModuleInfoJSON(moduleInfoJSONBuf, moduleInfoJSON)
+ moduleInfoJSONBuf.WriteString("}")
+ if err != nil {
+ return err
+ }
+ }
+ moduleInfoJSONBuf.WriteString("]")
+ WriteFileRule(ctx, moduleInfoJSONPath, moduleInfoJSONBuf.String())
+ return nil
+}
+
+func translateAndroidMkModule(ctx SingletonContext, w io.Writer, moduleInfoJSONs *[]*ModuleInfoJSON, mod blueprint.Module) error {
defer func() {
if r := recover(); r != nil {
panic(fmt.Errorf("%s in translateAndroidMkModule for module %s variant %s",
@@ -748,17 +783,23 @@
}()
// Additional cases here require review for correct license propagation to make.
+ var err error
switch x := mod.(type) {
case AndroidMkDataProvider:
- return translateAndroidModule(ctx, w, mod, x)
+ err = translateAndroidModule(ctx, w, moduleInfoJSONs, mod, x)
case bootstrap.GoBinaryTool:
- return translateGoBinaryModule(ctx, w, mod, x)
+ err = translateGoBinaryModule(ctx, w, mod, x)
case AndroidMkEntriesProvider:
- return translateAndroidMkEntriesModule(ctx, w, mod, x)
+ err = translateAndroidMkEntriesModule(ctx, w, moduleInfoJSONs, mod, x)
default:
// Not exported to make so no make variables to set.
- return nil
}
+
+ if err != nil {
+ return err
+ }
+
+ return err
}
// A simple, special Android.mk entry output func to make it possible to build blueprint tools using
@@ -801,8 +842,8 @@
// A support func for the deprecated AndroidMkDataProvider interface. Use AndroidMkEntryProvider
// instead.
-func translateAndroidModule(ctx SingletonContext, w io.Writer, mod blueprint.Module,
- provider AndroidMkDataProvider) error {
+func translateAndroidModule(ctx SingletonContext, w io.Writer, moduleInfoJSONs *[]*ModuleInfoJSON,
+ mod blueprint.Module, provider AndroidMkDataProvider) error {
amod := mod.(Module).base()
if shouldSkipAndroidMkProcessing(amod) {
@@ -865,17 +906,19 @@
WriteAndroidMkData(w, data)
}
+ if !data.Entries.disabled() {
+ if moduleInfoJSON, ok := SingletonModuleProvider(ctx, mod, ModuleInfoJSONProvider); ok {
+ *moduleInfoJSONs = append(*moduleInfoJSONs, moduleInfoJSON)
+ }
+ }
+
return nil
}
// A support func for the deprecated AndroidMkDataProvider interface. Use AndroidMkEntryProvider
// instead.
func WriteAndroidMkData(w io.Writer, data AndroidMkData) {
- if data.Disabled {
- return
- }
-
- if !data.OutputFile.Valid() {
+ if data.Entries.disabled() {
return
}
@@ -890,18 +933,26 @@
fmt.Fprintln(w, "include "+data.Include)
}
-func translateAndroidMkEntriesModule(ctx SingletonContext, w io.Writer, mod blueprint.Module,
- provider AndroidMkEntriesProvider) error {
+func translateAndroidMkEntriesModule(ctx SingletonContext, w io.Writer, moduleInfoJSONs *[]*ModuleInfoJSON,
+ mod blueprint.Module, provider AndroidMkEntriesProvider) error {
if shouldSkipAndroidMkProcessing(mod.(Module).base()) {
return nil
}
+ entriesList := provider.AndroidMkEntries()
+
// Any new or special cases here need review to verify correct propagation of license information.
- for _, entries := range provider.AndroidMkEntries() {
+ for _, entries := range entriesList {
entries.fillInEntries(ctx, mod)
entries.write(w)
}
+ if len(entriesList) > 0 && !entriesList[0].disabled() {
+ if moduleInfoJSON, ok := SingletonModuleProvider(ctx, mod, ModuleInfoJSONProvider); ok {
+ *moduleInfoJSONs = append(*moduleInfoJSONs, moduleInfoJSON)
+ }
+ }
+
return nil
}
diff --git a/android/makevars.go b/android/makevars.go
index d4cfd29..4039e7e 100644
--- a/android/makevars.go
+++ b/android/makevars.go
@@ -16,9 +16,11 @@
import (
"bytes"
+ "cmp"
"fmt"
"path/filepath"
"runtime"
+ "slices"
"sort"
"strings"
@@ -242,6 +244,8 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
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 1100fee..1a428e5 100644
--- a/android/module.go
+++ b/android/module.go
@@ -23,6 +23,7 @@
"net/url"
"path/filepath"
"reflect"
+ "slices"
"sort"
"strings"
@@ -839,8 +840,12 @@
// 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,12 +868,19 @@
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
// The path to the generated license metadata file for the module.
licenseMetadataFile WritablePath
+
+ // moduleInfoJSON can be filled out by GenerateAndroidBuildActions to write a JSON file that will
+ // be included in the final module-info.json produced by Make.
+ moduleInfoJSON *ModuleInfoJSON
}
func (m *ModuleBase) AddJSONData(d *map[string]interface{}) {
@@ -1684,6 +1696,41 @@
}
})
+ 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 +1741,6 @@
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
@@ -1741,11 +1776,90 @@
buildLicenseMetadata(ctx, m.licenseMetadataFile)
+ if m.moduleInfoJSON != nil {
+ var installed InstallPaths
+ installed = append(installed, m.katiInstalls.InstallPaths()...)
+ installed = append(installed, m.katiSymlinks.InstallPaths()...)
+ installed = append(installed, m.katiInitRcInstalls.InstallPaths()...)
+ installed = append(installed, m.katiVintfInstalls.InstallPaths()...)
+ installedStrings := installed.Strings()
+
+ var targetRequired, hostRequired []string
+ if ctx.Host() {
+ targetRequired = m.commonProperties.Target_required
+ } else {
+ hostRequired = m.commonProperties.Host_required
+ }
+
+ var data []string
+ for _, d := range m.testData {
+ data = append(data, d.ToRelativeInstallPath())
+ }
+
+ if m.moduleInfoJSON.Uninstallable {
+ installedStrings = nil
+ if len(m.moduleInfoJSON.CompatibilitySuites) == 1 && m.moduleInfoJSON.CompatibilitySuites[0] == "null-suite" {
+ m.moduleInfoJSON.CompatibilitySuites = nil
+ m.moduleInfoJSON.TestConfig = nil
+ m.moduleInfoJSON.AutoTestConfig = nil
+ data = nil
+ }
+ }
+
+ m.moduleInfoJSON.core = CoreModuleInfoJSON{
+ RegisterName: m.moduleInfoRegisterName(ctx, m.moduleInfoJSON.SubName),
+ Path: []string{ctx.ModuleDir()},
+ Installed: installedStrings,
+ ModuleName: m.BaseModuleName() + m.moduleInfoJSON.SubName,
+ SupportedVariants: []string{m.moduleInfoVariant(ctx)},
+ TargetDependencies: targetRequired,
+ HostDependencies: hostRequired,
+ Data: data,
+ }
+ SetProvider(ctx, ModuleInfoJSONProvider, m.moduleInfoJSON)
+ }
+
m.buildParams = ctx.buildParams
m.ruleParams = ctx.ruleParams
m.variables = ctx.variables
}
+func (m *ModuleBase) moduleInfoRegisterName(ctx ModuleContext, subName string) string {
+ name := m.BaseModuleName()
+
+ prefix := ""
+ if ctx.Host() {
+ if ctx.Os() != ctx.Config().BuildOS {
+ prefix = "host_cross_"
+ }
+ }
+ suffix := ""
+ arches := slices.Clone(ctx.Config().Targets[ctx.Os()])
+ arches = slices.DeleteFunc(arches, func(target Target) bool {
+ return target.NativeBridge != ctx.Target().NativeBridge
+ })
+ if len(arches) > 0 && ctx.Arch().ArchType != arches[0].Arch.ArchType {
+ if ctx.Arch().ArchType.Multilib == "lib32" {
+ suffix = "_32"
+ } else {
+ suffix = "_64"
+ }
+ }
+ return prefix + name + subName + suffix
+}
+
+func (m *ModuleBase) moduleInfoVariant(ctx ModuleContext) string {
+ variant := "DEVICE"
+ if ctx.Host() {
+ if ctx.Os() != ctx.Config().BuildOS {
+ variant = "HOST_CROSS"
+ } else {
+ variant = "HOST"
+ }
+ }
+ return variant
+}
+
// Check the supplied dist structure to make sure that it is valid.
//
// property - the base property, e.g. dist or dists[1], which is combined with the
diff --git a/android/module_context.go b/android/module_context.go
index 81692d5..e772f8b 100644
--- a/android/module_context.go
+++ b/android/module_context.go
@@ -210,6 +210,11 @@
// LicenseMetadataFile returns the path where the license metadata for this module will be
// generated.
LicenseMetadataFile() Path
+
+ // ModuleInfoJSON returns a pointer to the ModuleInfoJSON struct that can be filled out by
+ // GenerateAndroidBuildActions. If it is called then the struct will be written out and included in
+ // the module-info.json generated by Make, and Make will not generate its own data for this module.
+ ModuleInfoJSON() *ModuleInfoJSON
}
type moduleContext struct {
@@ -518,6 +523,8 @@
if !m.skipInstall() {
deps = append(deps, InstallPaths(m.module.base().installFilesDepSet.ToList())...)
+ deps = append(deps, m.module.base().installedInitRcPaths...)
+ deps = append(deps, m.module.base().installedVintfFragmentsPaths...)
var implicitDeps, orderOnlyDeps Paths
@@ -695,6 +702,15 @@
return m.module.base().licenseMetadataFile
}
+func (m *moduleContext) ModuleInfoJSON() *ModuleInfoJSON {
+ if moduleInfoJSON := m.module.base().moduleInfoJSON; moduleInfoJSON != nil {
+ return moduleInfoJSON
+ }
+ moduleInfoJSON := &ModuleInfoJSON{}
+ m.module.base().moduleInfoJSON = moduleInfoJSON
+ return moduleInfoJSON
+}
+
// Returns a list of paths expanded from globs and modules referenced using ":module" syntax. The property must
// be tagged with `android:"path" to support automatic source module dependency resolution.
//
diff --git a/android/module_info_json.go b/android/module_info_json.go
new file mode 100644
index 0000000..1c0a38e
--- /dev/null
+++ b/android/module_info_json.go
@@ -0,0 +1,103 @@
+package android
+
+import (
+ "encoding/json"
+ "io"
+ "slices"
+
+ "github.com/google/blueprint"
+)
+
+type CoreModuleInfoJSON struct {
+ RegisterName string `json:"-"`
+ Path []string `json:"path,omitempty"` // $(sort $(ALL_MODULES.$(m).PATH))
+ Installed []string `json:"installed,omitempty"` // $(sort $(ALL_MODULES.$(m).INSTALLED))
+ ModuleName string `json:"module_name,omitempty"` // $(ALL_MODULES.$(m).MODULE_NAME)
+ SupportedVariants []string `json:"supported_variants,omitempty"` // $(sort $(ALL_MODULES.$(m).SUPPORTED_VARIANTS))
+ HostDependencies []string `json:"host_dependencies,omitempty"` // $(sort $(ALL_MODULES.$(m).HOST_REQUIRED_FROM_TARGET))
+ TargetDependencies []string `json:"target_dependencies,omitempty"` // $(sort $(ALL_MODULES.$(m).TARGET_REQUIRED_FROM_HOST))
+ Data []string `json:"data,omitempty"` // $(sort $(ALL_MODULES.$(m).TEST_DATA))
+}
+
+type ModuleInfoJSON struct {
+ core CoreModuleInfoJSON
+ SubName string `json:"-"`
+ Uninstallable bool `json:"-"`
+ Class []string `json:"class,omitempty"` // $(sort $(ALL_MODULES.$(m).CLASS))
+ Tags []string `json:"tags,omitempty"` // $(sort $(ALL_MODULES.$(m).TAGS))
+ Dependencies []string `json:"dependencies,omitempty"` // $(sort $(ALL_DEPS.$(m).ALL_DEPS))
+ SharedLibs []string `json:"shared_libs,omitempty"` // $(sort $(ALL_MODULES.$(m).SHARED_LIBS))
+ StaticLibs []string `json:"static_libs,omitempty"` // $(sort $(ALL_MODULES.$(m).STATIC_LIBS))
+ SystemSharedLibs []string `json:"system_shared_libs,omitempty"` // $(sort $(ALL_MODULES.$(m).SYSTEM_SHARED_LIBS))
+ Srcs []string `json:"srcs,omitempty"` // $(sort $(ALL_MODULES.$(m).SRCS))
+ SrcJars []string `json:"srcjars,omitempty"` // $(sort $(ALL_MODULES.$(m).SRCJARS))
+ ClassesJar []string `json:"classes_jar,omitempty"` // $(sort $(ALL_MODULES.$(m).CLASSES_JAR))
+ TestMainlineModules []string `json:"test_mainline_modules,omitempty"` // $(sort $(ALL_MODULES.$(m).TEST_MAINLINE_MODULES))
+ IsUnitTest bool `json:"is_unit_test,omitempty"` // $(ALL_MODULES.$(m).IS_UNIT_TEST)
+ TestOptionsTags []string `json:"test_options_tags,omitempty"` // $(sort $(ALL_MODULES.$(m).TEST_OPTIONS_TAGS))
+ RuntimeDependencies []string `json:"runtime_dependencies,omitempty"` // $(sort $(ALL_MODULES.$(m).LOCAL_RUNTIME_LIBRARIES))
+ StaticDependencies []string `json:"static_dependencies,omitempty"` // $(sort $(ALL_MODULES.$(m).LOCAL_STATIC_LIBRARIES))
+ DataDependencies []string `json:"data_dependencies,omitempty"` // $(sort $(ALL_MODULES.$(m).TEST_DATA_BINS))
+
+ CompatibilitySuites []string `json:"compatibility_suites,omitempty"` // $(sort $(ALL_MODULES.$(m).COMPATIBILITY_SUITES))
+ AutoTestConfig []string `json:"auto_test_config,omitempty"` // $(ALL_MODULES.$(m).auto_test_config)
+ TestConfig []string `json:"test_config,omitempty"` // $(strip $(ALL_MODULES.$(m).TEST_CONFIG) $(ALL_MODULES.$(m).EXTRA_TEST_CONFIGS)
+}
+
+//ALL_DEPS.$(LOCAL_MODULE).ALL_DEPS := $(sort \
+//$(ALL_DEPS.$(LOCAL_MODULE).ALL_DEPS) \
+//$(LOCAL_STATIC_LIBRARIES) \
+//$(LOCAL_WHOLE_STATIC_LIBRARIES) \
+//$(LOCAL_SHARED_LIBRARIES) \
+//$(LOCAL_DYLIB_LIBRARIES) \
+//$(LOCAL_RLIB_LIBRARIES) \
+//$(LOCAL_PROC_MACRO_LIBRARIES) \
+//$(LOCAL_HEADER_LIBRARIES) \
+//$(LOCAL_STATIC_JAVA_LIBRARIES) \
+//$(LOCAL_JAVA_LIBRARIES) \
+//$(LOCAL_JNI_SHARED_LIBRARIES))
+
+type combinedModuleInfoJSON struct {
+ *CoreModuleInfoJSON
+ *ModuleInfoJSON
+}
+
+func encodeModuleInfoJSON(w io.Writer, moduleInfoJSON *ModuleInfoJSON) error {
+ moduleInfoJSONCopy := *moduleInfoJSON
+
+ sortAndUnique := func(s *[]string) {
+ *s = slices.Clone(*s)
+ slices.Sort(*s)
+ *s = slices.Compact(*s)
+ }
+
+ sortAndUnique(&moduleInfoJSONCopy.core.Path)
+ sortAndUnique(&moduleInfoJSONCopy.core.Installed)
+ sortAndUnique(&moduleInfoJSONCopy.core.SupportedVariants)
+ sortAndUnique(&moduleInfoJSONCopy.core.HostDependencies)
+ sortAndUnique(&moduleInfoJSONCopy.core.TargetDependencies)
+ sortAndUnique(&moduleInfoJSONCopy.core.Data)
+
+ sortAndUnique(&moduleInfoJSONCopy.Class)
+ sortAndUnique(&moduleInfoJSONCopy.Tags)
+ sortAndUnique(&moduleInfoJSONCopy.Dependencies)
+ sortAndUnique(&moduleInfoJSONCopy.SharedLibs)
+ sortAndUnique(&moduleInfoJSONCopy.StaticLibs)
+ sortAndUnique(&moduleInfoJSONCopy.SystemSharedLibs)
+ sortAndUnique(&moduleInfoJSONCopy.Srcs)
+ sortAndUnique(&moduleInfoJSONCopy.SrcJars)
+ sortAndUnique(&moduleInfoJSONCopy.ClassesJar)
+ sortAndUnique(&moduleInfoJSONCopy.TestMainlineModules)
+ sortAndUnique(&moduleInfoJSONCopy.TestOptionsTags)
+ sortAndUnique(&moduleInfoJSONCopy.RuntimeDependencies)
+ sortAndUnique(&moduleInfoJSONCopy.StaticDependencies)
+ sortAndUnique(&moduleInfoJSONCopy.DataDependencies)
+ sortAndUnique(&moduleInfoJSONCopy.CompatibilitySuites)
+ sortAndUnique(&moduleInfoJSONCopy.AutoTestConfig)
+ sortAndUnique(&moduleInfoJSONCopy.TestConfig)
+
+ encoder := json.NewEncoder(w)
+ return encoder.Encode(combinedModuleInfoJSON{&moduleInfoJSONCopy.core, &moduleInfoJSONCopy})
+}
+
+var ModuleInfoJSONProvider = blueprint.NewProvider[*ModuleInfoJSON]()
diff --git a/android/packaging.go b/android/packaging.go
index 2506378..8873540 100644
--- a/android/packaging.go
+++ b/android/packaging.go
@@ -240,10 +240,14 @@
// CopySpecsToDir is a helper that will add commands to the rule builder to copy the PackagingSpec
// entries into the specified directory.
func (p *PackagingBase) CopySpecsToDir(ctx ModuleContext, builder *RuleBuilder, specs map[string]PackagingSpec, dir WritablePath) (entries []string) {
+ if len(specs) == 0 {
+ return entries
+ }
seenDir := make(map[string]bool)
preparerPath := PathForModuleOut(ctx, "preparer.sh")
cmd := builder.Command().Tool(preparerPath)
var sb strings.Builder
+ sb.WriteString("set -e\n")
for _, k := range SortedKeys(specs) {
ps := specs[k]
destPath := filepath.Join(dir.String(), ps.relPathInPackage)
diff --git a/apex/apex.go b/apex/apex.go
index 45abbba..76e78bf 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -2853,17 +2853,6 @@
//
// Module separator
//
- m["com.android.mediaprovider"] = []string{
- "MediaProvider",
- "MediaProviderGoogle",
- "fmtlib_ndk",
- "libbase_ndk",
- "libfuse",
- "libfuse_jni",
- }
- //
- // Module separator
- //
m["com.android.runtime"] = []string{
"libdebuggerd",
"libdebuggerd_common_headers",
@@ -2885,14 +2874,6 @@
//
// Module separator
//
- m["com.android.tethering"] = []string{
- "android.hardware.tetheroffload.config-V1.0-java",
- "android.hardware.tetheroffload.control-V1.0-java",
- "net-utils-framework-common",
- }
- //
- // Module separator
- //
m["com.android.wifi"] = []string{
"PlatformProperties",
"android.hardware.wifi-V1.0-java",
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 54c7f97..bde096b 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -101,15 +101,6 @@
if len(c.Properties.AndroidMkSharedLibs) > 0 {
entries.AddStrings("LOCAL_SHARED_LIBRARIES", c.Properties.AndroidMkSharedLibs...)
}
- if len(c.Properties.AndroidMkStaticLibs) > 0 {
- entries.AddStrings("LOCAL_STATIC_LIBRARIES", c.Properties.AndroidMkStaticLibs...)
- }
- if len(c.Properties.AndroidMkWholeStaticLibs) > 0 {
- entries.AddStrings("LOCAL_WHOLE_STATIC_LIBRARIES", c.Properties.AndroidMkWholeStaticLibs...)
- }
- if len(c.Properties.AndroidMkHeaderLibs) > 0 {
- entries.AddStrings("LOCAL_HEADER_LIBRARIES", c.Properties.AndroidMkHeaderLibs...)
- }
if len(c.Properties.AndroidMkRuntimeLibs) > 0 {
entries.AddStrings("LOCAL_RUNTIME_LIBRARIES", c.Properties.AndroidMkRuntimeLibs...)
}
diff --git a/cc/binary.go b/cc/binary.go
index 61541ad..7aa8e20 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -541,6 +541,11 @@
return binary.Properties.Overrides
}
+func (binary *binaryDecorator) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON) {
+ moduleInfoJSON.Class = []string{"EXECUTABLES"}
+ binary.baseLinker.moduleInfoJSON(ctx, moduleInfoJSON)
+}
+
var _ overridable = (*binaryDecorator)(nil)
func init() {
diff --git a/cc/cc.go b/cc/cc.go
index 9f32c44..6b64b7b 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -543,6 +543,7 @@
isPreventInstall() bool
isCfiAssemblySupportEnabled() bool
getSharedFlags() *SharedFlags
+ notInPlatform() bool
}
type SharedFlags struct {
@@ -623,6 +624,8 @@
// Get the deps that have been explicitly specified in the properties.
linkerSpecifiedDeps(specifiedDeps specifiedDeps) specifiedDeps
+
+ moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON)
}
// specifiedDeps is a tuple struct representing dependencies of a linked binary owned by the linker.
@@ -1785,6 +1788,10 @@
return ctx.mod.isCfiAssemblySupportEnabled()
}
+func (ctx *moduleContextImpl) notInPlatform() bool {
+ return ctx.mod.NotInPlatform()
+}
+
func newBaseModule(hod android.HostOrDeviceSupported, multilib android.Multilib) *Module {
return &Module{
hod: hod,
@@ -1941,6 +1948,7 @@
"libdl_android": true,
"libm": true,
"libdl": true,
+ "libz": true,
// art apex
"libandroidio": true,
"libdexfile": true,
@@ -2139,6 +2147,39 @@
android.CollectDependencyAconfigFiles(ctx, &c.mergedAconfigFiles)
c.maybeInstall(ctx, apexInfo)
+
+ if c.linker != nil {
+ moduleInfoJSON := ctx.ModuleInfoJSON()
+ c.linker.moduleInfoJSON(ctx, moduleInfoJSON)
+ moduleInfoJSON.SharedLibs = c.Properties.AndroidMkSharedLibs
+ moduleInfoJSON.StaticLibs = c.Properties.AndroidMkStaticLibs
+ moduleInfoJSON.SystemSharedLibs = c.Properties.AndroidMkSystemSharedLibs
+ moduleInfoJSON.RuntimeDependencies = c.Properties.AndroidMkRuntimeLibs
+
+ moduleInfoJSON.Dependencies = append(moduleInfoJSON.Dependencies, c.Properties.AndroidMkSharedLibs...)
+ moduleInfoJSON.Dependencies = append(moduleInfoJSON.Dependencies, c.Properties.AndroidMkStaticLibs...)
+ moduleInfoJSON.Dependencies = append(moduleInfoJSON.Dependencies, c.Properties.AndroidMkHeaderLibs...)
+ moduleInfoJSON.Dependencies = append(moduleInfoJSON.Dependencies, c.Properties.AndroidMkWholeStaticLibs...)
+
+ if c.sanitize != nil && len(moduleInfoJSON.Class) > 0 &&
+ (moduleInfoJSON.Class[0] == "STATIC_LIBRARIES" || moduleInfoJSON.Class[0] == "HEADER_LIBRARIES") {
+ if Bool(c.sanitize.Properties.SanitizeMutated.Cfi) {
+ moduleInfoJSON.SubName += ".cfi"
+ }
+ if Bool(c.sanitize.Properties.SanitizeMutated.Hwaddress) {
+ moduleInfoJSON.SubName += ".hwasan"
+ }
+ if Bool(c.sanitize.Properties.SanitizeMutated.Scs) {
+ moduleInfoJSON.SubName += ".scs"
+ }
+ }
+ moduleInfoJSON.SubName += c.Properties.SubName
+
+ if c.Properties.IsSdkVariant && c.Properties.SdkAndPlatformVariantVisibleToMake {
+ moduleInfoJSON.Uninstallable = true
+ }
+
+ }
}
func (c *Module) maybeUnhideFromMake() {
diff --git a/cc/fuzz.go b/cc/fuzz.go
index f5642d6..2436f33 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -144,25 +144,35 @@
}
func (fuzz *fuzzBinary) linkerFlags(ctx ModuleContext, flags Flags) Flags {
+ subdir := "lib"
+ if ctx.inVendor() {
+ subdir = "lib/vendor"
+ }
+
flags = fuzz.binaryDecorator.linkerFlags(ctx, flags)
// RunPaths on devices isn't instantiated by the base linker. `../lib` for
// installed fuzz targets (both host and device), and `./lib` for fuzz
// target packages.
- flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN/lib`)
+ flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN/`+subdir)
// When running on device, fuzz targets with vendor: true set will be in
// fuzzer_name/vendor/fuzzer_name (note the extra 'vendor' and thus need to
// link with libraries in ../../lib/. Non-vendor binaries only need to look
// one level up, in ../lib/.
if ctx.inVendor() {
- flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN/../../lib`)
+ flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN/../../`+subdir)
} else {
- flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN/../lib`)
+ flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN/../`+subdir)
}
return flags
}
+func (fuzz *fuzzBinary) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON) {
+ fuzz.binaryDecorator.moduleInfoJSON(ctx, moduleInfoJSON)
+ moduleInfoJSON.Class = []string{"EXECUTABLES"}
+}
+
// IsValidSharedDependency takes a module and determines if it is a unique shared library
// that should be installed in the fuzz target output directories. This function
// returns true, unless:
@@ -216,19 +226,27 @@
}
func SharedLibraryInstallLocation(
- libraryBase string, isHost bool, fuzzDir string, archString string) string {
+ libraryBase string, isHost bool, isVendor bool, fuzzDir string, archString string) string {
installLocation := "$(PRODUCT_OUT)/data"
if isHost {
installLocation = "$(HOST_OUT)"
}
+ subdir := "lib"
+ if isVendor {
+ subdir = "lib/vendor"
+ }
installLocation = filepath.Join(
- installLocation, fuzzDir, archString, "lib", libraryBase)
+ installLocation, fuzzDir, archString, subdir, libraryBase)
return installLocation
}
// Get the device-only shared library symbols install directory.
-func SharedLibrarySymbolsInstallLocation(libraryBase string, fuzzDir string, archString string) string {
- return filepath.Join("$(PRODUCT_OUT)/symbols/data/", fuzzDir, archString, "/lib/", libraryBase)
+func SharedLibrarySymbolsInstallLocation(libraryBase string, isVendor bool, fuzzDir string, archString string) string {
+ subdir := "lib"
+ if isVendor {
+ subdir = "lib/vendor"
+ }
+ return filepath.Join("$(PRODUCT_OUT)/symbols/data/", fuzzDir, archString, subdir, libraryBase)
}
func (fuzzBin *fuzzBinary) install(ctx ModuleContext, file android.Path) {
@@ -239,16 +257,29 @@
// Grab the list of required shared libraries.
fuzzBin.sharedLibraries, _ = CollectAllSharedDependencies(ctx)
+ // TODO: does not mirror Android linkernamespaces
+ // the logic here has special cases for vendor, but it would need more work to
+ // work in arbitrary partitions, so just surface errors early for a few cases
+ //
+ // Even without these, there are certain situations across linkernamespaces
+ // that this won't support. For instance, you might have:
+ //
+ // my_fuzzer (vendor) -> libbinder_ndk (core) -> libbinder (vendor)
+ //
+ // This dependency chain wouldn't be possible to express in the current
+ // logic because all the deps currently match the variant of the source
+ // module.
+
for _, ruleBuilderInstall := range fuzzBin.sharedLibraries {
install := ruleBuilderInstall.To
fuzzBin.installedSharedDeps = append(fuzzBin.installedSharedDeps,
SharedLibraryInstallLocation(
- install, ctx.Host(), installBase, ctx.Arch().ArchType.String()))
+ install, ctx.Host(), ctx.inVendor(), installBase, ctx.Arch().ArchType.String()))
// Also add the dependency on the shared library symbols dir.
if !ctx.Host() {
fuzzBin.installedSharedDeps = append(fuzzBin.installedSharedDeps,
- SharedLibrarySymbolsInstallLocation(install, installBase, ctx.Arch().ArchType.String()))
+ SharedLibrarySymbolsInstallLocation(install, ctx.inVendor(), installBase, ctx.Arch().ArchType.String()))
}
}
@@ -407,6 +438,10 @@
}
sharedLibsInstallDirPrefix := "lib"
+ if ccModule.InVendor() {
+ sharedLibsInstallDirPrefix = "lib/vendor"
+ }
+
if !ccModule.IsFuzzModule() {
return
}
@@ -499,7 +534,7 @@
// install it to the output directory. Setup the install destination here,
// which will be used by $(copy-many-files) in the Make backend.
installDestination := SharedLibraryInstallLocation(
- install, module.Host(), fuzzDir, archString)
+ install, module.Host(), module.InVendor(), fuzzDir, archString)
if (*sharedLibraryInstalled)[installDestination] {
continue
}
@@ -517,7 +552,7 @@
// we want symbolization tools (like `stack`) to be able to find the symbols
// in $ANDROID_PRODUCT_OUT/symbols automagically.
if !module.Host() {
- symbolsInstallDestination := SharedLibrarySymbolsInstallLocation(install, fuzzDir, archString)
+ symbolsInstallDestination := SharedLibrarySymbolsInstallLocation(install, module.InVendor(), fuzzDir, archString)
symbolsInstallDestination = strings.ReplaceAll(symbolsInstallDestination, "$", "$$")
s.SharedLibInstallStrings = append(s.SharedLibInstallStrings,
library.String()+":"+symbolsInstallDestination)
diff --git a/cc/library.go b/cc/library.go
index 4c8deef..592f70f 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -1041,6 +1041,40 @@
return specifiedDeps
}
+func (library *libraryDecorator) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON) {
+ if library.static() {
+ moduleInfoJSON.Class = []string{"STATIC_LIBRARIES"}
+ moduleInfoJSON.Uninstallable = true
+ } else if library.shared() {
+ moduleInfoJSON.Class = []string{"SHARED_LIBRARIES"}
+ } else if library.header() {
+ moduleInfoJSON.Class = []string{"HEADER_LIBRARIES"}
+ moduleInfoJSON.Uninstallable = true
+ }
+
+ if library.buildStubs() && library.stubsVersion() != "" {
+ moduleInfoJSON.SubName += "." + library.stubsVersion()
+ }
+
+ // If a library providing a stub is included in an APEX, the private APIs of the library
+ // is accessible only inside the APEX. From outside of the APEX, clients can only use the
+ // public APIs via the stub. To enforce this, the (latest version of the) stub gets the
+ // name of the library. The impl library instead gets the `.bootstrap` suffix to so that
+ // they can be exceptionally used directly when APEXes are not available (e.g. during the
+ // very early stage in the boot process).
+ if len(library.Properties.Stubs.Versions) > 0 && !ctx.Host() && ctx.notInPlatform() &&
+ !ctx.inRamdisk() && !ctx.inVendorRamdisk() && !ctx.inRecovery() && !ctx.useVndk() && !ctx.static() {
+ if library.buildStubs() && library.isLatestStubVersion() {
+ moduleInfoJSON.SubName = ""
+ }
+ if !library.buildStubs() {
+ moduleInfoJSON.SubName = ".bootstrap"
+ }
+ }
+
+ library.baseLinker.moduleInfoJSON(ctx, moduleInfoJSON)
+}
+
func (library *libraryDecorator) linkStatic(ctx ModuleContext,
flags Flags, deps PathDeps, objs Objects) android.Path {
diff --git a/cc/linker.go b/cc/linker.go
index 357d1ce..85c128e 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -648,6 +648,9 @@
return specifiedDeps
}
+func (linker *baseLinker) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON) {
+}
+
// Injecting version symbols
// Some host modules want a version number, but we don't want to rebuild it every time. Optionally add a step
// after linking that injects a constant placeholder with the current version number.
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 98fb334..183e818 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -486,6 +486,12 @@
}
}
+func (linker *stubDecorator) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON) {
+ linker.libraryDecorator.moduleInfoJSON(ctx, moduleInfoJSON)
+ // Overwrites the SubName computed by libraryDecorator
+ moduleInfoJSON.SubName = ndkLibrarySuffix + "." + linker.apiLevel.String()
+}
+
func (linker *stubDecorator) Name(name string) string {
return name + ndkLibrarySuffix
}
diff --git a/cc/object.go b/cc/object.go
index 0dba99f..6c0391f 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -238,3 +238,8 @@
func (object *objectLinker) isCrt() bool {
return Bool(object.Properties.Crt)
}
+
+func (object *objectLinker) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON) {
+ object.baseLinker.moduleInfoJSON(ctx, moduleInfoJSON)
+ moduleInfoJSON.Class = []string{"STATIC_LIBRARIES"}
+}
diff --git a/cc/symbolfile/__init__.py b/cc/symbolfile/__init__.py
index 94c8567..345e9f9 100644
--- a/cc/symbolfile/__init__.py
+++ b/cc/symbolfile/__init__.py
@@ -46,6 +46,15 @@
Arch('x86_64'),
)
+# TODO: it would be nice to dedupe with 'has_*_tag' property methods
+SUPPORTED_TAGS = ALL_ARCHITECTURES + (
+ Tag('apex'),
+ Tag('llndk'),
+ Tag('platform-only'),
+ Tag('systemapi'),
+ Tag('var'),
+ Tag('weak'),
+)
# Arbitrary magic number. We use the same one in api-level.h for this purpose.
FUTURE_API_LEVEL = 10000
@@ -136,6 +145,8 @@
def is_api_level_tag(tag: Tag) -> bool:
"""Returns true if this tag has an API level that may need decoding."""
+ if tag.startswith('llndk-deprecated='):
+ return True
if tag.startswith('introduced='):
return True
if tag.startswith('introduced-'):
@@ -170,6 +181,9 @@
ParseError: An unknown version name was found in a tag.
"""
if not is_api_level_tag(tag):
+ if tag not in SUPPORTED_TAGS:
+ raise ParseError(f'Unsupported tag: {tag}')
+
return tag
name, value = split_tag(tag)
diff --git a/cc/symbolfile/test_symbolfile.py b/cc/symbolfile/test_symbolfile.py
index 856b9d7..83becc2 100644
--- a/cc/symbolfile/test_symbolfile.py
+++ b/cc/symbolfile/test_symbolfile.py
@@ -40,10 +40,20 @@
self.assertEqual(Tags(), symbolfile.get_tags('foo bar baz', {}))
def test_get_tags(self) -> None:
- self.assertEqual(Tags.from_strs(['foo', 'bar']),
- symbolfile.get_tags('# foo bar', {}))
- self.assertEqual(Tags.from_strs(['bar', 'baz']),
- symbolfile.get_tags('foo # bar baz', {}))
+ self.assertEqual(Tags.from_strs(['llndk', 'apex']),
+ symbolfile.get_tags('# llndk apex', {}))
+ self.assertEqual(Tags.from_strs(['llndk', 'apex']),
+ symbolfile.get_tags('foo # llndk apex', {}))
+
+ def test_get_unrecognized_tags(self) -> None:
+ with self.assertRaises(symbolfile.ParseError):
+ symbolfile.get_tags('# bar', {})
+ with self.assertRaises(symbolfile.ParseError):
+ symbolfile.get_tags('foo # bar', {})
+ with self.assertRaises(symbolfile.ParseError):
+ symbolfile.get_tags('# #', {})
+ with self.assertRaises(symbolfile.ParseError):
+ symbolfile.get_tags('# apex # llndk', {})
def test_split_tag(self) -> None:
self.assertTupleEqual(('foo', 'bar'),
@@ -425,13 +435,13 @@
def test_parse_version(self) -> None:
input_file = io.StringIO(textwrap.dedent("""\
- VERSION_1 { # foo bar
+ VERSION_1 { # weak introduced=35
baz;
- qux; # woodly doodly
+ qux; # apex llndk
};
VERSION_2 {
- } VERSION_1; # asdf
+ } VERSION_1; # not-a-tag
"""))
parser = symbolfile.SymbolFileParser(input_file, {}, self.filter)
@@ -439,11 +449,11 @@
version = parser.parse_version()
self.assertEqual('VERSION_1', version.name)
self.assertIsNone(version.base)
- self.assertEqual(Tags.from_strs(['foo', 'bar']), version.tags)
+ self.assertEqual(Tags.from_strs(['weak', 'introduced=35']), version.tags)
expected_symbols = [
Symbol('baz', Tags()),
- Symbol('qux', Tags.from_strs(['woodly', 'doodly'])),
+ Symbol('qux', Tags.from_strs(['apex', 'llndk'])),
]
self.assertEqual(expected_symbols, version.symbols)
@@ -476,7 +486,7 @@
def test_parse_symbol(self) -> None:
input_file = io.StringIO(textwrap.dedent("""\
foo;
- bar; # baz qux
+ bar; # llndk apex
"""))
parser = symbolfile.SymbolFileParser(input_file, {}, self.filter)
@@ -488,7 +498,7 @@
parser.next_line()
symbol = parser.parse_symbol()
self.assertEqual('bar', symbol.name)
- self.assertEqual(Tags.from_strs(['baz', 'qux']), symbol.tags)
+ self.assertEqual(Tags.from_strs(['llndk', 'apex']), symbol.tags)
def test_wildcard_symbol_global(self) -> None:
input_file = io.StringIO(textwrap.dedent("""\
@@ -537,13 +547,13 @@
hidden1;
global:
foo;
- bar; # baz
+ bar; # llndk
};
- VERSION_2 { # wasd
+ VERSION_2 { # weak
# Implicit global scope.
woodly;
- doodly; # asdf
+ doodly; # llndk
local:
qwerty;
} VERSION_1;
@@ -554,12 +564,12 @@
expected = [
symbolfile.Version('VERSION_1', None, Tags(), [
Symbol('foo', Tags()),
- Symbol('bar', Tags.from_strs(['baz'])),
+ Symbol('bar', Tags.from_strs(['llndk'])),
]),
symbolfile.Version(
- 'VERSION_2', 'VERSION_1', Tags.from_strs(['wasd']), [
+ 'VERSION_2', 'VERSION_1', Tags.from_strs(['weak']), [
Symbol('woodly', Tags()),
- Symbol('doodly', Tags.from_strs(['asdf'])),
+ Symbol('doodly', Tags.from_strs(['llndk'])),
]),
]
diff --git a/cc/test.go b/cc/test.go
index d02145b..347d7c9 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -321,6 +321,13 @@
return []interface{}{&test.InstallerProperties}
}
+func (test *testDecorator) moduleInfoJSON(ctx android.ModuleContext, moduleInfoJSON *android.ModuleInfoJSON) {
+ if android.PrefixInList(moduleInfoJSON.CompatibilitySuites, "mts-") &&
+ !android.InList("mts", moduleInfoJSON.CompatibilitySuites) {
+ moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "mts")
+ }
+}
+
func NewTestInstaller() *baseInstaller {
return NewBaseInstaller("nativetest", "nativetest64", InstallInData)
}
@@ -355,6 +362,38 @@
return flags
}
+func (test *testBinary) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON) {
+ if ctx.Host() && Bool(test.Properties.Test_options.Unit_test) {
+ moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "host-unit-tests")
+ }
+ moduleInfoJSON.TestOptionsTags = append(moduleInfoJSON.TestOptionsTags, test.Properties.Test_options.Tags...)
+ moduleInfoJSON.TestMainlineModules = append(moduleInfoJSON.TestMainlineModules, test.Properties.Test_mainline_modules...)
+ if test.testConfig != nil {
+ if _, ok := test.testConfig.(android.WritablePath); ok {
+ moduleInfoJSON.AutoTestConfig = []string{"true"}
+ }
+ moduleInfoJSON.TestConfig = append(moduleInfoJSON.TestConfig, test.testConfig.String())
+ }
+ moduleInfoJSON.TestConfig = append(moduleInfoJSON.TestConfig, test.extraTestConfigs.Strings()...)
+
+ if Bool(test.Properties.Test_per_src) {
+ moduleInfoJSON.SubName = "_" + String(test.binaryDecorator.Properties.Stem)
+ }
+
+ moduleInfoJSON.DataDependencies = append(moduleInfoJSON.DataDependencies, test.Properties.Data_bins...)
+
+ if len(test.InstallerProperties.Test_suites) > 0 {
+ moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, test.InstallerProperties.Test_suites...)
+ } else {
+ moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "null-suite")
+ }
+
+ test.binaryDecorator.moduleInfoJSON(ctx, moduleInfoJSON)
+ test.testDecorator.moduleInfoJSON(ctx, moduleInfoJSON)
+ moduleInfoJSON.Class = []string{"NATIVE_TESTS"}
+
+}
+
func (test *testBinary) installerProps() []interface{} {
return append(test.baseInstaller.installerProps(), test.testDecorator.installerProps()...)
}
@@ -532,6 +571,15 @@
return flags
}
+func (test *testLibrary) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON) {
+ if len(test.InstallerProperties.Test_suites) > 0 {
+ moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, test.InstallerProperties.Test_suites...)
+ }
+
+ test.libraryDecorator.moduleInfoJSON(ctx, moduleInfoJSON)
+ test.testDecorator.moduleInfoJSON(ctx, moduleInfoJSON)
+}
+
func (test *testLibrary) installerProps() []interface{} {
return append(test.baseInstaller.installerProps(), test.testDecorator.installerProps()...)
}
@@ -626,6 +674,29 @@
benchmark.binaryDecorator.baseInstaller.install(ctx, file)
}
+func (benchmark *benchmarkDecorator) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON) {
+ benchmark.binaryDecorator.moduleInfoJSON(ctx, moduleInfoJSON)
+
+ moduleInfoJSON.Class = []string{"NATIVE_TESTS"}
+ if len(benchmark.Properties.Test_suites) > 0 {
+ moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, benchmark.Properties.Test_suites...)
+ } else {
+ moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "null-suite")
+ }
+
+ if android.PrefixInList(moduleInfoJSON.CompatibilitySuites, "mts-") &&
+ !android.InList("mts", moduleInfoJSON.CompatibilitySuites) {
+ moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "mts")
+ }
+
+ if benchmark.testConfig != nil {
+ if _, ok := benchmark.testConfig.(android.WritablePath); ok {
+ moduleInfoJSON.AutoTestConfig = []string{"true"}
+ }
+ moduleInfoJSON.TestConfig = []string{benchmark.testConfig.String()}
+ }
+}
+
func NewBenchmark(hod android.HostOrDeviceSupported) *Module {
module, binary := newBinary(hod)
module.multilib = android.MultilibBoth
diff --git a/cc/vndk_prebuilt.go b/cc/vndk_prebuilt.go
index 3f3a025..eb1790f 100644
--- a/cc/vndk_prebuilt.go
+++ b/cc/vndk_prebuilt.go
@@ -187,6 +187,11 @@
return nil
}
+func (p *vndkPrebuiltLibraryDecorator) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON) {
+ p.libraryDecorator.moduleInfoJSON(ctx, moduleInfoJSON)
+ moduleInfoJSON.SubName += p.androidMkSuffix
+}
+
func (p *vndkPrebuiltLibraryDecorator) MatchesWithDevice(config android.DeviceConfig) bool {
arches := config.Arches()
if len(arches) == 0 || arches[0].ArchType.String() != p.arch() {
diff --git a/cmd/merge_module_info_json/Android.bp b/cmd/merge_module_info_json/Android.bp
new file mode 100644
index 0000000..1ae6a47
--- /dev/null
+++ b/cmd/merge_module_info_json/Android.bp
@@ -0,0 +1,30 @@
+// Copyright 2021 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+blueprint_go_binary {
+ name: "merge_module_info_json",
+ srcs: [
+ "merge_module_info_json.go",
+ ],
+ deps: [
+ "soong-response",
+ ],
+ testSrcs: [
+ "merge_module_info_json_test.go",
+ ],
+}
diff --git a/cmd/merge_module_info_json/merge_module_info_json.go b/cmd/merge_module_info_json/merge_module_info_json.go
new file mode 100644
index 0000000..0143984
--- /dev/null
+++ b/cmd/merge_module_info_json/merge_module_info_json.go
@@ -0,0 +1,223 @@
+// Copyright 2021 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// merge_module_info_json is a utility that merges module_info.json files generated by
+// Soong and Make.
+
+package main
+
+import (
+ "android/soong/response"
+ "cmp"
+ "encoding/json"
+ "flag"
+ "fmt"
+ "os"
+ "slices"
+)
+
+var (
+ out = flag.String("o", "", "output file")
+ listFile = flag.String("l", "", "input file list file")
+)
+
+func usage() {
+ fmt.Fprintf(os.Stderr, "usage: %s -o <output file> <input files>\n", os.Args[0])
+ flag.PrintDefaults()
+ fmt.Fprintln(os.Stderr, "merge_module_info_json reads input files that each contain an array of json objects")
+ fmt.Fprintln(os.Stderr, "and writes them out as a single json array to the output file.")
+
+ os.Exit(2)
+}
+
+func main() {
+ flag.Usage = usage
+ flag.Parse()
+
+ if *out == "" {
+ fmt.Fprintf(os.Stderr, "%s: error: -o is required\n", os.Args[0])
+ usage()
+ }
+
+ inputs := flag.Args()
+ if *listFile != "" {
+ listFileInputs, err := readListFile(*listFile)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "failed to read list file %s: %s", *listFile, err)
+ os.Exit(1)
+ }
+ inputs = append(inputs, listFileInputs...)
+ }
+
+ err := mergeJsonObjects(*out, inputs)
+
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "%s: error: %s\n", os.Args[0], err.Error())
+ os.Exit(1)
+ }
+}
+
+func readListFile(file string) ([]string, error) {
+ f, err := os.Open(*listFile)
+ if err != nil {
+ return nil, err
+ }
+ return response.ReadRspFile(f)
+}
+
+func mergeJsonObjects(output string, inputs []string) error {
+ combined := make(map[string]any)
+ for _, input := range inputs {
+ objects, err := decodeObjectFromJson(input)
+ if err != nil {
+ return err
+ }
+
+ for _, object := range objects {
+ for k, v := range object {
+ if old, exists := combined[k]; exists {
+ v = combine(old, v)
+ }
+ combined[k] = v
+ }
+ }
+ }
+
+ f, err := os.Create(output)
+ if err != nil {
+ return fmt.Errorf("failed to open output file: %w", err)
+ }
+ encoder := json.NewEncoder(f)
+ encoder.SetIndent("", " ")
+ err = encoder.Encode(combined)
+ if err != nil {
+ return fmt.Errorf("failed to encode to output file: %w", err)
+ }
+
+ return nil
+}
+
+func decodeObjectFromJson(input string) ([]map[string]any, error) {
+ f, err := os.Open(input)
+ if err != nil {
+ return nil, fmt.Errorf("failed to open input file: %w", err)
+ }
+
+ decoder := json.NewDecoder(f)
+ var object any
+ err = decoder.Decode(&object)
+ if err != nil {
+ return nil, fmt.Errorf("failed to parse input file %q: %w", input, err)
+ }
+
+ switch o := object.(type) {
+ case []any:
+ var ret []map[string]any
+ for _, arrayElement := range o {
+ if m, ok := arrayElement.(map[string]any); ok {
+ ret = append(ret, m)
+ } else {
+ return nil, fmt.Errorf("unknown JSON type in array %T", arrayElement)
+ }
+ }
+ return ret, nil
+
+ case map[string]any:
+ return []map[string]any{o}, nil
+ }
+
+ return nil, fmt.Errorf("unknown JSON type %T", object)
+}
+
+func combine(old, new any) any {
+ // fmt.Printf("%#v %#v\n", old, new)
+ switch oldTyped := old.(type) {
+ case map[string]any:
+ if newObject, ok := new.(map[string]any); ok {
+ return combineObjects(oldTyped, newObject)
+ } else {
+ panic(fmt.Errorf("expected map[string]any, got %#v", new))
+ }
+ case []any:
+ if newArray, ok := new.([]any); ok {
+ return combineArrays(oldTyped, newArray)
+ } else {
+ panic(fmt.Errorf("expected []any, got %#v", new))
+ }
+ case string:
+ if newString, ok := new.(string); ok {
+ if oldTyped != newString {
+ panic(fmt.Errorf("strings %q and %q don't match", oldTyped, newString))
+ }
+ return oldTyped
+ } else {
+ panic(fmt.Errorf("expected []any, got %#v", new))
+ }
+ default:
+ panic(fmt.Errorf("can't combine type %T", old))
+ }
+}
+
+func combineObjects(old, new map[string]any) map[string]any {
+ for k, newField := range new {
+ // HACK: Don't merge "test_config" field. This matches the behavior in base_rules.mk that overwrites
+ // instead of appending ALL_MODULES.$(my_register_name).TEST_CONFIG, keeping the
+ if k == "test_config" {
+ old[k] = newField
+ continue
+ }
+ if oldField, exists := old[k]; exists {
+ oldField = combine(oldField, newField)
+ old[k] = oldField
+ } else {
+ old[k] = newField
+ }
+ }
+
+ return old
+}
+
+func combineArrays(old, new []any) []any {
+ containsNonStrings := false
+ for _, oldElement := range old {
+ switch oldElement.(type) {
+ case string:
+ default:
+ containsNonStrings = true
+ }
+ }
+ for _, newElement := range new {
+ found := false
+ for _, oldElement := range old {
+ if oldElement == newElement {
+ found = true
+ break
+ }
+ }
+ if !found {
+ switch newElement.(type) {
+ case string:
+ default:
+ containsNonStrings = true
+ }
+ old = append(old, newElement)
+ }
+ }
+ if !containsNonStrings {
+ slices.SortFunc(old, func(a, b any) int {
+ return cmp.Compare(a.(string), b.(string))
+ })
+ }
+ return old
+}
diff --git a/cmd/merge_module_info_json/merge_module_info_json_test.go b/cmd/merge_module_info_json/merge_module_info_json_test.go
new file mode 100644
index 0000000..dbf1aa1
--- /dev/null
+++ b/cmd/merge_module_info_json/merge_module_info_json_test.go
@@ -0,0 +1,58 @@
+// Copyright 2021 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+ "reflect"
+ "testing"
+)
+
+func Test_combine(t *testing.T) {
+ tests := []struct {
+ name string
+ old any
+ new any
+ want any
+ }{
+ {
+ name: "objects",
+ old: map[string]any{
+ "foo": "bar",
+ "baz": []any{"a"},
+ },
+ new: map[string]any{
+ "foo": "bar",
+ "baz": []any{"b"},
+ },
+ want: map[string]any{
+ "foo": "bar",
+ "baz": []any{"a", "b"},
+ },
+ },
+ {
+ name: "arrays",
+ old: []any{"foo", "bar"},
+ new: []any{"foo", "baz"},
+ want: []any{"bar", "baz", "foo"},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if got := combine(tt.old, tt.new); !reflect.DeepEqual(got, tt.want) {
+ t.Errorf("combine() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
diff --git a/rust/fuzz.go b/rust/fuzz.go
index bacfa2d..1770d2e 100644
--- a/rust/fuzz.go
+++ b/rust/fuzz.go
@@ -142,12 +142,12 @@
fuzz.installedSharedDeps = append(fuzz.installedSharedDeps,
cc.SharedLibraryInstallLocation(
- install, ctx.Host(), installBase, ctx.Arch().ArchType.String()))
+ install, ctx.Host(), ctx.InstallInVendor(), installBase, ctx.Arch().ArchType.String()))
// Also add the dependency on the shared library symbols dir.
if !ctx.Host() {
fuzz.installedSharedDeps = append(fuzz.installedSharedDeps,
- cc.SharedLibrarySymbolsInstallLocation(install, installBase, ctx.Arch().ArchType.String()))
+ cc.SharedLibrarySymbolsInstallLocation(install, ctx.InstallInVendor(), installBase, ctx.Arch().ArchType.String()))
}
}
diff --git a/ui/build/Android.bp b/ui/build/Android.bp
index 21453ba..ee286f6 100644
--- a/ui/build/Android.bp
+++ b/ui/build/Android.bp
@@ -35,6 +35,7 @@
"blueprint",
"blueprint-bootstrap",
"blueprint-microfactory",
+ "soong-android",
"soong-finder",
"soong-remoteexec",
"soong-shared",
@@ -46,6 +47,7 @@
"soong-ui-tracer",
],
srcs: [
+ "androidmk_denylist.go",
"build.go",
"cleanbuild.go",
"config.go",
diff --git a/ui/build/androidmk_denylist.go b/ui/build/androidmk_denylist.go
new file mode 100644
index 0000000..b2266b2
--- /dev/null
+++ b/ui/build/androidmk_denylist.go
@@ -0,0 +1,44 @@
+// Copyright 2024 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package build
+
+import (
+ "strings"
+
+ "android/soong/android"
+)
+
+var androidmk_denylist []string = []string{
+ "chained_build_config/",
+ "cts/",
+ "dalvik/",
+ "developers/",
+ "kernel/",
+ "libcore/",
+ "libnativehelper/",
+ "pdk/",
+ "toolchain/",
+}
+
+func blockAndroidMks(androidMks []string) []string {
+ return android.FilterListPred(androidMks, func(s string) bool {
+ for _, d := range androidmk_denylist {
+ if strings.HasPrefix(s, d) {
+ return false
+ }
+ }
+ return true
+ })
+}
diff --git a/ui/build/finder.go b/ui/build/finder.go
index d0bcf40..a114079 100644
--- a/ui/build/finder.go
+++ b/ui/build/finder.go
@@ -128,6 +128,7 @@
// Stop searching a subdirectory recursively after finding an Android.mk.
androidMks := f.FindFirstNamedAt(".", "Android.mk")
+ androidMks = blockAndroidMks(androidMks)
err := dumpListToFile(ctx, config, androidMks, filepath.Join(dumpDir, "Android.mk.list"))
if err != nil {
ctx.Fatalf("Could not export module list: %v", err)