Merge "Support aapt2 resources flagging" into main
diff --git a/android/module.go b/android/module.go
index dd56031..98cd459 100644
--- a/android/module.go
+++ b/android/module.go
@@ -2504,8 +2504,9 @@
} else if cta, isCta := ctx.(*singletonContextAdaptor); isCta {
providerData, _ := cta.moduleProvider(module, OutputFilesProvider)
outputFiles, _ = providerData.(OutputFilesInfo)
+ } else {
+ return nil, fmt.Errorf("unsupported context %q in method outputFilesForModuleFromProvider", reflect.TypeOf(ctx))
}
- // TODO: Add a check for skipped context
if outputFiles.isEmpty() {
return nil, OutputFilesProviderNotSet
diff --git a/android/variable.go b/android/variable.go
index d144f7d..3b02bc7 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -132,9 +132,11 @@
Keep_symbols *bool
Keep_symbols_and_debug_frame *bool
}
- Static_libs []string
- Whole_static_libs []string
- Shared_libs []string
+ Static_libs []string
+ Exclude_static_libs []string
+ Whole_static_libs []string
+ Shared_libs []string
+ Jni_libs []string
Cmdline []string
diff --git a/apex/apex.go b/apex/apex.go
index 10fe372..f9b30d4 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -2663,12 +2663,20 @@
})
}
+// TODO (b/221087384): Remove this allowlist
+var (
+ updatableApexesWithCurrentMinSdkVersionAllowlist = []string{"com.android.profiling"}
+)
+
// checkUpdatable enforces APEX and its transitive dep properties to have desired values for updatable APEXes.
func (a *apexBundle) checkUpdatable(ctx android.ModuleContext) {
if a.Updatable() {
if a.minSdkVersionValue(ctx) == "" {
ctx.PropertyErrorf("updatable", "updatable APEXes should set min_sdk_version as well")
}
+ if a.minSdkVersion(ctx).IsCurrent() && !android.InList(ctx.ModuleName(), updatableApexesWithCurrentMinSdkVersionAllowlist) {
+ ctx.PropertyErrorf("updatable", "updatable APEXes should not set min_sdk_version to current. Please use a finalized API level or a recognized in-development codename")
+ }
if a.UsePlatformApis() {
ctx.PropertyErrorf("updatable", "updatable APEXes can't use platform APIs")
}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 15c713b..a2dbbfc 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -11721,3 +11721,20 @@
java.CheckModuleHasDependency(t, res.TestContext, "myoverrideapex", "android_common_myoverrideapex_myoverrideapex", "foo")
}
+
+func TestUpdatableApexMinSdkVersionCurrent(t *testing.T) {
+ testApexError(t, `"myapex" .*: updatable: updatable APEXes should not set min_sdk_version to current. Please use a finalized API level or a recognized in-development codename`, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ updatable: true,
+ min_sdk_version: "current",
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+ `)
+}
diff --git a/cc/cc.go b/cc/cc.go
index 740be3a..d307be6 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -1867,8 +1867,10 @@
"libdl": true,
"libz": true,
// art apex
+ // TODO(b/234351700): Remove this when com.android.art.debug is gone.
"libandroidio": true,
"libdexfile": true,
+ "libdexfiled": true, // com.android.art.debug only
"libnativebridge": true,
"libnativehelper": true,
"libnativeloader": true,
diff --git a/cc/ccdeps.go b/cc/ccdeps.go
index d30abba..469fe31 100644
--- a/cc/ccdeps.go
+++ b/cc/ccdeps.go
@@ -85,9 +85,8 @@
moduleDeps := ccDeps{}
moduleInfos := map[string]ccIdeInfo{}
- // Track which projects have already had CMakeLists.txt generated to keep the first
- // variant for each project.
- seenProjects := map[string]bool{}
+ // Track if best variant (device arch match) has been found.
+ bestVariantFound := map[string]bool{}
pathToCC, _ := evalVariable(ctx, "${config.ClangBin}/")
moduleDeps.C_clang = fmt.Sprintf("%s%s", buildCMakePath(pathToCC), cClang)
@@ -96,7 +95,7 @@
ctx.VisitAllModules(func(module android.Module) {
if ccModule, ok := module.(*Module); ok {
if compiledModule, ok := ccModule.compiler.(CompiledInterface); ok {
- generateCLionProjectData(ctx, compiledModule, ccModule, seenProjects, moduleInfos)
+ generateCLionProjectData(ctx, compiledModule, ccModule, bestVariantFound, moduleInfos)
}
}
})
@@ -180,26 +179,30 @@
}
func generateCLionProjectData(ctx android.SingletonContext, compiledModule CompiledInterface,
- ccModule *Module, seenProjects map[string]bool, moduleInfos map[string]ccIdeInfo) {
+ ccModule *Module, bestVariantFound map[string]bool, moduleInfos map[string]ccIdeInfo) {
+ moduleName := ccModule.ModuleBase.Name()
srcs := compiledModule.Srcs()
+
+ // Skip if best variant has already been found.
+ if bestVariantFound[moduleName] {
+ return
+ }
+
+ // Skip if sources are empty.
if len(srcs) == 0 {
return
}
- // Only keep the DeviceArch variant module.
- if ctx.DeviceConfig().DeviceArch() != ccModule.ModuleBase.Arch().ArchType.Name {
+ // Check if device arch matches, in which case this is the best variant and takes precedence.
+ if ccModule.Device() && ccModule.ModuleBase.Arch().ArchType.Name == ctx.DeviceConfig().DeviceArch() {
+ bestVariantFound[moduleName] = true
+ } else if _, ok := moduleInfos[moduleName]; ok {
+ // Skip because this isn't the best variant and a previous one has already been added.
+ // Heuristically, ones that appear first are likely to be more relevant.
return
}
- clionProjectLocation := getCMakeListsForModule(ccModule, ctx)
- if seenProjects[clionProjectLocation] {
- return
- }
-
- seenProjects[clionProjectLocation] = true
-
- name := ccModule.ModuleBase.Name()
- dpInfo := moduleInfos[name]
+ dpInfo := ccIdeInfo{}
dpInfo.Path = append(dpInfo.Path, path.Dir(ctx.BlueprintFile(ccModule)))
dpInfo.Srcs = append(dpInfo.Srcs, srcs.Strings()...)
@@ -216,9 +219,9 @@
dpInfo.Local_Cpp_flags = parseCompilerCCParameters(ctx, ccModule.flags.Local.CppFlags)
dpInfo.System_include_flags = parseCompilerCCParameters(ctx, ccModule.flags.SystemIncludeFlags)
- dpInfo.Module_name = name
+ dpInfo.Module_name = moduleName
- moduleInfos[name] = dpInfo
+ moduleInfos[moduleName] = dpInfo
}
type Deal struct {
diff --git a/cc/config/global.go b/cc/config/global.go
index 62a4765..bf2502f 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -397,8 +397,8 @@
// prebuilts/clang default settings.
ClangDefaultBase = "prebuilts/clang/host"
- ClangDefaultVersion = "clang-r522817"
- ClangDefaultShortVersion = "18"
+ ClangDefaultVersion = "clang-r530567"
+ ClangDefaultShortVersion = "19"
// Directories with warnings from Android.bp files.
WarningAllowedProjects = []string{
diff --git a/cmd/release_config/release_config_lib/flag_declaration.go b/cmd/release_config/release_config_lib/flag_declaration.go
index 97d4d4c..22001bf 100644
--- a/cmd/release_config/release_config_lib/flag_declaration.go
+++ b/cmd/release_config/release_config_lib/flag_declaration.go
@@ -18,10 +18,21 @@
rc_proto "android/soong/cmd/release_config/release_config_proto"
)
+var (
+ // Allowlist: these flags may have duplicate (identical) declarations
+ // without generating an error. This will be removed once all such
+ // declarations have been fixed.
+ DuplicateDeclarationAllowlist = map[string]bool{}
+)
+
func FlagDeclarationFactory(protoPath string) (fd *rc_proto.FlagDeclaration) {
fd = &rc_proto.FlagDeclaration{}
if protoPath != "" {
LoadMessage(protoPath, fd)
}
+ // If the input didn't specify a value, create one (== UnspecifiedValue).
+ if fd.Value == nil {
+ fd.Value = &rc_proto.Value{Val: &rc_proto.Value_UnspecifiedValue{false}}
+ }
return fd
}
diff --git a/cmd/release_config/release_config_lib/release_configs.go b/cmd/release_config/release_config_lib/release_configs.go
index f2e1388..97eb8f1 100644
--- a/cmd/release_config/release_config_lib/release_configs.go
+++ b/cmd/release_config/release_config_lib/release_configs.go
@@ -42,6 +42,10 @@
// Flags declared this directory's flag_declarations/*.textproto
FlagDeclarations []rc_proto.FlagDeclaration
+
+ // Potential aconfig and build flag contributions in this map directory.
+ // This is used to detect errors.
+ FlagValueDirs map[string][]string
}
type ReleaseConfigDirMap map[string]int
@@ -272,6 +276,20 @@
configs.Aliases[name] = alias.Target
}
var err error
+ // Temporarily allowlist duplicate flag declaration files to prevent
+ // more from entering the tree while we work to clean up the duplicates
+ // that already exist.
+ dupFlagFile := filepath.Join(dir, "duplicate_allowlist.txt")
+ data, err := os.ReadFile(dupFlagFile)
+ if err == nil {
+ for _, flag := range strings.Split(string(data), "\n") {
+ flag = strings.TrimSpace(flag)
+ if strings.HasPrefix(flag, "//") || strings.HasPrefix(flag, "#") {
+ continue
+ }
+ DuplicateDeclarationAllowlist[flag] = true
+ }
+ }
err = WalkTextprotoFiles(dir, "flag_declarations", func(path string, d fs.DirEntry, err error) error {
flagDeclaration := FlagDeclarationFactory(path)
// Container must be specified.
@@ -285,14 +303,6 @@
}
}
- // TODO: once we have namespaces initialized, we can throw an error here.
- if flagDeclaration.Namespace == nil {
- flagDeclaration.Namespace = proto.String("android_UNKNOWN")
- }
- // If the input didn't specify a value, create one (== UnspecifiedValue).
- if flagDeclaration.Value == nil {
- flagDeclaration.Value = &rc_proto.Value{Val: &rc_proto.Value_UnspecifiedValue{false}}
- }
m.FlagDeclarations = append(m.FlagDeclarations, *flagDeclaration)
name := *flagDeclaration.Name
if name == "RELEASE_ACONFIG_VALUE_SETS" {
@@ -300,8 +310,8 @@
}
if def, ok := configs.FlagArtifacts[name]; !ok {
configs.FlagArtifacts[name] = &FlagArtifact{FlagDeclaration: flagDeclaration, DeclarationIndex: ConfigDirIndex}
- } else if !proto.Equal(def.FlagDeclaration, flagDeclaration) {
- return fmt.Errorf("Duplicate definition of %s", *flagDeclaration.Name)
+ } else if !proto.Equal(def.FlagDeclaration, flagDeclaration) || !DuplicateDeclarationAllowlist[name] {
+ return fmt.Errorf("Duplicate definition of %s in %s", *flagDeclaration.Name, path)
}
// Set the initial value in the flag artifact.
configs.FilesUsedMap[path] = true
@@ -317,6 +327,21 @@
return err
}
+ subDirs := func(subdir string) (ret []string) {
+ if flagVersions, err := os.ReadDir(filepath.Join(dir, subdir)); err == nil {
+ for _, e := range flagVersions {
+ if e.IsDir() && validReleaseConfigName(e.Name()) {
+ ret = append(ret, e.Name())
+ }
+ }
+ }
+ return
+ }
+ m.FlagValueDirs = map[string][]string{
+ "aconfig": subDirs("aconfig"),
+ "flag_values": subDirs("flag_values"),
+ }
+
err = WalkTextprotoFiles(dir, "release_configs", func(path string, d fs.DirEntry, err error) error {
releaseConfigContribution := &ReleaseConfigContribution{path: path, DeclarationIndex: ConfigDirIndex}
LoadMessage(path, &releaseConfigContribution.proto)
@@ -424,6 +449,27 @@
}
}
+ // Look for ignored flagging values. Gather the entire list to make it easier to fix them.
+ errors := []string{}
+ for _, contrib := range configs.ReleaseConfigMaps {
+ dirName := filepath.Dir(contrib.path)
+ for k, names := range contrib.FlagValueDirs {
+ for _, rcName := range names {
+ if config, err := configs.GetReleaseConfig(rcName); err == nil {
+ rcPath := filepath.Join(dirName, "release_configs", fmt.Sprintf("%s.textproto", config.Name))
+ if _, err := os.Stat(rcPath); err != nil {
+ errors = append(errors, fmt.Sprintf("%s exists but %s does not contribute to %s",
+ filepath.Join(dirName, k, rcName), dirName, config.Name))
+ }
+ }
+
+ }
+ }
+ }
+ if len(errors) > 0 {
+ return fmt.Errorf("%s", strings.Join(errors, "\n"))
+ }
+
releaseConfig, err := configs.GetReleaseConfig(targetRelease)
if err != nil {
return err
diff --git a/cmd/release_config/release_config_lib/util.go b/cmd/release_config/release_config_lib/util.go
index 9919c70..b149293 100644
--- a/cmd/release_config/release_config_lib/util.go
+++ b/cmd/release_config/release_config_lib/util.go
@@ -31,8 +31,9 @@
)
var (
- disableWarnings bool
- containerRegexp, _ = regexp.Compile("^[a-z][a-z0-9]*([._][a-z][a-z0-9]*)*$")
+ disableWarnings bool
+ containerRegexp, _ = regexp.Compile("^[a-z][a-z0-9]*([._][a-z][a-z0-9]*)*$")
+ releaseConfigRegexp, _ = regexp.Compile("^[a-z][a-z0-9]*([._][a-z0-9]*)*$")
)
type StringList []string
@@ -179,6 +180,10 @@
return containerRegexp.MatchString(container)
}
+func validReleaseConfigName(name string) bool {
+ return releaseConfigRegexp.MatchString(name)
+}
+
// Returns the default value for release config artifacts.
func GetDefaultOutDir() string {
outEnv := os.Getenv("OUT_DIR")
diff --git a/elf/Android.bp b/elf/Android.bp
index 6450be1..6d3f4f0 100644
--- a/elf/Android.bp
+++ b/elf/Android.bp
@@ -20,6 +20,7 @@
name: "soong-elf",
pkgPath: "android/soong/elf",
srcs: [
+ "build_id_dir.go",
"elf.go",
],
testSrcs: [
diff --git a/elf/build_id_dir.go b/elf/build_id_dir.go
new file mode 100644
index 0000000..5fb7dda
--- /dev/null
+++ b/elf/build_id_dir.go
@@ -0,0 +1,172 @@
+// 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 elf
+
+import (
+ "io/fs"
+ "os"
+ "path/filepath"
+ "strings"
+ "sync"
+ "time"
+)
+
+func UpdateBuildIdDir(path string) error {
+ path = filepath.Clean(path)
+ buildIdPath := path + "/.build-id"
+
+ // Collect the list of files and build-id symlinks. If the symlinks are
+ // up to date (newer than the symbol files), there is nothing to do.
+ var buildIdFiles, symbolFiles []string
+ var buildIdMtime, symbolsMtime time.Time
+ filepath.WalkDir(path, func(path string, entry fs.DirEntry, err error) error {
+ if entry == nil || entry.IsDir() {
+ return nil
+ }
+ info, err := entry.Info()
+ if err != nil {
+ return err
+ }
+ mtime := info.ModTime()
+ if strings.HasPrefix(path, buildIdPath) {
+ if buildIdMtime.Compare(mtime) < 0 {
+ buildIdMtime = mtime
+ }
+ buildIdFiles = append(buildIdFiles, path)
+ } else {
+ if symbolsMtime.Compare(mtime) < 0 {
+ symbolsMtime = mtime
+ }
+ symbolFiles = append(symbolFiles, path)
+ }
+ return nil
+ })
+ if symbolsMtime.Compare(buildIdMtime) < 0 {
+ return nil
+ }
+
+ // Collect build-id -> file mapping from ELF files in the symbols directory.
+ concurrency := 8
+ done := make(chan error)
+ buildIdToFile := make(map[string]string)
+ var mu sync.Mutex
+ for i := 0; i != concurrency; i++ {
+ go func(paths []string) {
+ for _, path := range paths {
+ id, err := Identifier(path, true)
+ if err != nil {
+ done <- err
+ return
+ }
+ if id == "" {
+ continue
+ }
+ mu.Lock()
+ oldPath := buildIdToFile[id]
+ if oldPath == "" || oldPath > path {
+ buildIdToFile[id] = path
+ }
+ mu.Unlock()
+ }
+ done <- nil
+ }(symbolFiles[len(symbolFiles)*i/concurrency : len(symbolFiles)*(i+1)/concurrency])
+ }
+
+ // Collect previously generated build-id -> file mapping from the .build-id directory.
+ // We will use this for incremental updates. If we see anything in the .build-id
+ // directory that we did not expect, we'll delete it and start over.
+ prevBuildIdToFile := make(map[string]string)
+out:
+ for _, buildIdFile := range buildIdFiles {
+ if !strings.HasSuffix(buildIdFile, ".debug") {
+ prevBuildIdToFile = nil
+ break
+ }
+ buildId := buildIdFile[len(buildIdPath)+1 : len(buildIdFile)-6]
+ for i, ch := range buildId {
+ if i == 2 {
+ if ch != '/' {
+ prevBuildIdToFile = nil
+ break out
+ }
+ } else {
+ if (ch < '0' || ch > '9') && (ch < 'a' || ch > 'f') {
+ prevBuildIdToFile = nil
+ break out
+ }
+ }
+ }
+ target, err := os.Readlink(buildIdFile)
+ if err != nil || !strings.HasPrefix(target, "../../") {
+ prevBuildIdToFile = nil
+ break
+ }
+ prevBuildIdToFile[buildId[0:2]+buildId[3:]] = path + target[5:]
+ }
+ if prevBuildIdToFile == nil {
+ err := os.RemoveAll(buildIdPath)
+ if err != nil {
+ return err
+ }
+ prevBuildIdToFile = make(map[string]string)
+ }
+
+ // Wait for build-id collection from ELF files to finish.
+ for i := 0; i != concurrency; i++ {
+ err := <-done
+ if err != nil {
+ return err
+ }
+ }
+
+ // Delete old symlinks.
+ for id, _ := range prevBuildIdToFile {
+ if buildIdToFile[id] == "" {
+ symlinkDir := buildIdPath + "/" + id[:2]
+ symlinkPath := symlinkDir + "/" + id[2:] + ".debug"
+ if err := os.Remove(symlinkPath); err != nil {
+ return err
+ }
+ }
+ }
+
+ // Add new symlinks and update changed symlinks.
+ for id, path := range buildIdToFile {
+ prevPath := prevBuildIdToFile[id]
+ if prevPath == path {
+ continue
+ }
+ symlinkDir := buildIdPath + "/" + id[:2]
+ symlinkPath := symlinkDir + "/" + id[2:] + ".debug"
+ if prevPath == "" {
+ if err := os.MkdirAll(symlinkDir, 0755); err != nil {
+ return err
+ }
+ } else {
+ if err := os.Remove(symlinkPath); err != nil {
+ return err
+ }
+ }
+
+ target, err := filepath.Rel(symlinkDir, path)
+ if err != nil {
+ return err
+ }
+ if err := os.Symlink(target, symlinkPath); err != nil {
+ return err
+ }
+ }
+ return nil
+}
diff --git a/rust/test.go b/rust/test.go
index 3087d8d..b7ddd06 100644
--- a/rust/test.go
+++ b/rust/test.go
@@ -116,7 +116,8 @@
}
func (test *testDecorator) install(ctx ModuleContext) {
- testInstallBase := "/data/local/tests/unrestricted"
+ // TODO: (b/167308193) Switch to /data/local/tests/unrestricted as the default install base.
+ testInstallBase := "/data/local/tmp"
if ctx.RustModule().InVendorOrProduct() {
testInstallBase = "/data/local/tests/vendor"
}
diff --git a/ui/build/Android.bp b/ui/build/Android.bp
index ee286f6..fcf29c5 100644
--- a/ui/build/Android.bp
+++ b/ui/build/Android.bp
@@ -36,6 +36,7 @@
"blueprint-bootstrap",
"blueprint-microfactory",
"soong-android",
+ "soong-elf",
"soong-finder",
"soong-remoteexec",
"soong-shared",
diff --git a/ui/build/build.go b/ui/build/build.go
index 03d8392..c7319ed 100644
--- a/ui/build/build.go
+++ b/ui/build/build.go
@@ -22,6 +22,7 @@
"sync"
"text/template"
+ "android/soong/elf"
"android/soong/ui/metrics"
)
@@ -344,6 +345,7 @@
installCleanIfNecessary(ctx, config)
}
runNinjaForBuild(ctx, config)
+ updateBuildIdDir(ctx, config)
}
if what&RunDistActions != 0 {
@@ -351,6 +353,16 @@
}
}
+func updateBuildIdDir(ctx Context, config Config) {
+ ctx.BeginTrace(metrics.RunShutdownTool, "update_build_id_dir")
+ defer ctx.EndTrace()
+
+ symbolsDir := filepath.Join(config.ProductOut(), "symbols")
+ if err := elf.UpdateBuildIdDir(symbolsDir); err != nil {
+ ctx.Printf("failed to update %s/.build-id: %v", symbolsDir, err)
+ }
+}
+
func evaluateWhatToRun(config Config, verboseln func(v ...interface{})) int {
//evaluate what to run
what := 0