summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--android/apex.go96
-rw-r--r--android/apex_test.go42
-rw-r--r--android/bazel.go30
-rw-r--r--android/bazel_handler.go2
-rw-r--r--android/module.go31
-rw-r--r--apex/Android.bp1
-rw-r--r--apex/apex.go52
-rw-r--r--apex/bootclasspath_fragment_test.go37
-rw-r--r--apex/platform_bootclasspath_test.go136
-rw-r--r--apex/prebuilt.go3
-rw-r--r--apex/systemserver_classpath_fragment_test.go78
-rw-r--r--bazel/aquery.go165
-rw-r--r--bazel/aquery_test.go87
-rw-r--r--bazel/properties.go8
-rw-r--r--bp2build/build_conversion_test.go27
-rw-r--r--bp2build/bzl_conversion_test.go2
-rw-r--r--bp2build/cc_library_conversion_test.go49
-rw-r--r--bp2build/cc_library_headers_conversion_test.go79
-rw-r--r--bp2build/cc_library_static_conversion_test.go247
-rw-r--r--bp2build/cc_object_conversion_test.go17
-rw-r--r--bp2build/constants.go5
-rw-r--r--bp2build/conversion_test.go6
-rw-r--r--bp2build/python_binary_conversion_test.go4
-rw-r--r--bp2build/sh_conversion_test.go4
-rw-r--r--bp2build/testing.go15
-rw-r--r--cc/Android.bp1
-rw-r--r--cc/bp2build.go60
-rw-r--r--cc/cc.go2
-rw-r--r--cc/config/global.go25
-rw-r--r--cc/linker.go4
-rw-r--r--cc/makevars.go4
-rw-r--r--cc/sanitize.go4
-rw-r--r--cc/sanitize_test.go204
-rw-r--r--dexpreopt/config.go10
-rw-r--r--java/base.go31
-rw-r--r--java/boot_jars.go2
-rw-r--r--java/bootclasspath.go11
-rw-r--r--java/bootclasspath_fragment.go125
-rw-r--r--java/classpath_fragment.go29
-rw-r--r--java/dexpreopt_bootjars.go5
-rw-r--r--java/dexpreopt_test.go48
-rw-r--r--java/hiddenapi.go128
-rw-r--r--java/hiddenapi_modular.go21
-rw-r--r--java/hiddenapi_singleton.go4
-rw-r--r--java/hiddenapi_singleton_test.go53
-rw-r--r--java/java.go22
-rw-r--r--java/platform_bootclasspath.go13
-rw-r--r--java/sdk_library.go19
-rw-r--r--java/systemserver_classpath_fragment.go76
-rw-r--r--java/systemserver_classpath_fragment_test.go25
-rw-r--r--java/testing.go13
-rwxr-xr-xtests/bootstrap_test.sh34
-rwxr-xr-xtests/bp2build_bazel_test.sh22
-rw-r--r--ui/build/finder.go4
54 files changed, 1719 insertions, 503 deletions
diff --git a/android/apex.go b/android/apex.go
index b01b700b8..4b744364a 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -36,11 +36,16 @@ var (
// Accessible via `ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)`
type ApexInfo struct {
// Name of the apex variation that this module (i.e. the apex variant of the module) is
- // mutated into, or "" for a platform (i.e. non-APEX) variant. Note that a module can be
- // included in multiple APEXes, in which case, the module is mutated into one or more
- // variants, each of which is for an APEX. The variants then can later be deduped if they
- // don't need to be compiled differently. This is an optimization done in
- // mergeApexVariations.
+ // mutated into, or "" for a platform (i.e. non-APEX) variant. Note that this name and the
+ // Soong module name of the APEX can be different. That happens when there is
+ // `override_apex` that overrides `apex`. In that case, both Soong modules have the same
+ // apex variation name which usually is `com.android.foo`. This name is also the `name`
+ // in the path `/apex/<name>` where this apex is activated on at runtime.
+ //
+ // Also note that a module can be included in multiple APEXes, in which case, the module is
+ // mutated into one or more variants, each of which is for an APEX. The variants then can
+ // later be deduped if they don't need to be compiled differently. This is an optimization
+ // done in mergeApexVariations.
ApexVariationName string
// ApiLevel that this module has to support at minimum.
@@ -52,11 +57,19 @@ type ApexInfo struct {
// The list of SDK modules that the containing apexBundle depends on.
RequiredSdks SdkRefs
- // List of apexBundles that this apex variant of the module is associated with. Initially,
- // the size of this list is one because one apex variant is associated with one apexBundle.
- // When multiple apex variants are merged in mergeApexVariations, ApexInfo struct of the
- // merged variant holds the list of apexBundles that are merged together.
- InApexes []string
+ // List of Apex variant names that this module is associated with. This initially is the
+ // same as the `ApexVariationName` field. Then when multiple apex variants are merged in
+ // mergeApexVariations, ApexInfo struct of the merged variant holds the list of apexBundles
+ // that are merged together.
+ InApexVariants []string
+
+ // List of APEX Soong module names that this module is part of. Note that the list includes
+ // different variations of the same APEX. For example, if module `foo` is included in the
+ // apex `com.android.foo`, and also if there is an override_apex module
+ // `com.mycompany.android.foo` overriding `com.android.foo`, then this list contains both
+ // `com.android.foo` and `com.mycompany.android.foo`. If the APEX Soong module is a
+ // prebuilt, the name here doesn't have the `prebuilt_` prefix.
+ InApexModules []string
// Pointers to the ApexContents struct each of which is for apexBundle modules that this
// module is part of. The ApexContents gives information about which modules the apexBundle
@@ -93,23 +106,33 @@ func (i ApexInfo) IsForPlatform() bool {
return i.ApexVariationName == ""
}
-// InApex tells whether this apex variant of the module is part of the given apexBundle or not.
-func (i ApexInfo) InApex(apex string) bool {
- for _, a := range i.InApexes {
- if a == apex {
+// InApexVariant tells whether this apex variant of the module is part of the given apexVariant or
+// not.
+func (i ApexInfo) InApexVariant(apexVariant string) bool {
+ for _, a := range i.InApexVariants {
+ if a == apexVariant {
return true
}
}
return false
}
-// InApexByBaseName tells whether this apex variant of the module is part of the given APEX or not,
-// where the APEX is specified by its canonical base name, i.e. typically beginning with
+// InApexByBaseName tells whether this apex variant of the module is part of the given apexVariant
+// or not, where the APEX is specified by its canonical base name, i.e. typically beginning with
// "com.android.". In particular this function doesn't differentiate between source and prebuilt
// APEXes, where the latter may have "prebuilt_" prefixes.
-func (i ApexInfo) InApexByBaseName(apex string) bool {
- for _, a := range i.InApexes {
- if RemoveOptionalPrebuiltPrefix(a) == apex {
+func (i ApexInfo) InApexVariantByBaseName(apexVariant string) bool {
+ for _, a := range i.InApexVariants {
+ if RemoveOptionalPrebuiltPrefix(a) == apexVariant {
+ return true
+ }
+ }
+ return false
+}
+
+func (i ApexInfo) InApexModule(apexModuleName string) bool {
+ for _, a := range i.InApexModules {
+ if a == apexModuleName {
return true
}
}
@@ -345,8 +368,21 @@ func (m *ApexModuleBase) ApexAvailable() []string {
func (m *ApexModuleBase) BuildForApex(apex ApexInfo) {
m.apexInfosLock.Lock()
defer m.apexInfosLock.Unlock()
- for _, v := range m.apexInfos {
+ for i, v := range m.apexInfos {
if v.ApexVariationName == apex.ApexVariationName {
+ if len(apex.InApexModules) != 1 {
+ panic(fmt.Errorf("Newly created apexInfo must be for a single APEX"))
+ }
+ // Even when the ApexVariantNames are the same, the given ApexInfo might
+ // actually be for different APEX. This can happen when an APEX is
+ // overridden via override_apex. For example, there can be two apexes
+ // `com.android.foo` (from the `apex` module type) and
+ // `com.mycompany.android.foo` (from the `override_apex` module type), both
+ // of which has the same ApexVariantName `com.android.foo`. Add the apex
+ // name to the list so that it's not lost.
+ if !InList(apex.InApexModules[0], v.InApexModules) {
+ m.apexInfos[i].InApexModules = append(m.apexInfos[i].InApexModules, apex.InApexModules[0])
+ }
return
}
}
@@ -496,21 +532,23 @@ func mergeApexVariations(ctx PathContext, apexInfos []ApexInfo) (merged []ApexIn
// Merge the ApexInfo together. If a compatible ApexInfo exists then merge the information from
// this one into it, otherwise create a new merged ApexInfo from this one and save it away so
// other ApexInfo instances can be merged into it.
- apexName := apexInfo.ApexVariationName
+ variantName := apexInfo.ApexVariationName
mergedName := apexInfo.mergedName(ctx)
if index, exists := seen[mergedName]; exists {
// Variants having the same mergedName are deduped
- merged[index].InApexes = append(merged[index].InApexes, apexName)
+ merged[index].InApexVariants = append(merged[index].InApexVariants, variantName)
+ merged[index].InApexModules = append(merged[index].InApexModules, apexInfo.InApexModules...)
merged[index].ApexContents = append(merged[index].ApexContents, apexInfo.ApexContents...)
merged[index].Updatable = merged[index].Updatable || apexInfo.Updatable
} else {
seen[mergedName] = len(merged)
apexInfo.ApexVariationName = mergedName
- apexInfo.InApexes = CopyOf(apexInfo.InApexes)
+ apexInfo.InApexVariants = CopyOf(apexInfo.InApexVariants)
+ apexInfo.InApexModules = CopyOf(apexInfo.InApexModules)
apexInfo.ApexContents = append([]*ApexContents(nil), apexInfo.ApexContents...)
merged = append(merged, apexInfo)
}
- aliases = append(aliases, [2]string{apexName, mergedName})
+ aliases = append(aliases, [2]string{variantName, mergedName})
}
return merged, aliases
}
@@ -583,15 +621,15 @@ func CreateApexVariations(mctx BottomUpMutatorContext, module ApexModule) []Modu
// in the same APEX have unique APEX variations so that the module can link against the right
// variant.
func UpdateUniqueApexVariationsForDeps(mctx BottomUpMutatorContext, am ApexModule) {
- // anyInSameApex returns true if the two ApexInfo lists contain any values in an InApexes
- // list in common. It is used instead of DepIsInSameApex because it needs to determine if
- // the dep is in the same APEX due to being directly included, not only if it is included
- // _because_ it is a dependency.
+ // anyInSameApex returns true if the two ApexInfo lists contain any values in an
+ // InApexVariants list in common. It is used instead of DepIsInSameApex because it needs to
+ // determine if the dep is in the same APEX due to being directly included, not only if it
+ // is included _because_ it is a dependency.
anyInSameApex := func(a, b []ApexInfo) bool {
collectApexes := func(infos []ApexInfo) []string {
var ret []string
for _, info := range infos {
- ret = append(ret, info.InApexes...)
+ ret = append(ret, info.InApexVariants...)
}
return ret
}
diff --git a/android/apex_test.go b/android/apex_test.go
index 109b1c8b2..e1123692d 100644
--- a/android/apex_test.go
+++ b/android/apex_test.go
@@ -33,10 +33,10 @@ func Test_mergeApexVariations(t *testing.T) {
{
name: "single",
in: []ApexInfo{
- {"foo", FutureApiLevel, false, nil, []string{"foo"}, nil, NotForPrebuiltApex},
+ {"foo", FutureApiLevel, false, nil, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex},
},
wantMerged: []ApexInfo{
- {"apex10000", FutureApiLevel, false, nil, []string{"foo"}, nil, NotForPrebuiltApex},
+ {"apex10000", FutureApiLevel, false, nil, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex},
},
wantAliases: [][2]string{
{"foo", "apex10000"},
@@ -45,11 +45,11 @@ func Test_mergeApexVariations(t *testing.T) {
{
name: "merge",
in: []ApexInfo{
- {"foo", FutureApiLevel, false, SdkRefs{{"baz", "1"}}, []string{"foo"}, nil, NotForPrebuiltApex},
- {"bar", FutureApiLevel, false, SdkRefs{{"baz", "1"}}, []string{"bar"}, nil, NotForPrebuiltApex},
+ {"foo", FutureApiLevel, false, SdkRefs{{"baz", "1"}}, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex},
+ {"bar", FutureApiLevel, false, SdkRefs{{"baz", "1"}}, []string{"bar"}, []string{"bar"}, nil, NotForPrebuiltApex},
},
wantMerged: []ApexInfo{
- {"apex10000_baz_1", FutureApiLevel, false, SdkRefs{{"baz", "1"}}, []string{"bar", "foo"}, nil, false}},
+ {"apex10000_baz_1", FutureApiLevel, false, SdkRefs{{"baz", "1"}}, []string{"bar", "foo"}, []string{"bar", "foo"}, nil, false}},
wantAliases: [][2]string{
{"bar", "apex10000_baz_1"},
{"foo", "apex10000_baz_1"},
@@ -58,12 +58,12 @@ func Test_mergeApexVariations(t *testing.T) {
{
name: "don't merge version",
in: []ApexInfo{
- {"foo", FutureApiLevel, false, nil, []string{"foo"}, nil, NotForPrebuiltApex},
- {"bar", uncheckedFinalApiLevel(30), false, nil, []string{"bar"}, nil, NotForPrebuiltApex},
+ {"foo", FutureApiLevel, false, nil, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex},
+ {"bar", uncheckedFinalApiLevel(30), false, nil, []string{"bar"}, []string{"bar"}, nil, NotForPrebuiltApex},
},
wantMerged: []ApexInfo{
- {"apex30", uncheckedFinalApiLevel(30), false, nil, []string{"bar"}, nil, NotForPrebuiltApex},
- {"apex10000", FutureApiLevel, false, nil, []string{"foo"}, nil, NotForPrebuiltApex},
+ {"apex30", uncheckedFinalApiLevel(30), false, nil, []string{"bar"}, []string{"bar"}, nil, NotForPrebuiltApex},
+ {"apex10000", FutureApiLevel, false, nil, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex},
},
wantAliases: [][2]string{
{"bar", "apex30"},
@@ -73,11 +73,11 @@ func Test_mergeApexVariations(t *testing.T) {
{
name: "merge updatable",
in: []ApexInfo{
- {"foo", FutureApiLevel, false, nil, []string{"foo"}, nil, NotForPrebuiltApex},
- {"bar", FutureApiLevel, true, nil, []string{"bar"}, nil, NotForPrebuiltApex},
+ {"foo", FutureApiLevel, false, nil, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex},
+ {"bar", FutureApiLevel, true, nil, []string{"bar"}, []string{"bar"}, nil, NotForPrebuiltApex},
},
wantMerged: []ApexInfo{
- {"apex10000", FutureApiLevel, true, nil, []string{"bar", "foo"}, nil, NotForPrebuiltApex},
+ {"apex10000", FutureApiLevel, true, nil, []string{"bar", "foo"}, []string{"bar", "foo"}, nil, NotForPrebuiltApex},
},
wantAliases: [][2]string{
{"bar", "apex10000"},
@@ -87,12 +87,12 @@ func Test_mergeApexVariations(t *testing.T) {
{
name: "don't merge sdks",
in: []ApexInfo{
- {"foo", FutureApiLevel, false, SdkRefs{{"baz", "1"}}, []string{"foo"}, nil, NotForPrebuiltApex},
- {"bar", FutureApiLevel, false, SdkRefs{{"baz", "2"}}, []string{"bar"}, nil, NotForPrebuiltApex},
+ {"foo", FutureApiLevel, false, SdkRefs{{"baz", "1"}}, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex},
+ {"bar", FutureApiLevel, false, SdkRefs{{"baz", "2"}}, []string{"bar"}, []string{"bar"}, nil, NotForPrebuiltApex},
},
wantMerged: []ApexInfo{
- {"apex10000_baz_2", FutureApiLevel, false, SdkRefs{{"baz", "2"}}, []string{"bar"}, nil, NotForPrebuiltApex},
- {"apex10000_baz_1", FutureApiLevel, false, SdkRefs{{"baz", "1"}}, []string{"foo"}, nil, NotForPrebuiltApex},
+ {"apex10000_baz_2", FutureApiLevel, false, SdkRefs{{"baz", "2"}}, []string{"bar"}, []string{"bar"}, nil, NotForPrebuiltApex},
+ {"apex10000_baz_1", FutureApiLevel, false, SdkRefs{{"baz", "1"}}, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex},
},
wantAliases: [][2]string{
{"bar", "apex10000_baz_2"},
@@ -102,15 +102,15 @@ func Test_mergeApexVariations(t *testing.T) {
{
name: "don't merge when for prebuilt_apex",
in: []ApexInfo{
- {"foo", FutureApiLevel, false, nil, []string{"foo"}, nil, NotForPrebuiltApex},
- {"bar", FutureApiLevel, true, nil, []string{"bar"}, nil, NotForPrebuiltApex},
+ {"foo", FutureApiLevel, false, nil, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex},
+ {"bar", FutureApiLevel, true, nil, []string{"bar"}, []string{"bar"}, nil, NotForPrebuiltApex},
// This one should not be merged in with the others because it is for
// a prebuilt_apex.
- {"baz", FutureApiLevel, true, nil, []string{"baz"}, nil, ForPrebuiltApex},
+ {"baz", FutureApiLevel, true, nil, []string{"baz"}, []string{"baz"}, nil, ForPrebuiltApex},
},
wantMerged: []ApexInfo{
- {"apex10000", FutureApiLevel, true, nil, []string{"bar", "foo"}, nil, NotForPrebuiltApex},
- {"baz", FutureApiLevel, true, nil, []string{"baz"}, nil, ForPrebuiltApex},
+ {"apex10000", FutureApiLevel, true, nil, []string{"bar", "foo"}, []string{"bar", "foo"}, nil, NotForPrebuiltApex},
+ {"baz", FutureApiLevel, true, nil, []string{"baz"}, []string{"baz"}, nil, ForPrebuiltApex},
},
wantAliases: [][2]string{
{"bar", "apex10000"},
diff --git a/android/bazel.go b/android/bazel.go
index ba29f6d0f..2d4755fb5 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -160,14 +160,6 @@ var (
// Per-module denylist to always opt modules out of both bp2build and mixed builds.
bp2buildModuleDoNotConvertList = []string{
// Things that transitively depend on unconverted libc_* modules.
- "libc_nopthread", // http://b/186821550, cc_library_static, depends on //bionic/libc:libc_bionic_ndk (http://b/186822256)
- // also depends on //bionic/libc:libc_tzcode (http://b/186822591)
- // also depends on //bionic/libc:libstdc++ (http://b/186822597)
- "libc_common", // http://b/186821517, cc_library_static, depends on //bionic/libc:libc_nopthread (http://b/186821550)
- "libc_common_static", // http://b/186824119, cc_library_static, depends on //bionic/libc:libc_common (http://b/186821517)
- "libc_common_shared", // http://b/186824118, cc_library_static, depends on //bionic/libc:libc_common (http://b/186821517)
- "libc_nomalloc", // http://b/186825031, cc_library_static, depends on //bionic/libc:libc_common (http://b/186821517)
-
"libbionic_spawn_benchmark", // http://b/186824595, cc_library_static, depends on //external/google-benchmark (http://b/186822740)
// also depends on //system/logging/liblog:liblog (http://b/186822772)
@@ -186,12 +178,10 @@ var (
"liblinker_malloc", // http://b/186826466, cc_library_static, depends on //external/zlib:libz (http://b/186823782)
// also depends on //system/libziparchive:libziparchive (http://b/186823656)
// also depends on //system/logging/liblog:liblog (http://b/186822772)
- "libc_jemalloc_wrapper", // http://b/187012490, cc_library_static, depends on //external/jemalloc_new:libjemalloc5 (http://b/186828626)
- "libc_ndk", // http://b/187013218, cc_library_static, depends on //bionic/libm:libm (http://b/183064661)
- "libc", // http://b/183064430, cc_library, depends on //external/jemalloc_new:libjemalloc5 (http://b/186828626)
- "libc_bionic_ndk", // http://b/186822256, cc_library_static, fatal error: 'generated_android_ids.h' file not found
- "libc_malloc_hooks", // http://b/187016307, cc_library, ld.lld: error: undefined symbol: __malloc_hook
- "libm", // http://b/183064661, cc_library, math.h:25:16: error: unexpected token in argument list
+ "libc_ndk", // http://b/187013218, cc_library_static, depends on //bionic/libm:libm (http://b/183064661)
+ "libc", // http://b/183064430, cc_library, depends on //external/jemalloc_new:libjemalloc5 (http://b/186828626)
+ "libc_malloc_hooks", // http://b/187016307, cc_library, ld.lld: error: undefined symbol: __malloc_hook
+ "libm", // http://b/183064661, cc_library, math.h:25:16: error: unexpected token in argument list
// http://b/186823769: Needs C++ STL support, includes from unconverted standard libraries in //external/libcxx
// c++_static
@@ -211,7 +201,6 @@ var (
"note_memtag_heap_async", // http://b/185127353: cc_library_static, error: feature.h not found
"note_memtag_heap_sync", // http://b/185127353: cc_library_static, error: feature.h not found
- "libjemalloc5", // cc_library, ld.lld: error: undefined symbol: memset
"gwp_asan_crash_handler", // cc_library, ld.lld: error: undefined symbol: memset
// Tests. Handle later.
@@ -224,19 +213,26 @@ var (
// Per-module denylist of cc_library modules to only generate the static
// variant if their shared variant isn't ready or buildable by Bazel.
bp2buildCcLibraryStaticOnlyList = []string{
- "libstdc++", // http://b/186822597, cc_library, ld.lld: error: undefined symbol: __errno
+ "libstdc++", // http://b/186822597, cc_library, ld.lld: error: undefined symbol: __errno
+ "libjemalloc5", // http://b/188503688, cc_library, `target: { android: { enabled: false } }` for android targets.
}
// Per-module denylist to opt modules out of mixed builds. Such modules will
// still be generated via bp2build.
mixedBuildsDisabledList = []string{
+ "libc_bionic_ndk", // cparsons@ cc_library_static, depends on //bionic/libc:libsystemproperties
+ "libc_common", // cparsons@ cc_library_static, depends on //bionic/libc:libc_nopthread
+ "libc_common_static", // cparsons@ cc_library_static, depends on //bionic/libc:libc_common
+ "libc_common_shared", // cparsons@ cc_library_static, depends on //bionic/libc:libc_common
"libc_netbsd", // lberki@, cc_library_static, version script assignment of 'LIBC_PRIVATE' to symbol 'SHA1Final' failed: symbol not defined
+ "libc_nopthread", // cparsons@ cc_library_static, depends on //bionic/libc:libc_bionic_ndk
"libc_openbsd", // ruperts@, cc_library_static, OK for bp2build but error: duplicate symbol: strcpy for mixed builds
"libsystemproperties", // cparsons@, cc_library_static, wrong include paths
"libpropertyinfoparser", // cparsons@, cc_library_static, wrong include paths
"libarm-optimized-routines-string", // jingwen@, cc_library_static, OK for bp2build but b/186615213 (asflags not handled in bp2build), version script assignment of 'LIBC' to symbol 'memcmp' failed: symbol not defined (also for memrchr, strnlen)
"fmtlib_ndk", // http://b/187040371, cc_library_static, OK for bp2build but format-inl.h:11:10: fatal error: 'cassert' file not found for mixed builds
- }
+ "libc_nomalloc", // cc_library_static, OK for bp2build but ld.lld: error: undefined symbol: pthread_mutex_lock (and others)
+ }
// Used for quicker lookups
bp2buildModuleDoNotConvert = map[string]bool{}
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index 77d48b304..a1206dc53 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -333,7 +333,7 @@ func (r *builtinBazelRunner) issueBazelCommand(paths *bazelPaths, runName bazel.
// The actual platform values here may be overridden by configuration
// transitions from the buildroot.
cmdFlags = append(cmdFlags,
- fmt.Sprintf("--platforms=%s", "//build/bazel/platforms:android_x86_64"))
+ fmt.Sprintf("--platforms=%s", "//build/bazel/platforms:android_arm"))
cmdFlags = append(cmdFlags,
fmt.Sprintf("--extra_toolchains=%s", "//prebuilts/clang/host/linux-x86:all"))
// This should be parameterized on the host OS, but let's restrict to linux
diff --git a/android/module.go b/android/module.go
index c9a1662bb..69572dd23 100644
--- a/android/module.go
+++ b/android/module.go
@@ -1809,8 +1809,8 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
if m.Enabled() {
// ensure all direct android.Module deps are enabled
ctx.VisitDirectDepsBlueprint(func(bm blueprint.Module) {
- if _, ok := bm.(Module); ok {
- ctx.validateAndroidModule(bm, ctx.baseModuleContext.strictVisitDeps)
+ if m, ok := bm.(Module); ok {
+ ctx.validateAndroidModule(bm, ctx.OtherModuleDependencyTag(m), ctx.baseModuleContext.strictVisitDeps)
}
})
@@ -2234,7 +2234,12 @@ func (b *baseModuleContext) AddMissingDependencies(deps []string) {
}
}
-func (b *baseModuleContext) validateAndroidModule(module blueprint.Module, strict bool) Module {
+type AllowDisabledModuleDependency interface {
+ blueprint.DependencyTag
+ AllowDisabledModuleDependency(target Module) bool
+}
+
+func (b *baseModuleContext) validateAndroidModule(module blueprint.Module, tag blueprint.DependencyTag, strict bool) Module {
aModule, _ := module.(Module)
if !strict {
@@ -2247,10 +2252,12 @@ func (b *baseModuleContext) validateAndroidModule(module blueprint.Module, stric
}
if !aModule.Enabled() {
- if b.Config().AllowMissingDependencies() {
- b.AddMissingDependencies([]string{b.OtherModuleName(aModule)})
- } else {
- b.ModuleErrorf("depends on disabled module %q", b.OtherModuleName(aModule))
+ if t, ok := tag.(AllowDisabledModuleDependency); !ok || !t.AllowDisabledModuleDependency(aModule) {
+ if b.Config().AllowMissingDependencies() {
+ b.AddMissingDependencies([]string{b.OtherModuleName(aModule)})
+ } else {
+ b.ModuleErrorf("depends on disabled module %q", b.OtherModuleName(aModule))
+ }
}
return nil
}
@@ -2343,7 +2350,7 @@ func (b *baseModuleContext) VisitDirectDepsBlueprint(visit func(blueprint.Module
func (b *baseModuleContext) VisitDirectDeps(visit func(Module)) {
b.bp.VisitDirectDeps(func(module blueprint.Module) {
- if aModule := b.validateAndroidModule(module, b.strictVisitDeps); aModule != nil {
+ if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
visit(aModule)
}
})
@@ -2351,7 +2358,7 @@ func (b *baseModuleContext) VisitDirectDeps(visit func(Module)) {
func (b *baseModuleContext) VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) {
b.bp.VisitDirectDeps(func(module blueprint.Module) {
- if aModule := b.validateAndroidModule(module, b.strictVisitDeps); aModule != nil {
+ if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
if b.bp.OtherModuleDependencyTag(aModule) == tag {
visit(aModule)
}
@@ -2363,7 +2370,7 @@ func (b *baseModuleContext) VisitDirectDepsIf(pred func(Module) bool, visit func
b.bp.VisitDirectDepsIf(
// pred
func(module blueprint.Module) bool {
- if aModule := b.validateAndroidModule(module, b.strictVisitDeps); aModule != nil {
+ if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
return pred(aModule)
} else {
return false
@@ -2377,7 +2384,7 @@ func (b *baseModuleContext) VisitDirectDepsIf(pred func(Module) bool, visit func
func (b *baseModuleContext) VisitDepsDepthFirst(visit func(Module)) {
b.bp.VisitDepsDepthFirst(func(module blueprint.Module) {
- if aModule := b.validateAndroidModule(module, b.strictVisitDeps); aModule != nil {
+ if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
visit(aModule)
}
})
@@ -2387,7 +2394,7 @@ func (b *baseModuleContext) VisitDepsDepthFirstIf(pred func(Module) bool, visit
b.bp.VisitDepsDepthFirstIf(
// pred
func(module blueprint.Module) bool {
- if aModule := b.validateAndroidModule(module, b.strictVisitDeps); aModule != nil {
+ if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
return pred(aModule)
} else {
return false
diff --git a/apex/Android.bp b/apex/Android.bp
index e234181d3..14c877100 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -32,6 +32,7 @@ bootstrap_go_package {
"apex_test.go",
"bootclasspath_fragment_test.go",
"platform_bootclasspath_test.go",
+ "systemserver_classpath_fragment_test.go",
"vndk_test.go",
],
pluginFor: ["soong_build"],
diff --git a/apex/apex.go b/apex/apex.go
index a8fbf2274..da4f472d1 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -102,6 +102,9 @@ type apexBundleProperties struct {
// List of bootclasspath fragments that are embedded inside this APEX bundle.
Bootclasspath_fragments []string
+ // List of systemserverclasspath fragments that are embedded inside this APEX bundle.
+ Systemserverclasspath_fragments []string
+
// List of java libraries that are embedded inside this APEX bundle.
Java_libs []string
@@ -575,6 +578,7 @@ var (
executableTag = dependencyTag{name: "executable", payload: true}
fsTag = dependencyTag{name: "filesystem", payload: true}
bcpfTag = dependencyTag{name: "bootclasspathFragment", payload: true, sourceOnly: true}
+ sscpfTag = dependencyTag{name: "systemserverclasspathFragment", payload: true, sourceOnly: true}
compatConfigTag = dependencyTag{name: "compatConfig", payload: true, sourceOnly: true}
javaLibTag = dependencyTag{name: "javaLib", payload: true}
jniLibTag = dependencyTag{name: "jniLib", payload: true}
@@ -755,6 +759,7 @@ func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) {
// Common-arch dependencies come next
commonVariation := ctx.Config().AndroidCommonTarget.Variations()
ctx.AddFarVariationDependencies(commonVariation, bcpfTag, a.properties.Bootclasspath_fragments...)
+ ctx.AddFarVariationDependencies(commonVariation, sscpfTag, a.properties.Systemserverclasspath_fragments...)
ctx.AddFarVariationDependencies(commonVariation, javaLibTag, a.properties.Java_libs...)
ctx.AddFarVariationDependencies(commonVariation, bpfTag, a.properties.Bpfs...)
ctx.AddFarVariationDependencies(commonVariation, fsTag, a.properties.Filesystems...)
@@ -901,12 +906,16 @@ func (a *apexBundle) ApexInfoMutator(mctx android.TopDownMutatorContext) {
// This is the main part of this mutator. Mark the collected dependencies that they need to
// be built for this apexBundle.
+
+ // Note that there are many different names.
+ // ApexVariationName: this is the name of the apex variation
apexInfo := android.ApexInfo{
- ApexVariationName: mctx.ModuleName(),
+ ApexVariationName: mctx.ModuleName(), // could be com.android.foo
MinSdkVersion: minSdkVersion,
RequiredSdks: a.RequiredSdks(),
Updatable: a.Updatable(),
- InApexes: []string{mctx.ModuleName()},
+ InApexVariants: []string{mctx.ModuleName()}, // could be com.android.foo
+ InApexModules: []string{a.Name()}, // could be com.mycompany.android.foo
ApexContents: []*android.ApexContents{apexContents},
}
mctx.WalkDeps(func(child, parent android.Module) bool {
@@ -1599,7 +1608,7 @@ func (a *apexBundle) WalkPayloadDeps(ctx android.ModuleContext, do android.Paylo
}
ai := ctx.OtherModuleProvider(child, android.ApexInfoProvider).(android.ApexInfo)
- externalDep := !android.InList(ctx.ModuleName(), ai.InApexes)
+ externalDep := !android.InList(ctx.ModuleName(), ai.InApexVariants)
// Visit actually
return do(ctx, parent, am, externalDep)
@@ -1715,6 +1724,15 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
filesInfo = append(filesInfo, filesToAdd...)
return true
}
+ case sscpfTag:
+ {
+ if _, ok := child.(*java.SystemServerClasspathModule); !ok {
+ ctx.PropertyErrorf("systemserverclasspath_fragments", "%q is not a systemserverclasspath_fragment module", depName)
+ return false
+ }
+ filesInfo = append(filesInfo, apexClasspathFragmentProtoFile(ctx, child))
+ return true
+ }
case javaLibTag:
switch child.(type) {
case *java.Library, *java.SdkLibrary, *java.DexImport, *java.SdkLibraryImport, *java.Import:
@@ -1941,7 +1959,16 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
default:
ctx.PropertyErrorf("bootclasspath_fragments", "bootclasspath_fragment content %q of type %q is not supported", depName, ctx.OtherModuleType(child))
}
-
+ } else if java.IsSystemServerClasspathFragmentContentDepTag(depTag) {
+ // Add the contents of the systemserverclasspath fragment to the apex.
+ switch child.(type) {
+ case *java.Library, *java.SdkLibrary:
+ af := apexFileForJavaModule(ctx, child.(javaModule))
+ filesInfo = append(filesInfo, af)
+ return true // track transitive dependencies
+ default:
+ ctx.PropertyErrorf("systemserverclasspath_fragments", "systemserverclasspath_fragment content %q of type %q is not supported", depName, ctx.OtherModuleType(child))
+ }
} else if _, ok := depTag.(android.CopyDirectlyInAnyApexTag); ok {
// nothing
} else if am.CanHaveApexVariants() && am.IsInstallableToApex() {
@@ -2106,13 +2133,19 @@ func apexBootclasspathFragmentFiles(ctx android.ModuleContext, module blueprint.
}
// Add classpaths.proto config.
- classpathProtoOutput := bootclasspathFragmentInfo.ClasspathFragmentProtoOutput
- classpathProto := newApexFile(ctx, classpathProtoOutput, classpathProtoOutput.Base(), bootclasspathFragmentInfo.ClasspathFragmentProtoInstallDir.Rel(), etc, nil)
- filesToAdd = append(filesToAdd, classpathProto)
+ filesToAdd = append(filesToAdd, apexClasspathFragmentProtoFile(ctx, module))
return filesToAdd
}
+// apexClasspathFragmentProtoFile returns apexFile structure defining the classpath.proto config that
+// the module contributes to the apex.
+func apexClasspathFragmentProtoFile(ctx android.ModuleContext, module blueprint.Module) apexFile {
+ fragmentInfo := ctx.OtherModuleProvider(module, java.ClasspathFragmentProtoContentInfoProvider).(java.ClasspathFragmentProtoContentInfo)
+ classpathProtoOutput := fragmentInfo.ClasspathFragmentProtoOutput
+ return newApexFile(ctx, classpathProtoOutput, classpathProtoOutput.Base(), fragmentInfo.ClasspathFragmentProtoInstallDir.Rel(), etc, nil)
+}
+
// apexFileForBootclasspathFragmentContentModule creates an apexFile for a bootclasspath_fragment
// content module, i.e. a library that is part of the bootclasspath.
func apexFileForBootclasspathFragmentContentModule(ctx android.ModuleContext, fragmentModule blueprint.Module, javaModule javaModule) apexFile {
@@ -2120,7 +2153,10 @@ func apexFileForBootclasspathFragmentContentModule(ctx android.ModuleContext, fr
// Get the dexBootJar from the bootclasspath_fragment as that is responsible for performing the
// hidden API encpding.
- dexBootJar := bootclasspathFragmentInfo.DexBootJarPathForContentModule(javaModule)
+ dexBootJar, err := bootclasspathFragmentInfo.DexBootJarPathForContentModule(javaModule)
+ if err != nil {
+ ctx.ModuleErrorf("%s", err)
+ }
// Create an apexFile as for a normal java module but with the dex boot jar provided by the
// bootclasspath_fragment.
diff --git a/apex/bootclasspath_fragment_test.go b/apex/bootclasspath_fragment_test.go
index 7bb3ff611..9a8c7d0b6 100644
--- a/apex/bootclasspath_fragment_test.go
+++ b/apex/bootclasspath_fragment_test.go
@@ -433,6 +433,14 @@ func TestBootclasspathFragmentContentsNoName(t *testing.T) {
result := android.GroupFixturePreparers(
prepareForTestWithBootclasspathFragment,
prepareForTestWithMyapex,
+ // Configure bootclasspath jars to ensure that hidden API encoding is performed on them.
+ java.FixtureConfigureBootJars("myapex:foo", "myapex:bar"),
+ // Make sure that the frameworks/base/Android.bp file exists as otherwise hidden API encoding
+ // is disabled.
+ android.FixtureAddTextFile("frameworks/base/Android.bp", ""),
+
+ java.PrepareForTestWithJavaSdkLibraryFiles,
+ java.FixtureWithLastReleaseApis("foo"),
).RunTestWithBp(t, `
apex {
name: "myapex",
@@ -449,10 +457,11 @@ func TestBootclasspathFragmentContentsNoName(t *testing.T) {
private_key: "testkey.pem",
}
- java_library {
+ java_sdk_library {
name: "foo",
srcs: ["b.java"],
- installable: true,
+ shared_library: false,
+ public: {enabled: true},
apex_available: [
"myapex",
],
@@ -491,6 +500,30 @@ func TestBootclasspathFragmentContentsNoName(t *testing.T) {
`myapex.key`,
`mybootclasspathfragment`,
})
+
+ apex := result.ModuleForTests("myapex", "android_common_myapex_image")
+ apexRule := apex.Rule("apexRule")
+ copyCommands := apexRule.Args["copy_commands"]
+
+ // Make sure that the fragment provides the hidden API encoded dex jars to the APEX.
+ fragment := result.Module("mybootclasspathfragment", "android_common_apex10000")
+
+ info := result.ModuleProvider(fragment, java.BootclasspathFragmentApexContentInfoProvider).(java.BootclasspathFragmentApexContentInfo)
+
+ checkFragmentExportedDexJar := func(name string, expectedDexJar string) {
+ module := result.Module(name, "android_common_apex10000")
+ dexJar, err := info.DexBootJarPathForContentModule(module)
+ if err != nil {
+ t.Error(err)
+ }
+ android.AssertPathRelativeToTopEquals(t, name+" dex", expectedDexJar, dexJar)
+
+ expectedCopyCommand := fmt.Sprintf("&& cp -f %s out/soong/.intermediates/myapex/android_common_myapex_image/image.apex/javalib/%s.jar", expectedDexJar, name)
+ android.AssertStringDoesContain(t, name+" apex copy command", copyCommands, expectedCopyCommand)
+ }
+
+ checkFragmentExportedDexJar("foo", "out/soong/.intermediates/foo/android_common_apex10000/hiddenapi/foo.jar")
+ checkFragmentExportedDexJar("bar", "out/soong/.intermediates/bar/android_common_apex10000/hiddenapi/bar.jar")
}
// TODO(b/177892522) - add test for host apex.
diff --git a/apex/platform_bootclasspath_test.go b/apex/platform_bootclasspath_test.go
index 52b1689ba..ce12f4635 100644
--- a/apex/platform_bootclasspath_test.go
+++ b/apex/platform_bootclasspath_test.go
@@ -20,6 +20,7 @@ import (
"android/soong/android"
"android/soong/java"
"github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
)
// Contains tests for platform_bootclasspath logic from java/platform_bootclasspath.go that requires
@@ -174,6 +175,141 @@ func TestPlatformBootclasspathDependencies(t *testing.T) {
})
}
+// TestPlatformBootclasspath_AlwaysUsePrebuiltSdks verifies that the build does not fail when
+// AlwaysUsePrebuiltSdk() returns true. The structure of the modules in this test matches what
+// currently exists in some places in the Android build but it is not the intended structure. It is
+// in fact an invalid structure that should cause build failures. However, fixing that structure
+// will take too long so in the meantime this tests the workarounds to avoid build breakages.
+//
+// The main issues with this structure are:
+// 1. There is no prebuilt_bootclasspath_fragment referencing the "foo" java_sdk_library_import.
+// 2. There is no prebuilt_apex/apex_set which makes the dex implementation jar available to the
+// prebuilt_bootclasspath_fragment and the "foo" java_sdk_library_import.
+//
+// Together these cause the following symptoms:
+// 1. The "foo" java_sdk_library_import does not have a dex implementation jar.
+// 2. The "foo" java_sdk_library_import does not have a myapex variant.
+//
+// TODO(b/179354495): Fix the structure in this test once the main Android build has been fixed.
+func TestPlatformBootclasspath_AlwaysUsePrebuiltSdks(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForTestWithPlatformBootclasspath,
+ prepareForTestWithMyapex,
+ // Configure two libraries, the first is a java_sdk_library whose prebuilt will be used because
+ // of AlwaysUsePrebuiltsSdk() but does not have an appropriate apex variant and does not provide
+ // a boot dex jar. The second is a normal library that is unaffected. The order matters because
+ // if the dependency on myapex:foo is filtered out because of either of those conditions then
+ // the dependencies resolved by the platform_bootclasspath will not match the configured list
+ // and so will fail the test.
+ java.FixtureConfigureUpdatableBootJars("myapex:foo", "myapex:bar"),
+ java.PrepareForTestWithJavaSdkLibraryFiles,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.Always_use_prebuilt_sdks = proptools.BoolPtr(true)
+ }),
+ java.FixtureWithPrebuiltApis(map[string][]string{
+ "current": {},
+ "30": {"foo"},
+ }),
+ ).RunTestWithBp(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ bootclasspath_fragments: [
+ "mybootclasspath-fragment",
+ ],
+ updatable: false,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ java_library {
+ name: "bar",
+ srcs: ["b.java"],
+ installable: true,
+ apex_available: ["myapex"],
+ permitted_packages: ["bar"],
+ }
+
+ java_sdk_library {
+ name: "foo",
+ srcs: ["b.java"],
+ shared_library: false,
+ public: {
+ enabled: true,
+ },
+ apex_available: ["myapex"],
+ permitted_packages: ["foo"],
+ }
+
+ // A prebuilt java_sdk_library_import that is not preferred by default but will be preferred
+ // because AlwaysUsePrebuiltSdks() is true.
+ java_sdk_library_import {
+ name: "foo",
+ prefer: false,
+ shared_library: false,
+ public: {
+ jars: ["sdk_library/public/foo-stubs.jar"],
+ stub_srcs: ["sdk_library/public/foo_stub_sources"],
+ current_api: "sdk_library/public/foo.txt",
+ removed_api: "sdk_library/public/foo-removed.txt",
+ sdk_version: "current",
+ },
+ apex_available: ["myapex"],
+ }
+
+ // This always depends on the source foo module, its dependencies are not affected by the
+ // AlwaysUsePrebuiltSdks().
+ bootclasspath_fragment {
+ name: "mybootclasspath-fragment",
+ apex_available: [
+ "myapex",
+ ],
+ contents: [
+ "foo", "bar",
+ ],
+ }
+
+ platform_bootclasspath {
+ name: "myplatform-bootclasspath",
+ }
+`,
+ )
+
+ java.CheckPlatformBootclasspathModules(t, result, "myplatform-bootclasspath", []string{
+ // The configured contents of BootJars.
+ "platform:prebuilt_foo", // Note: This is the platform not myapex variant.
+ "myapex:bar",
+ })
+
+ // Make sure that the myplatform-bootclasspath has the correct dependencies.
+ CheckModuleDependencies(t, result.TestContext, "myplatform-bootclasspath", "android_common", []string{
+ // The following are stubs.
+ "platform:prebuilt_sdk_public_current_android",
+ "platform:prebuilt_sdk_system_current_android",
+ "platform:prebuilt_sdk_test_current_android",
+
+ // Not a prebuilt as no prebuilt existed when it was added.
+ "platform:legacy.core.platform.api.stubs",
+
+ // Needed for generating the boot image.
+ `platform:dex2oatd`,
+
+ // The platform_bootclasspath intentionally adds dependencies on both source and prebuilt
+ // modules when available as it does not know which one will be preferred.
+ //
+ // The source module has an APEX variant but the prebuilt does not.
+ "myapex:foo",
+ "platform:prebuilt_foo",
+
+ // Only a source module exists.
+ "myapex:bar",
+ })
+}
+
// CheckModuleDependencies checks the dependencies of the selected module against the expected list.
//
// The expected list must be a list of strings of the form "<apex>:<module>", where <apex> is the
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index 9d632a9b1..6125ef50f 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -230,7 +230,8 @@ func (p *prebuiltCommon) apexInfoMutator(mctx android.TopDownMutatorContext) {
// Create an ApexInfo for the prebuilt_apex.
apexInfo := android.ApexInfo{
ApexVariationName: android.RemoveOptionalPrebuiltPrefix(mctx.ModuleName()),
- InApexes: []string{mctx.ModuleName()},
+ InApexVariants: []string{mctx.ModuleName()},
+ InApexModules: []string{mctx.ModuleName()},
ApexContents: []*android.ApexContents{apexContents},
ForPrebuiltApex: true,
}
diff --git a/apex/systemserver_classpath_fragment_test.go b/apex/systemserver_classpath_fragment_test.go
new file mode 100644
index 000000000..e1a101ad9
--- /dev/null
+++ b/apex/systemserver_classpath_fragment_test.go
@@ -0,0 +1,78 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// 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 apex
+
+import (
+ "testing"
+
+ "android/soong/android"
+ "android/soong/java"
+)
+
+var prepareForTestWithSystemserverclasspathFragment = android.GroupFixturePreparers(
+ java.PrepareForTestWithDexpreopt,
+ PrepareForTestWithApexBuildComponents,
+)
+
+func TestSystemserverclasspathFragmentContents(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForTestWithSystemserverclasspathFragment,
+ prepareForTestWithMyapex,
+ ).RunTestWithBp(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ systemserverclasspath_fragments: [
+ "mysystemserverclasspathfragment",
+ ],
+ updatable: false,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ java_library {
+ name: "foo",
+ srcs: ["b.java"],
+ installable: true,
+ apex_available: [
+ "myapex",
+ ],
+ }
+
+ systemserverclasspath_fragment {
+ name: "mysystemserverclasspathfragment",
+ contents: [
+ "foo",
+ ],
+ apex_available: [
+ "myapex",
+ ],
+ }
+ `)
+
+ ensureExactContents(t, result.TestContext, "myapex", "android_common_myapex_image", []string{
+ "etc/classpaths/mysystemserverclasspathfragment.pb",
+ "javalib/foo.jar",
+ })
+
+ java.CheckModuleDependencies(t, result.TestContext, "myapex", "android_common_myapex_image", []string{
+ `myapex.key`,
+ `mysystemserverclasspathfragment`,
+ })
+}
diff --git a/bazel/aquery.go b/bazel/aquery.go
index 555f1dcb4..bda3a1ae6 100644
--- a/bazel/aquery.go
+++ b/bazel/aquery.go
@@ -81,23 +81,30 @@ type BuildStatement struct {
Mnemonic string
}
-// AqueryBuildStatements returns an array of BuildStatements which should be registered (and output
-// to a ninja file) to correspond one-to-one with the given action graph json proto (from a bazel
-// aquery invocation).
-func AqueryBuildStatements(aqueryJsonProto []byte) ([]BuildStatement, error) {
- buildStatements := []BuildStatement{}
-
- var aqueryResult actionGraphContainer
- err := json.Unmarshal(aqueryJsonProto, &aqueryResult)
-
- if err != nil {
- return nil, err
- }
+// A helper type for aquery processing which facilitates retrieval of path IDs from their
+// less readable Bazel structures (depset and path fragment).
+type aqueryArtifactHandler struct {
+ // Maps middleman artifact Id to input artifact depset ID.
+ // Middleman artifacts are treated as "substitute" artifacts for mixed builds. For example,
+ // if we find a middleman action which has outputs [foo, bar], and output [baz_middleman], then,
+ // for each other action which has input [baz_middleman], we add [foo, bar] to the inputs for
+ // that action instead.
+ middlemanIdToDepsetIds map[int][]int
+ // Maps depset Id to depset struct.
+ depsetIdToDepset map[int]depSetOfFiles
+ // depsetIdToArtifactIdsCache is a memoization of depset flattening, because flattening
+ // may be an expensive operation.
+ depsetIdToArtifactIdsCache map[int][]int
+ // Maps artifact Id to fully expanded path.
+ artifactIdToPath map[int]string
+}
+func newAqueryHandler(aqueryResult actionGraphContainer) (*aqueryArtifactHandler, error) {
pathFragments := map[int]pathFragment{}
for _, pathFragment := range aqueryResult.PathFragments {
pathFragments[pathFragment.Id] = pathFragment
}
+
artifactIdToPath := map[int]string{}
for _, artifact := range aqueryResult.Artifacts {
artifactPath, err := expandPathFragment(artifact.PathFragmentId, pathFragments)
@@ -112,22 +119,87 @@ func AqueryBuildStatements(aqueryJsonProto []byte) ([]BuildStatement, error) {
depsetIdToDepset[depset.Id] = depset
}
- // depsetIdToArtifactIdsCache is a memoization of depset flattening, because flattening
- // may be an expensive operation.
- depsetIdToArtifactIdsCache := map[int][]int{}
-
// Do a pass through all actions to identify which artifacts are middleman artifacts.
- // These will be omitted from the inputs of other actions.
- // TODO(b/180945500): Handle middleman actions; without proper handling, depending on generated
- // headers may cause build failures.
- middlemanArtifactIds := map[int]bool{}
+ middlemanIdToDepsetIds := map[int][]int{}
for _, actionEntry := range aqueryResult.Actions {
if actionEntry.Mnemonic == "Middleman" {
for _, outputId := range actionEntry.OutputIds {
- middlemanArtifactIds[outputId] = true
+ middlemanIdToDepsetIds[outputId] = actionEntry.InputDepSetIds
+ }
+ }
+ }
+ return &aqueryArtifactHandler{
+ middlemanIdToDepsetIds: middlemanIdToDepsetIds,
+ depsetIdToDepset: depsetIdToDepset,
+ depsetIdToArtifactIdsCache: map[int][]int{},
+ artifactIdToPath: artifactIdToPath,
+ }, nil
+}
+
+func (a *aqueryArtifactHandler) getInputPaths(depsetIds []int) ([]string, error) {
+ inputPaths := []string{}
+
+ for _, inputDepSetId := range depsetIds {
+ inputArtifacts, err := a.artifactIdsFromDepsetId(inputDepSetId)
+ if err != nil {
+ return nil, err
+ }
+ for _, inputId := range inputArtifacts {
+ if middlemanInputDepsetIds, isMiddlemanArtifact := a.middlemanIdToDepsetIds[inputId]; isMiddlemanArtifact {
+ // Add all inputs from middleman actions which created middleman artifacts which are
+ // in the inputs for this action.
+ swappedInputPaths, err := a.getInputPaths(middlemanInputDepsetIds)
+ if err != nil {
+ return nil, err
+ }
+ inputPaths = append(inputPaths, swappedInputPaths...)
+ } else {
+ inputPath, exists := a.artifactIdToPath[inputId]
+ if !exists {
+ return nil, fmt.Errorf("undefined input artifactId %d", inputId)
+ }
+ inputPaths = append(inputPaths, inputPath)
}
}
}
+ return inputPaths, nil
+}
+
+func (a *aqueryArtifactHandler) artifactIdsFromDepsetId(depsetId int) ([]int, error) {
+ if result, exists := a.depsetIdToArtifactIdsCache[depsetId]; exists {
+ return result, nil
+ }
+ if depset, exists := a.depsetIdToDepset[depsetId]; exists {
+ result := depset.DirectArtifactIds
+ for _, childId := range depset.TransitiveDepSetIds {
+ childArtifactIds, err := a.artifactIdsFromDepsetId(childId)
+ if err != nil {
+ return nil, err
+ }
+ result = append(result, childArtifactIds...)
+ }
+ a.depsetIdToArtifactIdsCache[depsetId] = result
+ return result, nil
+ } else {
+ return nil, fmt.Errorf("undefined input depsetId %d", depsetId)
+ }
+}
+
+// AqueryBuildStatements returns an array of BuildStatements which should be registered (and output
+// to a ninja file) to correspond one-to-one with the given action graph json proto (from a bazel
+// aquery invocation).
+func AqueryBuildStatements(aqueryJsonProto []byte) ([]BuildStatement, error) {
+ buildStatements := []BuildStatement{}
+
+ var aqueryResult actionGraphContainer
+ err := json.Unmarshal(aqueryJsonProto, &aqueryResult)
+ if err != nil {
+ return nil, err
+ }
+ aqueryHandler, err := newAqueryHandler(aqueryResult)
+ if err != nil {
+ return nil, err
+ }
for _, actionEntry := range aqueryResult.Actions {
if shouldSkipAction(actionEntry) {
@@ -136,7 +208,7 @@ func AqueryBuildStatements(aqueryJsonProto []byte) ([]BuildStatement, error) {
outputPaths := []string{}
var depfile *string
for _, outputId := range actionEntry.OutputIds {
- outputPath, exists := artifactIdToPath[outputId]
+ outputPath, exists := aqueryHandler.artifactIdToPath[outputId]
if !exists {
return nil, fmt.Errorf("undefined outputId %d", outputId)
}
@@ -151,25 +223,11 @@ func AqueryBuildStatements(aqueryJsonProto []byte) ([]BuildStatement, error) {
outputPaths = append(outputPaths, outputPath)
}
}
- inputPaths := []string{}
- for _, inputDepSetId := range actionEntry.InputDepSetIds {
- inputArtifacts, err :=
- artifactIdsFromDepsetId(depsetIdToDepset, depsetIdToArtifactIdsCache, inputDepSetId)
- if err != nil {
- return nil, err
- }
- for _, inputId := range inputArtifacts {
- if _, isMiddlemanArtifact := middlemanArtifactIds[inputId]; isMiddlemanArtifact {
- // Omit middleman artifacts.
- continue
- }
- inputPath, exists := artifactIdToPath[inputId]
- if !exists {
- return nil, fmt.Errorf("undefined input artifactId %d", inputId)
- }
- inputPaths = append(inputPaths, inputPath)
- }
+ inputPaths, err := aqueryHandler.getInputPaths(actionEntry.InputDepSetIds)
+ if err != nil {
+ return nil, err
}
+
buildStatement := BuildStatement{
Command: strings.Join(proptools.ShellEscapeList(actionEntry.Arguments), " "),
Depfile: depfile,
@@ -192,8 +250,9 @@ func shouldSkipAction(a action) bool {
if a.Mnemonic == "Symlink" || a.Mnemonic == "SourceSymlinkManifest" || a.Mnemonic == "SymlinkTree" {
return true
}
- // TODO(b/180945500): Handle middleman actions; without proper handling, depending on generated
- // headers may cause build failures.
+ // Middleman actions are not handled like other actions; they are handled separately as a
+ // preparatory step so that their inputs may be relayed to actions depending on middleman
+ // artifacts.
if a.Mnemonic == "Middleman" {
return true
}
@@ -209,28 +268,6 @@ func shouldSkipAction(a action) bool {
return false
}
-func artifactIdsFromDepsetId(depsetIdToDepset map[int]depSetOfFiles,
- depsetIdToArtifactIdsCache map[int][]int, depsetId int) ([]int, error) {
- if result, exists := depsetIdToArtifactIdsCache[depsetId]; exists {
- return result, nil
- }
- if depset, exists := depsetIdToDepset[depsetId]; exists {
- result := depset.DirectArtifactIds
- for _, childId := range depset.TransitiveDepSetIds {
- childArtifactIds, err :=
- artifactIdsFromDepsetId(depsetIdToDepset, depsetIdToArtifactIdsCache, childId)
- if err != nil {
- return nil, err
- }
- result = append(result, childArtifactIds...)
- }
- depsetIdToArtifactIdsCache[depsetId] = result
- return result, nil
- } else {
- return nil, fmt.Errorf("undefined input depsetId %d", depsetId)
- }
-}
-
func expandPathFragment(id int, pathFragmentsMap map[int]pathFragment) (string, error) {
labels := []string{}
currId := id
diff --git a/bazel/aquery_test.go b/bazel/aquery_test.go
index fa8810f0d..7b40dcdda 100644
--- a/bazel/aquery_test.go
+++ b/bazel/aquery_test.go
@@ -718,6 +718,93 @@ func TestTransitiveInputDepsets(t *testing.T) {
assertBuildStatements(t, expectedBuildStatements, actualbuildStatements)
}
+func TestMiddlemenAction(t *testing.T) {
+ const inputString = `
+{
+ "artifacts": [{
+ "id": 1,
+ "pathFragmentId": 1
+ }, {
+ "id": 2,
+ "pathFragmentId": 2
+ }, {
+ "id": 3,
+ "pathFragmentId": 3
+ }, {
+ "id": 4,
+ "pathFragmentId": 4
+ }, {
+ "id": 5,
+ "pathFragmentId": 5
+ }, {
+ "id": 6,
+ "pathFragmentId": 6
+ }],
+ "pathFragments": [{
+ "id": 1,
+ "label": "middleinput_one"
+ }, {
+ "id": 2,
+ "label": "middleinput_two"
+ }, {
+ "id": 3,
+ "label": "middleman_artifact"
+ }, {
+ "id": 4,
+ "label": "maininput_one"
+ }, {
+ "id": 5,
+ "label": "maininput_two"
+ }, {
+ "id": 6,
+ "label": "output"
+ }],
+ "depSetOfFiles": [{
+ "id": 1,
+ "directArtifactIds": [1, 2]
+ }, {
+ "id": 2,
+ "directArtifactIds": [3, 4, 5]
+ }],
+ "actions": [{
+ "targetId": 1,
+ "actionKey": "x",
+ "mnemonic": "Middleman",
+ "arguments": ["touch", "foo"],
+ "inputDepSetIds": [1],
+ "outputIds": [3],
+ "primaryOutputId": 3
+ }, {
+ "targetId": 2,
+ "actionKey": "y",
+ "mnemonic": "Main action",
+ "arguments": ["touch", "foo"],
+ "inputDepSetIds": [2],
+ "outputIds": [6],
+ "primaryOutputId": 6
+ }]
+}`
+
+ actual, err := AqueryBuildStatements([]byte(inputString))
+ if err != nil {
+ t.Errorf("Unexpected error %q", err)
+ }
+ if expected := 1; len(actual) != expected {
+ t.Fatalf("Expected %d build statements, got %d", expected, len(actual))
+ }
+
+ bs := actual[0]
+ expectedInputs := []string{"middleinput_one", "middleinput_two", "maininput_one", "maininput_two"}
+ if !reflect.DeepEqual(bs.InputPaths, expectedInputs) {
+ t.Errorf("Expected main action inputs %q, but got %q", expectedInputs, bs.InputPaths)
+ }
+
+ expectedOutputs := []string{"output"}
+ if !reflect.DeepEqual(bs.OutputPaths, expectedOutputs) {
+ t.Errorf("Expected main action outputs %q, but got %q", expectedOutputs, bs.OutputPaths)
+ }
+}
+
func assertError(t *testing.T, err error, expected string) {
if err == nil {
t.Errorf("expected error '%s', but got no error", expected)
diff --git a/bazel/properties.go b/bazel/properties.go
index a71b12bfd..3e778bb69 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -160,6 +160,14 @@ func SubtractBazelLabels(haystack []Label, needle []Label) []Label {
return labels
}
+// Appends two LabelLists, returning the combined list.
+func AppendBazelLabelLists(a LabelList, b LabelList) LabelList {
+ var result LabelList
+ result.Includes = append(a.Includes, b.Includes...)
+ result.Excludes = append(a.Excludes, b.Excludes...)
+ return result
+}
+
// Subtract needle from haystack
func SubtractBazelLabelList(haystack LabelList, needle LabelList) LabelList {
var result LabelList
diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go
index 63a6c2e5c..71660a8e1 100644
--- a/bp2build/build_conversion_test.go
+++ b/bp2build/build_conversion_test.go
@@ -324,11 +324,11 @@ custom {
ctx.RegisterForBazelConversion()
_, errs := ctx.ParseFileList(dir, []string{"Android.bp"})
- if Errored(t, "", errs) {
+ if errored(t, "", errs) {
continue
}
_, errs = ctx.ResolveDependencies(config)
- if Errored(t, "", errs) {
+ if errored(t, "", errs) {
continue
}
@@ -925,11 +925,11 @@ genrule {
ctx.RegisterForBazelConversion()
_, errs := ctx.ParseFileList(dir, toParse)
- if Errored(t, testCase.description, errs) {
+ if errored(t, testCase.description, errs) {
continue
}
_, errs = ctx.ResolveDependencies(config)
- if Errored(t, testCase.description, errs) {
+ if errored(t, testCase.description, errs) {
continue
}
@@ -957,17 +957,6 @@ genrule {
}
}
-func Errored(t *testing.T, desc string, errs []error) bool {
- t.Helper()
- if len(errs) > 0 {
- for _, err := range errs {
- t.Errorf("%s: %s", desc, err)
- }
- return true
- }
- return false
-}
-
type bp2buildMutator = func(android.TopDownMutatorContext)
func TestBp2BuildInlinesDefaults(t *testing.T) {
@@ -1483,11 +1472,11 @@ filegroup {
ctx.RegisterForBazelConversion()
_, errs := ctx.ParseFileList(dir, toParse)
- if Errored(t, testCase.description, errs) {
+ if errored(t, testCase.description, errs) {
continue
}
_, errs = ctx.ResolveDependencies(config)
- if Errored(t, testCase.description, errs) {
+ if errored(t, testCase.description, errs) {
continue
}
@@ -1606,11 +1595,11 @@ func TestGlobExcludeSrcs(t *testing.T) {
ctx.RegisterForBazelConversion()
_, errs := ctx.ParseFileList(dir, toParse)
- if Errored(t, testCase.description, errs) {
+ if errored(t, testCase.description, errs) {
continue
}
_, errs = ctx.ResolveDependencies(config)
- if Errored(t, testCase.description, errs) {
+ if errored(t, testCase.description, errs) {
continue
}
diff --git a/bp2build/bzl_conversion_test.go b/bp2build/bzl_conversion_test.go
index 32b12e42e..204c51986 100644
--- a/bp2build/bzl_conversion_test.go
+++ b/bp2build/bzl_conversion_test.go
@@ -22,8 +22,6 @@ import (
"testing"
)
-var buildDir string
-
func setUp() {
var err error
buildDir, err = ioutil.TempDir("", "bazel_queryview_test")
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index 8afc82bb7..a1ffabce9 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -113,6 +113,7 @@ cc_library {
copts = [
"-Wall",
"-I.",
+ "-I$(BINDIR)/.",
],
deps = [":some-headers"],
includes = ["foo-dir"],
@@ -183,6 +184,7 @@ cc_library {
"-Wunused",
"-Werror",
"-I.",
+ "-I$(BINDIR)/.",
],
deps = [":libc_headers"],
linkopts = [
@@ -242,7 +244,10 @@ cc_library {
bp: soongCcLibraryPreamble,
expectedBazelTargets: []string{`cc_library(
name = "fake-libarm-optimized-routines-math",
- copts = ["-Iexternal"] + select({
+ copts = [
+ "-Iexternal",
+ "-I$(BINDIR)/external",
+ ] + select({
"//build/bazel/platforms/arch:arm64": ["-DHAVE_FAST_FMA=1"],
"//conditions:default": [],
}),
@@ -310,6 +315,7 @@ cc_library { name: "shared_dep_for_both" }
copts = [
"bothflag",
"-Ifoo/bar",
+ "-I$(BINDIR)/foo/bar",
],
deps = [":static_dep_for_both"],
dynamic_deps = [":shared_dep_for_both"],
@@ -347,7 +353,10 @@ cc_library {
bp: soongCcLibraryPreamble,
expectedBazelTargets: []string{`cc_library(
name = "a",
- copts = ["-Ifoo/bar"],
+ copts = [
+ "-Ifoo/bar",
+ "-I$(BINDIR)/foo/bar",
+ ],
srcs = ["a.cpp"],
version_script = "v.map",
)`},
@@ -380,7 +389,10 @@ cc_library {
bp: soongCcLibraryPreamble,
expectedBazelTargets: []string{`cc_library(
name = "a",
- copts = ["-Ifoo/bar"],
+ copts = [
+ "-Ifoo/bar",
+ "-I$(BINDIR)/foo/bar",
+ ],
srcs = ["a.cpp"],
version_script = select({
"//build/bazel/platforms/arch:arm": "arm.map",
@@ -413,11 +425,17 @@ cc_library {
bp: soongCcLibraryPreamble,
expectedBazelTargets: []string{`cc_library(
name = "a",
- copts = ["-Ifoo/bar"],
+ copts = [
+ "-Ifoo/bar",
+ "-I$(BINDIR)/foo/bar",
+ ],
dynamic_deps = [":mylib"],
)`, `cc_library(
name = "mylib",
- copts = ["-Ifoo/bar"],
+ copts = [
+ "-Ifoo/bar",
+ "-I$(BINDIR)/foo/bar",
+ ],
)`},
},
{
@@ -461,12 +479,18 @@ cc_library {
bp: soongCcLibraryPreamble,
expectedBazelTargets: []string{`cc_library(
name = "a",
- copts = ["-Ifoo/bar"],
+ copts = [
+ "-Ifoo/bar",
+ "-I$(BINDIR)/foo/bar",
+ ],
linkopts = ["-Wl,--pack-dyn-relocs=none"],
srcs = ["a.cpp"],
)`, `cc_library(
name = "b",
- copts = ["-Ifoo/bar"],
+ copts = [
+ "-Ifoo/bar",
+ "-I$(BINDIR)/foo/bar",
+ ],
linkopts = select({
"//build/bazel/platforms/arch:x86_64": ["-Wl,--pack-dyn-relocs=none"],
"//conditions:default": [],
@@ -474,7 +498,10 @@ cc_library {
srcs = ["b.cpp"],
)`, `cc_library(
name = "c",
- copts = ["-Ifoo/bar"],
+ copts = [
+ "-Ifoo/bar",
+ "-I$(BINDIR)/foo/bar",
+ ],
linkopts = select({
"//build/bazel/platforms/os:darwin": ["-Wl,--pack-dyn-relocs=none"],
"//conditions:default": [],
@@ -505,6 +532,7 @@ cc_library {
"-include",
"header.h",
"-Ifoo/bar",
+ "-I$(BINDIR)/foo/bar",
],
)`},
},
@@ -548,6 +576,7 @@ cc_library {
"-fsigned-char",
"-pedantic",
"-Ifoo/bar",
+ "-I$(BINDIR)/foo/bar",
] + select({
"//build/bazel/platforms/arch:arm64": ["-DARM64=1"],
"//conditions:default": [],
@@ -588,11 +617,11 @@ cc_library {
ctx.RegisterForBazelConversion()
_, errs := ctx.ParseFileList(dir, toParse)
- if Errored(t, testCase.description, errs) {
+ if errored(t, testCase.description, errs) {
continue
}
_, errs = ctx.ResolveDependencies(config)
- if Errored(t, testCase.description, errs) {
+ if errored(t, testCase.description, errs) {
continue
}
diff --git a/bp2build/cc_library_headers_conversion_test.go b/bp2build/cc_library_headers_conversion_test.go
index 0905aba1f..a3965ed9d 100644
--- a/bp2build/cc_library_headers_conversion_test.go
+++ b/bp2build/cc_library_headers_conversion_test.go
@@ -131,7 +131,10 @@ cc_library_headers {
}`,
expectedBazelTargets: []string{`cc_library_headers(
name = "foo_headers",
- copts = ["-I."],
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
deps = [
":lib-1",
":lib-2",
@@ -147,11 +150,17 @@ cc_library_headers {
}),
)`, `cc_library_headers(
name = "lib-1",
- copts = ["-I."],
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
includes = ["lib-1"],
)`, `cc_library_headers(
name = "lib-2",
- copts = ["-I."],
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
includes = ["lib-2"],
)`},
},
@@ -185,16 +194,28 @@ cc_library_headers {
}`,
expectedBazelTargets: []string{`cc_library_headers(
name = "android-lib",
- copts = ["-I."],
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
)`, `cc_library_headers(
name = "base-lib",
- copts = ["-I."],
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
)`, `cc_library_headers(
name = "darwin-lib",
- copts = ["-I."],
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
)`, `cc_library_headers(
name = "foo_headers",
- copts = ["-I."],
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
deps = [":base-lib"] + select({
"//build/bazel/platforms/os:android": [":android-lib"],
"//build/bazel/platforms/os:darwin": [":darwin-lib"],
@@ -206,16 +227,28 @@ cc_library_headers {
}),
)`, `cc_library_headers(
name = "fuchsia-lib",
- copts = ["-I."],
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
)`, `cc_library_headers(
name = "linux-lib",
- copts = ["-I."],
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
)`, `cc_library_headers(
name = "linux_bionic-lib",
- copts = ["-I."],
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
)`, `cc_library_headers(
name = "windows-lib",
- copts = ["-I."],
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
)`},
},
{
@@ -236,13 +269,22 @@ cc_library_headers {
}`,
expectedBazelTargets: []string{`cc_library_headers(
name = "android-lib",
- copts = ["-I."],
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
)`, `cc_library_headers(
name = "exported-lib",
- copts = ["-I."],
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
)`, `cc_library_headers(
name = "foo_headers",
- copts = ["-I."],
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
deps = select({
"//build/bazel/platforms/os:android": [
":android-lib",
@@ -296,7 +338,10 @@ cc_library_headers {
}`,
expectedBazelTargets: []string{`cc_library_headers(
name = "foo_headers",
- copts = ["-I."],
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
includes = ["shared_include_dir"] + select({
"//build/bazel/platforms/arch:arm": ["arm_include_dir"],
"//build/bazel/platforms/arch:x86_64": ["x86_64_include_dir"],
@@ -340,11 +385,11 @@ cc_library_headers {
ctx.RegisterForBazelConversion()
_, errs := ctx.ParseFileList(dir, toParse)
- if Errored(t, testCase.description, errs) {
+ if errored(t, testCase.description, errs) {
continue
}
_, errs = ctx.ResolveDependencies(config)
- if Errored(t, testCase.description, errs) {
+ if errored(t, testCase.description, errs) {
continue
}
diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go
index d082db1bd..4fcf5e474 100644
--- a/bp2build/cc_library_static_conversion_test.go
+++ b/bp2build/cc_library_static_conversion_test.go
@@ -17,6 +17,8 @@ package bp2build
import (
"android/soong/android"
"android/soong/cc"
+ "android/soong/genrule"
+
"strings"
"testing"
)
@@ -179,10 +181,15 @@ cc_library_static {
"-Dflag1",
"-Dflag2",
"-Iinclude_dir_1",
+ "-I$(BINDIR)/include_dir_1",
"-Iinclude_dir_2",
+ "-I$(BINDIR)/include_dir_2",
"-Ilocal_include_dir_1",
+ "-I$(BINDIR)/local_include_dir_1",
"-Ilocal_include_dir_2",
+ "-I$(BINDIR)/local_include_dir_2",
"-I.",
+ "-I$(BINDIR)/.",
],
deps = [
":header_lib_1",
@@ -205,22 +212,34 @@ cc_library_static {
],
)`, `cc_library_static(
name = "static_lib_1",
- copts = ["-I."],
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
linkstatic = True,
srcs = ["static_lib_1.cc"],
)`, `cc_library_static(
name = "static_lib_2",
- copts = ["-I."],
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
linkstatic = True,
srcs = ["static_lib_2.cc"],
)`, `cc_library_static(
name = "whole_static_lib_1",
- copts = ["-I."],
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
linkstatic = True,
srcs = ["whole_static_lib_1.cc"],
)`, `cc_library_static(
name = "whole_static_lib_2",
- copts = ["-I."],
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
linkstatic = True,
srcs = ["whole_static_lib_2.cc"],
)`},
@@ -257,7 +276,9 @@ cc_library_static {
name = "foo_static",
copts = [
"-Isubpackage",
+ "-I$(BINDIR)/subpackage",
"-I.",
+ "-I$(BINDIR)/.",
],
linkstatic = True,
)`},
@@ -280,7 +301,10 @@ cc_library_static {
}`,
expectedBazelTargets: []string{`cc_library_static(
name = "foo_static",
- copts = ["-I."],
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
includes = ["subpackage"],
linkstatic = True,
)`},
@@ -303,7 +327,10 @@ cc_library_static {
}`,
expectedBazelTargets: []string{`cc_library_static(
name = "foo_static",
- copts = ["-I."],
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
includes = ["subpackage"],
linkstatic = True,
)`},
@@ -341,10 +368,15 @@ cc_library_static {
name = "foo_static",
copts = [
"-Isubpackage/subsubpackage",
+ "-I$(BINDIR)/subpackage/subsubpackage",
"-Isubpackage2",
+ "-I$(BINDIR)/subpackage2",
"-Isubpackage3/subsubpackage",
+ "-I$(BINDIR)/subpackage3/subsubpackage",
"-Isubpackage/subsubpackage2",
+ "-I$(BINDIR)/subpackage/subsubpackage2",
"-Isubpackage",
+ "-I$(BINDIR)/subpackage",
],
includes = ["./exported_subsubpackage"],
linkstatic = True,
@@ -372,7 +404,9 @@ cc_library_static {
name = "foo_static",
copts = [
"-Isubpackage",
+ "-I$(BINDIR)/subpackage",
"-Isubpackage2",
+ "-I$(BINDIR)/subpackage2",
],
linkstatic = True,
)`},
@@ -401,8 +435,11 @@ cc_library_static {
name = "foo_static",
copts = [
"-Isubpackage",
+ "-I$(BINDIR)/subpackage",
"-Isubpackage2",
+ "-I$(BINDIR)/subpackage2",
"-I.",
+ "-I$(BINDIR)/.",
],
linkstatic = True,
)`},
@@ -423,7 +460,10 @@ cc_library_static {
}`,
expectedBazelTargets: []string{`cc_library_static(
name = "foo_static",
- copts = ["-I."],
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
deps = select({
"//build/bazel/platforms/arch:arm64": [":static_dep"],
"//conditions:default": [],
@@ -435,11 +475,17 @@ cc_library_static {
}),
)`, `cc_library_static(
name = "static_dep",
- copts = ["-I."],
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
linkstatic = True,
)`, `cc_library_static(
name = "static_dep2",
- copts = ["-I."],
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
linkstatic = True,
)`},
},
@@ -459,7 +505,10 @@ cc_library_static {
}`,
expectedBazelTargets: []string{`cc_library_static(
name = "foo_static",
- copts = ["-I."],
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
deps = select({
"//build/bazel/platforms/os:android": [":static_dep"],
"//conditions:default": [],
@@ -471,11 +520,17 @@ cc_library_static {
}),
)`, `cc_library_static(
name = "static_dep",
- copts = ["-I."],
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
linkstatic = True,
)`, `cc_library_static(
name = "static_dep2",
- copts = ["-I."],
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
linkstatic = True,
)`},
},
@@ -500,7 +555,10 @@ cc_library_static {
}`,
expectedBazelTargets: []string{`cc_library_static(
name = "foo_static",
- copts = ["-I."],
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
deps = [":static_dep"] + select({
"//build/bazel/platforms/arch:arm64": [":static_dep4"],
"//conditions:default": [],
@@ -512,19 +570,31 @@ cc_library_static {
whole_archive_deps = [":static_dep2"],
)`, `cc_library_static(
name = "static_dep",
- copts = ["-I."],
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
linkstatic = True,
)`, `cc_library_static(
name = "static_dep2",
- copts = ["-I."],
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
linkstatic = True,
)`, `cc_library_static(
name = "static_dep3",
- copts = ["-I."],
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
linkstatic = True,
)`, `cc_library_static(
name = "static_dep4",
- copts = ["-I."],
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
linkstatic = True,
)`},
},
@@ -547,7 +617,10 @@ cc_library_static {
}`,
expectedBazelTargets: []string{`cc_library_static(
name = "foo_static",
- copts = ["-I."],
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
linkstatic = True,
srcs = [
"common.c",
@@ -573,7 +646,10 @@ cc_library_static {
}`,
expectedBazelTargets: []string{`cc_library_static(
name = "foo_static",
- copts = ["-I."],
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
linkstatic = True,
srcs = ["common.c"] + select({
"//build/bazel/platforms/arch:arm": ["foo-arm.c"],
@@ -604,7 +680,10 @@ cc_library_static {
}`,
expectedBazelTargets: []string{`cc_library_static(
name = "foo_static",
- copts = ["-I."],
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
linkstatic = True,
srcs = ["common.c"] + select({
"//build/bazel/platforms/arch:arm": ["for-arm.c"],
@@ -637,7 +716,10 @@ cc_library_static {
} `,
expectedBazelTargets: []string{`cc_library_static(
name = "foo_static",
- copts = ["-I."],
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
linkstatic = True,
srcs = ["common.c"] + select({
"//build/bazel/platforms/arch:arm": [
@@ -687,7 +769,10 @@ cc_library_static {
} `,
expectedBazelTargets: []string{`cc_library_static(
name = "foo_static",
- copts = ["-I."],
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
linkstatic = True,
srcs = ["common.c"] + select({
"//build/bazel/platforms/arch:arm": [
@@ -738,12 +823,18 @@ cc_library_static {
}`,
expectedBazelTargets: []string{`cc_library_static(
name = "foo_static",
- copts = ["-I."],
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
deps = [":static_dep"],
linkstatic = True,
)`, `cc_library_static(
name = "static_dep",
- copts = ["-I."],
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
linkstatic = True,
)`},
},
@@ -768,7 +859,10 @@ cc_library_static {
} `,
expectedBazelTargets: []string{`cc_library_static(
name = "foo_static",
- copts = ["-I."],
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
linkstatic = True,
srcs = ["common.c"] + select({
"//build/bazel/platforms/arch:arm": ["for-lib32.c"],
@@ -801,7 +895,10 @@ cc_library_static {
} `,
expectedBazelTargets: []string{`cc_library_static(
name = "foo_static2",
- copts = ["-I."],
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
linkstatic = True,
srcs = ["common.c"] + select({
"//build/bazel/platforms/arch:arm": [
@@ -867,7 +964,10 @@ cc_library_static {
}`,
expectedBazelTargets: []string{`cc_library_static(
name = "foo_static3",
- copts = ["-I."],
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
linkstatic = True,
srcs = ["common.c"] + select({
"//build/bazel/platforms/arch:arm": [
@@ -913,6 +1013,94 @@ cc_library_static {
}),
)`},
},
+ {
+ description: "cc_library_static arch srcs/exclude_srcs with generated files",
+ moduleTypeUnderTest: "cc_library_static",
+ moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
+ moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+ depsMutators: []android.RegisterMutatorFunc{cc.RegisterDepsBp2Build},
+ filesystem: map[string]string{
+ "common.c": "",
+ "for-x86.c": "",
+ "not-for-x86.c": "",
+ "not-for-everything.c": "",
+ "dep/Android.bp": `
+genrule {
+ name: "generated_src_other_pkg",
+ out: ["generated_src_other_pkg.cpp"],
+ cmd: "nothing to see here",
+}
+
+genrule {
+ name: "generated_hdr_other_pkg",
+ out: ["generated_hdr_other_pkg.cpp"],
+ cmd: "nothing to see here",
+}
+
+genrule {
+ name: "generated_hdr_other_pkg_x86",
+ out: ["generated_hdr_other_pkg_x86.cpp"],
+ cmd: "nothing to see here",
+}`,
+ },
+ bp: soongCcLibraryStaticPreamble + `
+genrule {
+ name: "generated_src",
+ out: ["generated_src.cpp"],
+ cmd: "nothing to see here",
+}
+
+genrule {
+ name: "generated_src_x86",
+ out: ["generated_src_x86.cpp"],
+ cmd: "nothing to see here",
+}
+
+genrule {
+ name: "generated_hdr",
+ out: ["generated_hdr.h"],
+ cmd: "nothing to see here",
+}
+
+cc_library_static {
+ name: "foo_static3",
+ srcs: ["common.c", "not-for-*.c"],
+ exclude_srcs: ["not-for-everything.c"],
+ generated_sources: ["generated_src", "generated_src_other_pkg"],
+ generated_headers: ["generated_hdr", "generated_hdr_other_pkg"],
+ arch: {
+ x86: {
+ srcs: ["for-x86.c"],
+ exclude_srcs: ["not-for-x86.c"],
+ generated_sources: ["generated_src_x86"],
+ generated_headers: ["generated_hdr_other_pkg_x86"],
+ },
+ },
+}
+`,
+ expectedBazelTargets: []string{`cc_library_static(
+ name = "foo_static3",
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
+ linkstatic = True,
+ srcs = [
+ "//dep:generated_hdr_other_pkg",
+ "//dep:generated_src_other_pkg",
+ ":generated_hdr",
+ ":generated_src",
+ "common.c",
+ ] + select({
+ "//build/bazel/platforms/arch:x86": [
+ "//dep:generated_hdr_other_pkg_x86",
+ ":generated_src_x86",
+ "for-x86.c",
+ ],
+ "//conditions:default": ["not-for-x86.c"],
+ }),
+)`},
+ },
}
dir := "."
@@ -933,6 +1121,7 @@ cc_library_static {
cc.RegisterCCBuildComponents(ctx)
ctx.RegisterModuleType("toolchain_library", cc.ToolchainLibraryFactory)
ctx.RegisterModuleType("cc_library_headers", cc.LibraryHeaderFactory)
+ ctx.RegisterModuleType("genrule", genrule.GenRuleFactory)
ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory)
for _, m := range testCase.depsMutators {
@@ -943,11 +1132,11 @@ cc_library_static {
ctx.RegisterForBazelConversion()
_, errs := ctx.ParseFileList(dir, toParse)
- if Errored(t, testCase.description, errs) {
+ if errored(t, testCase.description, errs) {
continue
}
_, errs = ctx.ResolveDependencies(config)
- if Errored(t, testCase.description, errs) {
+ if errored(t, testCase.description, errs) {
continue
}
diff --git a/bp2build/cc_object_conversion_test.go b/bp2build/cc_object_conversion_test.go
index 9efdb53de..ebc9c9449 100644
--- a/bp2build/cc_object_conversion_test.go
+++ b/bp2build/cc_object_conversion_test.go
@@ -65,7 +65,9 @@ func TestCcObjectBp2Build(t *testing.T) {
"-Wall",
"-Werror",
"-Iinclude",
+ "-I$(BINDIR)/include",
"-I.",
+ "-I$(BINDIR)/.",
],
srcs = ["a/b/c.c"],
)`,
@@ -109,7 +111,9 @@ cc_defaults {
"-Werror",
"-fno-addrsig",
"-Iinclude",
+ "-I$(BINDIR)/include",
"-I.",
+ "-I$(BINDIR)/.",
],
srcs = ["a/b/c.c"],
)`,
@@ -140,6 +144,7 @@ cc_object {
copts = [
"-fno-addrsig",
"-I.",
+ "-I$(BINDIR)/.",
],
srcs = ["x/y/z.c"],
)`, `cc_object(
@@ -147,6 +152,7 @@ cc_object {
copts = [
"-fno-addrsig",
"-I.",
+ "-I$(BINDIR)/.",
],
deps = [":bar"],
srcs = ["a/b/c.c"],
@@ -222,11 +228,11 @@ cc_object {
ctx.RegisterForBazelConversion()
_, errs := ctx.ParseFileList(dir, toParse)
- if Errored(t, testCase.description, errs) {
+ if errored(t, testCase.description, errs) {
continue
}
_, errs = ctx.ResolveDependencies(config)
- if Errored(t, testCase.description, errs) {
+ if errored(t, testCase.description, errs) {
continue
}
@@ -284,6 +290,7 @@ func TestCcObjectConfigurableAttributesBp2Build(t *testing.T) {
copts = [
"-fno-addrsig",
"-I.",
+ "-I$(BINDIR)/.",
] + select({
"//build/bazel/platforms/arch:x86": ["-fPIC"],
"//conditions:default": [],
@@ -329,6 +336,7 @@ func TestCcObjectConfigurableAttributesBp2Build(t *testing.T) {
copts = [
"-fno-addrsig",
"-I.",
+ "-I$(BINDIR)/.",
] + select({
"//build/bazel/platforms/arch:arm": ["-Wall"],
"//build/bazel/platforms/arch:arm64": ["-Wall"],
@@ -373,6 +381,7 @@ func TestCcObjectConfigurableAttributesBp2Build(t *testing.T) {
copts = [
"-fno-addrsig",
"-I.",
+ "-I$(BINDIR)/.",
] + select({
"//build/bazel/platforms/os:android": ["-fPIC"],
"//build/bazel/platforms/os:darwin": ["-Wall"],
@@ -402,11 +411,11 @@ func TestCcObjectConfigurableAttributesBp2Build(t *testing.T) {
ctx.RegisterForBazelConversion()
_, errs := ctx.ParseFileList(dir, toParse)
- if Errored(t, testCase.description, errs) {
+ if errored(t, testCase.description, errs) {
continue
}
_, errs = ctx.ResolveDependencies(config)
- if Errored(t, testCase.description, errs) {
+ if errored(t, testCase.description, errs) {
continue
}
diff --git a/bp2build/constants.go b/bp2build/constants.go
index 70f320e12..4870dffff 100644
--- a/bp2build/constants.go
+++ b/bp2build/constants.go
@@ -19,7 +19,10 @@ var (
// be preferred for use within a Bazel build.
// The file name used for automatically generated files.
- GeneratedBuildFileName = "BUILD"
+ GeneratedBuildFileName = "BUILD.bazel"
+
// The file name used for hand-crafted build targets.
+ // NOTE: It is okay that this matches GeneratedBuildFileName, since we generate BUILD files in a different directory to source files
+ // FIXME: Because there are hundreds of existing BUILD.bazel files in the AOSP tree, we should pick another name here, like BUILD.android
HandcraftedBuildFileName = "BUILD.bazel"
)
diff --git a/bp2build/conversion_test.go b/bp2build/conversion_test.go
index a08c03d05..0931ff7fc 100644
--- a/bp2build/conversion_test.go
+++ b/bp2build/conversion_test.go
@@ -29,7 +29,7 @@ func TestCreateBazelFiles_QueryView_AddsTopLevelFiles(t *testing.T) {
expectedFilePaths := []bazelFilepath{
{
dir: "",
- basename: "BUILD",
+ basename: "BUILD.bazel",
},
{
dir: "",
@@ -37,7 +37,7 @@ func TestCreateBazelFiles_QueryView_AddsTopLevelFiles(t *testing.T) {
},
{
dir: bazelRulesSubDir,
- basename: "BUILD",
+ basename: "BUILD.bazel",
},
{
dir: bazelRulesSubDir,
@@ -69,7 +69,7 @@ func TestCreateBazelFiles_QueryView_AddsTopLevelFiles(t *testing.T) {
if actualFile.Dir != expectedFile.dir || actualFile.Basename != expectedFile.basename {
t.Errorf("Did not find expected file %s/%s", actualFile.Dir, actualFile.Basename)
- } else if actualFile.Basename == "BUILD" || actualFile.Basename == "WORKSPACE" {
+ } else if actualFile.Basename == "BUILD.bazel" || actualFile.Basename == "WORKSPACE" {
if actualFile.Contents != "" {
t.Errorf("Expected %s to have no content.", actualFile)
}
diff --git a/bp2build/python_binary_conversion_test.go b/bp2build/python_binary_conversion_test.go
index 2054e0678..ed509bf15 100644
--- a/bp2build/python_binary_conversion_test.go
+++ b/bp2build/python_binary_conversion_test.go
@@ -128,11 +128,11 @@ func TestPythonBinaryHost(t *testing.T) {
ctx.RegisterForBazelConversion()
_, errs := ctx.ParseFileList(dir, toParse)
- if Errored(t, testCase.description, errs) {
+ if errored(t, testCase.description, errs) {
continue
}
_, errs = ctx.ResolveDependencies(config)
- if Errored(t, testCase.description, errs) {
+ if errored(t, testCase.description, errs) {
continue
}
diff --git a/bp2build/sh_conversion_test.go b/bp2build/sh_conversion_test.go
index 37f542ef7..575bf585c 100644
--- a/bp2build/sh_conversion_test.go
+++ b/bp2build/sh_conversion_test.go
@@ -101,11 +101,11 @@ func TestShBinaryBp2Build(t *testing.T) {
ctx.RegisterForBazelConversion()
_, errs := ctx.ParseFileList(dir, toParse)
- if Errored(t, testCase.description, errs) {
+ if errored(t, testCase.description, errs) {
continue
}
_, errs = ctx.ResolveDependencies(config)
- if Errored(t, testCase.description, errs) {
+ if errored(t, testCase.description, errs) {
continue
}
diff --git a/bp2build/testing.go b/bp2build/testing.go
index b925682c4..e575bc6ff 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -1,6 +1,8 @@
package bp2build
import (
+ "testing"
+
"android/soong/android"
"android/soong/bazel"
)
@@ -10,6 +12,8 @@ var (
bp2buildConfig = android.Bp2BuildConfig{
android.BP2BUILD_TOPLEVEL: android.Bp2BuildDefaultTrueRecursively,
}
+
+ buildDir string
)
type nestedProps struct {
@@ -39,6 +43,17 @@ type customModule struct {
props customProps
}
+func errored(t *testing.T, desc string, errs []error) bool {
+ t.Helper()
+ if len(errs) > 0 {
+ for _, err := range errs {
+ t.Errorf("%s: %s", desc, err)
+ }
+ return true
+ }
+ return false
+}
+
// OutputFiles is needed because some instances of this module use dist with a
// tag property which requires the module implements OutputFileProducer.
func (m *customModule) OutputFiles(tag string) (android.Paths, error) {
diff --git a/cc/Android.bp b/cc/Android.bp
index c32cca8b8..1fc8d9f68 100644
--- a/cc/Android.bp
+++ b/cc/Android.bp
@@ -92,6 +92,7 @@ bootstrap_go_package {
"object_test.go",
"prebuilt_test.go",
"proto_test.go",
+ "sanitize_test.go",
"test_data_test.go",
"vendor_public_library_test.go",
"vendor_snapshot_test.go",
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 33bb2699c..75543acf2 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -14,10 +14,11 @@
package cc
import (
- "android/soong/android"
- "android/soong/bazel"
"path/filepath"
"strings"
+
+ "android/soong/android"
+ "android/soong/bazel"
)
// bp2build functions and helpers for converting cc_* modules to Bazel.
@@ -49,6 +50,22 @@ func depsBp2BuildMutator(ctx android.BottomUpMutatorContext) {
var allDeps []string
+ for _, p := range module.GetTargetProperties(ctx, &BaseCompilerProperties{}) {
+ // base compiler props
+ if baseCompilerProps, ok := p.(*BaseCompilerProperties); ok {
+ allDeps = append(allDeps, baseCompilerProps.Generated_headers...)
+ allDeps = append(allDeps, baseCompilerProps.Generated_sources...)
+ }
+ }
+
+ for _, p := range module.GetArchProperties(ctx, &BaseCompilerProperties{}) {
+ // arch specific compiler props
+ if baseCompilerProps, ok := p.(*BaseCompilerProperties); ok {
+ allDeps = append(allDeps, baseCompilerProps.Generated_headers...)
+ allDeps = append(allDeps, baseCompilerProps.Generated_sources...)
+ }
+ }
+
for _, p := range module.GetTargetProperties(ctx, &BaseLinkerProperties{}) {
// arch specific linker props
if baseLinkerProps, ok := p.(*BaseLinkerProperties); ok {
@@ -74,12 +91,15 @@ func depsBp2BuildMutator(ctx android.BottomUpMutatorContext) {
allDeps = append(allDeps, lib.SharedProperties.Shared.Static_libs...)
allDeps = append(allDeps, lib.SharedProperties.Shared.Whole_static_libs...)
allDeps = append(allDeps, lib.SharedProperties.Shared.Shared_libs...)
- allDeps = append(allDeps, lib.SharedProperties.Shared.System_shared_libs...)
allDeps = append(allDeps, lib.StaticProperties.Static.Static_libs...)
allDeps = append(allDeps, lib.StaticProperties.Static.Whole_static_libs...)
allDeps = append(allDeps, lib.StaticProperties.Static.Shared_libs...)
- allDeps = append(allDeps, lib.StaticProperties.Static.System_shared_libs...)
+
+ // TODO(b/186024507, b/186489250): Temporarily exclude adding
+ // system_shared_libs deps until libc and libm builds.
+ // allDeps = append(allDeps, lib.SharedProperties.Shared.System_shared_libs...)
+ // allDeps = append(allDeps, lib.StaticProperties.Static.System_shared_libs...)
}
ctx.AddDependency(module, nil, android.SortedUniqueStrings(allDeps)...)
@@ -173,11 +193,19 @@ func bp2BuildParseCompilerProps(ctx android.TopDownMutatorContext, module *Modul
var srcs bazel.LabelListAttribute
var copts bazel.StringListAttribute
- // Creates the -I flag for a directory, while making the directory relative
+ // Creates the -I flags for a directory, while making the directory relative
// to the exec root for Bazel to work.
- includeFlag := func(dir string) string {
+ includeFlags := func(dir string) []string {
// filepath.Join canonicalizes the path, i.e. it takes care of . or .. elements.
- return "-I" + filepath.Join(ctx.ModuleDir(), dir)
+ moduleDirRootedPath := filepath.Join(ctx.ModuleDir(), dir)
+ return []string{
+ "-I" + moduleDirRootedPath,
+ // Include the bindir-rooted path (using make variable substitution). This most
+ // closely matches Bazel's native include path handling, which allows for dependency
+ // on generated headers in these directories.
+ // TODO(b/188084383): Handle local include directories in Bazel.
+ "-I$(BINDIR)/" + moduleDirRootedPath,
+ }
}
// Parse the list of module-relative include directories (-I).
@@ -197,7 +225,7 @@ func bp2BuildParseCompilerProps(ctx android.TopDownMutatorContext, module *Modul
copts = append(copts, strings.Split(flag, " ")...)
}
for _, dir := range parseLocalIncludeDirs(baseCompilerProps) {
- copts = append(copts, includeFlag(dir))
+ copts = append(copts, includeFlags(dir)...)
}
return copts
}
@@ -215,9 +243,17 @@ func bp2BuildParseCompilerProps(ctx android.TopDownMutatorContext, module *Modul
parseSrcs := func(baseCompilerProps *BaseCompilerProperties) bazel.LabelList {
// Combine the base srcs and arch-specific srcs
allSrcs := append(baseSrcs, baseCompilerProps.Srcs...)
+ // Add srcs-like dependencies such as generated files.
+ // First create a LabelList containing these dependencies, then merge the values with srcs.
+ generatedHdrsAndSrcs := baseCompilerProps.Generated_headers
+ generatedHdrsAndSrcs = append(generatedHdrsAndSrcs, baseCompilerProps.Generated_sources...)
+
+ generatedHdrsAndSrcsLabelList := android.BazelLabelForModuleDeps(ctx, generatedHdrsAndSrcs)
+
// Combine the base exclude_srcs and configuration-specific exclude_srcs
allExcludeSrcs := append(baseExcludeSrcs, baseCompilerProps.Exclude_srcs...)
- return android.BazelLabelForModuleSrcExcludes(ctx, allSrcs, allExcludeSrcs)
+ allSrcsLabelList := android.BazelLabelForModuleSrcExcludes(ctx, allSrcs, allExcludeSrcs)
+ return bazel.AppendBazelLabelLists(allSrcsLabelList, generatedHdrsAndSrcsLabelList)
}
for _, props := range module.compiler.compilerProps() {
@@ -227,8 +263,8 @@ func bp2BuildParseCompilerProps(ctx android.TopDownMutatorContext, module *Modul
// Used for arch-specific srcs later.
baseSrcs = baseCompilerProps.Srcs
- baseExcludeSrcs = baseCompilerProps.Exclude_srcs
baseSrcsLabelList = parseSrcs(baseCompilerProps)
+ baseExcludeSrcs = baseCompilerProps.Exclude_srcs
break
}
}
@@ -237,9 +273,9 @@ func bp2BuildParseCompilerProps(ctx android.TopDownMutatorContext, module *Modul
// target has access to all headers recursively in the package, and has
// "-I<module-dir>" in its copts.
if c, ok := module.compiler.(*baseCompiler); ok && c.includeBuildDirectory() {
- copts.Value = append(copts.Value, includeFlag("."))
+ copts.Value = append(copts.Value, includeFlags(".")...)
} else if c, ok := module.compiler.(*libraryDecorator); ok && c.includeBuildDirectory() {
- copts.Value = append(copts.Value, includeFlag("."))
+ copts.Value = append(copts.Value, includeFlags(".")...)
}
for arch, props := range module.GetArchProperties(ctx, &BaseCompilerProperties{}) {
diff --git a/cc/cc.go b/cc/cc.go
index a0ad0d688..8a34dadd5 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -2833,7 +2833,7 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
// Add the dependency to the APEX(es) providing the library so that
// m <module> can trigger building the APEXes as well.
depApexInfo := ctx.OtherModuleProvider(dep, android.ApexInfoProvider).(android.ApexInfo)
- for _, an := range depApexInfo.InApexes {
+ for _, an := range depApexInfo.InApexVariants {
c.Properties.ApexesProvidingSharedLibs = append(
c.Properties.ApexesProvidingSharedLibs, an)
}
diff --git a/cc/config/global.go b/cc/config/global.go
index 59fe8e13c..d6eba0fb1 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -225,18 +225,19 @@ func init() {
// Everything in these lists is a crime against abstraction and dependency tracking.
// Do not add anything to this list.
- pctx.PrefixedExistentPathsForSourcesVariable("CommonGlobalIncludes", "-I",
- []string{
- "system/core/include",
- "system/logging/liblog/include",
- "system/media/audio/include",
- "hardware/libhardware/include",
- "hardware/libhardware_legacy/include",
- "hardware/ril/include",
- "frameworks/native/include",
- "frameworks/native/opengl/include",
- "frameworks/av/include",
- })
+ commonGlobalIncludes := []string{
+ "system/core/include",
+ "system/logging/liblog/include",
+ "system/media/audio/include",
+ "hardware/libhardware/include",
+ "hardware/libhardware_legacy/include",
+ "hardware/ril/include",
+ "frameworks/native/include",
+ "frameworks/native/opengl/include",
+ "frameworks/av/include",
+ }
+ exportedVars.Set("CommonGlobalIncludes", commonGlobalIncludes)
+ pctx.PrefixedExistentPathsForSourcesVariable("CommonGlobalIncludes", "-I", commonGlobalIncludes)
pctx.SourcePathVariable("ClangDefaultBase", ClangDefaultBase)
pctx.VariableFunc("ClangBase", func(ctx android.PackageVarContext) string {
diff --git a/cc/linker.go b/cc/linker.go
index 196806d33..5bd21eda3 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -393,7 +393,7 @@ func CheckSdkVersionAtLeast(ctx ModuleContext, SdkVersion android.ApiLevel) bool
if ctx.minSdkVersion() == "current" {
return true
}
- parsedSdkVersion, err := android.ApiLevelFromUser(ctx, ctx.minSdkVersion())
+ parsedSdkVersion, err := nativeApiLevelFromUser(ctx, ctx.minSdkVersion())
if err != nil {
ctx.PropertyErrorf("min_sdk_version",
"Invalid min_sdk_version value (must be int or current): %q",
@@ -424,7 +424,7 @@ func (linker *baseLinker) linkerFlags(ctx ModuleContext, flags Flags) Flags {
// ANDROID_RELR relocations were supported at API level >= 28.
// Relocation packer was supported at API level >= 23.
// Do the best we can...
- if !ctx.useSdk() || CheckSdkVersionAtLeast(ctx, android.FirstShtRelrVersion) {
+ if (!ctx.useSdk() && ctx.minSdkVersion() == "") || CheckSdkVersionAtLeast(ctx, android.FirstShtRelrVersion) {
flags.Global.LdFlags = append(flags.Global.LdFlags, "-Wl,--pack-dyn-relocs=android+relr")
} else if CheckSdkVersionAtLeast(ctx, android.FirstAndroidRelrVersion) {
flags.Global.LdFlags = append(flags.Global.LdFlags,
diff --git a/cc/makevars.go b/cc/makevars.go
index da5f1fde2..2b326ef4f 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -288,9 +288,7 @@ func makeVarsToolchain(ctx android.MakeVarsContext, secondPrefix string,
ctx.Strict(makePrefix+"OBJCOPY", "${config.ClangBin}/llvm-objcopy")
ctx.Strict(makePrefix+"LD", "${config.ClangBin}/lld")
ctx.Strict(makePrefix+"NDK_TRIPLE", config.NDKTriple(toolchain))
- // TODO: work out whether to make this "${config.ClangBin}/llvm-", which
- // should mostly work, or remove it.
- ctx.Strict(makePrefix+"TOOLS_PREFIX", gccCmd(toolchain, ""))
+ ctx.Strict(makePrefix+"TOOLS_PREFIX", "${config.ClangBin}/llvm-")
// TODO: GCC version is obsolete now that GCC has been removed.
ctx.Strict(makePrefix+"GCC_VERSION", toolchain.GccVersion())
}
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 605a8d094..f486ee470 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -902,7 +902,7 @@ func sanitizerDepsMutator(t SanitizerType) func(android.TopDownMutatorContext) {
if d, ok := child.(PlatformSanitizeable); ok && d.SanitizePropDefined() &&
!d.SanitizeNever() &&
!d.IsSanitizerExplicitlyDisabled(t) {
- if t == cfi || t == Hwasan || t == scs {
+ if t == cfi || t == Hwasan || t == scs || t == Asan {
if d.StaticallyLinked() && d.SanitizerSupported(t) {
// Rust does not support some of these sanitizers, so we need to check if it's
// supported before setting this true.
@@ -1261,7 +1261,7 @@ func sanitizerMutator(t SanitizerType) func(android.BottomUpMutatorContext) {
modules[0].(PlatformSanitizeable).SetSanitizer(t, true)
} else if c.IsSanitizerEnabled(t) || c.SanitizeDep() {
isSanitizerEnabled := c.IsSanitizerEnabled(t)
- if c.StaticallyLinked() || c.Header() || t == Asan || t == Fuzzer {
+ if c.StaticallyLinked() || c.Header() || t == Fuzzer {
// Static and header libs are split into non-sanitized and sanitized variants.
// Shared libs are not split. However, for asan and fuzzer, we split even for shared
// libs because a library sanitized for asan/fuzzer can't be linked from a library
diff --git a/cc/sanitize_test.go b/cc/sanitize_test.go
new file mode 100644
index 000000000..f12634678
--- /dev/null
+++ b/cc/sanitize_test.go
@@ -0,0 +1,204 @@
+// 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 cc
+
+import (
+ "testing"
+
+ "android/soong/android"
+)
+
+var prepareForAsanTest = android.FixtureAddFile("asan/Android.bp", []byte(`
+ cc_library_shared {
+ name: "libclang_rt.asan-aarch64-android",
+ }
+
+ cc_library_shared {
+ name: "libclang_rt.asan-arm-android",
+ }
+`))
+
+func TestAsan(t *testing.T) {
+ bp := `
+ cc_binary {
+ name: "bin_with_asan",
+ host_supported: true,
+ shared_libs: [
+ "libshared",
+ "libasan",
+ ],
+ static_libs: [
+ "libstatic",
+ "libnoasan",
+ ],
+ sanitize: {
+ address: true,
+ }
+ }
+
+ cc_binary {
+ name: "bin_no_asan",
+ host_supported: true,
+ shared_libs: [
+ "libshared",
+ "libasan",
+ ],
+ static_libs: [
+ "libstatic",
+ "libnoasan",
+ ],
+ }
+
+ cc_library_shared {
+ name: "libshared",
+ host_supported: true,
+ shared_libs: ["libtransitive"],
+ }
+
+ cc_library_shared {
+ name: "libasan",
+ host_supported: true,
+ shared_libs: ["libtransitive"],
+ sanitize: {
+ address: true,
+ }
+ }
+
+ cc_library_shared {
+ name: "libtransitive",
+ host_supported: true,
+ }
+
+ cc_library_static {
+ name: "libstatic",
+ host_supported: true,
+ }
+
+ cc_library_static {
+ name: "libnoasan",
+ host_supported: true,
+ sanitize: {
+ address: false,
+ }
+ }
+ `
+
+ result := android.GroupFixturePreparers(
+ prepareForCcTest,
+ prepareForAsanTest,
+ ).RunTestWithBp(t, bp)
+
+ check := func(t *testing.T, result *android.TestResult, variant string) {
+ asanVariant := variant + "_asan"
+ sharedVariant := variant + "_shared"
+ sharedAsanVariant := sharedVariant + "_asan"
+ staticVariant := variant + "_static"
+ staticAsanVariant := staticVariant + "_asan"
+
+ // The binaries, one with asan and one without
+ binWithAsan := result.ModuleForTests("bin_with_asan", asanVariant)
+ binNoAsan := result.ModuleForTests("bin_no_asan", variant)
+
+ // Shared libraries that don't request asan
+ libShared := result.ModuleForTests("libshared", sharedVariant)
+ libTransitive := result.ModuleForTests("libtransitive", sharedVariant)
+
+ // Shared library that requests asan
+ libAsan := result.ModuleForTests("libasan", sharedAsanVariant)
+
+ // Static library that uses an asan variant for bin_with_asan and a non-asan variant
+ // for bin_no_asan.
+ libStaticAsanVariant := result.ModuleForTests("libstatic", staticAsanVariant)
+ libStaticNoAsanVariant := result.ModuleForTests("libstatic", staticVariant)
+
+ // Static library that never uses asan.
+ libNoAsan := result.ModuleForTests("libnoasan", staticVariant)
+
+ // expectSharedLinkDep verifies that the from module links against the to module as a
+ // shared library.
+ expectSharedLinkDep := func(from, to android.TestingModule) {
+ t.Helper()
+ fromLink := from.Description("link")
+ toLink := to.Description("strip")
+
+ if g, w := fromLink.OrderOnly.Strings(), toLink.Output.String(); !android.InList(w, g) {
+ t.Errorf("%s should link against %s, expected %q, got %q",
+ from.Module(), to.Module(), w, g)
+ }
+ }
+
+ // expectStaticLinkDep verifies that the from module links against the to module as a
+ // static library.
+ expectStaticLinkDep := func(from, to android.TestingModule) {
+ t.Helper()
+ fromLink := from.Description("link")
+ toLink := to.Description("static link")
+
+ if g, w := fromLink.Implicits.Strings(), toLink.Output.String(); !android.InList(w, g) {
+ t.Errorf("%s should link against %s, expected %q, got %q",
+ from.Module(), to.Module(), w, g)
+ }
+
+ }
+
+ // expectInstallDep verifies that the install rule of the from module depends on the
+ // install rule of the to module.
+ expectInstallDep := func(from, to android.TestingModule) {
+ t.Helper()
+ fromInstalled := from.Description("install")
+ toInstalled := to.Description("install")
+
+ // combine implicits and order-only dependencies, host uses implicit but device uses
+ // order-only.
+ got := append(fromInstalled.Implicits.Strings(), fromInstalled.OrderOnly.Strings()...)
+ want := toInstalled.Output.String()
+ if !android.InList(want, got) {
+ t.Errorf("%s installation should depend on %s, expected %q, got %q",
+ from.Module(), to.Module(), want, got)
+ }
+ }
+
+ expectSharedLinkDep(binWithAsan, libShared)
+ expectSharedLinkDep(binWithAsan, libAsan)
+ expectSharedLinkDep(libShared, libTransitive)
+ expectSharedLinkDep(libAsan, libTransitive)
+
+ expectStaticLinkDep(binWithAsan, libStaticAsanVariant)
+ expectStaticLinkDep(binWithAsan, libNoAsan)
+
+ expectInstallDep(binWithAsan, libShared)
+ expectInstallDep(binWithAsan, libAsan)
+ expectInstallDep(binWithAsan, libTransitive)
+ expectInstallDep(libShared, libTransitive)
+ expectInstallDep(libAsan, libTransitive)
+
+ expectSharedLinkDep(binNoAsan, libShared)
+ expectSharedLinkDep(binNoAsan, libAsan)
+ expectSharedLinkDep(libShared, libTransitive)
+ expectSharedLinkDep(libAsan, libTransitive)
+
+ expectStaticLinkDep(binNoAsan, libStaticNoAsanVariant)
+ expectStaticLinkDep(binNoAsan, libNoAsan)
+
+ expectInstallDep(binNoAsan, libShared)
+ expectInstallDep(binNoAsan, libAsan)
+ expectInstallDep(binNoAsan, libTransitive)
+ expectInstallDep(libShared, libTransitive)
+ expectInstallDep(libAsan, libTransitive)
+ }
+
+ t.Run("host", func(t *testing.T) { check(t, result, result.Config.BuildOSTarget.String()) })
+ t.Run("device", func(t *testing.T) { check(t, result, "android_arm64_armv8-a") })
+}
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index 7e73bf71d..0bcec17b5 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -372,6 +372,15 @@ func (d dex2oatDependencyTag) ExcludeFromVisibilityEnforcement() {
func (d dex2oatDependencyTag) ExcludeFromApexContents() {
}
+func (d dex2oatDependencyTag) AllowDisabledModuleDependency(target android.Module) bool {
+ // RegisterToolDeps may run after the prebuilt mutators and hence register a
+ // dependency on the source module even when the prebuilt is to be used.
+ // dex2oatPathFromDep takes that into account when it retrieves the path to
+ // the binary, but we also need to disable the check for dependencies on
+ // disabled modules.
+ return target.IsReplacedByPrebuilt()
+}
+
// Dex2oatDepTag represents the dependency onto the dex2oatd module. It is added to any module that
// needs dexpreopting and so it makes no sense for it to be checked for visibility or included in
// the apex.
@@ -379,6 +388,7 @@ var Dex2oatDepTag = dex2oatDependencyTag{}
var _ android.ExcludeFromVisibilityEnforcementTag = Dex2oatDepTag
var _ android.ExcludeFromApexContentsTag = Dex2oatDepTag
+var _ android.AllowDisabledModuleDependency = Dex2oatDepTag
// RegisterToolDeps adds the necessary dependencies to binary modules for tools
// that are required later when Get(Cached)GlobalSoongConfig is called. It
diff --git a/java/base.go b/java/base.go
index 03652be05..f7989b8a2 100644
--- a/java/base.go
+++ b/java/base.go
@@ -229,12 +229,6 @@ type DeviceProperties struct {
// otherwise provides defaults libraries to add to the bootclasspath.
System_modules *string
- // The name of the module as used in build configuration.
- //
- // Allows a library to separate its actual name from the name used in
- // build configuration, e.g.ctx.Config().BootJars().
- ConfigurationName *string `blueprint:"mutated"`
-
// set the name of the output
Stem *string
@@ -895,8 +889,8 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
kotlincFlags := j.properties.Kotlincflags
CheckKotlincFlags(ctx, kotlincFlags)
- // Dogfood the JVM_IR backend.
- kotlincFlags = append(kotlincFlags, "-Xuse-ir")
+ // Workaround for KT-46512
+ kotlincFlags = append(kotlincFlags, "-Xsam-conversions=class")
// If there are kotlin files, compile them first but pass all the kotlin and java files
// kotlinc will use the java files to resolve types referenced by the kotlin files, but
@@ -1223,12 +1217,6 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
return
}
- // Update hidden API paths.
- j.hiddenAPIUpdatePaths(ctx, dexOutputFile, j.implementationJarFile)
-
- // Encode hidden API flags in dex file.
- dexOutputFile = j.hiddenAPIEncodeDex(ctx, dexOutputFile, proptools.Bool(j.dexProperties.Uncompress_dex))
-
// merge dex jar with resources if necessary
if j.resourceJar != nil {
jars := android.Paths{dexOutputFile, j.resourceJar}
@@ -1244,6 +1232,12 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
}
}
+ // Initialize the hiddenapi structure.
+ j.initHiddenAPI(ctx, dexOutputFile, j.implementationJarFile, j.dexProperties.Uncompress_dex)
+
+ // Encode hidden API flags in dex file, if needed.
+ dexOutputFile = j.hiddenAPIEncodeDex(ctx, dexOutputFile)
+
j.dexJarFile = dexOutputFile
// Dexpreopting
@@ -1501,15 +1495,6 @@ func (j *Module) Stem() string {
return proptools.StringDefault(j.deviceProperties.Stem, j.Name())
}
-// ConfigurationName returns the name of the module as used in build configuration.
-//
-// This is usually the same as BaseModuleName() except for the <x>.impl libraries created by
-// java_sdk_library in which case this is the BaseModuleName() without the ".impl" suffix,
-// i.e. just <x>.
-func (j *Module) ConfigurationName() string {
- return proptools.StringDefault(j.deviceProperties.ConfigurationName, j.BaseModuleName())
-}
-
func (j *Module) JacocoReportClassesFile() android.Path {
return j.jacocoReportClassesFile
}
diff --git a/java/boot_jars.go b/java/boot_jars.go
index 1fb3deb0a..7abda8031 100644
--- a/java/boot_jars.go
+++ b/java/boot_jars.go
@@ -89,7 +89,7 @@ func (b *bootJarsSingleton) GenerateBuildActions(ctx android.SingletonContext) {
name := android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName(module))
if apex, ok := moduleToApex[name]; ok {
apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
- if (apex == "platform" && apexInfo.IsForPlatform()) || apexInfo.InApexByBaseName(apex) {
+ if (apex == "platform" && apexInfo.IsForPlatform()) || apexInfo.InApexModule(apex) {
// The module name/apex variant should be unique in the system but double check
// just in case something has gone wrong.
if existing, ok := nameToApexVariant[name]; ok {
diff --git a/java/bootclasspath.go b/java/bootclasspath.go
index 02833ab66..634959a7e 100644
--- a/java/bootclasspath.go
+++ b/java/bootclasspath.go
@@ -29,7 +29,7 @@ func init() {
func registerBootclasspathBuildComponents(ctx android.RegistrationContext) {
ctx.FinalDepsMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.BottomUp("bootclasspath_deps", bootclasspathDepsMutator)
+ ctx.BottomUp("bootclasspath_deps", bootclasspathDepsMutator).Parallel()
})
}
@@ -95,6 +95,15 @@ func addDependencyOntoApexModulePair(ctx android.BottomUpMutatorContext, apex st
if ctx.OtherModuleDependencyVariantExists(variations, prebuiltName) {
ctx.AddVariationDependencies(variations, tag, prebuiltName)
addedDep = true
+ } else if ctx.Config().AlwaysUsePrebuiltSdks() && len(variations) > 0 {
+ // TODO(b/179354495): Remove this code path once the Android build has been fully migrated to
+ // use bootclasspath_fragment properly.
+ // Some prebuilt java_sdk_library modules do not yet have an APEX variations so try and add a
+ // dependency on the non-APEX variant.
+ if ctx.OtherModuleDependencyVariantExists(nil, prebuiltName) {
+ ctx.AddVariationDependencies(nil, tag, prebuiltName)
+ addedDep = true
+ }
}
// If no appropriate variant existing for this, so no dependency could be added, then it is an
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index 16aa5e2ea..6b395fbf0 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -112,6 +112,11 @@ type bootclasspathFragmentProperties struct {
Coverage BootclasspathFragmentCoverageAffectedProperties
Hidden_api HiddenAPIFlagFileProperties
+
+ // Properties that allow a fragment to depend on other fragments. This is needed for hidden API
+ // processing as it needs access to all the classes used by a fragment including those provided
+ // by other fragments.
+ BootclasspathFragmentsDepsProperties
}
type BootclasspathFragmentModule struct {
@@ -263,27 +268,15 @@ var BootclasspathFragmentApexContentInfoProvider = blueprint.NewProvider(Bootcla
// BootclasspathFragmentApexContentInfo contains the bootclasspath_fragments contributions to the
// apex contents.
type BootclasspathFragmentApexContentInfo struct {
- // ClasspathFragmentProtoOutput is an output path for the generated classpaths.proto config of this module.
- //
- // The file should be copied to a relevant place on device, see ClasspathFragmentProtoInstallDir
- // for more details.
- ClasspathFragmentProtoOutput android.OutputPath
-
- // ClasspathFragmentProtoInstallDir contains information about on device location for the generated classpaths.proto file.
- //
- // The path encodes expected sub-location within partitions, i.e. etc/classpaths/<proto-file>,
- // for ClasspathFragmentProtoOutput. To get sub-location, instead of the full output / make path
- // use android.InstallPath#Rel().
- //
- // This is only relevant for APEX modules as they perform their own installation; while regular
- // system files are installed via ClasspathFragmentBase#androidMkEntries().
- ClasspathFragmentProtoInstallDir android.InstallPath
-
// The image config, internal to this module (and the dex_bootjars singleton).
//
// Will be nil if the BootclasspathFragmentApexContentInfo has not been provided for a specific module. That can occur
// when SkipDexpreoptBootJars(ctx) returns true.
imageConfig *bootImageConfig
+
+ // Map from the name of the context module (as returned by Name()) to the hidden API encoded dex
+ // jar path.
+ contentModuleDexJarPaths map[string]android.Path
}
func (i BootclasspathFragmentApexContentInfo) Modules() android.ConfiguredJarList {
@@ -310,10 +303,14 @@ func (i BootclasspathFragmentApexContentInfo) AndroidBootImageFilesByArchType()
// DexBootJarPathForContentModule returns the path to the dex boot jar for specified module.
//
// The dex boot jar is one which has had hidden API encoding performed on it.
-func (i BootclasspathFragmentApexContentInfo) DexBootJarPathForContentModule(module android.Module) android.Path {
- j := module.(UsesLibraryDependency)
- dexJar := j.DexJarBuildPath()
- return dexJar
+func (i BootclasspathFragmentApexContentInfo) DexBootJarPathForContentModule(module android.Module) (android.Path, error) {
+ name := module.Name()
+ if dexJar, ok := i.contentModuleDexJarPaths[name]; ok {
+ return dexJar, nil
+ } else {
+ return nil, fmt.Errorf("unknown bootclasspath_fragment content module %s, expected one of %s",
+ name, strings.Join(android.SortedStringKeys(i.contentModuleDexJarPaths), ", "))
+ }
}
func (b *BootclasspathFragmentModule) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
@@ -391,27 +388,52 @@ func (b *BootclasspathFragmentModule) GenerateAndroidBuildActions(ctx android.Mo
// Perform hidden API processing.
b.generateHiddenAPIBuildActions(ctx, contents)
- // Construct the boot image info from the config.
+ // Verify that the image_name specified on a bootclasspath_fragment is valid even if this is a
+ // prebuilt which will not use the image config.
+ imageConfig := b.getImageConfig(ctx)
+
+ // A prebuilt fragment cannot contribute to the apex.
+ if !android.IsModulePrebuilt(ctx.Module()) {
+ // Provide the apex content info.
+ b.provideApexContentInfo(ctx, imageConfig, contents)
+ }
+}
+
+// provideApexContentInfo creates, initializes and stores the apex content info for use by other
+// modules.
+func (b *BootclasspathFragmentModule) provideApexContentInfo(ctx android.ModuleContext, imageConfig *bootImageConfig, contents []android.Module) {
+ // Construct the apex content info from the config.
info := BootclasspathFragmentApexContentInfo{
- ClasspathFragmentProtoInstallDir: b.classpathFragmentBase().installDirPath,
- ClasspathFragmentProtoOutput: b.classpathFragmentBase().outputFilepath,
- imageConfig: nil,
+ imageConfig: imageConfig,
}
+ // Populate the apex content info with paths to the dex jars.
+ b.populateApexContentInfoDexJars(ctx, &info, contents)
+
if !SkipDexpreoptBootJars(ctx) {
// Force the GlobalSoongConfig to be created and cached for use by the dex_bootjars
// GenerateSingletonBuildActions method as it cannot create it for itself.
dexpreopt.GetGlobalSoongConfig(ctx)
- info.imageConfig = b.getImageConfig(ctx)
// Only generate the boot image if the configuration does not skip it.
b.generateBootImageBuildActions(ctx, contents)
}
- // Make it available for other modules.
+ // Make the apex content info available for other modules.
ctx.SetProvider(BootclasspathFragmentApexContentInfoProvider, info)
}
+// populateApexContentInfoDexJars adds paths to the dex jars provided by this fragment to the
+// apex content info.
+func (b *BootclasspathFragmentModule) populateApexContentInfoDexJars(ctx android.ModuleContext, info *BootclasspathFragmentApexContentInfo, contents []android.Module) {
+ info.contentModuleDexJarPaths = map[string]android.Path{}
+ for _, m := range contents {
+ j := m.(UsesLibraryDependency)
+ dexJar := j.DexJarBuildPath()
+ info.contentModuleDexJarPaths[m.Name()] = dexJar
+ }
+}
+
// generateClasspathProtoBuildActions generates all required build actions for classpath.proto config
func (b *BootclasspathFragmentModule) generateClasspathProtoBuildActions(ctx android.ModuleContext) {
var classpathJars []classpathJar
@@ -448,12 +470,54 @@ func (b *BootclasspathFragmentModule) getImageConfig(ctx android.EarlyModuleCont
return imageConfig
}
+// canPerformHiddenAPIProcessing determines whether hidden API processing should be performed.
+//
+// A temporary workaround to avoid existing bootclasspath_fragments that do not provide the
+// appropriate information needed for hidden API processing breaking the build.
+// TODO(b/179354495): Remove this workaround.
+func (b *BootclasspathFragmentModule) canPerformHiddenAPIProcessing(ctx android.ModuleContext) bool {
+ // Hidden API processing is always enabled in tests.
+ if ctx.Config().TestProductVariables != nil {
+ return true
+ }
+ // A module that has fragments should have access to the information it needs in order to perform
+ // hidden API processing.
+ if len(b.properties.Fragments) != 0 {
+ return true
+ }
+
+ // The art bootclasspath fragment does not depend on any other fragments but already supports
+ // hidden API processing.
+ imageName := proptools.String(b.properties.Image_name)
+ if imageName == "art" {
+ return true
+ }
+
+ // Disable it for everything else.
+ return false
+}
+
// generateHiddenAPIBuildActions generates all the hidden API related build rules.
func (b *BootclasspathFragmentModule) generateHiddenAPIBuildActions(ctx android.ModuleContext, contents []android.Module) {
+ // A temporary workaround to avoid existing bootclasspath_fragments that do not provide the
+ // appropriate information needed for hidden API processing breaking the build.
+ if !b.canPerformHiddenAPIProcessing(ctx) {
+ // Nothing to do.
+ return
+ }
+
// Convert the kind specific lists of modules into kind specific lists of jars.
stubJarsByKind := hiddenAPIGatherStubLibDexJarPaths(ctx, contents)
+ // Performing hidden API processing without stubs is not supported and it is unlikely to ever be
+ // required as the whole point of adding something to the bootclasspath fragment is to add it to
+ // the bootclasspath in order to be used by something else in the system. Without any stubs it
+ // cannot do that.
+ if len(stubJarsByKind) == 0 {
+ return
+ }
+
// Store the information for use by other modules.
bootclasspathApiInfo := bootclasspathApiInfo{stubJarsByKind: stubJarsByKind}
ctx.SetProvider(bootclasspathApiInfoProvider, bootclasspathApiInfo)
@@ -474,15 +538,6 @@ func (b *BootclasspathFragmentModule) generateHiddenAPIBuildActions(ctx android.
// produceHiddenAPIAllFlagsFile produces the hidden API all-flags.csv file (and supporting files)
// for the fragment.
func (b *BootclasspathFragmentModule) produceHiddenAPIAllFlagsFile(ctx android.ModuleContext, contents []hiddenAPIModule, stubJarsByKind map[android.SdkKind]android.Paths, flagFileInfo *hiddenAPIFlagFileInfo) {
- // If no stubs have been provided then don't perform hidden API processing. This is a temporary
- // workaround to avoid existing bootclasspath_fragments that do not provide stubs breaking the
- // build.
- // TODO(b/179354495): Remove this workaround.
- if len(stubJarsByKind) == 0 {
- // Nothing to do.
- return
- }
-
// Generate the rules to create the hidden API flags and update the supplied flagFileInfo with the
// paths to the created files.
hiddenAPIGenerateAllFlagsForBootclasspathFragment(ctx, contents, stubJarsByKind, flagFileInfo)
diff --git a/java/classpath_fragment.go b/java/classpath_fragment.go
index 7422fa2d5..bc0416a47 100644
--- a/java/classpath_fragment.go
+++ b/java/classpath_fragment.go
@@ -18,6 +18,7 @@ package java
import (
"fmt"
+ "github.com/google/blueprint"
"strings"
"android/soong/android"
@@ -120,6 +121,12 @@ func (c *ClasspathFragmentBase) generateClasspathProtoBuildActions(ctx android.M
FlagWithOutput("--output=", c.outputFilepath)
rule.Build("classpath_fragment", "Compiling "+c.outputFilepath.String())
+
+ classpathProtoInfo := ClasspathFragmentProtoContentInfo{
+ ClasspathFragmentProtoInstallDir: c.installDirPath,
+ ClasspathFragmentProtoOutput: c.outputFilepath,
+ }
+ ctx.SetProvider(ClasspathFragmentProtoContentInfoProvider, classpathProtoInfo)
}
func writeClasspathsJson(ctx android.ModuleContext, output android.WritablePath, jars []classpathJar) {
@@ -129,7 +136,7 @@ func writeClasspathsJson(ctx android.ModuleContext, output android.WritablePath,
for idx, jar := range jars {
fmt.Fprintf(&content, "{\n")
- fmt.Fprintf(&content, "\"relativePath\": \"%s\",\n", jar.path)
+ fmt.Fprintf(&content, "\"path\": \"%s\",\n", jar.path)
fmt.Fprintf(&content, "\"classpath\": \"%s\"\n", jar.classpath)
if idx < len(jars)-1 {
@@ -157,3 +164,23 @@ func (c *ClasspathFragmentBase) androidMkEntries() []android.AndroidMkEntries {
},
}}
}
+
+var ClasspathFragmentProtoContentInfoProvider = blueprint.NewProvider(ClasspathFragmentProtoContentInfo{})
+
+type ClasspathFragmentProtoContentInfo struct {
+ // ClasspathFragmentProtoOutput is an output path for the generated classpaths.proto config of this module.
+ //
+ // The file should be copied to a relevant place on device, see ClasspathFragmentProtoInstallDir
+ // for more details.
+ ClasspathFragmentProtoOutput android.OutputPath
+
+ // ClasspathFragmentProtoInstallDir contains information about on device location for the generated classpaths.proto file.
+ //
+ // The path encodes expected sub-location within partitions, i.e. etc/classpaths/<proto-file>,
+ // for ClasspathFragmentProtoOutput. To get sub-location, instead of the full output / make path
+ // use android.InstallPath#Rel().
+ //
+ // This is only relevant for APEX modules as they perform their own installation; while regular
+ // system files are installed via ClasspathFragmentBase#androidMkEntries().
+ ClasspathFragmentProtoInstallDir android.InstallPath
+}
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index be202c0db..e1a36507a 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -766,7 +766,7 @@ func generateUpdatableBcpPackagesRule(ctx android.ModuleContext, image *bootImag
if len(pp) > 0 {
updatablePackages = append(updatablePackages, pp...)
} else {
- ctx.ModuleErrorf("Missing permitted_packages")
+ ctx.OtherModuleErrorf(module, "Missing permitted_packages")
}
}
}
@@ -803,8 +803,7 @@ func dumpOatRules(ctx android.ModuleContext, image *bootImageConfig) {
rule := android.NewRuleBuilder(pctx, ctx)
imageLocationsOnHost, _ := image.imageLocations()
rule.Command().
- // TODO: for now, use the debug version for better error reporting
- BuiltTool("oatdumpd").
+ BuiltTool("oatdump").
FlagWithInputList("--runtime-arg -Xbootclasspath:", image.dexPathsDeps.Paths(), ":").
FlagWithList("--runtime-arg -Xbootclasspath-locations:", image.dexLocationsDeps, ":").
FlagWithArg("--image=", strings.Join(imageLocationsOnHost, ":")).Implicits(image.imagesDeps.Paths()).
diff --git a/java/dexpreopt_test.go b/java/dexpreopt_test.go
index a9e0773b7..f065534d5 100644
--- a/java/dexpreopt_test.go
+++ b/java/dexpreopt_test.go
@@ -15,7 +15,12 @@
package java
import (
+ "fmt"
"testing"
+
+ "android/soong/android"
+ "android/soong/cc"
+ "android/soong/dexpreopt"
)
func TestDexpreoptEnabled(t *testing.T) {
@@ -166,3 +171,46 @@ func enabledString(enabled bool) string {
return "disabled"
}
}
+
+func TestDex2oatToolDeps(t *testing.T) {
+ preparers := android.GroupFixturePreparers(
+ cc.PrepareForTestWithCcDefaultModules,
+ PrepareForTestWithJavaDefaultModulesWithoutFakeDex2oatd,
+ dexpreopt.PrepareForTestByEnablingDexpreopt)
+
+ testDex2oatToolDep := func(sourceEnabled, prebuiltEnabled, prebuiltPreferred bool,
+ expectedDex2oatPath string) {
+ name := fmt.Sprintf("sourceEnabled:%t,prebuiltEnabled:%t,prebuiltPreferred:%t",
+ sourceEnabled, prebuiltEnabled, prebuiltPreferred)
+ t.Run(name, func(t *testing.T) {
+ result := preparers.RunTestWithBp(t, fmt.Sprintf(`
+ cc_binary {
+ name: "dex2oatd",
+ enabled: %t,
+ host_supported: true,
+ }
+ cc_prebuilt_binary {
+ name: "dex2oatd",
+ enabled: %t,
+ prefer: %t,
+ host_supported: true,
+ srcs: ["x86_64/bin/dex2oatd"],
+ }
+ java_library {
+ name: "myjavalib",
+ }
+ `, sourceEnabled, prebuiltEnabled, prebuiltPreferred))
+ pathContext := android.PathContextForTesting(result.Config)
+ dex2oatPath := dexpreopt.GetCachedGlobalSoongConfig(pathContext).Dex2oat
+ android.AssertStringEquals(t, "Testing "+name, expectedDex2oatPath, android.NormalizePathForTesting(dex2oatPath))
+ })
+ }
+
+ sourceDex2oatPath := "host/linux-x86/bin/dex2oatd"
+ prebuiltDex2oatPath := ".intermediates/prebuilt_dex2oatd/linux_glibc_x86_64/dex2oatd"
+
+ testDex2oatToolDep(true, false, false, sourceDex2oatPath)
+ testDex2oatToolDep(true, true, false, sourceDex2oatPath)
+ testDex2oatToolDep(true, true, true, prebuiltDex2oatPath)
+ testDex2oatToolDep(false, true, false, prebuiltDex2oatPath)
+}
diff --git a/java/hiddenapi.go b/java/hiddenapi.go
index 829c47383..c9e3c29a3 100644
--- a/java/hiddenapi.go
+++ b/java/hiddenapi.go
@@ -26,27 +26,10 @@ var hiddenAPIGenerateCSVRule = pctx.AndroidStaticRule("hiddenAPIGenerateCSV", bl
}, "outFlag", "stubAPIFlags")
type hiddenAPI struct {
- // The name of the module as it would be used in the boot jars configuration, e.g. without any
- // prebuilt_ prefix (if it is a prebuilt) and without any ".impl" suffix if it is a
- // java_sdk_library implementation library.
- configurationName string
-
// True if the module containing this structure contributes to the hiddenapi information or has
// that information encoded within it.
active bool
- // Identifies the active module variant which will be used as the source of hiddenapi information.
- //
- // A class may be compiled into a number of different module variants each of which will need the
- // hiddenapi information encoded into it and so will be marked as active. However, only one of
- // them must be used as a source of information by hiddenapi otherwise it will end up with
- // duplicate entries. That module will have primary=true.
- //
- // Note, that modules <x>-hiddenapi that provide additional annotation information for module <x>
- // that is on the bootclasspath are marked as primary=true as they are the primary source of that
- // annotation information.
- primary bool
-
// The path to the dex jar that is in the boot class path. If this is nil then the associated
// module is not a boot jar, but could be one of the <x>-hiddenapi modules that provide additional
// annotations for the <x> boot dex jar but which do not actually provide a boot dex jar
@@ -60,6 +43,10 @@ type hiddenAPI struct {
// the UnsupportedAppUsage annotation that need to be extracted as part of the hidden API
// processing.
classesJarPaths android.Paths
+
+ // The compressed state of the dex file being encoded. This is used to ensure that the encoded
+ // dex file has the same state.
+ uncompressDexState *bool
}
func (h *hiddenAPI) bootDexJar() android.Path {
@@ -70,6 +57,10 @@ func (h *hiddenAPI) classesJars() android.Paths {
return h.classesJarPaths
}
+func (h *hiddenAPI) uncompressDex() *bool {
+ return h.uncompressDexState
+}
+
// hiddenAPIModule is the interface a module that embeds the hiddenAPI structure must implement.
type hiddenAPIModule interface {
android.Module
@@ -79,18 +70,39 @@ type hiddenAPIModule interface {
type hiddenAPIIntf interface {
bootDexJar() android.Path
classesJars() android.Paths
+ uncompressDex() *bool
}
var _ hiddenAPIIntf = (*hiddenAPI)(nil)
// Initialize the hiddenapi structure
-func (h *hiddenAPI) initHiddenAPI(ctx android.BaseModuleContext, configurationName string) {
+//
+// uncompressedDexState should be nil when the module is a prebuilt and so does not require hidden
+// API encoding.
+func (h *hiddenAPI) initHiddenAPI(ctx android.ModuleContext, dexJar, classesJar android.Path, uncompressedDexState *bool) {
+
+ // Save the classes jars even if this is not active as they may be used by modular hidden API
+ // processing.
+ classesJars := android.Paths{classesJar}
+ ctx.VisitDirectDepsWithTag(hiddenApiAnnotationsTag, func(dep android.Module) {
+ javaInfo := ctx.OtherModuleProvider(dep, JavaInfoProvider).(JavaInfo)
+ classesJars = append(classesJars, javaInfo.ImplementationJars...)
+ })
+ h.classesJarPaths = classesJars
+
+ // Save the unencoded dex jar so it can be used when generating the
+ // hiddenAPISingletonPathsStruct.stubFlags file.
+ h.bootDexJarPath = dexJar
+
+ h.uncompressDexState = uncompressedDexState
+
// If hiddenapi processing is disabled treat this as inactive.
if ctx.Config().IsEnvTrue("UNSAFE_DISABLE_HIDDENAPI_FLAGS") {
return
}
- h.configurationName = configurationName
+ // The context module must implement hiddenAPIModule.
+ module := ctx.Module().(hiddenAPIModule)
// If the frameworks/base directories does not exist and no prebuilt hidden API flag files have
// been configured then it is not possible to do hidden API encoding.
@@ -102,52 +114,7 @@ func (h *hiddenAPI) initHiddenAPI(ctx android.BaseModuleContext, configurationNa
// on the boot jars list because the runtime only enforces access to the hidden API for the
// bootclassloader. If information is gathered for modules not on the list then that will cause
// failures in the CtsHiddenApiBlocklist... tests.
- module := ctx.Module()
h.active = isModuleInBootClassPath(ctx, module)
- if !h.active {
- // The rest of the properties will be ignored if active is false.
- return
- }
-
- // Determine whether this module is the primary module or not.
- primary := true
-
- // A prebuilt module is only primary if it is preferred and conversely a source module is only
- // primary if it has not been replaced by a prebuilt module.
- if pi, ok := module.(android.PrebuiltInterface); ok {
- if p := pi.Prebuilt(); p != nil {
- primary = p.UsePrebuilt()
- }
- } else {
- // The only module that will pass a different configurationName to its module name to this
- // method is the implementation library of a java_sdk_library. It has a configuration name of
- // <x> the same as its parent java_sdk_library but a module name of <x>.impl. It is not the
- // primary module, the java_sdk_library with the name of <x> is.
- primary = configurationName == ctx.ModuleName()
-
- // A source module that has been replaced by a prebuilt can never be the primary module.
- if module.IsReplacedByPrebuilt() {
- if ctx.HasProvider(android.ApexInfoProvider) {
- // The source module is in an APEX but the prebuilt module on which it depends is not in an
- // APEX and so is not the one that will actually be used for hidden API processing. That
- // means it is not possible to check to see if it is a suitable replacement so just assume
- // that it is.
- primary = false
- } else {
- ctx.VisitDirectDepsWithTag(android.PrebuiltDepTag, func(prebuilt android.Module) {
- if h, ok := prebuilt.(hiddenAPIIntf); ok && h.bootDexJar() != nil {
- primary = false
- } else {
- ctx.ModuleErrorf(
- "hiddenapi has determined that the source module %q should be ignored as it has been"+
- " replaced by the prebuilt module %q but unfortunately it does not provide a"+
- " suitable boot dex jar", ctx.ModuleName(), ctx.OtherModuleName(prebuilt))
- }
- })
- }
- }
- }
- h.primary = primary
}
func isModuleInBootClassPath(ctx android.BaseModuleContext, module android.Module) bool {
@@ -166,13 +133,19 @@ func isModuleInBootClassPath(ctx android.BaseModuleContext, module android.Modul
//
// Otherwise, it creates a copy of the supplied dex file into which it has encoded the hiddenapi
// flags and returns this instead of the supplied dex jar.
-func (h *hiddenAPI) hiddenAPIEncodeDex(ctx android.ModuleContext, dexJar android.OutputPath, uncompressDex bool) android.OutputPath {
+func (h *hiddenAPI) hiddenAPIEncodeDex(ctx android.ModuleContext, dexJar android.OutputPath) android.OutputPath {
if !h.active {
return dexJar
}
- hiddenAPIJar := android.PathForModuleOut(ctx, "hiddenapi", h.configurationName+".jar").OutputPath
+ // A nil uncompressDexState prevents the dex file from being encoded.
+ if h.uncompressDexState == nil {
+ ctx.ModuleErrorf("cannot encode dex file %s when uncompressDexState is nil", dexJar)
+ }
+ uncompressDex := *h.uncompressDexState
+
+ hiddenAPIJar := android.PathForModuleOut(ctx, "hiddenapi", dexJar.Base()).OutputPath
// Create a copy of the dex jar which has been encoded with hiddenapi flags.
hiddenAPIEncodeDex(ctx, hiddenAPIJar, dexJar, uncompressDex)
@@ -183,27 +156,6 @@ func (h *hiddenAPI) hiddenAPIEncodeDex(ctx android.ModuleContext, dexJar android
return dexJar
}
-// hiddenAPIUpdatePaths generates ninja rules to extract the information from the classes
-// jar, and outputs it to the appropriate module specific CSV file.
-//
-// It also makes the dex jar available for use when generating the
-// hiddenAPISingletonPathsStruct.stubFlags.
-func (h *hiddenAPI) hiddenAPIUpdatePaths(ctx android.ModuleContext, dexJar, classesJar android.Path) {
-
- // Save the classes jars even if this is not active as they may be used by modular hidden API
- // processing.
- classesJars := android.Paths{classesJar}
- ctx.VisitDirectDepsWithTag(hiddenApiAnnotationsTag, func(dep android.Module) {
- javaInfo := ctx.OtherModuleProvider(dep, JavaInfoProvider).(JavaInfo)
- classesJars = append(classesJars, javaInfo.ImplementationJars...)
- })
- h.classesJarPaths = classesJars
-
- // Save the unencoded dex jar so it can be used when generating the
- // hiddenAPISingletonPathsStruct.stubFlags file.
- h.bootDexJarPath = dexJar
-}
-
// buildRuleToGenerateAnnotationFlags builds a ninja rule to generate the annotation-flags.csv file
// from the classes jars and stub-flags.csv files.
//
@@ -283,7 +235,7 @@ var hiddenAPIEncodeDexRule = pctx.AndroidStaticRule("hiddenAPIEncodeDex", bluepr
echo "--output-dex=$tmpDir/dex-output/$$(basename $${INPUT_DEX})";
done | xargs ${config.HiddenAPI} encode --api-flags=$flagsCsv $hiddenapiFlags &&
${config.SoongZipCmd} $soongZipFlags -o $tmpDir/dex.jar -C $tmpDir/dex-output -f "$tmpDir/dex-output/classes*.dex" &&
- ${config.MergeZipsCmd} -D -zipToNotStrip $tmpDir/dex.jar -stripFile "classes*.dex" -stripFile "**/*.uau" $out $tmpDir/dex.jar $in`,
+ ${config.MergeZipsCmd} -j -D -zipToNotStrip $tmpDir/dex.jar -stripFile "classes*.dex" -stripFile "**/*.uau" $out $tmpDir/dex.jar $in`,
CommandDeps: []string{
"${config.HiddenAPI}",
"${config.SoongZipCmd}",
diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go
index 2dceb6535..f5afe5d5b 100644
--- a/java/hiddenapi_modular.go
+++ b/java/hiddenapi_modular.go
@@ -15,6 +15,7 @@
package java
import (
+ "fmt"
"strings"
"android/soong/android"
@@ -560,7 +561,25 @@ func extractBootDexJarsFromHiddenAPIModules(ctx android.ModuleContext, contents
for _, module := range contents {
bootDexJar := module.bootDexJar()
if bootDexJar == nil {
- ctx.ModuleErrorf("module %s does not provide a dex jar", module)
+ if ctx.Config().AlwaysUsePrebuiltSdks() {
+ // TODO(b/179354495): Remove this work around when it is unnecessary.
+ // Prebuilt modules like framework-wifi do not yet provide dex implementation jars. So,
+ // create a fake one that will cause a build error only if it is used.
+ fake := android.PathForModuleOut(ctx, "fake/boot-dex/%s.jar", module.Name())
+
+ // Create an error rule that pretends to create the output file but will actually fail if it
+ // is run.
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.ErrorRule,
+ Output: fake,
+ Args: map[string]string{
+ "error": fmt.Sprintf("missing dependencies: boot dex jar for %s", module),
+ },
+ })
+ bootDexJars = append(bootDexJars, fake)
+ } else {
+ ctx.ModuleErrorf("module %s does not provide a dex jar", module)
+ }
} else {
bootDexJars = append(bootDexJars, bootDexJar)
}
diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go
index 848aa59bc..bdf055abc 100644
--- a/java/hiddenapi_singleton.go
+++ b/java/hiddenapi_singleton.go
@@ -167,11 +167,11 @@ func isModuleInConfiguredList(ctx android.BaseModuleContext, module android.Modu
// Now match the apex part of the boot image configuration.
requiredApex := configuredBootJars.Apex(index)
if requiredApex == "platform" || requiredApex == "system_ext" {
- if len(apexInfo.InApexes) != 0 {
+ if len(apexInfo.InApexVariants) != 0 {
// A platform variant is required but this is for an apex so ignore it.
return false
}
- } else if !apexInfo.InApexByBaseName(requiredApex) {
+ } else if !apexInfo.InApexVariantByBaseName(requiredApex) {
// An apex variant for a specific apex is required but this is the wrong apex.
return false
}
diff --git a/java/hiddenapi_singleton_test.go b/java/hiddenapi_singleton_test.go
index e6b45ac20..dcd363c2c 100644
--- a/java/hiddenapi_singleton_test.go
+++ b/java/hiddenapi_singleton_test.go
@@ -274,3 +274,56 @@ func TestHiddenAPISingletonWithPrebuiltCsvFile(t *testing.T) {
android.AssertStringEquals(t, "hiddenapi encode dex rule flags csv", expectedFlagsCsv, actualFlagsCsv)
}
+
+func TestHiddenAPIEncoding_JavaSdkLibrary(t *testing.T) {
+
+ result := android.GroupFixturePreparers(
+ hiddenApiFixtureFactory,
+ FixtureConfigureBootJars("platform:foo"),
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithLastReleaseApis("foo"),
+
+ // Make sure that the frameworks/base/Android.bp file exists as otherwise hidden API encoding
+ // is disabled.
+ android.FixtureAddTextFile("frameworks/base/Android.bp", ""),
+ ).RunTestWithBp(t, `
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java"],
+ shared_library: false,
+ compile_dex: true,
+ public: {enabled: true},
+ }
+ `)
+
+ checkDexEncoded := func(t *testing.T, name, unencodedDexJar, encodedDexJar string) {
+ moduleForTests := result.ModuleForTests(name, "android_common")
+
+ encodeDexRule := moduleForTests.Rule("hiddenAPIEncodeDex")
+ actualUnencodedDexJar := encodeDexRule.Input
+
+ // Make sure that the module has its dex jar encoded.
+ android.AssertStringEquals(t, "encode embedded java_library", unencodedDexJar, actualUnencodedDexJar.String())
+
+ // Make sure that the encoded dex jar is the exported one.
+ exportedDexJar := moduleForTests.Module().(UsesLibraryDependency).DexJarBuildPath()
+ android.AssertPathRelativeToTopEquals(t, "encode embedded java_library", encodedDexJar, exportedDexJar)
+ }
+
+ // The java_library embedded with the java_sdk_library must be dex encoded.
+ t.Run("foo", func(t *testing.T) {
+ expectedUnencodedDexJar := "out/soong/.intermediates/foo/android_common/aligned/foo.jar"
+ expectedEncodedDexJar := "out/soong/.intermediates/foo/android_common/hiddenapi/foo.jar"
+ checkDexEncoded(t, "foo", expectedUnencodedDexJar, expectedEncodedDexJar)
+ })
+
+ // The dex jar of the child implementation java_library of the java_sdk_library is not currently
+ // dex encoded.
+ t.Run("foo.impl", func(t *testing.T) {
+ fooImpl := result.ModuleForTests("foo.impl", "android_common")
+ encodeDexRule := fooImpl.MaybeRule("hiddenAPIEncodeDex")
+ if encodeDexRule.Rule != nil {
+ t.Errorf("foo.impl is not expected to be encoded")
+ }
+ })
+}
diff --git a/java/java.go b/java/java.go
index f85de3d77..2bbb5b102 100644
--- a/java/java.go
+++ b/java/java.go
@@ -57,6 +57,10 @@ func registerJavaBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("java_host_for_device", HostForDeviceFactory)
ctx.RegisterModuleType("dex_import", DexImportFactory)
+ // This mutator registers dependencies on dex2oat for modules that should be
+ // dexpreopted. This is done late when the final variants have been
+ // established, to not get the dependencies split into the wrong variants and
+ // to support the checks in dexpreoptDisabled().
ctx.FinalDepsMutators(func(ctx android.RegisterMutatorsContext) {
ctx.BottomUp("dexpreopt_tool_deps", dexpreoptToolDepsMutator).Parallel()
})
@@ -481,11 +485,6 @@ func shouldUncompressDex(ctx android.ModuleContext, dexpreopter *dexpreopter) bo
}
func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- // Initialize the hiddenapi structure. Pass in the configuration name rather than the module name
- // so the hidden api will encode the <x>.impl java_ library created by java_sdk_library just as it
- // would the <x> library if <x> was configured as a boot jar.
- j.initHiddenAPI(ctx, j.ConfigurationName())
-
j.sdkVersion = j.SdkVersion(ctx)
j.minSdkVersion = j.MinSdkVersion(ctx)
@@ -1241,9 +1240,6 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
j.sdkVersion = j.SdkVersion(ctx)
j.minSdkVersion = j.MinSdkVersion(ctx)
- // Initialize the hiddenapi structure.
- j.initHiddenAPI(ctx, j.BaseModuleName())
-
if !ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).IsForPlatform() {
j.hideApexVariantFromMake = true
}
@@ -1315,7 +1311,9 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
di := ctx.OtherModuleProvider(deapexerModule, android.DeapexerProvider).(android.DeapexerInfo)
if dexOutputPath := di.PrebuiltExportPath(j.BaseModuleName(), ".dexjar"); dexOutputPath != nil {
j.dexJarFile = dexOutputPath
- j.hiddenAPIUpdatePaths(ctx, dexOutputPath, outputFile)
+
+ // Initialize the hiddenapi structure.
+ j.initHiddenAPI(ctx, dexOutputPath, outputFile, nil)
} else {
// This should never happen as a variant for a prebuilt_apex is only created if the
// prebuilt_apex has been configured to export the java library dex file.
@@ -1346,11 +1344,11 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
return
}
- // Update hidden API paths.
- j.hiddenAPIUpdatePaths(ctx, dexOutputFile, outputFile)
+ // Initialize the hiddenapi structure.
+ j.initHiddenAPI(ctx, dexOutputFile, outputFile, j.dexProperties.Uncompress_dex)
// Encode hidden API flags in dex file.
- dexOutputFile = j.hiddenAPIEncodeDex(ctx, dexOutputFile, proptools.Bool(j.dexProperties.Uncompress_dex))
+ dexOutputFile = j.hiddenAPIEncodeDex(ctx, dexOutputFile)
j.dexJarFile = dexOutputFile
}
diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go
index c8fafede6..10bf179d2 100644
--- a/java/platform_bootclasspath.go
+++ b/java/platform_bootclasspath.go
@@ -225,7 +225,7 @@ func (b *platformBootclasspathModule) checkNonUpdatableModules(ctx android.Modul
fromUpdatableApex := apexInfo.Updatable
if fromUpdatableApex {
// error: this jar is part of an updatable apex
- ctx.ModuleErrorf("module %q from updatable apexes %q is not allowed in the framework boot image", ctx.OtherModuleName(m), apexInfo.InApexes)
+ ctx.ModuleErrorf("module %q from updatable apexes %q is not allowed in the framework boot image", ctx.OtherModuleName(m), apexInfo.InApexVariants)
} else {
// ok: this jar is part of the platform or a non-updatable apex
}
@@ -242,8 +242,15 @@ func (b *platformBootclasspathModule) checkUpdatableModules(ctx android.ModuleCo
} else {
name := ctx.OtherModuleName(m)
if apexInfo.IsForPlatform() {
- // error: this jar is part of the platform
- ctx.ModuleErrorf("module %q from platform is not allowed in the updatable boot jars list", name)
+ // If AlwaysUsePrebuiltSdks() returns true then it is possible that the updatable list will
+ // include platform variants of a prebuilt module due to workarounds elsewhere. In that case
+ // do not treat this as an error.
+ // TODO(b/179354495): Always treat this as an error when migration to bootclasspath_fragment
+ // modules is complete.
+ if !ctx.Config().AlwaysUsePrebuiltSdks() {
+ // error: this jar is part of the platform
+ ctx.ModuleErrorf("module %q from platform is not allowed in the updatable boot jars list", name)
+ }
} else {
// TODO(b/177892522): Treat this as an error.
// Cannot do that at the moment because framework-wifi and framework-tethering are in the
diff --git a/java/sdk_library.go b/java/sdk_library.go
index f04f837cc..b5b6232d6 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -1235,16 +1235,13 @@ func childModuleVisibility(childVisibility []string) []string {
// Creates the implementation java library
func (module *SdkLibrary) createImplLibrary(mctx android.DefaultableHookContext) {
- moduleNamePtr := proptools.StringPtr(module.BaseModuleName())
-
visibility := childModuleVisibility(module.sdkLibraryProperties.Impl_library_visibility)
props := struct {
- Name *string
- Visibility []string
- Instrument bool
- Libs []string
- ConfigurationName *string
+ Name *string
+ Visibility []string
+ Instrument bool
+ Libs []string
}{
Name: proptools.StringPtr(module.implLibraryModuleName()),
Visibility: visibility,
@@ -1253,9 +1250,6 @@ func (module *SdkLibrary) createImplLibrary(mctx android.DefaultableHookContext)
// Set the impl_only libs. Note that the module's "Libs" get appended as well, via the
// addition of &module.properties below.
Libs: module.sdkLibraryProperties.Impl_only_libs,
-
- // Make the created library behave as if it had the same name as this module.
- ConfigurationName: moduleNamePtr,
}
properties := []interface{}{
@@ -1552,7 +1546,7 @@ func PrebuiltJars(ctx android.BaseModuleContext, baseName string, s android.SdkS
func withinSameApexesAs(ctx android.BaseModuleContext, other android.Module) bool {
apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
otherApexInfo := ctx.OtherModuleProvider(other, android.ApexInfoProvider).(android.ApexInfo)
- return len(otherApexInfo.InApexes) > 0 && reflect.DeepEqual(apexInfo.InApexes, otherApexInfo.InApexes)
+ return len(otherApexInfo.InApexVariants) > 0 && reflect.DeepEqual(apexInfo.InApexVariants, otherApexInfo.InApexVariants)
}
func (module *SdkLibrary) sdkJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec, headerJars bool) android.Paths {
@@ -2127,8 +2121,7 @@ func (module *SdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleCo
di := ctx.OtherModuleProvider(deapexerModule, android.DeapexerProvider).(android.DeapexerInfo)
if dexOutputPath := di.PrebuiltExportPath(module.BaseModuleName(), ".dexjar"); dexOutputPath != nil {
module.dexJarFile = dexOutputPath
- module.initHiddenAPI(ctx, module.configurationName)
- module.hiddenAPIUpdatePaths(ctx, dexOutputPath, module.findScopePaths(apiScopePublic).stubsImplPath[0])
+ module.initHiddenAPI(ctx, dexOutputPath, module.findScopePaths(apiScopePublic).stubsImplPath[0], nil)
} else {
// This should never happen as a variant for a prebuilt_apex is only created if the
// prebuilt_apex has been configured to export the java library dex file.
diff --git a/java/systemserver_classpath_fragment.go b/java/systemserver_classpath_fragment.go
index 82cdb8926..a505c6d01 100644
--- a/java/systemserver_classpath_fragment.go
+++ b/java/systemserver_classpath_fragment.go
@@ -17,6 +17,7 @@ package java
import (
"android/soong/android"
"android/soong/dexpreopt"
+ "github.com/google/blueprint"
)
func init() {
@@ -24,8 +25,8 @@ func init() {
}
func registerSystemserverClasspathBuildComponents(ctx android.RegistrationContext) {
- // TODO(satayev): add systemserver_classpath_fragment module
ctx.RegisterModuleType("platform_systemserverclasspath", platformSystemServerClasspathFactory)
+ ctx.RegisterModuleType("systemserverclasspath_fragment", systemServerClasspathFactory)
}
type platformSystemServerClasspathModule struct {
@@ -41,18 +42,18 @@ func platformSystemServerClasspathFactory() android.Module {
return m
}
-func (b *platformSystemServerClasspathModule) AndroidMkEntries() (entries []android.AndroidMkEntries) {
- return b.classpathFragmentBase().androidMkEntries()
+func (p *platformSystemServerClasspathModule) AndroidMkEntries() (entries []android.AndroidMkEntries) {
+ return p.classpathFragmentBase().androidMkEntries()
}
-func (b *platformSystemServerClasspathModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- configuredJars := configuredJarListToClasspathJars(ctx, b.ClasspathFragmentToConfiguredJarList(ctx), b.classpathType)
- b.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, configuredJars)
+func (p *platformSystemServerClasspathModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ configuredJars := configuredJarListToClasspathJars(ctx, p.ClasspathFragmentToConfiguredJarList(ctx), p.classpathType)
+ p.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, configuredJars)
}
var platformSystemServerClasspathKey = android.NewOnceKey("platform_systemserverclasspath")
-func (b *platformSystemServerClasspathModule) ClasspathFragmentToConfiguredJarList(ctx android.ModuleContext) android.ConfiguredJarList {
+func (p *platformSystemServerClasspathModule) ClasspathFragmentToConfiguredJarList(ctx android.ModuleContext) android.ConfiguredJarList {
return ctx.Config().Once(platformSystemServerClasspathKey, func() interface{} {
global := dexpreopt.GetGlobalConfig(ctx)
@@ -65,3 +66,64 @@ func (b *platformSystemServerClasspathModule) ClasspathFragmentToConfiguredJarLi
return jars
}).(android.ConfiguredJarList)
}
+
+type SystemServerClasspathModule struct {
+ android.ModuleBase
+ android.ApexModuleBase
+
+ ClasspathFragmentBase
+
+ properties systemServerClasspathFragmentProperties
+}
+
+func (s *SystemServerClasspathModule) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion android.ApiLevel) error {
+ return nil
+}
+
+type systemServerClasspathFragmentProperties struct {
+ // The contents of this systemserverclasspath_fragment, could be either java_library, or java_sdk_library.
+ //
+ // The order of this list matters as it is the order that is used in the SYSTEMSERVERCLASSPATH.
+ Contents []string
+}
+
+func systemServerClasspathFactory() android.Module {
+ m := &SystemServerClasspathModule{}
+ m.AddProperties(&m.properties)
+ android.InitApexModule(m)
+ initClasspathFragment(m, SYSTEMSERVERCLASSPATH)
+ android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
+ return m
+}
+
+func (s *SystemServerClasspathModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ if len(s.properties.Contents) == 0 {
+ ctx.PropertyErrorf("contents", "empty contents are not allowed")
+ }
+
+ s.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, configuredJarListToClasspathJars(ctx, s.ClasspathFragmentToConfiguredJarList(ctx)))
+}
+
+func (s *SystemServerClasspathModule) ClasspathFragmentToConfiguredJarList(ctx android.ModuleContext) android.ConfiguredJarList {
+ // TODO(satayev): populate with actual content
+ return android.EmptyConfiguredJarList()
+}
+
+type systemServerClasspathFragmentContentDependencyTag struct {
+ blueprint.BaseDependencyTag
+}
+
+// The tag used for the dependency between the systemserverclasspath_fragment module and its contents.
+var systemServerClasspathFragmentContentDepTag = systemServerClasspathFragmentContentDependencyTag{}
+
+func IsSystemServerClasspathFragmentContentDepTag(tag blueprint.DependencyTag) bool {
+ return tag == systemServerClasspathFragmentContentDepTag
+}
+
+func (s *SystemServerClasspathModule) ComponentDepsMutator(ctx android.BottomUpMutatorContext) {
+ module := ctx.Module()
+
+ for _, name := range s.properties.Contents {
+ ctx.AddDependency(module, systemServerClasspathFragmentContentDepTag, name)
+ }
+}
diff --git a/java/systemserver_classpath_fragment_test.go b/java/systemserver_classpath_fragment_test.go
index 6126d5eb1..5272f271d 100644
--- a/java/systemserver_classpath_fragment_test.go
+++ b/java/systemserver_classpath_fragment_test.go
@@ -20,13 +20,13 @@ import (
"android/soong/android"
)
-var prepareForTestWithSystemserverClasspath = android.GroupFixturePreparers(
+var prepareForTestWithSystemServerClasspath = android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
)
-func TestSystemserverClasspathVariant(t *testing.T) {
+func TestPlatformSystemserverClasspathVariant(t *testing.T) {
result := android.GroupFixturePreparers(
- prepareForTestWithSystemserverClasspath,
+ prepareForTestWithSystemServerClasspath,
android.FixtureWithRootAndroidBp(`
platform_systemserverclasspath {
name: "platform-systemserverclasspath",
@@ -38,9 +38,9 @@ func TestSystemserverClasspathVariant(t *testing.T) {
android.AssertIntEquals(t, "expect 1 variant", 1, len(variants))
}
-func TestSystemserverClasspath_ClasspathFragmentPaths(t *testing.T) {
+func TestPlatformSystemserverClasspath_ClasspathFragmentPaths(t *testing.T) {
result := android.GroupFixturePreparers(
- prepareForTestWithSystemserverClasspath,
+ prepareForTestWithSystemServerClasspath,
android.FixtureWithRootAndroidBp(`
platform_systemserverclasspath {
name: "platform-systemserverclasspath",
@@ -53,9 +53,9 @@ func TestSystemserverClasspath_ClasspathFragmentPaths(t *testing.T) {
android.AssertPathRelativeToTopEquals(t, "install filepath", "out/soong/target/product/test_device/system/etc/classpaths", p.ClasspathFragmentBase.installDirPath)
}
-func TestSystemserverClasspathModule_AndroidMkEntries(t *testing.T) {
+func TestPlatformSystemserverClasspathModule_AndroidMkEntries(t *testing.T) {
preparer := android.GroupFixturePreparers(
- prepareForTestWithSystemserverClasspath,
+ prepareForTestWithSystemServerClasspath,
android.FixtureWithRootAndroidBp(`
platform_systemserverclasspath {
name: "platform-systemserverclasspath",
@@ -95,3 +95,14 @@ func TestSystemserverClasspathModule_AndroidMkEntries(t *testing.T) {
}
})
}
+
+func TestSystemserverclasspathFragmentWithoutContents(t *testing.T) {
+ prepareForTestWithSystemServerClasspath.
+ ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
+ `\Qempty contents are not allowed\E`)).
+ RunTestWithBp(t, `
+ systemserverclasspath_fragment {
+ name: "systemserverclasspath-fragment",
+ }
+ `)
+}
diff --git a/java/testing.go b/java/testing.go
index 387d59573..1fef337cc 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -24,6 +24,7 @@ import (
"android/soong/android"
"android/soong/cc"
"android/soong/dexpreopt"
+
"github.com/google/blueprint"
)
@@ -55,8 +56,9 @@ var PrepareForTestWithJavaBuildComponents = android.GroupFixturePreparers(
}.AddToFixture(),
)
-// Test fixture preparer that will define default java modules, e.g. standard prebuilt modules.
-var PrepareForTestWithJavaDefaultModules = android.GroupFixturePreparers(
+// Test fixture preparer that will define all default java modules except the
+// fake_tool_binary for dex2oatd.
+var PrepareForTestWithJavaDefaultModulesWithoutFakeDex2oatd = android.GroupFixturePreparers(
// Make sure that all the module types used in the defaults are registered.
PrepareForTestWithJavaBuildComponents,
// Additional files needed when test disallows non-existent source.
@@ -72,6 +74,11 @@ var PrepareForTestWithJavaDefaultModules = android.GroupFixturePreparers(
android.FixtureAddTextFile(defaultJavaDir+"/Android.bp", gatherRequiredDepsForTest()),
// Add dexpreopt compat libs (android.test.base, etc.) and a fake dex2oatd module.
dexpreopt.PrepareForTestWithDexpreoptCompatLibs,
+)
+
+// Test fixture preparer that will define default java modules, e.g. standard prebuilt modules.
+var PrepareForTestWithJavaDefaultModules = android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModulesWithoutFakeDex2oatd,
dexpreopt.PrepareForTestWithFakeDex2oatd,
)
@@ -371,7 +378,7 @@ func apexNamePairFromModule(ctx *android.TestContext, module android.Module) str
if apexInfo.IsForPlatform() {
apex = "platform"
} else {
- apex = apexInfo.InApexes[0]
+ apex = apexInfo.InApexVariants[0]
}
return fmt.Sprintf("%s:%s", apex, name)
diff --git a/tests/bootstrap_test.sh b/tests/bootstrap_test.sh
index 3f51114f9..42363e9c0 100755
--- a/tests/bootstrap_test.sh
+++ b/tests/bootstrap_test.sh
@@ -7,6 +7,8 @@ set -o pipefail
source "$(dirname "$0")/lib.sh"
+readonly GENERATED_BUILD_FILE_NAME="BUILD.bazel"
+
function test_smoke {
setup
run_soong
@@ -505,8 +507,8 @@ filegroup {
EOF
GENERATE_BAZEL_FILES=1 run_soong
- [[ -e out/soong/bp2build/a/BUILD ]] || fail "a/BUILD not created"
- [[ -L out/soong/workspace/a/BUILD ]] || fail "a/BUILD not symlinked"
+ [[ -e out/soong/bp2build/a/${GENERATED_BUILD_FILE_NAME} ]] || fail "a/${GENERATED_BUILD_FILE_NAME} not created"
+ [[ -L out/soong/workspace/a/${GENERATED_BUILD_FILE_NAME} ]] || fail "a/${GENERATED_BUILD_FILE_NAME} not symlinked"
mkdir -p b
touch b/b.txt
@@ -519,8 +521,8 @@ filegroup {
EOF
GENERATE_BAZEL_FILES=1 run_soong
- [[ -e out/soong/bp2build/b/BUILD ]] || fail "a/BUILD not created"
- [[ -L out/soong/workspace/b/BUILD ]] || fail "a/BUILD not symlinked"
+ [[ -e out/soong/bp2build/b/${GENERATED_BUILD_FILE_NAME} ]] || fail "a/${GENERATED_BUILD_FILE_NAME} not created"
+ [[ -L out/soong/workspace/b/${GENERATED_BUILD_FILE_NAME} ]] || fail "a/${GENERATED_BUILD_FILE_NAME} not symlinked"
}
function test_bp2build_null_build {
@@ -551,11 +553,11 @@ filegroup {
EOF
GENERATE_BAZEL_FILES=1 run_soong
- grep -q a1.txt out/soong/bp2build/a/BUILD || fail "a1.txt not in BUILD file"
+ grep -q a1.txt "out/soong/bp2build/a/${GENERATED_BUILD_FILE_NAME}" || fail "a1.txt not in ${GENERATED_BUILD_FILE_NAME} file"
touch a/a2.txt
GENERATE_BAZEL_FILES=1 run_soong
- grep -q a2.txt out/soong/bp2build/a/BUILD || fail "a2.txt not in BUILD file"
+ grep -q a2.txt "out/soong/bp2build/a/${GENERATED_BUILD_FILE_NAME}" || fail "a2.txt not in ${GENERATED_BUILD_FILE_NAME} file"
}
function test_dump_json_module_graph() {
@@ -583,8 +585,8 @@ EOF
GENERATE_BAZEL_FILES=1 run_soong
[[ -e out/soong/workspace ]] || fail "Bazel workspace not created"
[[ -d out/soong/workspace/a/b ]] || fail "module directory not a directory"
- [[ -L out/soong/workspace/a/b/BUILD ]] || fail "BUILD file not symlinked"
- [[ "$(readlink -f out/soong/workspace/a/b/BUILD)" =~ bp2build/a/b/BUILD$ ]] \
+ [[ -L "out/soong/workspace/a/b/${GENERATED_BUILD_FILE_NAME}" ]] || fail "${GENERATED_BUILD_FILE_NAME} file not symlinked"
+ [[ "$(readlink -f out/soong/workspace/a/b/${GENERATED_BUILD_FILE_NAME})" =~ "bp2build/a/b/${GENERATED_BUILD_FILE_NAME}"$ ]] \
|| fail "BUILD files symlinked at the wrong place"
[[ -L out/soong/workspace/a/b/b.txt ]] || fail "a/b/b.txt not symlinked"
[[ -L out/soong/workspace/a/a.txt ]] || fail "a/b/a.txt not symlinked"
@@ -616,7 +618,7 @@ function test_bp2build_build_file_precedence {
mkdir -p a
touch a/a.txt
- touch a/BUILD
+ touch a/${GENERATED_BUILD_FILE_NAME}
cat > a/Android.bp <<EOF
filegroup {
name: "a",
@@ -626,15 +628,15 @@ filegroup {
EOF
GENERATE_BAZEL_FILES=1 run_soong
- [[ -L out/soong/workspace/a/BUILD ]] || fail "BUILD file not symlinked"
- [[ "$(readlink -f out/soong/workspace/a/BUILD)" =~ bp2build/a/BUILD$ ]] \
- || fail "BUILD files symlinked to the wrong place"
+ [[ -L "out/soong/workspace/a/${GENERATED_BUILD_FILE_NAME}" ]] || fail "${GENERATED_BUILD_FILE_NAME} file not symlinked"
+ [[ "$(readlink -f out/soong/workspace/a/${GENERATED_BUILD_FILE_NAME})" =~ "bp2build/a/${GENERATED_BUILD_FILE_NAME}"$ ]] \
+ || fail "${GENERATED_BUILD_FILE_NAME} files symlinked to the wrong place"
}
function test_bp2build_reports_multiple_errors {
setup
- mkdir -p a/BUILD
+ mkdir -p "a/${GENERATED_BUILD_FILE_NAME}"
touch a/a.txt
cat > a/Android.bp <<EOF
filegroup {
@@ -644,7 +646,7 @@ filegroup {
}
EOF
- mkdir -p b/BUILD
+ mkdir -p "b/${GENERATED_BUILD_FILE_NAME}"
touch b/b.txt
cat > b/Android.bp <<EOF
filegroup {
@@ -658,8 +660,8 @@ EOF
fail "Build should have failed"
fi
- grep -q "a/BUILD' exist" "$MOCK_TOP/errors" || fail "Error for a/BUILD not found"
- grep -q "b/BUILD' exist" "$MOCK_TOP/errors" || fail "Error for b/BUILD not found"
+ grep -q "a/${GENERATED_BUILD_FILE_NAME}' exist" "$MOCK_TOP/errors" || fail "Error for a/${GENERATED_BUILD_FILE_NAME} not found"
+ grep -q "b/${GENERATED_BUILD_FILE_NAME}' exist" "$MOCK_TOP/errors" || fail "Error for b/${GENERATED_BUILD_FILE_NAME} not found"
}
test_smoke
diff --git a/tests/bp2build_bazel_test.sh b/tests/bp2build_bazel_test.sh
index 082cd0671..e3577107f 100755
--- a/tests/bp2build_bazel_test.sh
+++ b/tests/bp2build_bazel_test.sh
@@ -6,6 +6,8 @@ set -o pipefail
source "$(dirname "$0")/lib.sh"
+readonly GENERATED_BUILD_FILE_NAME="BUILD.bazel"
+
function test_bp2build_generates_all_buildfiles {
setup
create_mock_bazel
@@ -40,24 +42,24 @@ EOF
run_bp2build
- if [[ ! -f "./out/soong/workspace/foo/convertible_soong_module/BUILD" ]]; then
- fail "./out/soong/workspace/foo/convertible_soong_module/BUILD was not generated"
+ if [[ ! -f "./out/soong/workspace/foo/convertible_soong_module/${GENERATED_BUILD_FILE_NAME}" ]]; then
+ fail "./out/soong/workspace/foo/convertible_soong_module/${GENERATED_BUILD_FILE_NAME} was not generated"
fi
- if [[ ! -f "./out/soong/workspace/foo/unconvertible_soong_module/BUILD" ]]; then
- fail "./out/soong/workspace/foo/unconvertible_soong_module/BUILD was not generated"
+ if [[ ! -f "./out/soong/workspace/foo/unconvertible_soong_module/${GENERATED_BUILD_FILE_NAME}" ]]; then
+ fail "./out/soong/workspace/foo/unconvertible_soong_module/${GENERATED_BUILD_FILE_NAME} was not generated"
fi
- if ! grep "the_answer" "./out/soong/workspace/foo/convertible_soong_module/BUILD"; then
- fail "missing BUILD target the_answer in convertible_soong_module/BUILD"
+ if ! grep "the_answer" "./out/soong/workspace/foo/convertible_soong_module/${GENERATED_BUILD_FILE_NAME}"; then
+ fail "missing BUILD target the_answer in convertible_soong_module/${GENERATED_BUILD_FILE_NAME}"
fi
- if grep "not_the_answer" "./out/soong/workspace/foo/unconvertible_soong_module/BUILD"; then
- fail "found unexpected BUILD target not_the_answer in unconvertible_soong_module/BUILD"
+ if grep "not_the_answer" "./out/soong/workspace/foo/unconvertible_soong_module/${GENERATED_BUILD_FILE_NAME}"; then
+ fail "found unexpected BUILD target not_the_answer in unconvertible_soong_module/${GENERATED_BUILD_FILE_NAME}"
fi
- if ! grep "filegroup" "./out/soong/workspace/foo/unconvertible_soong_module/BUILD"; then
- fail "missing filegroup in unconvertible_soong_module/BUILD"
+ if ! grep "filegroup" "./out/soong/workspace/foo/unconvertible_soong_module/${GENERATED_BUILD_FILE_NAME}"; then
+ fail "missing filegroup in unconvertible_soong_module/${GENERATED_BUILD_FILE_NAME}"
fi
# NOTE: We don't actually use the extra BUILD file for anything here
diff --git a/ui/build/finder.go b/ui/build/finder.go
index 2eb84ca38..09d53cc1e 100644
--- a/ui/build/finder.go
+++ b/ui/build/finder.go
@@ -76,6 +76,8 @@ func NewSourceFinder(ctx Context, config Config) (f *finder.Finder) {
"Blueprints",
// Bazel build definitions.
"BUILD.bazel",
+ // Bazel build definitions.
+ "BUILD",
// Kati clean definitions.
"CleanSpec.mk",
// Ownership definition.
@@ -102,7 +104,7 @@ func NewSourceFinder(ctx Context, config Config) (f *finder.Finder) {
func findBazelFiles(entries finder.DirEntries) (dirNames []string, fileNames []string) {
matches := []string{}
for _, foundName := range entries.FileNames {
- if foundName == "BUILD.bazel" || foundName == "WORKSPACE" || strings.HasSuffix(foundName, ".bzl") {
+ if foundName == "BUILD.bazel" || foundName == "BUILD" || foundName == "WORKSPACE" || strings.HasSuffix(foundName, ".bzl") {
matches = append(matches, foundName)
}
}