Merge changes I0918f2fa,I3fc6ff91,I7adc97cb,I674a5fa1,I22c45cbf into main
* changes:
Change the profile path on host.
Extract duplicate code to common helper functions.
Fix dumpOatRules.
Remove Modules() from BootclasspathFragmentApexContentInfo.
Fix some tests for dexpreopt and remove unnecessary tests.
diff --git a/android/arch.go b/android/arch.go
index 4b4691b..152016c 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -1884,10 +1884,10 @@
buildTargets = filterMultilibTargets(targets, "lib64")
// Reverse the targets so that the first architecture can depend on the second
// architecture module in order to merge the outputs.
- reverseSliceInPlace(buildTargets)
+ ReverseSliceInPlace(buildTargets)
case "darwin_universal_common_first":
archTargets := filterMultilibTargets(targets, "lib64")
- reverseSliceInPlace(archTargets)
+ ReverseSliceInPlace(archTargets)
buildTargets = append(getCommonTargets(targets), archTargets...)
default:
return nil, fmt.Errorf(`compile_multilib must be "both", "first", "32", "64", "prefer32" or "first_prefer32" found %q`,
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index d5ccfca..5d93f06 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -1270,6 +1270,12 @@
// because this would cause circular dependency. So, until we move aquery processing
// to the 'android' package, we need to handle special cases here.
switch buildStatement.Mnemonic {
+ case "RepoMappingManifest":
+ // It appears RepoMappingManifest files currently have
+ // non-deterministic content. Just emit empty files for
+ // now because they're unused.
+ out := PathForBazelOut(ctx, buildStatement.OutputPaths[0])
+ WriteFileRuleVerbatim(ctx, out, "")
case "FileWrite", "SourceSymlinkManifest":
out := PathForBazelOut(ctx, buildStatement.OutputPaths[0])
WriteFileRuleVerbatim(ctx, out, buildStatement.FileContents)
diff --git a/android/config.go b/android/config.go
index 839ff05..fa43962 100644
--- a/android/config.go
+++ b/android/config.go
@@ -701,6 +701,10 @@
if c.productVariables.DeviceArch != nil && *c.productVariables.DeviceArch == "riscv64" {
return false
}
+ // Disable Bazel when Kythe is running
+ if c.EmitXrefRules() {
+ return false
+ }
if c.IsEnvTrue("GLOBAL_THINLTO") {
return false
}
diff --git a/android/depset_generic.go b/android/depset_generic.go
index ae14d32..45c1937 100644
--- a/android/depset_generic.go
+++ b/android/depset_generic.go
@@ -79,8 +79,8 @@
if order == TOPOLOGICAL {
// TOPOLOGICAL is implemented as a postorder traversal followed by reversing the output.
// Pre-reverse the inputs here so their order is maintained in the output.
- directCopy = reverseSlice(direct)
- transitiveCopy = reverseSlice(transitive)
+ directCopy = ReverseSlice(direct)
+ transitiveCopy = ReverseSlice(transitive)
} else {
directCopy = append([]T(nil), direct...)
transitiveCopy = append([]*DepSet[T](nil), transitive...)
@@ -175,16 +175,6 @@
// its transitive dependencies, in which case the ordering of the duplicated element is not
// guaranteed).
func (d *DepSet[T]) ToList() []T {
- return d.toList(firstUnique[T])
-}
-
-// toList returns the DepSet flattened to a list. The order in the list is based on the order
-// of the DepSet. POSTORDER and PREORDER orders return a postordered or preordered left to right
-// flattened list. TOPOLOGICAL returns a list that guarantees that elements of children are listed
-// after all of their parents (unless there are duplicate direct elements in the DepSet or any of
-// its transitive dependencies, in which case the ordering of the duplicated element is not
-// guaranteed). The firstUniqueFunc is used to remove duplicates from the list.
-func (d *DepSet[T]) toList(firstUniqueFunc func([]T) []T) []T {
if d == nil {
return nil
}
@@ -192,9 +182,9 @@
d.walk(func(paths []T) {
list = append(list, paths...)
})
- list = firstUniqueFunc(list)
+ list = firstUniqueInPlace(list)
if d.reverse {
- reverseSliceInPlace(list)
+ ReverseSliceInPlace(list)
}
return list
}
diff --git a/android/util.go b/android/util.go
index 9695454..e17d7b2 100644
--- a/android/util.go
+++ b/android/util.go
@@ -25,12 +25,12 @@
)
// CopyOf returns a new slice that has the same contents as s.
-func CopyOf(s []string) []string {
+func CopyOf[T any](s []T) []T {
// If the input is nil, return nil and not an empty list
if s == nil {
return s
}
- return append([]string{}, s...)
+ return append([]T{}, s...)
}
// Concat returns a new slice concatenated from the two input slices. It does not change the input
@@ -288,22 +288,25 @@
}
// FirstUniqueStrings returns all unique elements of a slice of strings, keeping the first copy of
-// each. It modifies the slice contents in place, and returns a subslice of the original slice.
+// each. It does not modify the input slice.
func FirstUniqueStrings(list []string) []string {
- // Do not moodify the input in-place, operate on a copy instead.
- list = CopyOf(list)
- // 128 was chosen based on BenchmarkFirstUniqueStrings results.
- if len(list) > 128 {
- return firstUnique(list)
- }
return firstUnique(list)
}
// firstUnique returns all unique elements of a slice, keeping the first copy of each. It
-// modifies the slice contents in place, and returns a subslice of the original slice.
+// does not modify the input slice.
func firstUnique[T comparable](slice []T) []T {
- // 4 was chosen based on Benchmark_firstUnique results.
- if len(slice) > 4 {
+ // Do not modify the input in-place, operate on a copy instead.
+ slice = CopyOf(slice)
+ return firstUniqueInPlace(slice)
+}
+
+// firstUniqueInPlace returns all unique elements of a slice, keeping the first copy of
+// each. It modifies the slice contents in place, and returns a subslice of the original
+// slice.
+func firstUniqueInPlace[T comparable](slice []T) []T {
+ // 128 was chosen based on BenchmarkFirstUniqueStrings results.
+ if len(slice) > 128 {
return firstUniqueMap(slice)
}
return firstUniqueList(slice)
@@ -348,15 +351,19 @@
return in[0:writeIndex]
}
-// reverseSliceInPlace reverses the elements of a slice in place.
-func reverseSliceInPlace[T any](in []T) {
+// ReverseSliceInPlace reverses the elements of a slice in place and returns it.
+func ReverseSliceInPlace[T any](in []T) []T {
for i, j := 0, len(in)-1; i < j; i, j = i+1, j-1 {
in[i], in[j] = in[j], in[i]
}
+ return in
}
-// reverseSlice returns a copy of a slice in reverse order.
-func reverseSlice[T any](in []T) []T {
+// ReverseSlice returns a copy of a slice in reverse order.
+func ReverseSlice[T any](in []T) []T {
+ if in == nil {
+ return in
+ }
out := make([]T, len(in))
for i := 0; i < len(in); i++ {
out[i] = in[len(in)-1-i]
diff --git a/android/util_test.go b/android/util_test.go
index bee31a9..20161e5 100644
--- a/android/util_test.go
+++ b/android/util_test.go
@@ -20,6 +20,7 @@
"strconv"
"strings"
"testing"
+ "unsafe"
)
var firstUniqueStringsTestCases = []struct {
@@ -385,7 +386,7 @@
emptyList := []string{}
copyOfEmptyList := CopyOf(emptyList)
AssertBoolEquals(t, "Copy of an empty list should be an empty list and not nil", true, copyOfEmptyList != nil)
- copyOfNilList := CopyOf(nil)
+ copyOfNilList := CopyOf([]string(nil))
AssertBoolEquals(t, "Copy of a nil list should be a nil list and not an empty list", true, copyOfNilList == nil)
}
@@ -754,3 +755,65 @@
})
}
}
+
+var reverseTestCases = []struct {
+ name string
+ in []string
+ expected []string
+}{
+ {
+ name: "nil",
+ in: nil,
+ expected: nil,
+ },
+ {
+ name: "empty",
+ in: []string{},
+ expected: []string{},
+ },
+ {
+ name: "one",
+ in: []string{"one"},
+ expected: []string{"one"},
+ },
+ {
+ name: "even",
+ in: []string{"one", "two"},
+ expected: []string{"two", "one"},
+ },
+ {
+ name: "odd",
+ in: []string{"one", "two", "three"},
+ expected: []string{"three", "two", "one"},
+ },
+}
+
+func TestReverseSliceInPlace(t *testing.T) {
+ for _, testCase := range reverseTestCases {
+ t.Run(testCase.name, func(t *testing.T) {
+ slice := CopyOf(testCase.in)
+ slice2 := slice
+ ReverseSliceInPlace(slice)
+ if !reflect.DeepEqual(slice, testCase.expected) {
+ t.Errorf("expected %#v, got %#v", testCase.expected, slice)
+ }
+ if unsafe.SliceData(slice) != unsafe.SliceData(slice2) {
+ t.Errorf("expected slices to share backing array")
+ }
+ })
+ }
+}
+
+func TestReverseSlice(t *testing.T) {
+ for _, testCase := range reverseTestCases {
+ t.Run(testCase.name, func(t *testing.T) {
+ slice := ReverseSlice(testCase.in)
+ if !reflect.DeepEqual(slice, testCase.expected) {
+ t.Errorf("expected %#v, got %#v", testCase.expected, slice)
+ }
+ if slice != nil && unsafe.SliceData(testCase.in) == unsafe.SliceData(slice) {
+ t.Errorf("expected slices to have different backing arrays")
+ }
+ })
+ }
+}
diff --git a/android_sdk/sdk_repo_host.go b/android_sdk/sdk_repo_host.go
index 9623a8b..7212a07 100644
--- a/android_sdk/sdk_repo_host.go
+++ b/android_sdk/sdk_repo_host.go
@@ -166,7 +166,7 @@
}
} else {
llvmStrip := config.ClangPath(ctx, "bin/llvm-strip")
- llvmLib := config.ClangPath(ctx, "lib/x86_64-unknown-linux-gnu/libc++.so.1")
+ llvmLib := config.ClangPath(ctx, "lib/x86_64-unknown-linux-gnu/libc++.so")
for _, strip := range s.properties.Strip_files {
cmd := builder.Command().Tool(llvmStrip).ImplicitTool(llvmLib)
if !ctx.Windows() {
diff --git a/bazel/aquery.go b/bazel/aquery.go
index 95e52ae..480158c 100644
--- a/bazel/aquery.go
+++ b/bazel/aquery.go
@@ -677,7 +677,7 @@
if len(actionEntry.Arguments) < 1 {
return a.templateExpandActionBuildStatement(actionEntry)
}
- case "FileWrite", "SourceSymlinkManifest":
+ case "FileWrite", "SourceSymlinkManifest", "RepoMappingManifest":
return a.fileWriteActionBuildStatement(actionEntry)
case "SymlinkTree":
return a.symlinkTreeActionBuildStatement(actionEntry)
diff --git a/bp2build/android_app_conversion_test.go b/bp2build/android_app_conversion_test.go
index 7f7aa6a..d1b4d40 100644
--- a/bp2build/android_app_conversion_test.go
+++ b/bp2build/android_app_conversion_test.go
@@ -349,7 +349,7 @@
}})
}
-func TestAndroidAppMinSdkProvided(t *testing.T) {
+func TestAndroidAppManifestSdkVersionsProvided(t *testing.T) {
runAndroidAppTestCase(t, Bp2buildTestCase{
Description: "Android app with value for min_sdk_version",
ModuleTypeUnderTest: "android_app",
@@ -359,7 +359,9 @@
android_app {
name: "foo",
sdk_version: "current",
- min_sdk_version: "24",
+ min_sdk_version: "24",
+ max_sdk_version: "30",
+ target_sdk_version: "29",
}
`,
ExpectedBazelTargets: []string{
@@ -367,14 +369,16 @@
"manifest": `"AndroidManifest.xml"`,
"resource_files": `[]`,
"manifest_values": `{
+ "maxSdkVersion": "30",
"minSdkVersion": "24",
+ "targetSdkVersion": "29",
}`,
"sdk_version": `"current"`,
}),
}})
}
-func TestAndroidAppMinSdkDefaultToSdkVersion(t *testing.T) {
+func TestAndroidAppMinAndTargetSdkDefaultToSdkVersion(t *testing.T) {
runAndroidAppTestCase(t, Bp2buildTestCase{
Description: "Android app with value for sdk_version",
ModuleTypeUnderTest: "android_app",
@@ -392,6 +396,7 @@
"resource_files": `[]`,
"manifest_values": `{
"minSdkVersion": "30",
+ "targetSdkVersion": "30",
}`,
"sdk_version": `"30"`,
}),
diff --git a/build_kzip.bash b/build_kzip.bash
index eeef7d4..4c42048 100755
--- a/build_kzip.bash
+++ b/build_kzip.bash
@@ -35,8 +35,16 @@
# sufficiently many files were generated.
declare -r out="${OUT_DIR:-out}"
-# Build extraction files for C++ and Java. Build `merge_zips` which we use later.
-build/soong/soong_ui.bash --build-mode --all-modules --dir=$PWD -k merge_zips xref_cxx xref_java xref_rust
+# Build extraction files and `merge_zips` which we use later.
+kzip_targets=(
+ merge_zips
+ xref_cxx
+ xref_java
+ # TODO: b/286390153 - reenable rust
+ # xref_rust
+)
+
+build/soong/soong_ui.bash --build-mode --all-modules --dir=$PWD -k --skip-soong-tests --ninja_weight_source=not_used "${kzip_targets[@]}"
# Build extraction file for Go the files in build/{blueprint,soong} directories.
declare -r abspath_out=$(realpath "${out}")
@@ -63,10 +71,9 @@
set +e
declare -r kzip_count=$(find "$out" -name '*.kzip' | wc -l)
-(($kzip_count>100000)) || { printf "Too few kzip files were generated: %d\n" $kzip_count; exit 1; }
+(($kzip_count>100000)) || { >&2 printf "ERROR: Too few kzip files were generated: %d\n" $kzip_count; exit 1; }
# Pack
-# TODO(asmundak): this should be done by soong.
declare -r allkzip="$KZIP_NAME.kzip"
"$out/host/linux-x86/bin/merge_zips" "$DIST_DIR/$allkzip" @<(find "$out" -name '*.kzip')
diff --git a/cc/afdo.go b/cc/afdo.go
index 137ea97..bc7cd52 100644
--- a/cc/afdo.go
+++ b/cc/afdo.go
@@ -34,7 +34,8 @@
var afdoProfileProjectsConfigKey = android.NewOnceKey("AfdoProfileProjects")
-const afdoCFlagsFormat = "-fprofile-sample-use=%s"
+// This flag needs to be in both CFlags and LdFlags to ensure correct symbol ordering
+const afdoFlagsFormat = "-fprofile-sample-use=%s"
func recordMissingAfdoProfileFile(ctx android.BaseModuleContext, missing string) {
getNamedMapForConfig(ctx.Config(), modulesMissingProfileFileKey).Store(missing, true)
@@ -86,7 +87,7 @@
}
if path := afdo.Properties.FdoProfilePath; path != nil {
// The flags are prepended to allow overriding.
- profileUseFlag := fmt.Sprintf(afdoCFlagsFormat, *path)
+ profileUseFlag := fmt.Sprintf(afdoFlagsFormat, *path)
flags.Local.CFlags = append([]string{profileUseFlag}, flags.Local.CFlags...)
flags.Local.LdFlags = append([]string{profileUseFlag, "-Wl,-mllvm,-no-warn-sample-unused=true"}, flags.Local.LdFlags...)
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 7534db2..fe54463 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -4979,6 +4979,7 @@
conly := []string{"-fPIC", "${config.CommonGlobalConlyflags}"}
cppOnly := []string{"-fPIC", "${config.CommonGlobalCppflags}", "${config.DeviceGlobalCppflags}", "${config.ArmCppflags}"}
+ ltoFlags := []string{"-flto=thin", "-fsplit-lto-unit"}
cflags := []string{"-Werror", "-std=candcpp"}
cstd := []string{"-std=gnu17", "-std=conly"}
@@ -5005,17 +5006,17 @@
{
name: "c",
src: "foo.c",
- expected: combineSlices(baseExpectedFlags, conly, expectedIncludes, cflags, cstd, lastIncludes, []string{"${config.NoOverrideGlobalCflags}", "${config.NoOverrideExternalGlobalCflags}"}),
+ expected: combineSlices(baseExpectedFlags, conly, expectedIncludes, cflags, ltoFlags, cstd, lastIncludes, []string{"${config.NoOverrideGlobalCflags}", "${config.NoOverrideExternalGlobalCflags}"}),
},
{
name: "cc",
src: "foo.cc",
- expected: combineSlices(baseExpectedFlags, cppOnly, expectedIncludes, cflags, cppstd, lastIncludes, []string{"${config.NoOverrideGlobalCflags}", "${config.NoOverrideExternalGlobalCflags}"}),
+ expected: combineSlices(baseExpectedFlags, cppOnly, expectedIncludes, cflags, ltoFlags, cppstd, lastIncludes, []string{"${config.NoOverrideGlobalCflags}", "${config.NoOverrideExternalGlobalCflags}"}),
},
{
name: "assemble",
src: "foo.s",
- expected: combineSlices(baseExpectedFlags, []string{"${config.CommonGlobalAsflags}"}, expectedIncludes, lastIncludes),
+ expected: combineSlices(baseExpectedFlags, []string{"${config.CommonGlobalAsflags}"}, expectedIncludes, ltoFlags, lastIncludes),
},
}
diff --git a/cc/config/arm_device.go b/cc/config/arm_device.go
index dec2b45..3397e3d 100644
--- a/cc/config/arm_device.go
+++ b/cc/config/arm_device.go
@@ -43,9 +43,7 @@
armNoFixCortexA8LdFlags = []string{"-Wl,--no-fix-cortex-a8"}
- armArmCflags = []string{
- "-fstrict-aliasing",
- }
+ armArmCflags = []string{}
armThumbCflags = []string{
"-mthumb",
diff --git a/cc/config/global.go b/cc/config/global.go
index e450ba7..7f9a6e0 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -111,6 +111,9 @@
// Turn off FMA which got enabled by default in clang-r445002 (http://b/218805949)
"-ffp-contract=off",
+
+ // Using simple template names reduces the size of debug builds.
+ "-gsimple-template-names",
}
commonGlobalConlyflags = []string{}
@@ -305,7 +308,7 @@
// prebuilts/clang default settings.
ClangDefaultBase = "prebuilts/clang/host"
- ClangDefaultVersion = "clang-r487747c"
+ ClangDefaultVersion = "clang-r498229"
ClangDefaultShortVersion = "17"
// Directories with warnings from Android.bp files.
diff --git a/cc/lto.go b/cc/lto.go
index 547ebff..ff2bf5a 100644
--- a/cc/lto.go
+++ b/cc/lto.go
@@ -47,6 +47,7 @@
} `android:"arch_variant"`
LtoEnabled bool `blueprint:"mutated"`
+ LtoDefault bool `blueprint:"mutated"`
// Dep properties indicate that this module needs to be built with LTO
// since it is an object dependency of an LTO module.
@@ -66,7 +67,34 @@
}
func (lto *lto) begin(ctx BaseModuleContext) {
- lto.Properties.LtoEnabled = lto.LTO(ctx)
+ // First, determine the module indepedent default LTO mode.
+ ltoDefault := GlobalThinLTO(ctx)
+ if ctx.Config().IsEnvTrue("DISABLE_LTO") {
+ ltoDefault = false
+ } else if ctx.Host() {
+ // Performance and binary size are less important for host binaries.
+ ltoDefault = false
+ }
+
+ // Then, determine the actual LTO mode to use. If different from `ltoDefault`, a variant needs
+ // to be created.
+ ltoEnabled := ltoDefault
+ if lto.Never() {
+ ltoEnabled = false
+ } else if lto.ThinLTO() {
+ // Module explicitly requests for LTO.
+ ltoEnabled = true
+ } else if ctx.testBinary() || ctx.testLibrary() {
+ // Do not enable LTO for tests for better debugging.
+ ltoEnabled = false
+ } else if ctx.isVndk() {
+ // FIXME: ThinLTO for VNDK produces different output.
+ // b/169217596
+ ltoEnabled = false
+ }
+
+ lto.Properties.LtoDefault = ltoDefault
+ lto.Properties.LtoEnabled = ltoEnabled
}
func (lto *lto) flags(ctx BaseModuleContext, flags Flags) Flags {
@@ -76,75 +104,48 @@
return flags
}
if lto.Properties.LtoEnabled {
- var ltoCFlag string
- var ltoLdFlag string
- if lto.ThinLTO() {
- ltoCFlag = "-flto=thin -fsplit-lto-unit"
- } else {
- ltoCFlag = "-flto=thin -fsplit-lto-unit"
- ltoLdFlag = "-Wl,--lto-O0"
+ ltoCFlags := []string{"-flto=thin", "-fsplit-lto-unit"}
+ var ltoLdFlags []string
+
+ // The module did not explicitly turn on LTO. Only leverage LTO's
+ // better dead code elinmination and CFG simplification, but do
+ // not perform costly optimizations for a balance between compile
+ // time, binary size and performance.
+ if !lto.ThinLTO() {
+ ltoLdFlags = append(ltoLdFlags, "-Wl,--lto-O0")
}
- flags.Local.CFlags = append(flags.Local.CFlags, ltoCFlag)
- flags.Local.AsFlags = append(flags.Local.AsFlags, ltoCFlag)
- flags.Local.LdFlags = append(flags.Local.LdFlags, ltoCFlag)
- flags.Local.LdFlags = append(flags.Local.LdFlags, ltoLdFlag)
-
if Bool(lto.Properties.Whole_program_vtables) {
- flags.Local.CFlags = append(flags.Local.CFlags, "-fwhole-program-vtables")
+ ltoCFlags = append(ltoCFlags, "-fwhole-program-vtables")
}
if ctx.Config().IsEnvTrue("USE_THINLTO_CACHE") {
// Set appropriate ThinLTO cache policy
cacheDirFormat := "-Wl,--thinlto-cache-dir="
cacheDir := android.PathForOutput(ctx, "thinlto-cache").String()
- flags.Local.LdFlags = append(flags.Local.LdFlags, cacheDirFormat+cacheDir)
+ ltoLdFlags = append(ltoLdFlags, cacheDirFormat+cacheDir)
// Limit the size of the ThinLTO cache to the lesser of 10% of available
// disk space and 10GB.
cachePolicyFormat := "-Wl,--thinlto-cache-policy="
policy := "cache_size=10%:cache_size_bytes=10g"
- flags.Local.LdFlags = append(flags.Local.LdFlags, cachePolicyFormat+policy)
+ ltoLdFlags = append(ltoLdFlags, cachePolicyFormat+policy)
}
// If the module does not have a profile, be conservative and limit cross TU inline
// limit to 5 LLVM IR instructions, to balance binary size increase and performance.
if !ctx.Darwin() && !ctx.isPgoCompile() && !ctx.isAfdoCompile() {
- flags.Local.LdFlags = append(flags.Local.LdFlags,
- "-Wl,-plugin-opt,-import-instr-limit=5")
+ ltoLdFlags = append(ltoLdFlags, "-Wl,-plugin-opt,-import-instr-limit=5")
}
+
+ flags.Local.CFlags = append(flags.Local.CFlags, ltoCFlags...)
+ flags.Local.AsFlags = append(flags.Local.AsFlags, ltoCFlags...)
+ flags.Local.LdFlags = append(flags.Local.LdFlags, ltoCFlags...)
+ flags.Local.LdFlags = append(flags.Local.LdFlags, ltoLdFlags...)
}
return flags
}
-// Determine which LTO mode to use for the given module.
-func (lto *lto) LTO(ctx BaseModuleContext) bool {
- if lto.Never() {
- return false
- }
- if ctx.Config().IsEnvTrue("DISABLE_LTO") {
- return false
- }
- // Module explicitly requests for LTO.
- if lto.ThinLTO() {
- return true
- }
- // LP32 has many subtle issues and less test coverage.
- if ctx.Arch().ArchType.Multilib == "lib32" {
- return false
- }
- // Performance and binary size are less important for host binaries and tests.
- if ctx.Host() || ctx.testBinary() || ctx.testLibrary() {
- return false
- }
- // FIXME: ThinLTO for VNDK produces different output.
- // b/169217596
- if ctx.isVndk() {
- return false
- }
- return GlobalThinLTO(ctx)
-}
-
func (lto *lto) ThinLTO() bool {
return lto != nil && proptools.Bool(lto.Properties.Lto.Thin)
}
@@ -154,15 +155,13 @@
}
func GlobalThinLTO(ctx android.BaseModuleContext) bool {
- return ctx.Config().IsEnvTrue("GLOBAL_THINLTO")
+ return !ctx.Config().IsEnvFalse("GLOBAL_THINLTO")
}
// Propagate lto requirements down from binaries
func ltoDepsMutator(mctx android.TopDownMutatorContext) {
- defaultLTOMode := GlobalThinLTO(mctx)
-
if m, ok := mctx.Module().(*Module); ok {
- if m.lto == nil || m.lto.Properties.LtoEnabled == defaultLTOMode {
+ if m.lto == nil || m.lto.Properties.LtoEnabled == m.lto.Properties.LtoDefault {
return
}
@@ -237,6 +236,7 @@
}
variation.Properties.PreventInstall = true
variation.Properties.HideFromMake = true
+ variation.lto.Properties.LtoDefault = m.lto.Properties.LtoDefault
variation.lto.Properties.LtoDep = false
variation.lto.Properties.NoLtoDep = false
}
diff --git a/dexpreopt/class_loader_context.go b/dexpreopt/class_loader_context.go
index 6ead589..57c7ae8 100644
--- a/dexpreopt/class_loader_context.go
+++ b/dexpreopt/class_loader_context.go
@@ -310,7 +310,7 @@
// Nested class loader context shouldn't have conditional part (it is allowed only at the top level).
for ver, _ := range nestedClcMap {
if ver != AnySdkVersion {
- clcPaths := ComputeClassLoaderContextDependencies(nestedClcMap)
+ _, clcPaths := ComputeClassLoaderContextDependencies(nestedClcMap)
return fmt.Errorf("nested class loader context shouldn't have conditional part: %+v", clcPaths)
}
}
@@ -553,27 +553,28 @@
return true, nil
}
-// Returns a slice of build paths for all possible dependencies that the class loader context may
-// refer to.
+// Returns a slice of library names and a slice of build paths for all possible dependencies that
+// the class loader context may refer to.
// Perform a depth-first preorder traversal of the class loader context tree for each SDK version.
-func ComputeClassLoaderContextDependencies(clcMap ClassLoaderContextMap) android.Paths {
- var paths android.Paths
+func ComputeClassLoaderContextDependencies(clcMap ClassLoaderContextMap) (names []string, paths android.Paths) {
for _, clcs := range clcMap {
- hostPaths := ComputeClassLoaderContextDependenciesRec(clcs)
- paths = append(paths, hostPaths...)
+ currentNames, currentPaths := ComputeClassLoaderContextDependenciesRec(clcs)
+ names = append(names, currentNames...)
+ paths = append(paths, currentPaths...)
}
- return android.FirstUniquePaths(paths)
+ return android.FirstUniqueStrings(names), android.FirstUniquePaths(paths)
}
// Helper function for ComputeClassLoaderContextDependencies() that handles recursion.
-func ComputeClassLoaderContextDependenciesRec(clcs []*ClassLoaderContext) android.Paths {
- var paths android.Paths
+func ComputeClassLoaderContextDependenciesRec(clcs []*ClassLoaderContext) (names []string, paths android.Paths) {
for _, clc := range clcs {
- subPaths := ComputeClassLoaderContextDependenciesRec(clc.Subcontexts)
+ subNames, subPaths := ComputeClassLoaderContextDependenciesRec(clc.Subcontexts)
+ names = append(names, clc.Name)
paths = append(paths, clc.Host)
+ names = append(names, subNames...)
paths = append(paths, subPaths...)
}
- return paths
+ return names, paths
}
// Class loader contexts that come from Make via JSON dexpreopt.config. JSON CLC representation is
diff --git a/dexpreopt/class_loader_context_test.go b/dexpreopt/class_loader_context_test.go
index 39b4652..7260abb 100644
--- a/dexpreopt/class_loader_context_test.go
+++ b/dexpreopt/class_loader_context_test.go
@@ -97,10 +97,11 @@
fixClassLoaderContext(m)
- var havePaths android.Paths
+ var actualNames []string
+ var actualPaths android.Paths
var haveUsesLibsReq, haveUsesLibsOpt []string
if valid && validationError == nil {
- havePaths = ComputeClassLoaderContextDependencies(m)
+ actualNames, actualPaths = ComputeClassLoaderContextDependencies(m)
haveUsesLibsReq, haveUsesLibsOpt = m.UsesLibs()
}
@@ -112,19 +113,26 @@
})
// Test that all expected build paths are gathered.
- t.Run("paths", func(t *testing.T) {
- wantPaths := []string{
+ t.Run("names and paths", func(t *testing.T) {
+ expectedNames := []string{
+ "a'", "a1", "a2", "a3", "android.hidl.base-V1.0-java", "android.hidl.manager-V1.0-java", "b",
+ "b1", "b2", "b3", "c", "c2", "d", "f",
+ }
+ expectedPaths := []string{
"out/soong/android.hidl.manager-V1.0-java.jar", "out/soong/android.hidl.base-V1.0-java.jar",
"out/soong/a.jar", "out/soong/b.jar", "out/soong/c.jar", "out/soong/d.jar",
"out/soong/a2.jar", "out/soong/b2.jar", "out/soong/c2.jar",
"out/soong/a1.jar", "out/soong/b1.jar",
"out/soong/f.jar", "out/soong/a3.jar", "out/soong/b3.jar",
}
- actual := havePaths.Strings()
+ actualPathsStrs := actualPaths.Strings()
// The order does not matter.
- sort.Strings(wantPaths)
- sort.Strings(actual)
- android.AssertArrayString(t, "", wantPaths, actual)
+ sort.Strings(expectedNames)
+ sort.Strings(actualNames)
+ android.AssertArrayString(t, "", expectedNames, actualNames)
+ sort.Strings(expectedPaths)
+ sort.Strings(actualPathsStrs)
+ android.AssertArrayString(t, "", expectedPaths, actualPathsStrs)
})
// Test the JSON passed to construct_context.py.
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index 20737e3..29ae188 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -353,7 +353,7 @@
}
// Generate command that saves host and target class loader context in shell variables.
- paths := ComputeClassLoaderContextDependencies(module.ClassLoaderContexts)
+ _, paths := ComputeClassLoaderContextDependencies(module.ClassLoaderContexts)
rule.Command().
Text(`eval "$(`).Tool(globalSoong.ConstructContext).
Text(` --target-sdk-version ${target_sdk_version}`).
@@ -630,5 +630,3 @@
}
return false
}
-
-var copyOf = android.CopyOf
diff --git a/fuzz/fuzz_common.go b/fuzz/fuzz_common.go
index b470304..ada4712 100644
--- a/fuzz/fuzz_common.go
+++ b/fuzz/fuzz_common.go
@@ -368,6 +368,9 @@
Triage_assignee string `json:"triage_assignee,omitempty"`
// Specifies libs used to initialize ART (java only, 'use_none' for no initialization)
Use_platform_libs UsePlatformLibs `json:"use_platform_libs,omitempty"`
+ // Specifies whether fuzz target should check presubmitted code changes for crashes.
+ // Defaults to false.
+ Use_for_presubmit *bool `json:"use_for_presubmit,omitempty"`
}
type FuzzFrameworks struct {
diff --git a/genrule/allowlists.go b/genrule/allowlists.go
index c767685..012c59c 100644
--- a/genrule/allowlists.go
+++ b/genrule/allowlists.go
@@ -56,7 +56,6 @@
"RSTest-rscript",
"BluetoothGeneratedDumpsysBinarySchema_bfbs",
"TracingVMProtoStub_h",
- "FrontendStub_h",
"VehicleServerProtoStub_cc",
"AudioFocusControlProtoStub_cc",
"AudioFocusControlProtoStub_h",
@@ -98,7 +97,6 @@
"BlueberryFacadeGeneratedStub_cc",
"BlueberryFacadeGeneratedStub_h",
"BluetoothGeneratedDumpsysDataSchema_h",
- "FrontendStub_cc",
"OpenwrtControlServerProto_cc",
"OpenwrtControlServerProto_h",
"c2hal_test_genc++",
@@ -117,6 +115,11 @@
"nos_app_weaver_service_genc++_headers",
"nos_app_weaver_service_genc++_mock",
"nos_generator_test_service_genc++",
+ "framework-cppstream-protos",
+ "framework-javastream-protos",
+ "aidl_camera_build_version",
+ "cronet_aml_base_android_runtime_unchecked_jni_headers",
+ "cronet_aml_base_android_runtime_jni_headers",
}
SandboxingDenyPathList = []string{
diff --git a/java/app.go b/java/app.go
index d9272e4..fd626e1 100755
--- a/java/app.go
+++ b/java/app.go
@@ -1571,7 +1571,9 @@
}
type manifestValueAttribute struct {
- MinSdkVersion *string
+ MinSdkVersion *string
+ MaxSdkVersion *string
+ TargetSdkVersion *string
}
type bazelAndroidAppAttributes struct {
@@ -1601,12 +1603,25 @@
// MinSdkVersion(ctx) calls SdkVersion(ctx) if no value for min_sdk_version is set
minSdkVersion := a.MinSdkVersion(ctx)
if !minSdkVersion.IsPreview() && !minSdkVersion.IsInvalid() {
- minSdkStr, err := minSdkVersion.EffectiveVersionString(ctx)
- if err == nil {
+ if minSdkStr, err := minSdkVersion.EffectiveVersionString(ctx); err == nil {
manifestValues.MinSdkVersion = &minSdkStr
}
}
+ maxSdkVersion := a.MaxSdkVersion(ctx)
+ if !maxSdkVersion.IsPreview() && !maxSdkVersion.IsInvalid() {
+ if maxSdkStr, err := maxSdkVersion.EffectiveVersionString(ctx); err == nil {
+ manifestValues.MaxSdkVersion = &maxSdkStr
+ }
+ }
+
+ targetSdkVersion := a.TargetSdkVersion(ctx)
+ if !targetSdkVersion.IsPreview() && !targetSdkVersion.IsInvalid() {
+ if targetSdkStr, err := targetSdkVersion.EffectiveVersionString(ctx); err == nil {
+ manifestValues.TargetSdkVersion = &targetSdkStr
+ }
+ }
+
appAttrs := &bazelAndroidAppAttributes{
// TODO(b/209576404): handle package name override by product variable PRODUCT_MANIFEST_PACKAGE_NAME_OVERRIDES
Custom_package: a.overridableAppProperties.Package_name,
diff --git a/java/app_import.go b/java/app_import.go
index 9c01960..e25bcd1 100644
--- a/java/app_import.go
+++ b/java/app_import.go
@@ -17,6 +17,7 @@
// This file contains the module implementations for android_app_import and android_test_import.
import (
+ "fmt"
"reflect"
"github.com/google/blueprint"
@@ -334,11 +335,19 @@
// Sign or align the package if package has not been preprocessed
if proptools.Bool(a.properties.Preprocessed) {
- output := srcApk
+ var output android.WritablePath
if !proptools.Bool(a.properties.Skip_preprocessed_apk_checks) {
- writableOutput := android.PathForModuleOut(ctx, "validated-prebuilt", apkFilename)
- a.validatePreprocessedApk(ctx, srcApk, writableOutput)
- output = writableOutput
+ output = android.PathForModuleOut(ctx, "validated-prebuilt", apkFilename)
+ a.validatePreprocessedApk(ctx, srcApk, output)
+ } else {
+ // If using the input APK unmodified, still make a copy of it so that the output filename has the
+ // right basename.
+ output = android.PathForModuleOut(ctx, apkFilename)
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cp,
+ Input: srcApk,
+ Output: output,
+ })
}
a.outputFile = output
a.certificate = PresignedCertificate
@@ -410,6 +419,15 @@
return a.outputFile
}
+func (a *AndroidAppImport) OutputFiles(tag string) (android.Paths, error) {
+ switch tag {
+ case "":
+ return []android.Path{a.outputFile}, nil
+ default:
+ return nil, fmt.Errorf("unsupported module reference tag %q", tag)
+ }
+}
+
func (a *AndroidAppImport) JacocoReportClassesFile() android.Path {
return nil
}
diff --git a/java/app_test.go b/java/app_test.go
index cf7d174..12c3a95 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -717,7 +717,262 @@
}
}
-func TestAndroidResources(t *testing.T) {
+func TestAndroidResourceProcessor(t *testing.T) {
+ testCases := []struct {
+ name string
+
+ dontVerifyApp bool
+ appResources []string
+ appOverlays []string
+ appImports []string
+ appSrcJars []string
+ appClasspath []string
+ appCombined []string
+
+ dontVerifyDirect bool
+ directResources []string
+ directOverlays []string
+ directImports []string
+ directSrcJars []string
+ directClasspath []string
+ directCombined []string
+
+ dontVerifyTransitive bool
+ transitiveResources []string
+ transitiveOverlays []string
+ transitiveImports []string
+ transitiveSrcJars []string
+ transitiveClasspath []string
+ transitiveCombined []string
+
+ dontVerifyDirectImport bool
+ directImportResources []string
+ directImportOverlays []string
+ directImportImports []string
+
+ dontVerifyTransitiveImport bool
+ transitiveImportResources []string
+ transitiveImportOverlays []string
+ transitiveImportImports []string
+ }{
+ {
+ name: "legacy",
+
+ appResources: nil,
+ appOverlays: []string{
+ "out/soong/.intermediates/transitive/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive_import/android_common/package-res.apk",
+ "out/soong/.intermediates/direct/android_common/package-res.apk",
+ "out/soong/.intermediates/direct_import/android_common/package-res.apk",
+ "out/soong/.intermediates/app/android_common/aapt2/app/res/values_strings.arsc.flat",
+ },
+ appImports: []string{"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk"},
+ appSrcJars: []string{"out/soong/.intermediates/app/android_common/gen/android/R.srcjar"},
+ appClasspath: []string{
+ "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
+ "out/soong/.intermediates/direct/android_common/turbine-combined/direct.jar",
+ "out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar",
+ },
+ appCombined: []string{
+ "out/soong/.intermediates/app/android_common/javac/app.jar",
+ "out/soong/.intermediates/direct/android_common/combined/direct.jar",
+ "out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar",
+ },
+
+ directResources: nil,
+ directOverlays: []string{
+ "out/soong/.intermediates/transitive/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive_import/android_common/package-res.apk",
+ "out/soong/.intermediates/direct/android_common/aapt2/direct/res/values_strings.arsc.flat",
+ },
+ directImports: []string{"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk"},
+ directSrcJars: []string{"out/soong/.intermediates/direct/android_common/gen/android/R.srcjar"},
+ directClasspath: []string{
+ "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
+ "out/soong/.intermediates/transitive/android_common/turbine-combined/transitive.jar",
+ "out/soong/.intermediates/transitive_import/android_common/aar/classes-combined.jar",
+ },
+ directCombined: []string{
+ "out/soong/.intermediates/direct/android_common/javac/direct.jar",
+ "out/soong/.intermediates/transitive/android_common/javac/transitive.jar",
+ "out/soong/.intermediates/transitive_import/android_common/aar/classes-combined.jar",
+ },
+
+ transitiveResources: []string{"out/soong/.intermediates/transitive/android_common/aapt2/transitive/res/values_strings.arsc.flat"},
+ transitiveOverlays: nil,
+ transitiveImports: []string{"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk"},
+ transitiveSrcJars: []string{"out/soong/.intermediates/transitive/android_common/gen/android/R.srcjar"},
+ transitiveClasspath: []string{"out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar"},
+ transitiveCombined: nil,
+
+ directImportResources: nil,
+ directImportOverlays: []string{
+ "out/soong/.intermediates/direct_import/android_common/flat-res/gen_res.flata",
+ "out/soong/.intermediates/direct_import_dep/android_common/package-res.apk",
+ },
+ directImportImports: []string{"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk"},
+
+ transitiveImportResources: nil,
+ transitiveImportOverlays: []string{
+ "out/soong/.intermediates/transitive_import/android_common/flat-res/gen_res.flata",
+ "out/soong/.intermediates/transitive_import_dep/android_common/package-res.apk",
+ },
+ transitiveImportImports: []string{"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk"},
+ },
+ }
+
+ for _, testCase := range testCases {
+ t.Run(testCase.name, func(t *testing.T) {
+ bp := fmt.Sprintf(`
+ android_app {
+ name: "app",
+ sdk_version: "current",
+ srcs: ["app/app.java"],
+ resource_dirs: ["app/res"],
+ manifest: "app/AndroidManifest.xml",
+ static_libs: ["direct", "direct_import"],
+ }
+
+ android_library {
+ name: "direct",
+ sdk_version: "current",
+ srcs: ["direct/direct.java"],
+ resource_dirs: ["direct/res"],
+ manifest: "direct/AndroidManifest.xml",
+ static_libs: ["transitive", "transitive_import"],
+ }
+
+ android_library {
+ name: "transitive",
+ sdk_version: "current",
+ srcs: ["transitive/transitive.java"],
+ resource_dirs: ["transitive/res"],
+ manifest: "transitive/AndroidManifest.xml",
+ }
+
+ android_library_import {
+ name: "direct_import",
+ sdk_version: "current",
+ aars: ["direct_import.aar"],
+ static_libs: ["direct_import_dep"],
+ }
+
+ android_library_import {
+ name: "direct_import_dep",
+ sdk_version: "current",
+ aars: ["direct_import_dep.aar"],
+ }
+
+ android_library_import {
+ name: "transitive_import",
+ sdk_version: "current",
+ aars: ["transitive_import.aar"],
+ static_libs: ["transitive_import_dep"],
+ }
+
+ android_library_import {
+ name: "transitive_import_dep",
+ sdk_version: "current",
+ aars: ["transitive_import_dep.aar"],
+ }
+ `)
+
+ fs := android.MockFS{
+ "app/res/values/strings.xml": nil,
+ "direct/res/values/strings.xml": nil,
+ "transitive/res/values/strings.xml": nil,
+ }
+
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ PrepareForTestWithOverlayBuildComponents,
+ fs.AddToFixture(),
+ ).RunTestWithBp(t, bp)
+
+ type aaptInfo struct {
+ resources, overlays, imports, srcJars, classpath, combined android.Paths
+ }
+
+ getAaptInfo := func(moduleName string) (aaptInfo aaptInfo) {
+ mod := result.ModuleForTests(moduleName, "android_common")
+ resourceListRule := mod.MaybeOutput("aapt2/res.list")
+ overlayListRule := mod.MaybeOutput("aapt2/overlay.list")
+ aaptRule := mod.Rule("aapt2Link")
+ javacRule := mod.MaybeRule("javac")
+ combinedRule := mod.MaybeOutput("combined/" + moduleName + ".jar")
+
+ aaptInfo.resources = resourceListRule.Inputs
+ aaptInfo.overlays = overlayListRule.Inputs
+
+ aaptFlags := strings.Split(aaptRule.Args["flags"], " ")
+ for i, flag := range aaptFlags {
+ if flag == "-I" && i+1 < len(aaptFlags) {
+ aaptInfo.imports = append(aaptInfo.imports, android.PathForTesting(aaptFlags[i+1]))
+ }
+ }
+
+ if len(javacRule.Args["srcJars"]) > 0 {
+ aaptInfo.srcJars = android.PathsForTesting(strings.Split(javacRule.Args["srcJars"], " ")...)
+ }
+
+ if len(javacRule.Args["classpath"]) > 0 {
+ classpathArg := strings.TrimPrefix(javacRule.Args["classpath"], "-classpath ")
+ aaptInfo.classpath = android.PathsForTesting(strings.Split(classpathArg, ":")...)
+ }
+
+ aaptInfo.combined = combinedRule.Inputs
+ return
+ }
+
+ app := getAaptInfo("app")
+ direct := getAaptInfo("direct")
+ transitive := getAaptInfo("transitive")
+ directImport := getAaptInfo("direct_import")
+ transitiveImport := getAaptInfo("transitive_import")
+
+ if !testCase.dontVerifyApp {
+ android.AssertPathsRelativeToTopEquals(t, "app resources", testCase.appResources, app.resources)
+ android.AssertPathsRelativeToTopEquals(t, "app overlays", testCase.appOverlays, app.overlays)
+ android.AssertPathsRelativeToTopEquals(t, "app imports", testCase.appImports, app.imports)
+ android.AssertPathsRelativeToTopEquals(t, "app srcjars", testCase.appSrcJars, app.srcJars)
+ android.AssertPathsRelativeToTopEquals(t, "app classpath", testCase.appClasspath, app.classpath)
+ android.AssertPathsRelativeToTopEquals(t, "app combined", testCase.appCombined, app.combined)
+ }
+
+ if !testCase.dontVerifyDirect {
+ android.AssertPathsRelativeToTopEquals(t, "direct resources", testCase.directResources, direct.resources)
+ android.AssertPathsRelativeToTopEquals(t, "direct overlays", testCase.directOverlays, direct.overlays)
+ android.AssertPathsRelativeToTopEquals(t, "direct imports", testCase.directImports, direct.imports)
+ android.AssertPathsRelativeToTopEquals(t, "direct srcjars", testCase.directSrcJars, direct.srcJars)
+ android.AssertPathsRelativeToTopEquals(t, "direct classpath", testCase.directClasspath, direct.classpath)
+ android.AssertPathsRelativeToTopEquals(t, "direct combined", testCase.directCombined, direct.combined)
+ }
+
+ if !testCase.dontVerifyTransitive {
+ android.AssertPathsRelativeToTopEquals(t, "transitive resources", testCase.transitiveResources, transitive.resources)
+ android.AssertPathsRelativeToTopEquals(t, "transitive overlays", testCase.transitiveOverlays, transitive.overlays)
+ android.AssertPathsRelativeToTopEquals(t, "transitive imports", testCase.transitiveImports, transitive.imports)
+ android.AssertPathsRelativeToTopEquals(t, "transitive srcjars", testCase.transitiveSrcJars, transitive.srcJars)
+ android.AssertPathsRelativeToTopEquals(t, "transitive classpath", testCase.transitiveClasspath, transitive.classpath)
+ android.AssertPathsRelativeToTopEquals(t, "transitive combined", testCase.transitiveCombined, transitive.combined)
+ }
+
+ if !testCase.dontVerifyDirectImport {
+ android.AssertPathsRelativeToTopEquals(t, "direct_import resources", testCase.directImportResources, directImport.resources)
+ android.AssertPathsRelativeToTopEquals(t, "direct_import overlays", testCase.directImportOverlays, directImport.overlays)
+ android.AssertPathsRelativeToTopEquals(t, "direct_import imports", testCase.directImportImports, directImport.imports)
+ }
+
+ if !testCase.dontVerifyTransitiveImport {
+ android.AssertPathsRelativeToTopEquals(t, "transitive_import resources", testCase.transitiveImportResources, transitiveImport.resources)
+ android.AssertPathsRelativeToTopEquals(t, "transitive_import overlays", testCase.transitiveImportOverlays, transitiveImport.overlays)
+ android.AssertPathsRelativeToTopEquals(t, "transitive_import imports", testCase.transitiveImportImports, transitiveImport.imports)
+ }
+ })
+ }
+}
+
+func TestAndroidResourceOverlays(t *testing.T) {
testCases := []struct {
name string
enforceRROTargets []string
@@ -2697,7 +2952,7 @@
cmd := app.Rule("dexpreopt").RuleParams.Command
android.AssertStringDoesContain(t, "dexpreopt app cmd context", cmd, "--context-json=")
android.AssertStringDoesContain(t, "dexpreopt app cmd product_packages", cmd,
- "--product-packages=out/soong/target/product/test_device/product_packages.txt")
+ "--product-packages=out/soong/.intermediates/app/android_common/dexpreopt/product_packages.txt")
}
func TestDexpreoptBcp(t *testing.T) {
diff --git a/java/base.go b/java/base.go
index 75e25e3..f2ad5c2 100644
--- a/java/base.go
+++ b/java/base.go
@@ -2202,7 +2202,7 @@
func (j *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
switch ctx.ModuleType() {
- case "java_library", "java_library_host", "java_library_static":
+ case "java_library", "java_library_host", "java_library_static", "tradefed_java_library_host":
if lib, ok := ctx.Module().(*Library); ok {
javaLibraryBp2Build(ctx, lib)
}
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index e588c9a..998730e 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -16,6 +16,7 @@
import (
"path/filepath"
+ "sort"
"strings"
"android/soong/android"
@@ -390,11 +391,37 @@
globalSoong := dexpreopt.GetGlobalSoongConfig(ctx)
- // "product_packages.txt" is generated by `build/make/core/Makefile`.
+ // The root "product_packages.txt" is generated by `build/make/core/Makefile`. It contains a list
+ // of all packages that are installed on the device. We use `grep` to filter the list by the app's
+ // dependencies to create a per-app list, and use `rsync --checksum` to prevent the file's mtime
+ // from being changed if the contents don't change. This avoids unnecessary dexpreopt reruns.
productPackages := android.PathForModuleInPartitionInstall(ctx, "", "product_packages.txt")
+ appProductPackages := android.PathForModuleOut(ctx, "dexpreopt", "product_packages.txt")
+ appProductPackagesStaging := appProductPackages.ReplaceExtension(ctx, "txt.tmp")
+ clcNames, _ := dexpreopt.ComputeClassLoaderContextDependencies(dexpreoptConfig.ClassLoaderContexts)
+ sort.Strings(clcNames) // The order needs to be deterministic.
+ productPackagesRule := android.NewRuleBuilder(pctx, ctx)
+ if len(clcNames) > 0 {
+ productPackagesRule.Command().
+ Text("grep -F -x").
+ FlagForEachArg("-e ", clcNames).
+ Input(productPackages).
+ FlagWithOutput("> ", appProductPackagesStaging).
+ Text("|| true")
+ } else {
+ productPackagesRule.Command().
+ Text("rm -f").Output(appProductPackagesStaging).
+ Text("&&").
+ Text("touch").Output(appProductPackagesStaging)
+ }
+ productPackagesRule.Command().
+ Text("rsync --checksum").
+ Input(appProductPackagesStaging).
+ Output(appProductPackages)
+ productPackagesRule.Restat().Build("product_packages", "dexpreopt product_packages")
dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(
- ctx, globalSoong, global, dexpreoptConfig, productPackages)
+ ctx, globalSoong, global, dexpreoptConfig, appProductPackages)
if err != nil {
ctx.ModuleErrorf("error generating dexpreopt rule: %s", err.Error())
return
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 0ffe152..7b56a19 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -788,7 +788,6 @@
Flag("--generate-build-id").
Flag("--image-format=lz4hc").
FlagWithArg("--oat-symbols=", symbolsFile.String()).
- Flag("--strip").
FlagWithArg("--oat-file=", outputPath.String()).
FlagWithArg("--oat-location=", oatLocation).
FlagWithArg("--image=", imagePath.String()).
@@ -798,6 +797,11 @@
Flag("--force-determinism").
Flag("--abort-on-hard-verifier-error")
+ // We don't strip on host to make perf tools work.
+ if image.target.Os == android.Android {
+ cmd.Flag("--strip")
+ }
+
// If the image is profile-guided but the profile is disabled, we omit "--compiler-filter" to
// leave the decision to dex2oat to pick the compiler filter.
if !(image.isProfileGuided() && global.DisableGenerateProfile) {
diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go
index d9c474d..abbb96a 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -248,8 +248,6 @@
var defaultBootclasspathKey = android.NewOnceKey("defaultBootclasspath")
-var copyOf = android.CopyOf
-
func init() {
android.RegisterMakeVarsProvider(pctx, dexpreoptConfigMakevars)
}
diff --git a/java/java.go b/java/java.go
index caafaa2..50d48ab 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1624,13 +1624,6 @@
})
}
-type JavaApiLibraryDepsInfo struct {
- JavaInfo
- StubsSrcJar android.Path
-}
-
-var JavaApiLibraryDepsProvider = blueprint.NewProvider(JavaApiLibraryDepsInfo{})
-
type ApiLibrary struct {
android.ModuleBase
android.DefaultableModuleBase
@@ -1672,10 +1665,11 @@
// merge zipped after metalava invocation
Static_libs []string
- // Java Api library to provide the full API surface text files and jar file.
- // If this property is set, the provided full API surface text files and
- // jar file are passed to metalava invocation.
- Dep_api_srcs *string
+ // Java Api library to provide the full API surface stub jar file.
+ // If this property is set, the stub jar of this module is created by
+ // extracting the compiled class files provided by the
+ // full_api_surface_stub module.
+ Full_api_surface_stub *string
}
func ApiLibraryFactory() android.Module {
@@ -1762,35 +1756,37 @@
}
}
-// This method extracts the stub java files from the srcjar file provided from dep_api_srcs module
-// and replaces the java stubs generated by invoking metalava in this module.
+// This method extracts the stub class files from the stub jar file provided
+// from full_api_surface_stub module instead of compiling the srcjar generated from invoking metalava.
// This method is used because metalava can generate compilable from-text stubs only when
-// the codebase encompasses all classes listed in the input API text file, but a class can extend
+// the codebase encompasses all classes listed in the input API text file, and a class can extend
// a class that is not within the same API domain.
-func (al *ApiLibrary) extractApiSrcs(ctx android.ModuleContext, rule *android.RuleBuilder, stubsDir android.OptionalPath, depApiSrcsSrcJar android.Path) {
- generatedStubsList := android.PathForModuleOut(ctx, "metalava", "sources.txt")
+func (al *ApiLibrary) extractApiSrcs(ctx android.ModuleContext, rule *android.RuleBuilder, stubsDir android.OptionalPath, fullApiSurfaceStubJar android.Path) {
+ classFilesList := android.PathForModuleOut(ctx, "metalava", "classes.txt")
unzippedSrcJarDir := android.PathForModuleOut(ctx, "metalava", "unzipDir")
rule.Command().
BuiltTool("list_files").
Text(stubsDir.String()).
- FlagWithOutput("--out ", generatedStubsList).
+ FlagWithOutput("--out ", classFilesList).
FlagWithArg("--extensions ", ".java").
- FlagWithArg("--root ", unzippedSrcJarDir.String())
+ FlagWithArg("--root ", unzippedSrcJarDir.String()).
+ Flag("--classes")
rule.Command().
Text("unzip").
Flag("-q").
- Input(depApiSrcsSrcJar).
+ Input(fullApiSurfaceStubJar).
FlagWithArg("-d ", unzippedSrcJarDir.String())
rule.Command().
BuiltTool("soong_zip").
- Flag("-srcjar").
+ Flag("-jar").
Flag("-write_if_changed").
+ Flag("-ignore_missing_files").
FlagWithArg("-C ", unzippedSrcJarDir.String()).
- FlagWithInput("-l ", generatedStubsList).
- FlagWithOutput("-o ", al.stubsSrcJar)
+ FlagWithInput("-l ", classFilesList).
+ FlagWithOutput("-o ", al.stubsJarWithoutStaticLibs)
}
func (al *ApiLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
@@ -1800,8 +1796,8 @@
}
ctx.AddVariationDependencies(nil, libTag, al.properties.Libs...)
ctx.AddVariationDependencies(nil, staticLibTag, al.properties.Static_libs...)
- if al.properties.Dep_api_srcs != nil {
- ctx.AddVariationDependencies(nil, depApiSrcsTag, String(al.properties.Dep_api_srcs))
+ if al.properties.Full_api_surface_stub != nil {
+ ctx.AddVariationDependencies(nil, depApiSrcsTag, String(al.properties.Full_api_surface_stub))
}
}
@@ -1823,7 +1819,7 @@
var srcFiles android.Paths
var classPaths android.Paths
var staticLibs android.Paths
- var depApiSrcsStubsSrcJar android.Path
+ var depApiSrcsStubsJar android.Path
ctx.VisitDirectDeps(func(dep android.Module) {
tag := ctx.OtherModuleDependencyTag(dep)
switch tag {
@@ -1841,9 +1837,8 @@
provider := ctx.OtherModuleProvider(dep, JavaInfoProvider).(JavaInfo)
staticLibs = append(staticLibs, provider.HeaderJars...)
case depApiSrcsTag:
- provider := ctx.OtherModuleProvider(dep, JavaApiLibraryDepsProvider).(JavaApiLibraryDepsInfo)
- classPaths = append(classPaths, provider.HeaderJars...)
- depApiSrcsStubsSrcJar = provider.StubsSrcJar
+ provider := ctx.OtherModuleProvider(dep, JavaInfoProvider).(JavaInfo)
+ depApiSrcsStubsJar = provider.HeaderJars[0]
}
})
@@ -1861,31 +1856,31 @@
al.stubsFlags(ctx, cmd, stubsDir)
al.stubsSrcJar = android.PathForModuleOut(ctx, "metalava", ctx.ModuleName()+"-"+"stubs.srcjar")
+ al.stubsJarWithoutStaticLibs = android.PathForModuleOut(ctx, "metalava", "stubs.jar")
+ al.stubsJar = android.PathForModuleOut(ctx, ctx.ModuleName(), fmt.Sprintf("%s.jar", ctx.ModuleName()))
- if depApiSrcsStubsSrcJar != nil {
- al.extractApiSrcs(ctx, rule, stubsDir, depApiSrcsStubsSrcJar)
- } else {
- rule.Command().
- BuiltTool("soong_zip").
- Flag("-write_if_changed").
- Flag("-jar").
- FlagWithOutput("-o ", al.stubsSrcJar).
- FlagWithArg("-C ", stubsDir.String()).
- FlagWithArg("-D ", stubsDir.String())
+ if depApiSrcsStubsJar != nil {
+ al.extractApiSrcs(ctx, rule, stubsDir, depApiSrcsStubsJar)
}
+ rule.Command().
+ BuiltTool("soong_zip").
+ Flag("-write_if_changed").
+ Flag("-jar").
+ FlagWithOutput("-o ", al.stubsSrcJar).
+ FlagWithArg("-C ", stubsDir.String()).
+ FlagWithArg("-D ", stubsDir.String())
rule.Build("metalava", "metalava merged")
- al.stubsJarWithoutStaticLibs = android.PathForModuleOut(ctx, ctx.ModuleName(), "stubs.jar")
- al.stubsJar = android.PathForModuleOut(ctx, ctx.ModuleName(), fmt.Sprintf("%s.jar", ctx.ModuleName()))
+ if depApiSrcsStubsJar == nil {
+ var flags javaBuilderFlags
+ flags.javaVersion = getStubsJavaVersion()
+ flags.javacFlags = strings.Join(al.properties.Javacflags, " ")
+ flags.classpath = classpath(classPaths)
- var flags javaBuilderFlags
- flags.javaVersion = getStubsJavaVersion()
- flags.javacFlags = strings.Join(al.properties.Javacflags, " ")
- flags.classpath = classpath(classPaths)
-
- TransformJavaToClasses(ctx, al.stubsJarWithoutStaticLibs, 0, android.Paths{},
- android.Paths{al.stubsSrcJar}, flags, android.Paths{})
+ TransformJavaToClasses(ctx, al.stubsJarWithoutStaticLibs, 0, android.Paths{},
+ android.Paths{al.stubsSrcJar}, flags, android.Paths{})
+ }
builder := android.NewRuleBuilder(pctx, ctx)
builder.Command().
@@ -1917,13 +1912,6 @@
ImplementationJars: android.PathsIfNonNil(al.stubsJar),
AidlIncludeDirs: android.Paths{},
})
-
- ctx.SetProvider(JavaApiLibraryDepsProvider, JavaApiLibraryDepsInfo{
- JavaInfo: JavaInfo{
- HeaderJars: android.PathsIfNonNil(al.stubsJar),
- },
- StubsSrcJar: al.stubsSrcJar,
- })
}
func (al *ApiLibrary) DexJarBuildPath() OptionalDexJarPath {
diff --git a/java/java_test.go b/java/java_test.go
index 561b187..4738304 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -2208,7 +2208,7 @@
}
}
-func TestJavaApiLibraryDepApiSrcs(t *testing.T) {
+func TestJavaApiLibraryFullApiSurfaceStub(t *testing.T) {
provider_bp_a := `
java_api_contribution {
name: "foo1",
@@ -2234,7 +2234,7 @@
name: "bar1",
api_surface: "public",
api_contributions: ["foo1"],
- dep_api_srcs: "lib1",
+ full_api_surface_stub: "lib1",
}
`,
map[string][]byte{
@@ -2247,9 +2247,7 @@
manifest := m.Output("metalava.sbox.textproto")
sboxProto := android.RuleBuilderSboxProtoForTests(t, manifest)
manifestCommand := sboxProto.Commands[0].GetCommand()
-
- android.AssertStringDoesContain(t, "Command expected to contain module srcjar file", manifestCommand, "bar1-stubs.srcjar")
- android.AssertStringDoesContain(t, "Command expected to contain output files list text file flag", manifestCommand, "--out __SBOX_SANDBOX_DIR__/out/sources.txt")
+ android.AssertStringDoesContain(t, "Command expected to contain full_api_surface_stub output jar", manifestCommand, "lib1.jar")
}
func TestJavaApiLibraryFilegroupInput(t *testing.T) {
diff --git a/java/resourceshrinker.go b/java/resourceshrinker.go
index 6d59601..bf1b04d 100644
--- a/java/resourceshrinker.go
+++ b/java/resourceshrinker.go
@@ -22,7 +22,8 @@
var shrinkResources = pctx.AndroidStaticRule("shrinkResources",
blueprint.RuleParams{
- Command: `${config.ResourceShrinkerCmd} --output $out --input $in --raw_resources $raw_resources`,
+ // Note that we suppress stdout to avoid successful log confirmations.
+ Command: `${config.ResourceShrinkerCmd} --output $out --input $in --raw_resources $raw_resources >/dev/null`,
CommandDeps: []string{"${config.ResourceShrinkerCmd}"},
}, "raw_resources")
diff --git a/java/robolectric.go b/java/robolectric.go
index 6bbe872..0041af4 100644
--- a/java/robolectric.go
+++ b/java/robolectric.go
@@ -299,7 +299,7 @@
func (r *robolectricTest) generateRoboSrcJar(ctx android.ModuleContext, outputFile android.WritablePath,
instrumentedApp *AndroidApp) {
- srcJarArgs := copyOf(instrumentedApp.srcJarArgs)
+ srcJarArgs := android.CopyOf(instrumentedApp.srcJarArgs)
srcJarDeps := append(android.Paths(nil), instrumentedApp.srcJarDeps...)
for _, m := range ctx.GetDirectDepsWithTag(roboCoverageLibsTag) {
diff --git a/java/sdk_library.go b/java/sdk_library.go
index a3d81ce..dbb2f02 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -1780,12 +1780,12 @@
func (module *SdkLibrary) createApiLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) {
props := struct {
- Name *string
- Visibility []string
- Api_contributions []string
- Libs []string
- Static_libs []string
- Dep_api_srcs *string
+ Name *string
+ Visibility []string
+ Api_contributions []string
+ Libs []string
+ Static_libs []string
+ Full_api_surface_stub *string
}{}
props.Name = proptools.StringPtr(module.apiLibraryModuleName(apiScope))
@@ -1807,12 +1807,12 @@
props.Libs = append(props.Libs, module.sdkLibraryProperties.Stub_only_libs...)
props.Libs = append(props.Libs, "stub-annotations")
props.Static_libs = module.sdkLibraryProperties.Stub_only_static_libs
- props.Dep_api_srcs = proptools.StringPtr(apiScope.kind.DefaultJavaLibraryName() + ".from-text")
+ props.Full_api_surface_stub = proptools.StringPtr(apiScope.kind.DefaultJavaLibraryName() + ".from-text")
// android_module_lib_stubs_current.from-text only comprises api contributions from art, conscrypt and i18n.
// Thus, replace with android_module_lib_stubs_current_full.from-text, which comprises every api domains.
if apiScope.kind == android.SdkModule {
- props.Dep_api_srcs = proptools.StringPtr(apiScope.kind.DefaultJavaLibraryName() + "_full.from-text")
+ props.Full_api_surface_stub = proptools.StringPtr(apiScope.kind.DefaultJavaLibraryName() + "_full.from-text")
}
mctx.CreateModule(ApiLibraryFactory, &props)
diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go
index 7ba1f6d..c22b980 100644
--- a/java/sdk_library_test.go
+++ b/java/sdk_library_test.go
@@ -1442,35 +1442,35 @@
`)
testCases := []struct {
- scope *apiScope
- apiContributions []string
- depApiSrcs string
+ scope *apiScope
+ apiContributions []string
+ fullApiSurfaceStub string
}{
{
- scope: apiScopePublic,
- apiContributions: []string{"foo.stubs.source.api.contribution"},
- depApiSrcs: "android_stubs_current.from-text",
+ scope: apiScopePublic,
+ apiContributions: []string{"foo.stubs.source.api.contribution"},
+ fullApiSurfaceStub: "android_stubs_current.from-text",
},
{
- scope: apiScopeSystem,
- apiContributions: []string{"foo.stubs.source.system.api.contribution", "foo.stubs.source.api.contribution"},
- depApiSrcs: "android_system_stubs_current.from-text",
+ scope: apiScopeSystem,
+ apiContributions: []string{"foo.stubs.source.system.api.contribution", "foo.stubs.source.api.contribution"},
+ fullApiSurfaceStub: "android_system_stubs_current.from-text",
},
{
- scope: apiScopeTest,
- apiContributions: []string{"foo.stubs.source.test.api.contribution", "foo.stubs.source.system.api.contribution", "foo.stubs.source.api.contribution"},
- depApiSrcs: "android_test_stubs_current.from-text",
+ scope: apiScopeTest,
+ apiContributions: []string{"foo.stubs.source.test.api.contribution", "foo.stubs.source.system.api.contribution", "foo.stubs.source.api.contribution"},
+ fullApiSurfaceStub: "android_test_stubs_current.from-text",
},
{
- scope: apiScopeModuleLib,
- apiContributions: []string{"foo.stubs.source.module_lib.api.contribution", "foo.stubs.source.system.api.contribution", "foo.stubs.source.api.contribution"},
- depApiSrcs: "android_module_lib_stubs_current_full.from-text",
+ scope: apiScopeModuleLib,
+ apiContributions: []string{"foo.stubs.source.module_lib.api.contribution", "foo.stubs.source.system.api.contribution", "foo.stubs.source.api.contribution"},
+ fullApiSurfaceStub: "android_module_lib_stubs_current_full.from-text",
},
}
for _, c := range testCases {
m := result.ModuleForTests(c.scope.apiLibraryModuleName("foo"), "android_common").Module().(*ApiLibrary)
android.AssertArrayString(t, "Module expected to contain api contributions", c.apiContributions, m.properties.Api_contributions)
- android.AssertStringEquals(t, "Module expected to contain full api surface api library", c.depApiSrcs, *m.properties.Dep_api_srcs)
+ android.AssertStringEquals(t, "Module expected to contain full api surface api library", c.fullApiSurfaceStub, *m.properties.Full_api_surface_stub)
}
}
diff --git a/rust/bindgen.go b/rust/bindgen.go
index 96645b0..7dc1b4b 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -247,7 +247,7 @@
var cmd, cmdDesc string
if b.Properties.Custom_bindgen != "" {
- cmd = ctx.GetDirectDepWithTag(b.Properties.Custom_bindgen, customBindgenDepTag).(*Module).HostToolPath().String()
+ cmd = ctx.GetDirectDepWithTag(b.Properties.Custom_bindgen, customBindgenDepTag).(android.HostToolProvider).HostToolPath().String()
cmdDesc = b.Properties.Custom_bindgen
} else {
cmd = "$bindgenCmd"
diff --git a/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go
index 60c297b..ac23aab 100644
--- a/sdk/bootclasspath_fragment_sdk_test.go
+++ b/sdk/bootclasspath_fragment_sdk_test.go
@@ -1194,3 +1194,58 @@
expectedSnapshot, expectedCopyRules, expectedStubFlagsInputs, "")
})
}
+
+func TestSnapshotWithEmptyBootClasspathFragment(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForSdkTestWithJava,
+ java.PrepareForTestWithJavaDefaultModules,
+ java.PrepareForTestWithJavaSdkLibraryFiles,
+ java.FixtureWithLastReleaseApis("mysdklibrary", "mynewsdklibrary"),
+ java.FixtureConfigureApexBootJars("myapex:mysdklibrary", "myapex:mynewsdklibrary"),
+ prepareForSdkTestWithApex,
+ // Add a platform_bootclasspath that depends on the fragment.
+ fixtureAddPlatformBootclasspathForBootclasspathFragment("myapex", "mybootclasspathfragment"),
+ android.FixtureMergeEnv(map[string]string{
+ "SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE": "S",
+ }),
+ android.FixtureWithRootAndroidBp(`
+ sdk {
+ name: "mysdk",
+ apexes: ["myapex"],
+ }
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ min_sdk_version: "S",
+ bootclasspath_fragments: ["mybootclasspathfragment"],
+ }
+ bootclasspath_fragment {
+ name: "mybootclasspathfragment",
+ apex_available: ["myapex"],
+ contents: ["mysdklibrary", "mynewsdklibrary"],
+ hidden_api: {
+ split_packages: [],
+ },
+ }
+ java_sdk_library {
+ name: "mysdklibrary",
+ apex_available: ["myapex"],
+ srcs: ["Test.java"],
+ shared_library: false,
+ public: {enabled: true},
+ min_sdk_version: "Tiramisu",
+ }
+ java_sdk_library {
+ name: "mynewsdklibrary",
+ apex_available: ["myapex"],
+ srcs: ["Test.java"],
+ compile_dex: true,
+ public: {enabled: true},
+ min_sdk_version: "Tiramisu",
+ permitted_packages: ["mynewsdklibrary"],
+ }
+ `),
+ ).RunTest(t)
+
+ CheckSnapshot(t, result, "mysdk", "", checkAndroidBpContents(`// This is auto-generated. DO NOT EDIT.`))
+}
diff --git a/sdk/bp.go b/sdk/bp.go
index 7ff85a1..57eb2ca 100644
--- a/sdk/bp.go
+++ b/sdk/bp.go
@@ -311,13 +311,15 @@
}
func (m *bpModule) deepCopy() *bpModule {
- return m.transform(deepCopyTransformer)
+ return transformModule(m, deepCopyTransformer)
}
-func (m *bpModule) transform(transformer bpTransformer) *bpModule {
+func transformModule(m *bpModule, transformer bpTransformer) *bpModule {
transformedModule := transformer.transformModule(m)
- // Copy the contents of the returned property set into the module and then transform that.
- transformedModule.bpPropertySet, _ = transformPropertySet(transformer, "", transformedModule.bpPropertySet, nil)
+ if transformedModule != nil {
+ // Copy the contents of the returned property set into the module and then transform that.
+ transformedModule.bpPropertySet, _ = transformPropertySet(transformer, "", transformedModule.bpPropertySet, nil)
+ }
return transformedModule
}
diff --git a/sdk/systemserverclasspath_fragment_sdk_test.go b/sdk/systemserverclasspath_fragment_sdk_test.go
index 66c44c8..7ccc114 100644
--- a/sdk/systemserverclasspath_fragment_sdk_test.go
+++ b/sdk/systemserverclasspath_fragment_sdk_test.go
@@ -86,6 +86,51 @@
)
}
+func TestSnapshotWithEmptySystemServerClasspathFragment(t *testing.T) {
+ commonSdk := `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ min_sdk_version: "Tiramisu",
+ systemserverclasspath_fragments: ["mysystemserverclasspathfragment"],
+ }
+ systemserverclasspath_fragment {
+ name: "mysystemserverclasspathfragment",
+ apex_available: ["myapex"],
+ contents: ["mysdklibrary"],
+ }
+ java_sdk_library {
+ name: "mysdklibrary",
+ apex_available: ["myapex"],
+ srcs: ["Test.java"],
+ min_sdk_version: "34", // UpsideDownCake
+ }
+ sdk {
+ name: "mysdk",
+ apexes: ["myapex"],
+ }
+ `
+
+ result := android.GroupFixturePreparers(
+ prepareForSdkTestWithJava,
+ java.PrepareForTestWithJavaDefaultModules,
+ java.PrepareForTestWithJavaSdkLibraryFiles,
+ java.FixtureWithLastReleaseApis("mysdklibrary"),
+ dexpreopt.FixtureSetApexSystemServerJars("myapex:mysdklibrary"),
+ android.FixtureModifyEnv(func(env map[string]string) {
+ // targeting Tiramisu here means that we won't export mysdklibrary
+ env["SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE"] = "Tiramisu"
+ }),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.Platform_version_active_codenames = []string{"UpsideDownCake"}
+ }),
+ prepareForSdkTestWithApex,
+ android.FixtureWithRootAndroidBp(commonSdk),
+ ).RunTest(t)
+
+ CheckSnapshot(t, result, "mysdk", "", checkAndroidBpContents(`// This is auto-generated. DO NOT EDIT.`))
+}
+
func TestSnapshotWithSystemServerClasspathFragment(t *testing.T) {
commonSdk := `
diff --git a/sdk/update.go b/sdk/update.go
index d3c59b0..4c39fae 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -455,11 +455,14 @@
for _, module := range builder.prebuiltOrder {
// Prune any empty property sets.
- module = module.transform(pruneEmptySetTransformer{})
+ module = transformModule(module, pruneEmptySetTransformer{})
// Transform the module module to make it suitable for use in the snapshot.
- module.transform(snapshotTransformer)
- bpFile.AddModule(module)
+ module = transformModule(module, snapshotTransformer)
+ module = transformModule(module, emptyClasspathContentsTransformation{})
+ if module != nil {
+ bpFile.AddModule(module)
+ }
}
// generate Android.bp
@@ -835,9 +838,11 @@
}
func (t snapshotTransformation) transformModule(module *bpModule) *bpModule {
- // If the module is an internal member then use a unique name for it.
- name := module.Name()
- module.setProperty("name", t.builder.snapshotSdkMemberName(name, true))
+ if module != nil {
+ // If the module is an internal member then use a unique name for it.
+ name := module.Name()
+ module.setProperty("name", t.builder.snapshotSdkMemberName(name, true))
+ }
return module
}
@@ -850,6 +855,25 @@
}
}
+type emptyClasspathContentsTransformation struct {
+ identityTransformation
+}
+
+func (t emptyClasspathContentsTransformation) transformModule(module *bpModule) *bpModule {
+ classpathModuleTypes := []string{
+ "prebuilt_bootclasspath_fragment",
+ "prebuilt_systemserverclasspath_fragment",
+ }
+ if module != nil && android.InList(module.moduleType, classpathModuleTypes) {
+ if contents, ok := module.bpPropertySet.properties["contents"].([]string); ok {
+ if len(contents) == 0 {
+ return nil
+ }
+ }
+ }
+ return module
+}
+
type pruneEmptySetTransformer struct {
identityTransformation
}
diff --git a/tests/sbom_test.sh b/tests/sbom_test.sh
index 19987f2..30a1d37 100755
--- a/tests/sbom_test.sh
+++ b/tests/sbom_test.sh
@@ -223,4 +223,65 @@
cleanup "${out_dir}"
}
-test_sbom_aosp_cf_x86_64_phone
\ No newline at end of file
+function test_sbom_unbundled_apex {
+ # Setup
+ out_dir="$(setup)"
+
+ # run_soong to build com.android.adbd.apex
+ run_soong "module_arm64" "${out_dir}" "sbom deapexer" "com.android.adbd"
+
+ deapexer=${out_dir}/host/linux-x86/bin/deapexer
+ debugfs=${out_dir}/host/linux-x86/bin/debugfs_static
+ apex_file=${out_dir}/target/product/module_arm64/system/apex/com.android.adbd.apex
+ echo "============ Diffing files in $apex_file and SBOM"
+ set +e
+ # deapexer prints the list of all files and directories
+ # sed extracts the file/directory names
+ # grep removes directories
+ # sed removes leading ./ in file names
+ diff -I /system/apex/com.android.adbd.apex -I apex_manifest.pb \
+ <($deapexer --debugfs_path=$debugfs list --extents ${apex_file} | sed -E 's#(.*) \[.*\]$#\1#' | grep -v "/$" | sed -E 's#^\./(.*)#\1#' | sort -n) \
+ <(grep '"fileName": ' ${apex_file}.spdx.json | sed -E 's/.*"fileName": "(.*)",/\1/' | sort -n )
+
+ if [ $? != "0" ]; then
+ echo "Diffs found in $apex_file and SBOM"
+ exit 1
+ else
+ echo "No diffs."
+ fi
+ set -e
+
+ # Teardown
+ cleanup "${out_dir}"
+}
+
+function test_sbom_unbundled_apk {
+ # Setup
+ out_dir="$(setup)"
+
+ # run_soong to build Browser2.apk
+ run_soong "module_arm64" "${out_dir}" "sbom" "Browser2"
+
+ sbom_file=${out_dir}/target/product/module_arm64/system/product/app/Browser2/Browser2.apk.spdx.json
+ echo "============ Diffing files in Browser2.apk and SBOM"
+ set +e
+ # There is only one file in SBOM of APKs
+ diff \
+ <(echo "/system/product/app/Browser2/Browser2.apk" ) \
+ <(grep '"fileName": ' ${sbom_file} | sed -E 's/.*"fileName": "(.*)",/\1/' )
+
+ if [ $? != "0" ]; then
+ echo "Diffs found in $sbom_file"
+ exit 1
+ else
+ echo "No diffs."
+ fi
+ set -e
+
+ # Teardown
+ cleanup "${out_dir}"
+}
+
+test_sbom_aosp_cf_x86_64_phone
+test_sbom_unbundled_apex
+test_sbom_unbundled_apk
\ No newline at end of file
diff --git a/ui/build/config.go b/ui/build/config.go
index e642772..fb5f7dd 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -1375,10 +1375,15 @@
}
func (c *configImpl) UseRBE() bool {
+ // These alternate modes of running Soong do not use RBE / reclient.
+ if c.Bp2Build() || c.Queryview() || c.ApiBp2build() || c.JsonModuleGraph() {
+ return false
+ }
+
authType, _ := c.rbeAuth()
// Do not use RBE with prod credentials in scenarios when stubby doesn't exist, since
// its unlikely that we will be able to obtain necessary creds without stubby.
- if !c.StubbyExists() && strings.Contains(authType, "use_google_prod_creds"){
+ if !c.StubbyExists() && strings.Contains(authType, "use_google_prod_creds") {
return false
}
if v, ok := c.Environment().Get("USE_RBE"); ok {