Merge "Disable BTI for now."
diff --git a/android/bazel.go b/android/bazel.go
index 0940205..d5fdfd7 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -235,6 +235,7 @@
// Configure modules in these directories to enable bp2build_available: true or false by default.
bp2buildDefaultConfig = Bp2BuildConfig{
+ "art/libartpalette": Bp2BuildDefaultTrueRecursively,
"art/libdexfile": Bp2BuildDefaultTrueRecursively,
"art/runtime": Bp2BuildDefaultTrueRecursively,
"art/tools": Bp2BuildDefaultTrue,
@@ -291,11 +292,14 @@
"external/bouncycastle": Bp2BuildDefaultTrue,
"external/brotli": Bp2BuildDefaultTrue,
"external/conscrypt": Bp2BuildDefaultTrue,
- "external/error_prone": Bp2BuildDefaultTrue,
+ "external/error_prone": Bp2BuildDefaultTrueRecursively,
"external/fmtlib": Bp2BuildDefaultTrueRecursively,
"external/google-benchmark": Bp2BuildDefaultTrueRecursively,
"external/googletest": Bp2BuildDefaultTrueRecursively,
"external/gwp_asan": Bp2BuildDefaultTrueRecursively,
+ "external/icu": Bp2BuildDefaultTrueRecursively,
+ "external/icu/android_icu4j": Bp2BuildDefaultFalse, // java rules incomplete
+ "external/icu/icu4j": Bp2BuildDefaultFalse, // java rules incomplete
"external/jemalloc_new": Bp2BuildDefaultTrueRecursively,
"external/jsoncpp": Bp2BuildDefaultTrueRecursively,
"external/libcap": Bp2BuildDefaultTrueRecursively,
@@ -431,8 +435,19 @@
"libprotobuf-internal-protos", // b/210751803, we don't handle path property for filegroups
"libprotobuf-internal-python-srcs", // b/210751803, we don't handle path property for filegroups
"libprotobuf-java-full", // b/210751803, we don't handle path property for filegroups
+ "host-libprotobuf-java-full", // b/210751803, we don't handle path property for filegroups
"libprotobuf-java-util-full", // b/210751803, we don't handle path property for filegroups
- "conscrypt", // b/210751803, we don't handle path property for filegroups
+
+ "conscrypt", // b/210751803, we don't handle path property for filegroups
+ "conscrypt-for-host", // b/210751803, we don't handle path property for filegroups
+
+ "host-libprotobuf-java-lite", // b/217236083, java_library cannot have deps without srcs
+ "host-libprotobuf-java-micro", // b/217236083, java_library cannot have deps without srcs
+ "host-libprotobuf-java-nano", // b/217236083, java_library cannot have deps without srcs
+ "error_prone_core", // b/217236083, java_library cannot have deps without srcs
+ "bouncycastle-host", // b/217236083, java_library cannot have deps without srcs
+
+ "apex_manifest_proto_java", // b/215230097, we don't handle .proto files in java_library srcs attribute
// python protos
"libprotobuf-python", // contains .proto sources
@@ -470,14 +485,30 @@
"libdexfiled", // depends on unconverted modules: dexfile_operator_srcs, libartbased, libartpalette
// go deps:
- "apex-protos", // depends on soong_zip, a go binary
- "robolectric_tzdata", // depends on soong_zip, a go binary
- "robolectric-sqlite4java-native", // depends on soong_zip, a go binary
+ "apex-protos", // depends on soong_zip, a go binary
+ "generated_android_icu4j_src_files", "generated_android_icu4j_test_files", "icu4c_test_data", // depends on unconverted modules: soong_zip
"host_bionic_linker_asm", // depends on extract_linker, a go binary.
"host_bionic_linker_script", // depends on extract_linker, a go binary.
+ "robolectric-sqlite4java-native", // depends on soong_zip, a go binary
+ "robolectric_tzdata", // depends on soong_zip, a go binary
+
+ "android_icu4j_srcgen_binary", // Bazel build error: deps not allowed without srcs; move to runtime_deps
+ "core-icu4j-for-host", // Bazel build error: deps not allowed without srcs; move to runtime_deps
// java deps
- "bin2c_fastdeployagent", // depends on deployagent, a java binary
+ "android_icu4j_srcgen", // depends on unconverted modules: currysrc
+ "bin2c_fastdeployagent", // depends on deployagent, a java binary
+ "currysrc", // depends on unconverted modules: currysrc_org.eclipse, guavalib, jopt-simple-4.9
+ "robolectric-sqlite4java-0.282", // depends on unconverted modules: robolectric-sqlite4java-import, robolectric-sqlite4java-native
+ "timezone-host", // depends on unconverted modules: art.module.api.annotations
+ "truth-host-prebuilt", // depends on unconverted modules: truth-prebuilt
+ "truth-prebuilt", // depends on unconverted modules: asm-7.0, guava
+
+ "generated_android_icu4j_resources", // depends on unconverted modules: android_icu4j_srcgen_binary, soong_zip
+ "generated_android_icu4j_test_resources", // depends on unconverted modules: android_icu4j_srcgen_binary, soong_zip
+
+ "art-script", // depends on unconverted modules: dalvikvm, dex2oat
+ "dex2oat-script", // depends on unconverted modules: dex2oat
}
// Per-module denylist of cc_library modules to only generate the static
diff --git a/android/module.go b/android/module.go
index 00aed95..d0807c3 100644
--- a/android/module.go
+++ b/android/module.go
@@ -1165,6 +1165,11 @@
productConfigEnabledLabels, nil,
})
+ moduleSupportsDevice := mod.commonProperties.HostOrDeviceSupported&deviceSupported == deviceSupported
+ if mod.commonProperties.HostOrDeviceSupported != NeitherHostNorDeviceSupported && !moduleSupportsDevice {
+ enabledProperty.SetSelectValue(bazel.OsConfigurationAxis, Android.Name, proptools.BoolPtr(false))
+ }
+
platformEnabledAttribute, err := enabledProperty.ToLabelListAttribute(
bazel.LabelList{[]bazel.Label{bazel.Label{Label: "@platforms//:incompatible"}}, nil},
bazel.LabelList{[]bazel.Label{}, nil})
diff --git a/android/testing.go b/android/testing.go
index 8daf6b7..39864e1 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -781,19 +781,21 @@
return p
}
-func (b baseTestingComponent) maybeBuildParamsFromDescription(desc string) TestingBuildParams {
+func (b baseTestingComponent) maybeBuildParamsFromDescription(desc string) (TestingBuildParams, []string) {
+ var searchedDescriptions []string
for _, p := range b.provider.BuildParamsForTests() {
+ searchedDescriptions = append(searchedDescriptions, p.Description)
if strings.Contains(p.Description, desc) {
- return b.newTestingBuildParams(p)
+ return b.newTestingBuildParams(p), searchedDescriptions
}
}
- return TestingBuildParams{}
+ return TestingBuildParams{}, searchedDescriptions
}
func (b baseTestingComponent) buildParamsFromDescription(desc string) TestingBuildParams {
- p := b.maybeBuildParamsFromDescription(desc)
+ p, searchedDescriptions := b.maybeBuildParamsFromDescription(desc)
if p.Rule == nil {
- panic(fmt.Errorf("couldn't find description %q", desc))
+ panic(fmt.Errorf("couldn't find description %q\nall descriptions:\n%s", desc, strings.Join(searchedDescriptions, "\n")))
}
return p
}
@@ -860,7 +862,8 @@
// MaybeDescription finds a call to ctx.Build with BuildParams.Description set to a the given string. Returns an empty
// BuildParams if no rule is found.
func (b baseTestingComponent) MaybeDescription(desc string) TestingBuildParams {
- return b.maybeBuildParamsFromDescription(desc)
+ p, _ := b.maybeBuildParamsFromDescription(desc)
+ return p
}
// Description finds a call to ctx.Build with BuildParams.Description set to a the given string. Panics if no rule is
diff --git a/apex/bootclasspath_fragment_test.go b/apex/bootclasspath_fragment_test.go
index 8f44fc5..ce6b7f7 100644
--- a/apex/bootclasspath_fragment_test.go
+++ b/apex/bootclasspath_fragment_test.go
@@ -553,12 +553,66 @@
`prebuilt_com.android.art`,
})
+ // The boot images are installed in the APEX by Soong, so there shouldn't be any dexpreopt-related Make modules.
+ ensureDoesNotContainRequiredDeps(t, result.TestContext, "com.android.art", "android_common_com.android.art_image", []string{
+ "mybootclasspathfragment-dexpreopt-arm64-boot.art",
+ "mybootclasspathfragment-dexpreopt-arm64-boot.oat",
+ "mybootclasspathfragment-dexpreopt-arm64-boot.vdex",
+ "mybootclasspathfragment-dexpreopt-arm64-boot-bar.art",
+ "mybootclasspathfragment-dexpreopt-arm64-boot-bar.oat",
+ "mybootclasspathfragment-dexpreopt-arm64-boot-bar.vdex",
+ "mybootclasspathfragment-dexpreopt-arm-boot.art",
+ "mybootclasspathfragment-dexpreopt-arm-boot.oat",
+ "mybootclasspathfragment-dexpreopt-arm-boot.vdex",
+ "mybootclasspathfragment-dexpreopt-arm-boot-bar.art",
+ "mybootclasspathfragment-dexpreopt-arm-boot-bar.oat",
+ "mybootclasspathfragment-dexpreopt-arm-boot-bar.vdex",
+ })
+
// Make sure that the prebuilt bootclasspath_fragment copies its dex files to the predefined
// locations for the art image.
module := result.ModuleForTests("prebuilt_mybootclasspathfragment", "android_common_com.android.art")
checkCopiesToPredefinedLocationForArt(t, result.Config, module, "bar", "foo")
})
+ t.Run("boot image files from preferred prebuilt no boot image in apex", func(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ commonPreparer,
+
+ // Configure some libraries in the art bootclasspath_fragment that match the source
+ // bootclasspath_fragment's contents property.
+ java.FixtureConfigureBootJars("com.android.art:foo", "com.android.art:bar"),
+ addSource("foo", "bar"),
+
+ // Make sure that a preferred prebuilt with consistent contents doesn't affect the apex.
+ addPrebuilt(true, "foo", "bar"),
+
+ java.FixtureSetBootImageInstallDirOnDevice("art", "system/framework"),
+ ).RunTest(t)
+
+ ensureExactContents(t, result.TestContext, "com.android.art", "android_common_com.android.art_image", []string{
+ "etc/boot-image.prof",
+ "etc/classpaths/bootclasspath.pb",
+ "javalib/bar.jar",
+ "javalib/foo.jar",
+ })
+
+ ensureContainsRequiredDeps(t, result.TestContext, "com.android.art", "android_common_com.android.art_image", []string{
+ "mybootclasspathfragment-dexpreopt-arm64-boot.art",
+ "mybootclasspathfragment-dexpreopt-arm64-boot.oat",
+ "mybootclasspathfragment-dexpreopt-arm64-boot.vdex",
+ "mybootclasspathfragment-dexpreopt-arm64-boot-bar.art",
+ "mybootclasspathfragment-dexpreopt-arm64-boot-bar.oat",
+ "mybootclasspathfragment-dexpreopt-arm64-boot-bar.vdex",
+ "mybootclasspathfragment-dexpreopt-arm-boot.art",
+ "mybootclasspathfragment-dexpreopt-arm-boot.oat",
+ "mybootclasspathfragment-dexpreopt-arm-boot.vdex",
+ "mybootclasspathfragment-dexpreopt-arm-boot-bar.art",
+ "mybootclasspathfragment-dexpreopt-arm-boot-bar.oat",
+ "mybootclasspathfragment-dexpreopt-arm-boot-bar.vdex",
+ })
+ })
+
t.Run("source with inconsistency between config and contents", func(t *testing.T) {
android.GroupFixturePreparers(
commonPreparer,
@@ -631,6 +685,7 @@
// Configure some libraries in the art bootclasspath_fragment.
java.FixtureConfigureBootJars("com.android.art:foo", "com.android.art:bar"),
+ java.FixtureSetBootImageInstallDirOnDevice("art", "apex/com.android.art/javalib"),
)
bp := `
diff --git a/apex/builder.go b/apex/builder.go
index a66e1e0..1a1f22b 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -397,6 +397,22 @@
return output.OutputPath
}
+func markManifestTestOnly(ctx android.ModuleContext, androidManifestFile android.Path) android.Path {
+ return java.ManifestFixer(java.ManifestFixerParams{
+ Ctx: ctx,
+ Manifest: androidManifestFile,
+ SdkContext: nil,
+ ClassLoaderContexts: nil,
+ IsLibrary: false,
+ UseEmbeddedNativeLibs: false,
+ UsesNonSdkApis: false,
+ UseEmbeddedDex: false,
+ HasNoCode: false,
+ TestOnly: true,
+ LoggingParent: "",
+ })
+}
+
// buildUnflattendApex creates build rules to build an APEX using apexer.
func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) {
apexType := a.properties.ApexType
@@ -595,6 +611,11 @@
if a.properties.AndroidManifest != nil {
androidManifestFile := android.PathForModuleSrc(ctx, proptools.String(a.properties.AndroidManifest))
+
+ if a.testApex {
+ androidManifestFile = markManifestTestOnly(ctx, androidManifestFile)
+ }
+
implicitInputs = append(implicitInputs, androidManifestFile)
optFlags = append(optFlags, "--android_manifest "+androidManifestFile.String())
}
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index 02d8075..158c804 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -65,7 +65,8 @@
// Installed locations of symlinks for backward compatibility.
compatSymlinks android.InstallPaths
- hostRequired []string
+ hostRequired []string
+ requiredModuleNames []string
}
type sanitizedPrebuilt interface {
@@ -195,9 +196,19 @@
}
p.apexFilesForAndroidMk = append(p.apexFilesForAndroidMk, af)
}
- } else if tag == exportedBootclasspathFragmentTag ||
- tag == exportedSystemserverclasspathFragmentTag {
- // Visit the children of the bootclasspath_fragment and systemserver_fragment.
+ } else if tag == exportedBootclasspathFragmentTag {
+ bcpfModule, ok := child.(*java.PrebuiltBootclasspathFragmentModule)
+ if !ok {
+ ctx.PropertyErrorf("exported_bootclasspath_fragments", "%q is not a prebuilt_bootclasspath_fragment module", name)
+ return false
+ }
+ for _, makeModuleName := range bcpfModule.BootImageDeviceInstallMakeModules() {
+ p.requiredModuleNames = append(p.requiredModuleNames, makeModuleName)
+ }
+ // Visit the children of the bootclasspath_fragment.
+ return true
+ } else if tag == exportedSystemserverclasspathFragmentTag {
+ // Visit the children of the systemserver_fragment.
return true
}
@@ -211,6 +222,7 @@
entries.AddStrings("LOCAL_TARGET_REQUIRED_MODULES", fi.targetRequiredModuleNames...)
entries.AddStrings("LOCAL_HOST_REQUIRED_MODULES", fi.hostRequiredModuleNames...)
}
+ entries.AddStrings("LOCAL_REQUIRED_MODULES", p.requiredModuleNames...)
}
func (p *prebuiltCommon) AndroidMkEntries() []android.AndroidMkEntries {
diff --git a/bp2build/cc_binary_conversion_test.go b/bp2build/cc_binary_conversion_test.go
index a156480..f9adc78 100644
--- a/bp2build/cc_binary_conversion_test.go
+++ b/bp2build/cc_binary_conversion_test.go
@@ -84,13 +84,13 @@
t.Helper()
testCase := tc
for i, tar := range testCase.targets {
- if tar.typ != "cc_binary" {
- continue
- }
- tar.attrs["target_compatible_with"] = `select({
+ switch tar.typ {
+ case "cc_binary", "proto_library", "cc_lite_proto_library":
+ tar.attrs["target_compatible_with"] = `select({
"//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
"//conditions:default": [],
})`
+ }
testCase.targets[i] = tar
}
moduleTypeUnderTest := "cc_binary_host"
diff --git a/bp2build/genrule_conversion_test.go b/bp2build/genrule_conversion_test.go
index 0666da7..9244b99 100644
--- a/bp2build/genrule_conversion_test.go
+++ b/bp2build/genrule_conversion_test.go
@@ -97,13 +97,22 @@
}`
for _, tc := range testCases {
+ moduleAttrs := attrNameToString{
+ "cmd": fmt.Sprintf(`"$(location :foo.tool) --genDir=%s arg $(SRCS) $(OUTS)"`, tc.genDir),
+ "outs": `["foo.out"]`,
+ "srcs": `["foo.in"]`,
+ "tools": `[":foo.tool"]`,
+ }
+
+ if tc.moduleType == "java_genrule_host" {
+ moduleAttrs["target_compatible_with"] = `select({
+ "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+ "//conditions:default": [],
+ })`
+ }
+
expectedBazelTargets := []string{
- makeBazelTarget("genrule", "foo", attrNameToString{
- "cmd": fmt.Sprintf(`"$(location :foo.tool) --genDir=%s arg $(SRCS) $(OUTS)"`, tc.genDir),
- "outs": `["foo.out"]`,
- "srcs": `["foo.in"]`,
- "tools": `[":foo.tool"]`,
- }),
+ makeBazelTarget("genrule", "foo", moduleAttrs),
}
t.Run(tc.moduleType, func(t *testing.T) {
@@ -158,25 +167,36 @@
bazel_module: { bp2build_available: true },
}`
- expectedBazelTargets :=
- []string{
- makeBazelTarget("genrule", "foo", attrNameToString{
- "cmd": `"$(locations :foo.tools) -s $(OUTS) $(SRCS)"`,
- "outs": `["foo.out"]`,
- "srcs": `["foo.in"]`,
- "tools": `[":foo.tools"]`,
- }),
- makeBazelTarget("genrule", "foo.tools", attrNameToString{
- "cmd": `"cp $(SRCS) $(OUTS)"`,
- "outs": `[
+ for _, tc := range testCases {
+ fooAttrs := attrNameToString{
+ "cmd": `"$(locations :foo.tools) -s $(OUTS) $(SRCS)"`,
+ "outs": `["foo.out"]`,
+ "srcs": `["foo.in"]`,
+ "tools": `[":foo.tools"]`,
+ }
+ fooToolsAttrs := attrNameToString{
+ "cmd": `"cp $(SRCS) $(OUTS)"`,
+ "outs": `[
"foo_tool.out",
"foo_tool2.out",
]`,
- "srcs": `["foo_tool.in"]`,
- }),
+ "srcs": `["foo_tool.in"]`,
}
- for _, tc := range testCases {
+ if tc.moduleType == "java_genrule_host" {
+ compatibilityAttrs := `select({
+ "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+ "//conditions:default": [],
+ })`
+ fooAttrs["target_compatible_with"] = compatibilityAttrs
+ fooToolsAttrs["target_compatible_with"] = compatibilityAttrs
+ }
+
+ expectedBazelTargets := []string{
+ makeBazelTarget("genrule", "foo", fooAttrs),
+ makeBazelTarget("genrule", "foo.tools", fooToolsAttrs),
+ }
+
t.Run(tc.moduleType, func(t *testing.T) {
runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {},
bp2buildTestCase{
@@ -221,16 +241,25 @@
bazel_module: { bp2build_available: true },
}`
- expectedBazelTargets := []string{
- makeBazelTarget("genrule", "foo", attrNameToString{
+ for _, tc := range testCases {
+ moduleAttrs := attrNameToString{
"cmd": `"$(locations //other:foo.tool) -s $(OUTS) $(SRCS)"`,
"outs": `["foo.out"]`,
"srcs": `["foo.in"]`,
"tools": `["//other:foo.tool"]`,
- }),
- }
+ }
- for _, tc := range testCases {
+ if tc.moduleType == "java_genrule_host" {
+ moduleAttrs["target_compatible_with"] = `select({
+ "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+ "//conditions:default": [],
+ })`
+ }
+
+ expectedBazelTargets := []string{
+ makeBazelTarget("genrule", "foo", moduleAttrs),
+ }
+
t.Run(tc.moduleType, func(t *testing.T) {
runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {},
bp2buildTestCase{
@@ -276,16 +305,25 @@
bazel_module: { bp2build_available: true },
}`
- expectedBazelTargets := []string{
- makeBazelTarget("genrule", "foo", attrNameToString{
+ for _, tc := range testCases {
+ moduleAttrs := attrNameToString{
"cmd": `"$(locations //other:foo.tool) -s $(OUTS) $(location //other:other.tool)"`,
"outs": `["foo.out"]`,
"srcs": `["//other:other.tool"]`,
"tools": `["//other:foo.tool"]`,
- }),
- }
+ }
- for _, tc := range testCases {
+ if tc.moduleType == "java_genrule_host" {
+ moduleAttrs["target_compatible_with"] = `select({
+ "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+ "//conditions:default": [],
+ })`
+ }
+
+ expectedBazelTargets := []string{
+ makeBazelTarget("genrule", "foo", moduleAttrs),
+ }
+
t.Run(tc.moduleType, func(t *testing.T) {
runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {},
bp2buildTestCase{
@@ -331,8 +369,8 @@
bazel_module: { bp2build_available: true },
}`
- expectedBazelTargets := []string{
- makeBazelTarget("genrule", "foo", attrNameToString{
+ for _, tc := range testCases {
+ moduleAttrs := attrNameToString{
"cmd": `"$(location //other:foo.tool) -s $(OUTS) $(SRCS)"`,
"outs": `["foo.out"]`,
"srcs": `["foo.in"]`,
@@ -340,9 +378,19 @@
"//other:foo.tool",
"//other:other.tool",
]`,
- })}
+ }
- for _, tc := range testCases {
+ if tc.moduleType == "java_genrule_host" {
+ moduleAttrs["target_compatible_with"] = `select({
+ "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+ "//conditions:default": [],
+ })`
+ }
+
+ expectedBazelTargets := []string{
+ makeBazelTarget("genrule", "foo", moduleAttrs),
+ }
+
t.Run(tc.moduleType, func(t *testing.T) {
runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {},
bp2buildTestCase{
@@ -388,8 +436,8 @@
bazel_module: { bp2build_available: true },
}`
- expectedBazelTargets := []string{
- makeBazelTarget("genrule", "foo", attrNameToString{
+ for _, tc := range testCases {
+ moduleAttrs := attrNameToString{
"cmd": `"$(locations //other:foo.tool) -s $(OUTS) $(SRCS)"`,
"outs": `["foo.out"]`,
"srcs": `["foo.in"]`,
@@ -397,9 +445,19 @@
"//other:foo.tool",
"//other:other.tool",
]`,
- })}
+ }
- for _, tc := range testCases {
+ if tc.moduleType == "java_genrule_host" {
+ moduleAttrs["target_compatible_with"] = `select({
+ "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+ "//conditions:default": [],
+ })`
+ }
+
+ expectedBazelTargets := []string{
+ makeBazelTarget("genrule", "foo", moduleAttrs),
+ }
+
t.Run(tc.moduleType, func(t *testing.T) {
runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {},
bp2buildTestCase{
@@ -444,14 +502,24 @@
bazel_module: { bp2build_available: true },
}`
- expectedBazelTargets := []string{
- makeBazelTarget("genrule", "foo", attrNameToString{
+ for _, tc := range testCases {
+ moduleAttrs := attrNameToString{
"cmd": `"cp $(SRCS) $(OUTS)"`,
"outs": `["foo.out"]`,
"srcs": `["foo.in"]`,
- })}
+ }
- for _, tc := range testCases {
+ if tc.moduleType == "java_genrule_host" {
+ moduleAttrs["target_compatible_with"] = `select({
+ "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+ "//conditions:default": [],
+ })`
+ }
+
+ expectedBazelTargets := []string{
+ makeBazelTarget("genrule", "foo", moduleAttrs),
+ }
+
t.Run(tc.moduleType, func(t *testing.T) {
runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {},
bp2buildTestCase{
diff --git a/bp2build/java_binary_host_conversion_test.go b/bp2build/java_binary_host_conversion_test.go
index c683b25..65136d9 100644
--- a/bp2build/java_binary_host_conversion_test.go
+++ b/bp2build/java_binary_host_conversion_test.go
@@ -59,6 +59,10 @@
"deps": `["//other:jni-lib-1"]`,
"jvm_flags": `["-Djava.library.path=$${RUNPATH}other"]`,
"javacopts": `["-Xdoclint:all/protected"]`,
+ "target_compatible_with": `select({
+ "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+ "//conditions:default": [],
+ })`,
}),
},
})
diff --git a/bp2build/java_library_host_conversion_test.go b/bp2build/java_library_host_conversion_test.go
index 6ac82db..73abdd2 100644
--- a/bp2build/java_library_host_conversion_test.go
+++ b/bp2build/java_library_host_conversion_test.go
@@ -48,9 +48,17 @@
makeBazelTarget("java_library", "java-lib-host-1", attrNameToString{
"srcs": `["a.java"]`,
"deps": `[":java-lib-host-2"]`,
+ "target_compatible_with": `select({
+ "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+ "//conditions:default": [],
+ })`,
}),
makeBazelTarget("java_library", "java-lib-host-2", attrNameToString{
"srcs": `["c.java"]`,
+ "target_compatible_with": `select({
+ "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+ "//conditions:default": [],
+ })`,
}),
},
})
diff --git a/bp2build/java_plugin_conversion_test.go b/bp2build/java_plugin_conversion_test.go
new file mode 100644
index 0000000..ff13bb0
--- /dev/null
+++ b/bp2build/java_plugin_conversion_test.go
@@ -0,0 +1,72 @@
+// 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 bp2build
+
+import (
+ "testing"
+
+ "android/soong/android"
+ "android/soong/java"
+)
+
+func runJavaPluginTestCase(t *testing.T, tc bp2buildTestCase) {
+ t.Helper()
+ (&tc).moduleTypeUnderTest = "java_plugin"
+ (&tc).moduleTypeUnderTestFactory = java.PluginFactory
+ runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("java_library", java.LibraryFactory)
+ }, tc)
+}
+
+func TestJavaPlugin(t *testing.T) {
+ runJavaPluginTestCase(t, bp2buildTestCase{
+ description: "java_plugin with srcs, libs, static_libs",
+ blueprint: `java_plugin {
+ name: "java-plug-1",
+ srcs: ["a.java", "b.java"],
+ libs: ["java-lib-1"],
+ static_libs: ["java-lib-2"],
+ bazel_module: { bp2build_available: true },
+}
+
+java_library {
+ name: "java-lib-1",
+ srcs: ["b.java"],
+ bazel_module: { bp2build_available: false },
+}
+
+java_library {
+ name: "java-lib-2",
+ srcs: ["c.java"],
+ bazel_module: { bp2build_available: false },
+}`,
+ expectedBazelTargets: []string{
+ makeBazelTarget("java_plugin", "java-plug-1", attrNameToString{
+ "target_compatible_with": `select({
+ "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+ "//conditions:default": [],
+ })`,
+ "deps": `[
+ ":java-lib-1",
+ ":java-lib-2",
+ ]`,
+ "srcs": `[
+ "a.java",
+ "b.java",
+ ]`,
+ }),
+ },
+ })
+}
diff --git a/bp2build/python_binary_conversion_test.go b/bp2build/python_binary_conversion_test.go
index 40c8ba1..dfa11d1 100644
--- a/bp2build/python_binary_conversion_test.go
+++ b/bp2build/python_binary_conversion_test.go
@@ -51,6 +51,10 @@
"b/c.py",
"b/d.py",
]`,
+ "target_compatible_with": `select({
+ "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+ "//conditions:default": [],
+ })`,
}),
},
})
@@ -80,6 +84,10 @@
makeBazelTarget("py_binary", "foo", attrNameToString{
"python_version": `"PY2"`,
"srcs": `["a.py"]`,
+ "target_compatible_with": `select({
+ "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+ "//conditions:default": [],
+ })`,
}),
},
})
@@ -109,6 +117,10 @@
// python_version is PY3 by default.
makeBazelTarget("py_binary", "foo", attrNameToString{
"srcs": `["a.py"]`,
+ "target_compatible_with": `select({
+ "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+ "//conditions:default": [],
+ })`,
}),
},
})
@@ -141,6 +153,10 @@
"//build/bazel/platforms/arch:x86": ["x86.py"],
"//conditions:default": [],
})`,
+ "target_compatible_with": `select({
+ "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+ "//conditions:default": [],
+ })`,
}),
},
})
diff --git a/bp2build/python_library_conversion_test.go b/bp2build/python_library_conversion_test.go
index 6b26105..356d52e 100644
--- a/bp2build/python_library_conversion_test.go
+++ b/bp2build/python_library_conversion_test.go
@@ -11,19 +11,51 @@
// TODO(alexmarquez): Should be lifted into a generic Bp2Build file
type PythonLibBp2Build func(ctx android.TopDownMutatorContext)
-func runPythonLibraryTestCase(t *testing.T, tc bp2buildTestCase) {
+type pythonLibBp2BuildTestCase struct {
+ description string
+ filesystem map[string]string
+ blueprint string
+ expectedBazelTargets []testBazelTarget
+}
+
+func convertPythonLibTestCaseToBp2build_Host(tc pythonLibBp2BuildTestCase) bp2buildTestCase {
+ for i := range tc.expectedBazelTargets {
+ tc.expectedBazelTargets[i].attrs["target_compatible_with"] = `select({
+ "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+ "//conditions:default": [],
+ })`
+ }
+
+ return convertPythonLibTestCaseToBp2build(tc)
+}
+
+func convertPythonLibTestCaseToBp2build(tc pythonLibBp2BuildTestCase) bp2buildTestCase {
+ var bp2BuildTargets []string
+ for _, t := range tc.expectedBazelTargets {
+ bp2BuildTargets = append(bp2BuildTargets, makeBazelTarget(t.typ, t.name, t.attrs))
+ }
+ return bp2buildTestCase{
+ description: tc.description,
+ filesystem: tc.filesystem,
+ blueprint: tc.blueprint,
+ expectedBazelTargets: bp2BuildTargets,
+ }
+}
+
+func runPythonLibraryTestCase(t *testing.T, tc pythonLibBp2BuildTestCase) {
t.Helper()
- testCase := tc
+ testCase := convertPythonLibTestCaseToBp2build(tc)
testCase.description = fmt.Sprintf(testCase.description, "python_library")
testCase.blueprint = fmt.Sprintf(testCase.blueprint, "python_library")
testCase.moduleTypeUnderTest = "python_library"
testCase.moduleTypeUnderTestFactory = python.PythonLibraryFactory
+
runBp2BuildTestCaseSimple(t, testCase)
}
-func runPythonLibraryHostTestCase(t *testing.T, tc bp2buildTestCase) {
+func runPythonLibraryHostTestCase(t *testing.T, tc pythonLibBp2BuildTestCase) {
t.Helper()
- testCase := tc
+ testCase := convertPythonLibTestCaseToBp2build_Host(tc)
testCase.description = fmt.Sprintf(testCase.description, "python_library_host")
testCase.blueprint = fmt.Sprintf(testCase.blueprint, "python_library_host")
testCase.moduleTypeUnderTest = "python_library_host"
@@ -34,14 +66,14 @@
testCase)
}
-func runPythonLibraryTestCases(t *testing.T, tc bp2buildTestCase) {
+func runPythonLibraryTestCases(t *testing.T, tc pythonLibBp2BuildTestCase) {
t.Helper()
runPythonLibraryTestCase(t, tc)
runPythonLibraryHostTestCase(t, tc)
}
func TestSimplePythonLib(t *testing.T) {
- testCases := []bp2buildTestCase{
+ testCases := []pythonLibBp2BuildTestCase{
{
description: "simple %s converts to a native py_library",
filesystem: map[string]string{
@@ -64,17 +96,21 @@
srcs: ["b/e.py"],
bazel_module: { bp2build_available: false },
}`,
- expectedBazelTargets: []string{
- makeBazelTarget("py_library", "foo", attrNameToString{
- "data": `["files/data.txt"]`,
- "deps": `[":bar"]`,
- "srcs": `[
+ expectedBazelTargets: []testBazelTarget{
+ {
+ typ: "py_library",
+ name: "foo",
+ attrs: attrNameToString{
+ "data": `["files/data.txt"]`,
+ "deps": `[":bar"]`,
+ "srcs": `[
"a.py",
"b/c.py",
"b/d.py",
]`,
- "srcs_version": `"PY3"`,
- }),
+ "srcs_version": `"PY3"`,
+ },
+ },
},
},
{
@@ -93,11 +129,15 @@
bazel_module: { bp2build_available: true },
}`,
- expectedBazelTargets: []string{
- makeBazelTarget("py_library", "foo", attrNameToString{
- "srcs": `["a.py"]`,
- "srcs_version": `"PY2"`,
- }),
+ expectedBazelTargets: []testBazelTarget{
+ {
+ typ: "py_library",
+ name: "foo",
+ attrs: attrNameToString{
+ "srcs": `["a.py"]`,
+ "srcs_version": `"PY2"`,
+ },
+ },
},
},
{
@@ -116,11 +156,15 @@
bazel_module: { bp2build_available: true },
}`,
- expectedBazelTargets: []string{
- makeBazelTarget("py_library", "foo", attrNameToString{
- "srcs": `["a.py"]`,
- "srcs_version": `"PY3"`,
- }),
+ expectedBazelTargets: []testBazelTarget{
+ {
+ typ: "py_library",
+ name: "foo",
+ attrs: attrNameToString{
+ "srcs": `["a.py"]`,
+ "srcs_version": `"PY3"`,
+ },
+ },
},
},
{
@@ -139,11 +183,15 @@
bazel_module: { bp2build_available: true },
}`,
- expectedBazelTargets: []string{
- // srcs_version is PY2ANDPY3 by default.
- makeBazelTarget("py_library", "foo", attrNameToString{
- "srcs": `["a.py"]`,
- }),
+ expectedBazelTargets: []testBazelTarget{
+ {
+ // srcs_version is PY2ANDPY3 by default.
+ typ: "py_library",
+ name: "foo",
+ attrs: attrNameToString{
+ "srcs": `["a.py"]`,
+ },
+ },
},
},
}
@@ -156,7 +204,7 @@
}
func TestPythonArchVariance(t *testing.T) {
- runPythonLibraryTestCases(t, bp2buildTestCase{
+ runPythonLibraryTestCases(t, pythonLibBp2BuildTestCase{
description: "test %s arch variants",
filesystem: map[string]string{
"dir/arm.py": "",
@@ -173,15 +221,19 @@
},
},
}`,
- expectedBazelTargets: []string{
- makeBazelTarget("py_library", "foo", attrNameToString{
- "srcs": `select({
+ expectedBazelTargets: []testBazelTarget{
+ {
+ typ: "py_library",
+ name: "foo",
+ attrs: attrNameToString{
+ "srcs": `select({
"//build/bazel/platforms/arch:arm": ["arm.py"],
"//build/bazel/platforms/arch:x86": ["x86.py"],
"//conditions:default": [],
})`,
- "srcs_version": `"PY3"`,
- }),
+ "srcs_version": `"PY3"`,
+ },
+ },
},
})
}
diff --git a/cc/binary.go b/cc/binary.go
index ee3de3f..05923b1 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -76,7 +76,6 @@
// cc_binary_host produces a binary that is runnable on a host.
func BinaryHostFactory() android.Module {
module, _ := newBinary(android.HostSupported, true)
- module.bazelable = true
return module.Init()
}
@@ -606,19 +605,12 @@
Features: baseAttrs.features,
}
- var enabledProperty bazel.BoolAttribute
- if typ == "cc_binary_host" {
- falseVal := false
- enabledProperty.SetSelectValue(bazel.OsConfigurationAxis, android.Android.Name, &falseVal)
- }
-
- ctx.CreateBazelTargetModuleWithRestrictions(bazel.BazelTargetModuleProperties{
+ ctx.CreateBazelTargetModule(bazel.BazelTargetModuleProperties{
Rule_class: "cc_binary",
Bzl_load_location: "//build/bazel/rules:cc_binary.bzl",
},
android.CommonAttributes{Name: m.Name()},
- attrs,
- enabledProperty)
+ attrs)
}
// binaryAttributes contains Bazel attributes corresponding to a cc binary
diff --git a/cc/bp2build.go b/cc/bp2build.go
index c5eab06..30c3c50 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -844,10 +844,8 @@
func bazelLabelForStaticModule(ctx android.BazelConversionPathContext, m blueprint.Module) string {
label := android.BazelModuleLabel(ctx, m)
- if aModule, ok := m.(android.Module); ok {
- if ctx.OtherModuleType(aModule) == "cc_library" && !android.GenerateCcLibraryStaticOnly(m.Name()) {
- label += "_bp2build_cc_library_static"
- }
+ if ccModule, ok := m.(*Module); ok && ccModule.typ() == fullLibrary && !android.GenerateCcLibraryStaticOnly(m.Name()) {
+ label += "_bp2build_cc_library_static"
}
return label
}
diff --git a/cc/cc.go b/cc/cc.go
index 31babc2..46e3b91 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -1751,7 +1751,7 @@
// Returns true if Bazel was successfully used for the analysis of this module.
func (c *Module) maybeGenerateBazelActions(actx android.ModuleContext) bool {
var bazelModuleLabel string
- if actx.ModuleType() == "cc_library" && c.static() {
+ if c.typ() == fullLibrary && c.static() {
// cc_library is a special case in bp2build; two targets are generated -- one for each
// of the shared and static variants. The shared variant keeps the module name, but the
// static variant uses a different suffixed name.
@@ -1759,6 +1759,7 @@
} else {
bazelModuleLabel = c.GetBazelLabel(actx, c)
}
+
bazelActionsUsed := false
// Mixed builds mode is disabled for modules outside of device OS.
// TODO(b/200841190): Support non-device OS in mixed builds.
@@ -3466,17 +3467,23 @@
var _ snapshot.RelativeInstallPath = (*Module)(nil)
-// ConvertWithBp2build converts Module to Bazel for bp2build.
-func (c *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- prebuilt := c.IsPrebuilt()
+type moduleType int
+
+const (
+ unknownType moduleType = iota
+ binary
+ object
+ fullLibrary
+ staticLibrary
+ sharedLibrary
+ headerLibrary
+)
+
+func (c *Module) typ() moduleType {
if c.Binary() {
- if !prebuilt {
- binaryBp2build(ctx, c, ctx.ModuleType())
- }
+ return binary
} else if c.Object() {
- if !prebuilt {
- objectBp2Build(ctx, c)
- }
+ return object
} else if c.CcLibrary() {
static := false
shared := false
@@ -3487,25 +3494,48 @@
static = library.MutatedProperties.BuildStatic
shared = library.MutatedProperties.BuildShared
}
-
if static && shared {
- if !prebuilt {
- libraryBp2Build(ctx, c)
- }
+ return fullLibrary
} else if !static && !shared {
- libraryHeadersBp2Build(ctx, c)
+ return headerLibrary
} else if static {
- if prebuilt {
- prebuiltLibraryStaticBp2Build(ctx, c)
- } else {
- sharedOrStaticLibraryBp2Build(ctx, c, true)
- }
- } else if shared {
- if prebuilt {
- prebuiltLibrarySharedBp2Build(ctx, c)
- } else {
- sharedOrStaticLibraryBp2Build(ctx, c, false)
- }
+ return staticLibrary
+ }
+ return sharedLibrary
+ }
+ return unknownType
+}
+
+// ConvertWithBp2build converts Module to Bazel for bp2build.
+func (c *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+ prebuilt := c.IsPrebuilt()
+ switch c.typ() {
+ case binary:
+ if !prebuilt {
+ binaryBp2build(ctx, c, ctx.ModuleType())
+ }
+ case object:
+ if !prebuilt {
+ objectBp2Build(ctx, c)
+ }
+ case fullLibrary:
+ if !prebuilt {
+ libraryBp2Build(ctx, c)
+ }
+ case headerLibrary:
+ libraryHeadersBp2Build(ctx, c)
+ case staticLibrary:
+
+ if prebuilt {
+ prebuiltLibraryStaticBp2Build(ctx, c)
+ } else {
+ sharedOrStaticLibraryBp2Build(ctx, c, true)
+ }
+ case sharedLibrary:
+ if prebuilt {
+ prebuiltLibrarySharedBp2Build(ctx, c)
+ } else {
+ sharedOrStaticLibraryBp2Build(ctx, c, false)
}
}
}
diff --git a/cc/config/arm64_linux_host.go b/cc/config/arm64_linux_host.go
index 853d818..5c7f926 100644
--- a/cc/config/arm64_linux_host.go
+++ b/cc/config/arm64_linux_host.go
@@ -41,7 +41,6 @@
"-Wl,-z,relro",
"-Wl,-z,now",
"-Wl,--build-id=md5",
- "-Wl,--warn-shared-textrel",
"-Wl,--fatal-warnings",
"-Wl,--hash-style=gnu",
"-Wl,--no-undefined-version",
diff --git a/cc/config/global.go b/cc/config/global.go
index 5acc7f5..48a8b48 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -95,6 +95,9 @@
// Nested and array designated initialization is nice to have.
"-Wno-c99-designator",
+ // Many old files still have GNU designator syntax.
+ "-Wno-gnu-designator",
+
// Warnings from clang-12
"-Wno-gnu-folding-constant",
@@ -139,7 +142,6 @@
"-Wl,-z,relro",
"-Wl,-z,now",
"-Wl,--build-id=md5",
- "-Wl,--warn-shared-textrel",
"-Wl,--fatal-warnings",
"-Wl,--no-undefined-version",
// TODO: Eventually we should link against a libunwind.a with hidden symbols, and then these
diff --git a/cc/config/x86_linux_bionic_host.go b/cc/config/x86_linux_bionic_host.go
index 4b7ba6a..976cc25 100644
--- a/cc/config/x86_linux_bionic_host.go
+++ b/cc/config/x86_linux_bionic_host.go
@@ -47,7 +47,6 @@
"-Wl,-z,relro",
"-Wl,-z,now",
"-Wl,--build-id=md5",
- "-Wl,--warn-shared-textrel",
"-Wl,--fatal-warnings",
"-Wl,--hash-style=gnu",
"-Wl,--no-undefined-version",
diff --git a/java/aar.go b/java/aar.go
index aabbec6..4687424 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -276,9 +276,19 @@
manifestFile := proptools.StringDefault(a.aaptProperties.Manifest, "AndroidManifest.xml")
manifestSrcPath := android.PathForModuleSrc(ctx, manifestFile)
- manifestPath := manifestFixer(ctx, manifestSrcPath, sdkContext, classLoaderContexts,
- a.isLibrary, a.useEmbeddedNativeLibs, a.usesNonSdkApis, a.useEmbeddedDex, a.hasNoCode,
- a.LoggingParent)
+ manifestPath := ManifestFixer(ManifestFixerParams{
+ Ctx: ctx,
+ Manifest: manifestSrcPath,
+ SdkContext: sdkContext,
+ ClassLoaderContexts: classLoaderContexts,
+ IsLibrary: a.isLibrary,
+ UseEmbeddedNativeLibs: a.useEmbeddedNativeLibs,
+ UsesNonSdkApis: a.usesNonSdkApis,
+ UseEmbeddedDex: a.useEmbeddedDex,
+ HasNoCode: a.hasNoCode,
+ TestOnly: false,
+ LoggingParent: a.LoggingParent,
+ })
// Add additional manifest files to transitive manifests.
additionalManifests := android.PathsForModuleSrc(ctx, a.aaptProperties.Additional_manifests)
diff --git a/java/android_manifest.go b/java/android_manifest.go
index f29d8ad..a5d5b97 100644
--- a/java/android_manifest.go
+++ b/java/android_manifest.go
@@ -28,13 +28,10 @@
var manifestFixerRule = pctx.AndroidStaticRule("manifestFixer",
blueprint.RuleParams{
Command: `${config.ManifestFixerCmd} ` +
- `--minSdkVersion ${minSdkVersion} ` +
- `--targetSdkVersion ${targetSdkVersion} ` +
- `--raise-min-sdk-version ` +
`$args $in $out`,
CommandDeps: []string{"${config.ManifestFixerCmd}"},
},
- "minSdkVersion", "targetSdkVersion", "args")
+ "args")
var manifestMergerRule = pctx.AndroidStaticRule("manifestMerger",
blueprint.RuleParams{
@@ -58,84 +55,110 @@
return targetSdkVersion
}
-// Uses manifest_fixer.py to inject minSdkVersion, etc. into an AndroidManifest.xml
-func manifestFixer(ctx android.ModuleContext, manifest android.Path, sdkContext android.SdkContext,
- classLoaderContexts dexpreopt.ClassLoaderContextMap, isLibrary, useEmbeddedNativeLibs, usesNonSdkApis,
- useEmbeddedDex, hasNoCode bool, loggingParent string) android.Path {
+type ManifestFixerParams struct {
+ Ctx android.ModuleContext
+ Manifest android.Path
+ SdkContext android.SdkContext
+ ClassLoaderContexts dexpreopt.ClassLoaderContextMap
+ IsLibrary bool
+ UseEmbeddedNativeLibs bool
+ UsesNonSdkApis bool
+ UseEmbeddedDex bool
+ HasNoCode bool
+ TestOnly bool
+ LoggingParent string
+}
+// Uses manifest_fixer.py to inject minSdkVersion, etc. into an AndroidManifest.xml
+func ManifestFixer(params ManifestFixerParams) android.Path {
var args []string
- if isLibrary {
+
+ if params.IsLibrary {
args = append(args, "--library")
- } else {
- minSdkVersion, err := sdkContext.MinSdkVersion(ctx).EffectiveVersion(ctx)
+ } else if params.SdkContext != nil {
+ minSdkVersion, err := params.SdkContext.MinSdkVersion(params.Ctx).EffectiveVersion(params.Ctx)
if err != nil {
- ctx.ModuleErrorf("invalid minSdkVersion: %s", err)
+ params.Ctx.ModuleErrorf("invalid minSdkVersion: %s", err)
}
if minSdkVersion.FinalOrFutureInt() >= 23 {
- args = append(args, fmt.Sprintf("--extract-native-libs=%v", !useEmbeddedNativeLibs))
- } else if useEmbeddedNativeLibs {
- ctx.ModuleErrorf("module attempted to store uncompressed native libraries, but minSdkVersion=%d doesn't support it",
+ args = append(args, fmt.Sprintf("--extract-native-libs=%v", !params.UseEmbeddedNativeLibs))
+ } else if params.UseEmbeddedNativeLibs {
+ params.Ctx.ModuleErrorf("module attempted to store uncompressed native libraries, but minSdkVersion=%d doesn't support it",
minSdkVersion)
}
}
- if usesNonSdkApis {
+ if params.UsesNonSdkApis {
args = append(args, "--uses-non-sdk-api")
}
- if useEmbeddedDex {
+ if params.UseEmbeddedDex {
args = append(args, "--use-embedded-dex")
}
- // manifest_fixer should add only the implicit SDK libraries inferred by Soong, not those added
- // explicitly via `uses_libs`/`optional_uses_libs`.
- requiredUsesLibs, optionalUsesLibs := classLoaderContexts.ImplicitUsesLibs()
- for _, usesLib := range requiredUsesLibs {
- args = append(args, "--uses-library", usesLib)
- }
- for _, usesLib := range optionalUsesLibs {
- args = append(args, "--optional-uses-library", usesLib)
+ if params.ClassLoaderContexts != nil {
+ // manifest_fixer should add only the implicit SDK libraries inferred by Soong, not those added
+ // explicitly via `uses_libs`/`optional_uses_libs`.
+ requiredUsesLibs, optionalUsesLibs := params.ClassLoaderContexts.ImplicitUsesLibs()
+
+ for _, usesLib := range requiredUsesLibs {
+ args = append(args, "--uses-library", usesLib)
+ }
+ for _, usesLib := range optionalUsesLibs {
+ args = append(args, "--optional-uses-library", usesLib)
+ }
}
- if hasNoCode {
+ if params.HasNoCode {
args = append(args, "--has-no-code")
}
- if loggingParent != "" {
- args = append(args, "--logging-parent", loggingParent)
+ if params.TestOnly {
+ args = append(args, "--test-only")
+ }
+
+ if params.LoggingParent != "" {
+ args = append(args, "--logging-parent", params.LoggingParent)
}
var deps android.Paths
- targetSdkVersion := targetSdkVersionForManifestFixer(ctx, sdkContext)
+ var argsMapper = make(map[string]string)
- if UseApiFingerprint(ctx) && ctx.ModuleName() != "framework-res" {
- targetSdkVersion = ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", ApiFingerprintPath(ctx).String())
- deps = append(deps, ApiFingerprintPath(ctx))
+ if params.SdkContext != nil {
+ targetSdkVersion := targetSdkVersionForManifestFixer(params.Ctx, params.SdkContext)
+ args = append(args, "--targetSdkVersion ", targetSdkVersion)
+
+ if UseApiFingerprint(params.Ctx) && params.Ctx.ModuleName() != "framework-res" {
+ targetSdkVersion = params.Ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", ApiFingerprintPath(params.Ctx).String())
+ deps = append(deps, ApiFingerprintPath(params.Ctx))
+ }
+
+ minSdkVersion, err := params.SdkContext.MinSdkVersion(params.Ctx).EffectiveVersionString(params.Ctx)
+ if err != nil {
+ params.Ctx.ModuleErrorf("invalid minSdkVersion: %s", err)
+ }
+
+ if UseApiFingerprint(params.Ctx) && params.Ctx.ModuleName() != "framework-res" {
+ minSdkVersion = params.Ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", ApiFingerprintPath(params.Ctx).String())
+ deps = append(deps, ApiFingerprintPath(params.Ctx))
+ }
+
+ if err != nil {
+ params.Ctx.ModuleErrorf("invalid minSdkVersion: %s", err)
+ }
+ args = append(args, "--minSdkVersion ", minSdkVersion)
+ args = append(args, "--raise-min-sdk-version")
}
- minSdkVersion, err := sdkContext.MinSdkVersion(ctx).EffectiveVersionString(ctx)
- if err != nil {
- ctx.ModuleErrorf("invalid minSdkVersion: %s", err)
- }
- if UseApiFingerprint(ctx) && ctx.ModuleName() != "framework-res" {
- minSdkVersion = ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", ApiFingerprintPath(ctx).String())
- deps = append(deps, ApiFingerprintPath(ctx))
- }
+ fixedManifest := android.PathForModuleOut(params.Ctx, "manifest_fixer", "AndroidManifest.xml")
+ argsMapper["args"] = strings.Join(args, " ")
- fixedManifest := android.PathForModuleOut(ctx, "manifest_fixer", "AndroidManifest.xml")
- if err != nil {
- ctx.ModuleErrorf("invalid minSdkVersion: %s", err)
- }
- ctx.Build(pctx, android.BuildParams{
+ params.Ctx.Build(pctx, android.BuildParams{
Rule: manifestFixerRule,
Description: "fix manifest",
- Input: manifest,
+ Input: params.Manifest,
Implicits: deps,
Output: fixedManifest,
- Args: map[string]string{
- "minSdkVersion": minSdkVersion,
- "targetSdkVersion": targetSdkVersion,
- "args": strings.Join(args, " "),
- },
+ Args: argsMapper,
})
return fixedManifest.WithoutRel()
diff --git a/java/app.go b/java/app.go
index 7ae73f7..9f2f99a 100755
--- a/java/app.go
+++ b/java/app.go
@@ -1432,17 +1432,15 @@
}
type bazelAndroidAppAttributes struct {
- Srcs bazel.LabelListAttribute
+ *javaLibraryAttributes
Manifest bazel.Label
Custom_package *string
Resource_files bazel.LabelListAttribute
- Deps bazel.LabelListAttribute
}
// ConvertWithBp2build is used to convert android_app to Bazel.
func (a *AndroidApp) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- //TODO(b/209577426): Support multiple arch variants
- srcs := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrcExcludes(ctx, a.properties.Srcs, a.properties.Exclude_srcs))
+ libAttrs := a.convertLibraryAttrsBp2Build(ctx)
manifest := proptools.StringDefault(a.aaptProperties.Manifest, "AndroidManifest.xml")
@@ -1454,15 +1452,12 @@
resourceFiles.Includes = append(resourceFiles.Includes, files...)
}
- deps := bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, a.properties.Static_libs))
-
attrs := &bazelAndroidAppAttributes{
- Srcs: srcs,
- Manifest: android.BazelLabelForModuleSrcSingle(ctx, manifest),
+ libAttrs,
+ android.BazelLabelForModuleSrcSingle(ctx, manifest),
// TODO(b/209576404): handle package name override by product variable PRODUCT_MANIFEST_PACKAGE_NAME_OVERRIDES
- Custom_package: a.overridableAppProperties.Package_name,
- Resource_files: bazel.MakeLabelListAttribute(resourceFiles),
- Deps: deps,
+ a.overridableAppProperties.Package_name,
+ bazel.MakeLabelListAttribute(resourceFiles),
}
props := bazel.BazelTargetModuleProperties{Rule_class: "android_binary",
Bzl_load_location: "@rules_android//rules:rules.bzl"}
diff --git a/java/app_test.go b/java/app_test.go
index 2322ef4..16bbec1 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -2512,7 +2512,7 @@
`--uses-library qux ` +
`--uses-library quuz ` +
`--uses-library runtime-library`
- android.AssertStringEquals(t, "manifest_fixer args", expectManifestFixerArgs, actualManifestFixerArgs)
+ android.AssertStringDoesContain(t, "manifest_fixer args", actualManifestFixerArgs, expectManifestFixerArgs)
// Test that all libraries are verified (library order matters).
verifyCmd := app.Rule("verify_uses_libraries").RuleParams.Command
@@ -3055,7 +3055,7 @@
result := fixture.RunTestWithBp(t, bp)
foo := result.ModuleForTests("foo", "android_common")
- manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args
- android.AssertStringEquals(t, testCase.name, testCase.targetSdkVersionExpected, manifestFixerArgs["targetSdkVersion"])
+ manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
+ android.AssertStringDoesContain(t, testCase.name, manifestFixerArgs, "--targetSdkVersion "+testCase.targetSdkVersionExpected)
}
}
diff --git a/java/base.go b/java/base.go
index a3eb8de..42d7733 100644
--- a/java/base.go
+++ b/java/base.go
@@ -1969,7 +1969,7 @@
func (j *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
switch ctx.ModuleType() {
- case "java_library", "java_library_host":
+ case "java_library", "java_library_host", "java_library_static":
if lib, ok := ctx.Module().(*Library); ok {
javaLibraryBp2Build(ctx, lib)
}
@@ -1978,5 +1978,4 @@
javaBinaryHostBp2Build(ctx, binary)
}
}
-
}
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index 4794180..a36bd6a 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -1073,7 +1073,7 @@
// At the moment this is basically just a bootclasspath_fragment module that can be used as a
// prebuilt. Eventually as more functionality is migrated into the bootclasspath_fragment module
// type from the various singletons then this will diverge.
-type prebuiltBootclasspathFragmentModule struct {
+type PrebuiltBootclasspathFragmentModule struct {
BootclasspathFragmentModule
prebuilt android.Prebuilt
@@ -1081,16 +1081,16 @@
prebuiltProperties prebuiltBootclasspathFragmentProperties
}
-func (module *prebuiltBootclasspathFragmentModule) Prebuilt() *android.Prebuilt {
+func (module *PrebuiltBootclasspathFragmentModule) Prebuilt() *android.Prebuilt {
return &module.prebuilt
}
-func (module *prebuiltBootclasspathFragmentModule) Name() string {
+func (module *PrebuiltBootclasspathFragmentModule) Name() string {
return module.prebuilt.Name(module.ModuleBase.Name())
}
// produceHiddenAPIOutput returns a path to the prebuilt all-flags.csv or nil if none is specified.
-func (module *prebuiltBootclasspathFragmentModule) produceHiddenAPIOutput(ctx android.ModuleContext, contents []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput {
+func (module *PrebuiltBootclasspathFragmentModule) produceHiddenAPIOutput(ctx android.ModuleContext, contents []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput {
pathForOptionalSrc := func(src *string, defaultPath android.Path) android.Path {
if src == nil {
return defaultPath
@@ -1131,7 +1131,7 @@
}
// produceBootImageFiles extracts the boot image files from the APEX if available.
-func (module *prebuiltBootclasspathFragmentModule) produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageFilesByArch {
+func (module *PrebuiltBootclasspathFragmentModule) produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageFilesByArch {
if !shouldCopyBootFilesToPredefinedLocations(ctx, imageConfig) {
return nil
}
@@ -1141,37 +1141,53 @@
return nil // An error has been reported by FindDeapexerProviderForModule.
}
- files := bootImageFilesByArch{}
- for _, variant := range imageConfig.apexVariants() {
- arch := variant.target.Arch.ArchType
- for _, toPath := range variant.imagesDeps {
- apexRelativePath := apexRootRelativePathToBootImageFile(arch, toPath.Base())
- // Get the path to the file that the deapexer extracted from the prebuilt apex file.
- fromPath := di.PrebuiltExportPath(apexRelativePath)
-
- // Return the toPath as the calling code expects the paths in the returned map to be the
- // paths predefined in the bootImageConfig.
- files[arch] = append(files[arch], toPath)
-
- // Copy the file to the predefined location.
- ctx.Build(pctx, android.BuildParams{
- Rule: android.Cp,
- Input: fromPath,
- Output: toPath,
- })
- }
+ profile := (android.WritablePath)(nil)
+ if imageConfig.profileInstallPathInApex != "" {
+ profile = di.PrebuiltExportPath(imageConfig.profileInstallPathInApex)
}
- // Build the boot image files for the host variants. These are built from the dex files provided
- // by the contents of this module as prebuilt versions of the host boot image files are not
- // available, i.e. there is no host specific prebuilt apex containing them. This has to be built
- // without a profile as the prebuilt modules do not provide a profile.
- buildBootImageVariantsForBuildOs(ctx, imageConfig, nil)
+ // Build the boot image files for the host variants. These are always built from the dex files
+ // provided by the contents of this module as prebuilt versions of the host boot image files are
+ // not available, i.e. there is no host specific prebuilt apex containing them. This has to be
+ // built without a profile as the prebuilt modules do not provide a profile.
+ buildBootImageVariantsForBuildOs(ctx, imageConfig, profile)
- return files
+ if imageConfig.shouldInstallInApex() {
+ // If the boot image files for the android variants are in the prebuilt apex, we must use those
+ // rather than building new ones because those boot image files are going to be used on device.
+ files := bootImageFilesByArch{}
+ for _, variant := range imageConfig.apexVariants() {
+ arch := variant.target.Arch.ArchType
+ for _, toPath := range variant.imagesDeps {
+ apexRelativePath := apexRootRelativePathToBootImageFile(arch, toPath.Base())
+ // Get the path to the file that the deapexer extracted from the prebuilt apex file.
+ fromPath := di.PrebuiltExportPath(apexRelativePath)
+
+ // Return the toPath as the calling code expects the paths in the returned map to be the
+ // paths predefined in the bootImageConfig.
+ files[arch] = append(files[arch], toPath)
+
+ // Copy the file to the predefined location.
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cp,
+ Input: fromPath,
+ Output: toPath,
+ })
+ }
+ }
+ return files
+ } else {
+ if profile == nil {
+ ctx.ModuleErrorf("Unable to produce boot image files: neither boot image files nor profiles exists in the prebuilt apex")
+ return nil
+ }
+ // Build boot image files for the android variants from the dex files provided by the contents
+ // of this module.
+ return buildBootImageVariantsForAndroidOs(ctx, imageConfig, profile)
+ }
}
-var _ commonBootclasspathFragment = (*prebuiltBootclasspathFragmentModule)(nil)
+var _ commonBootclasspathFragment = (*PrebuiltBootclasspathFragmentModule)(nil)
// createBootImageTag creates the tag to uniquely identify the boot image file among all of the
// files that a module requires from the prebuilt .apex file.
@@ -1185,16 +1201,22 @@
//
// If there is no image config associated with this fragment then it returns nil. Otherwise, it
// returns the files that are listed in the image config.
-func (module *prebuiltBootclasspathFragmentModule) RequiredFilesFromPrebuiltApex(ctx android.BaseModuleContext) []string {
+func (module *PrebuiltBootclasspathFragmentModule) RequiredFilesFromPrebuiltApex(ctx android.BaseModuleContext) []string {
imageConfig := module.getImageConfig(ctx)
if imageConfig != nil {
- // Add the boot image files, e.g. .art, .oat and .vdex files.
files := []string{}
- for _, variant := range imageConfig.apexVariants() {
- arch := variant.target.Arch.ArchType
- for _, path := range variant.imagesDeps.Paths() {
- base := path.Base()
- files = append(files, apexRootRelativePathToBootImageFile(arch, base))
+ if imageConfig.profileInstallPathInApex != "" {
+ // Add the boot image profile.
+ files = append(files, imageConfig.profileInstallPathInApex)
+ }
+ if imageConfig.shouldInstallInApex() {
+ // Add the boot image files, e.g. .art, .oat and .vdex files.
+ for _, variant := range imageConfig.apexVariants() {
+ arch := variant.target.Arch.ArchType
+ for _, path := range variant.imagesDeps.Paths() {
+ base := path.Base()
+ files = append(files, apexRootRelativePathToBootImageFile(arch, base))
+ }
}
}
return files
@@ -1206,10 +1228,10 @@
return filepath.Join("javalib", arch.String(), base)
}
-var _ android.RequiredFilesFromPrebuiltApex = (*prebuiltBootclasspathFragmentModule)(nil)
+var _ android.RequiredFilesFromPrebuiltApex = (*PrebuiltBootclasspathFragmentModule)(nil)
func prebuiltBootclasspathFragmentFactory() android.Module {
- m := &prebuiltBootclasspathFragmentModule{}
+ m := &PrebuiltBootclasspathFragmentModule{}
m.AddProperties(&m.properties, &m.prebuiltProperties)
// This doesn't actually have any prebuilt files of its own so pass a placeholder for the srcs
// array.
diff --git a/java/droidstubs.go b/java/droidstubs.go
index 7ad316f..f9dcfd6 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -334,7 +334,11 @@
// TODO(tnorbye): find owners to fix these warnings when annotation was enabled.
cmd.FlagWithArg("--hide ", "HiddenTypedefConstant").
FlagWithArg("--hide ", "SuperfluousPrefix").
- FlagWithArg("--hide ", "AnnotationExtraction")
+ FlagWithArg("--hide ", "AnnotationExtraction").
+ // (b/217545629)
+ FlagWithArg("--hide ", "ChangedThrows").
+ // (b/217552813)
+ FlagWithArg("--hide ", "ChangedAbstract")
}
}
diff --git a/java/java.go b/java/java.go
index fef9912..e55f045 100644
--- a/java/java.go
+++ b/java/java.go
@@ -2010,7 +2010,8 @@
Javacopts bazel.StringListAttribute
}
-func javaLibraryBp2Build(ctx android.TopDownMutatorContext, m *Library) {
+func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) *javaLibraryAttributes {
+ //TODO(b/209577426): Support multiple arch variants
srcs := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrcExcludes(ctx, m.properties.Srcs, m.properties.Exclude_srcs))
attrs := &javaLibraryAttributes{
Srcs: srcs,
@@ -2020,9 +2021,21 @@
attrs.Javacopts = bazel.MakeStringListAttribute(m.properties.Javacflags)
}
+ var deps bazel.LabelList
if m.properties.Libs != nil {
- attrs.Deps = bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, m.properties.Libs))
+ deps.Append(android.BazelLabelForModuleDeps(ctx, m.properties.Libs))
}
+ if m.properties.Static_libs != nil {
+ //TODO(b/217236083) handle static libs similarly to Soong
+ deps.Append(android.BazelLabelForModuleDeps(ctx, m.properties.Static_libs))
+ }
+ attrs.Deps = bazel.MakeLabelListAttribute(deps)
+
+ return attrs
+}
+
+func javaLibraryBp2Build(ctx android.TopDownMutatorContext, m *Library) {
+ attrs := m.convertLibraryAttrsBp2Build(ctx)
props := bazel.BazelTargetModuleProperties{
Rule_class: "java_library",
diff --git a/java/plugin.go b/java/plugin.go
index 297ac2c..4b174b9 100644
--- a/java/plugin.go
+++ b/java/plugin.go
@@ -14,7 +14,10 @@
package java
-import "android/soong/android"
+import (
+ "android/soong/android"
+ "android/soong/bazel"
+)
func init() {
registerJavaPluginBuildComponents(android.InitRegistrationContext)
@@ -24,7 +27,6 @@
ctx.RegisterModuleType("java_plugin", PluginFactory)
}
-// A java_plugin module describes a host java library that will be used by javac as an annotation processor.
func PluginFactory() android.Module {
module := &Plugin{}
@@ -32,9 +34,13 @@
module.AddProperties(&module.pluginProperties)
InitJavaModule(module, android.HostSupported)
+
+ android.InitBazelModule(module)
+
return module
}
+// Plugin describes a java_plugin module, a host java library that will be used by javac as an annotation processor.
type Plugin struct {
Library
@@ -50,3 +56,29 @@
// parallelism and cause more recompilation for modules that depend on modules that use this plugin.
Generates_api *bool
}
+
+type pluginAttributes struct {
+ *javaLibraryAttributes
+ Processor_class *string
+ Target_compatible_with bazel.LabelListAttribute
+}
+
+// ConvertWithBp2build is used to convert android_app to Bazel.
+func (p *Plugin) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+ libAttrs := p.convertLibraryAttrsBp2Build(ctx)
+ attrs := &pluginAttributes{
+ libAttrs,
+ nil,
+ bazel.LabelListAttribute{},
+ }
+
+ if p.pluginProperties.Processor_class != nil {
+ attrs.Processor_class = p.pluginProperties.Processor_class
+ }
+
+ props := bazel.BazelTargetModuleProperties{
+ Rule_class: "java_plugin",
+ }
+
+ ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: p.Name()}, attrs)
+}
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 57ab268..6a2a7a8 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -2755,7 +2755,7 @@
android.SdkMemberPropertiesBase
// Scope to per scope properties.
- Scopes map[*apiScope]scopeProperties
+ Scopes map[*apiScope]*scopeProperties
// The Java stubs source files.
Stub_srcs []string
@@ -2808,14 +2808,14 @@
StubsSrcJar android.Path
CurrentApiFile android.Path
RemovedApiFile android.Path
- AnnotationsZip android.Path
+ AnnotationsZip android.Path `supported_build_releases:"T+"`
SdkVersion string
}
func (s *sdkLibrarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
sdk := variant.(*SdkLibrary)
- s.Scopes = make(map[*apiScope]scopeProperties)
+ s.Scopes = make(map[*apiScope]*scopeProperties)
for _, apiScope := range allApiScopes {
paths := sdk.findScopePaths(apiScope)
if paths == nil {
@@ -2838,7 +2838,7 @@
if paths.annotationsZip.Valid() {
properties.AnnotationsZip = paths.annotationsZip.Path()
}
- s.Scopes[apiScope] = properties
+ s.Scopes[apiScope] = &properties
}
}
diff --git a/mk2rbc/expr.go b/mk2rbc/expr.go
index 3f355ac..07f7ca1 100644
--- a/mk2rbc/expr.go
+++ b/mk2rbc/expr.go
@@ -378,32 +378,6 @@
}
}
-// variableDefinedExpr corresponds to Make's ifdef VAR
-type variableDefinedExpr struct {
- v variable
-}
-
-func (v *variableDefinedExpr) emit(gctx *generationContext) {
- if v.v != nil {
- v.v.emitDefined(gctx)
- return
- }
- gctx.writef("%s(%q)", cfnWarning, "TODO(VAR)")
-}
-
-func (_ *variableDefinedExpr) typ() starlarkType {
- return starlarkTypeBool
-}
-
-func (v *variableDefinedExpr) emitListVarCopy(gctx *generationContext) {
- v.emit(gctx)
-}
-
-func (v *variableDefinedExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
- // TODO: VariableDefinedExpr isn't really an expression?
- return v
-}
-
type listExpr struct {
items []starlarkExpr
}
diff --git a/mk2rbc/mk2rbc.go b/mk2rbc/mk2rbc.go
index e317cad..03cf21e 100644
--- a/mk2rbc/mk2rbc.go
+++ b/mk2rbc/mk2rbc.go
@@ -370,10 +370,6 @@
}
}
-type nodeReceiver interface {
- newNode(node starlarkNode)
-}
-
// Information about the generated Starlark script.
type StarlarkScript struct {
mkFile string
@@ -389,10 +385,6 @@
nodeLocator func(pos mkparser.Pos) int
}
-func (ss *StarlarkScript) newNode(node starlarkNode) {
- ss.nodes = append(ss.nodes, node)
-}
-
// varAssignmentScope points to the last assignment for each variable
// in the current block. It is used during the parsing to chain
// the assignments to a variable together.
@@ -415,8 +407,6 @@
tracedVariables map[string]bool // variables to be traced in the generated script
variables map[string]variable
varAssignments *varAssignmentScope
- receiver nodeReceiver // receptacle for the generated starlarkNode's
- receiverStack []nodeReceiver
outputDir string
dependentModules map[string]*moduleInfo
soongNamespaces map[string]map[string]bool
@@ -503,20 +493,6 @@
ctx.varAssignments = ctx.varAssignments.outer
}
-func (ctx *parseContext) pushReceiver(rcv nodeReceiver) {
- ctx.receiverStack = append(ctx.receiverStack, ctx.receiver)
- ctx.receiver = rcv
-}
-
-func (ctx *parseContext) popReceiver() {
- last := len(ctx.receiverStack) - 1
- if last < 0 {
- panic(fmt.Errorf("popReceiver: receiver stack empty"))
- }
- ctx.receiver = ctx.receiverStack[last]
- ctx.receiverStack = ctx.receiverStack[0:last]
-}
-
func (ctx *parseContext) hasNodes() bool {
return ctx.currentNodeIndex < len(ctx.nodes)
}
@@ -537,11 +513,10 @@
ctx.currentNodeIndex--
}
-func (ctx *parseContext) handleAssignment(a *mkparser.Assignment) {
+func (ctx *parseContext) handleAssignment(a *mkparser.Assignment) []starlarkNode {
// Handle only simple variables
if !a.Name.Const() {
- ctx.errorf(a, "Only simple variables are handled")
- return
+ return []starlarkNode{ctx.newBadNode(a, "Only simple variables are handled")}
}
name := a.Name.Strings[0]
// The `override` directive
@@ -549,18 +524,16 @@
// is parsed as an assignment to a variable named `override FOO`.
// There are very few places where `override` is used, just flag it.
if strings.HasPrefix(name, "override ") {
- ctx.errorf(a, "cannot handle override directive")
+ return []starlarkNode{ctx.newBadNode(a, "cannot handle override directive")}
}
// Soong configuration
if strings.HasPrefix(name, soongNsPrefix) {
- ctx.handleSoongNsAssignment(strings.TrimPrefix(name, soongNsPrefix), a)
- return
+ return ctx.handleSoongNsAssignment(strings.TrimPrefix(name, soongNsPrefix), a)
}
lhs := ctx.addVariable(name)
if lhs == nil {
- ctx.errorf(a, "unknown variable %s", name)
- return
+ return []starlarkNode{ctx.newBadNode(a, "unknown variable %s", name)}
}
_, isTraced := ctx.tracedVariables[name]
asgn := &assignmentNode{lhs: lhs, mkValue: a.Value, isTraced: isTraced, location: ctx.errorLocation(a)}
@@ -568,8 +541,7 @@
// Try to divine variable type from the RHS
asgn.value = ctx.parseMakeString(a, a.Value)
if xBad, ok := asgn.value.(*badExpr); ok {
- ctx.wrapBadExpr(xBad)
- return
+ return []starlarkNode{&exprNode{xBad}}
}
inferred_type := asgn.value.typ()
if inferred_type != starlarkTypeUnknown {
@@ -577,9 +549,9 @@
}
}
if lhs.valueType() == starlarkTypeList {
- xConcat := ctx.buildConcatExpr(a)
- if xConcat == nil {
- return
+ xConcat, xBad := ctx.buildConcatExpr(a)
+ if xBad != nil {
+ return []starlarkNode{&exprNode{expr: xBad}}
}
switch len(xConcat.items) {
case 0:
@@ -592,8 +564,7 @@
} else {
asgn.value = ctx.parseMakeString(a, a.Value)
if xBad, ok := asgn.value.(*badExpr); ok {
- ctx.wrapBadExpr(xBad)
- return
+ return []starlarkNode{&exprNode{expr: xBad}}
}
}
@@ -614,14 +585,13 @@
panic(fmt.Errorf("unexpected assignment type %s", a.Type))
}
- ctx.receiver.newNode(asgn)
+ return []starlarkNode{asgn}
}
-func (ctx *parseContext) handleSoongNsAssignment(name string, asgn *mkparser.Assignment) {
+func (ctx *parseContext) handleSoongNsAssignment(name string, asgn *mkparser.Assignment) []starlarkNode {
val := ctx.parseMakeString(asgn, asgn.Value)
if xBad, ok := val.(*badExpr); ok {
- ctx.wrapBadExpr(xBad)
- return
+ return []starlarkNode{&exprNode{expr: xBad}}
}
// Unfortunately, Soong namespaces can be set up by directly setting corresponding Make
@@ -634,17 +604,18 @@
// $(call add_soong_config_namespace,foo)
s, ok := maybeString(val)
if !ok {
- ctx.errorf(asgn, "cannot handle variables in SOONG_CONFIG_NAMESPACES assignment, please use add_soong_config_namespace instead")
- return
+ return []starlarkNode{ctx.newBadNode(asgn, "cannot handle variables in SOONG_CONFIG_NAMESPACES assignment, please use add_soong_config_namespace instead")}
}
+ result := make([]starlarkNode, 0)
for _, ns := range strings.Fields(s) {
ctx.addSoongNamespace(ns)
- ctx.receiver.newNode(&exprNode{&callExpr{
+ result = append(result, &exprNode{&callExpr{
name: baseName + ".soong_config_namespace",
args: []starlarkExpr{&globalsExpr{}, &stringLiteralExpr{ns}},
returnType: starlarkTypeVoid,
}})
}
+ return result
} else {
// Upon seeing
// SOONG_CONFIG_x_y = v
@@ -664,45 +635,41 @@
continue
}
if namespaceName != "" {
- ctx.errorf(asgn, "ambiguous soong namespace (may be either `%s` or `%s`)", namespaceName, name[0:pos])
- return
+ return []starlarkNode{ctx.newBadNode(asgn, "ambiguous soong namespace (may be either `%s` or `%s`)", namespaceName, name[0:pos])}
}
namespaceName = name[0:pos]
varName = name[pos+1:]
}
if namespaceName == "" {
- ctx.errorf(asgn, "cannot figure out Soong namespace, please use add_soong_config_var_value macro instead")
- return
+ return []starlarkNode{ctx.newBadNode(asgn, "cannot figure out Soong namespace, please use add_soong_config_var_value macro instead")}
}
if varName == "" {
// Remember variables in this namespace
s, ok := maybeString(val)
if !ok {
- ctx.errorf(asgn, "cannot handle variables in SOONG_CONFIG_ assignment, please use add_soong_config_var_value instead")
- return
+ return []starlarkNode{ctx.newBadNode(asgn, "cannot handle variables in SOONG_CONFIG_ assignment, please use add_soong_config_var_value instead")}
}
ctx.updateSoongNamespace(asgn.Type != "+=", namespaceName, strings.Fields(s))
- return
+ return []starlarkNode{}
}
// Finally, handle assignment to a namespace variable
if !ctx.hasNamespaceVar(namespaceName, varName) {
- ctx.errorf(asgn, "no %s variable in %s namespace, please use add_soong_config_var_value instead", varName, namespaceName)
- return
+ return []starlarkNode{ctx.newBadNode(asgn, "no %s variable in %s namespace, please use add_soong_config_var_value instead", varName, namespaceName)}
}
fname := baseName + "." + soongConfigAssign
if asgn.Type == "+=" {
fname = baseName + "." + soongConfigAppend
}
- ctx.receiver.newNode(&exprNode{&callExpr{
+ return []starlarkNode{&exprNode{&callExpr{
name: fname,
args: []starlarkExpr{&globalsExpr{}, &stringLiteralExpr{namespaceName}, &stringLiteralExpr{varName}, val},
returnType: starlarkTypeVoid,
- }})
+ }}}
}
}
-func (ctx *parseContext) buildConcatExpr(a *mkparser.Assignment) *concatExpr {
+func (ctx *parseContext) buildConcatExpr(a *mkparser.Assignment) (*concatExpr, *badExpr) {
xConcat := &concatExpr{}
var xItemList *listExpr
addToItemList := func(x ...starlarkExpr) {
@@ -724,8 +691,7 @@
// expressions return individual elements.
switch x := ctx.parseMakeString(a, item).(type) {
case *badExpr:
- ctx.wrapBadExpr(x)
- return nil
+ return nil, x
case *stringLiteralExpr:
addToItemList(maybeConvertToStringList(x).(*listExpr).items...)
default:
@@ -749,7 +715,7 @@
if xItemList != nil {
xConcat.items = append(xConcat.items, xItemList)
}
- return xConcat
+ return xConcat, nil
}
func (ctx *parseContext) newDependentModule(path string, optional bool) *moduleInfo {
@@ -779,7 +745,7 @@
}
func (ctx *parseContext) handleSubConfig(
- v mkparser.Node, pathExpr starlarkExpr, loadAlways bool, processModule func(inheritedModule)) {
+ v mkparser.Node, pathExpr starlarkExpr, loadAlways bool, processModule func(inheritedModule) starlarkNode) []starlarkNode {
// In a simple case, the name of a module to inherit/include is known statically.
if path, ok := maybeString(pathExpr); ok {
@@ -788,18 +754,19 @@
moduleShouldExist := loadAlways && ctx.ifNestLevel == 0
if strings.Contains(path, "*") {
if paths, err := fs.Glob(ctx.script.sourceFS, path); err == nil {
+ result := make([]starlarkNode, 0)
for _, p := range paths {
mi := ctx.newDependentModule(p, !moduleShouldExist)
- processModule(inheritedStaticModule{mi, loadAlways})
+ result = append(result, processModule(inheritedStaticModule{mi, loadAlways}))
}
+ return result
} else {
- ctx.errorf(v, "cannot glob wildcard argument")
+ return []starlarkNode{ctx.newBadNode(v, "cannot glob wildcard argument")}
}
} else {
mi := ctx.newDependentModule(path, !moduleShouldExist)
- processModule(inheritedStaticModule{mi, loadAlways})
+ return []starlarkNode{processModule(inheritedStaticModule{mi, loadAlways})}
}
- return
}
// If module path references variables (e.g., $(v1)/foo/$(v2)/device-config.mk), find all the paths in the
@@ -819,8 +786,7 @@
var matchingPaths []string
varPath, ok := pathExpr.(*interpolateExpr)
if !ok {
- ctx.errorf(v, "inherit-product/include argument is too complex")
- return
+ return []starlarkNode{ctx.newBadNode(v, "inherit-product/include argument is too complex")}
}
pathPattern := []string{varPath.chunks[0]}
@@ -829,11 +795,7 @@
pathPattern = append(pathPattern, chunk)
}
}
- if pathPattern[0] == "" {
- if len(ctx.includeTops) == 0 {
- ctx.errorf(v, "inherit-product/include statements must not be prefixed with a variable, or must include a #RBC# include_top comment beforehand giving a root directory to search.")
- return
- }
+ if pathPattern[0] == "" && len(ctx.includeTops) > 0 {
// If pattern starts from the top. restrict it to the directories where
// we know inherit-product uses dynamically calculated path.
for _, p := range ctx.includeTops {
@@ -846,17 +808,22 @@
// Safeguard against $(call inherit-product,$(PRODUCT_PATH))
const maxMatchingFiles = 150
if len(matchingPaths) > maxMatchingFiles {
- ctx.errorf(v, "there are >%d files matching the pattern, please rewrite it", maxMatchingFiles)
- return
+ return []starlarkNode{ctx.newBadNode(v, "there are >%d files matching the pattern, please rewrite it", maxMatchingFiles)}
}
- res := inheritedDynamicModule{*varPath, []*moduleInfo{}, loadAlways}
- for _, p := range matchingPaths {
- // A product configuration files discovered dynamically may attempt to inherit
- // from another one which does not exist in this source tree. Prevent load errors
- // by always loading the dynamic files as optional.
- res.candidateModules = append(res.candidateModules, ctx.newDependentModule(p, true))
+ if len(matchingPaths) == 1 {
+ res := inheritedStaticModule{ctx.newDependentModule(matchingPaths[0], loadAlways && ctx.ifNestLevel == 0), loadAlways}
+ return []starlarkNode{processModule(res)}
+ } else {
+ needsWarning := pathPattern[0] == "" && len(ctx.includeTops) == 0
+ res := inheritedDynamicModule{*varPath, []*moduleInfo{}, loadAlways, ctx.errorLocation(v), needsWarning}
+ for _, p := range matchingPaths {
+ // A product configuration files discovered dynamically may attempt to inherit
+ // from another one which does not exist in this source tree. Prevent load errors
+ // by always loading the dynamic files as optional.
+ res.candidateModules = append(res.candidateModules, ctx.newDependentModule(p, true))
+ }
+ return []starlarkNode{processModule(res)}
}
- processModule(res)
}
func (ctx *parseContext) findMatchingPaths(pattern []string) []string {
@@ -883,25 +850,25 @@
return res
}
-func (ctx *parseContext) handleInheritModule(v mkparser.Node, args *mkparser.MakeString, loadAlways bool) {
+func (ctx *parseContext) handleInheritModule(v mkparser.Node, args *mkparser.MakeString, loadAlways bool) []starlarkNode {
args.TrimLeftSpaces()
args.TrimRightSpaces()
pathExpr := ctx.parseMakeString(v, args)
if _, ok := pathExpr.(*badExpr); ok {
- ctx.errorf(v, "Unable to parse argument to inherit")
+ return []starlarkNode{ctx.newBadNode(v, "Unable to parse argument to inherit")}
}
- ctx.handleSubConfig(v, pathExpr, loadAlways, func(im inheritedModule) {
- ctx.receiver.newNode(&inheritNode{im, loadAlways})
+ return ctx.handleSubConfig(v, pathExpr, loadAlways, func(im inheritedModule) starlarkNode {
+ return &inheritNode{im, loadAlways}
})
}
-func (ctx *parseContext) handleInclude(v mkparser.Node, pathExpr starlarkExpr, loadAlways bool) {
- ctx.handleSubConfig(v, pathExpr, loadAlways, func(im inheritedModule) {
- ctx.receiver.newNode(&includeNode{im, loadAlways})
+func (ctx *parseContext) handleInclude(v mkparser.Node, pathExpr starlarkExpr, loadAlways bool) []starlarkNode {
+ return ctx.handleSubConfig(v, pathExpr, loadAlways, func(im inheritedModule) starlarkNode {
+ return &includeNode{im, loadAlways}
})
}
-func (ctx *parseContext) handleVariable(v *mkparser.Variable) {
+func (ctx *parseContext) handleVariable(v *mkparser.Variable) []starlarkNode {
// Handle:
// $(call inherit-product,...)
// $(call inherit-product-if-exists,...)
@@ -916,67 +883,57 @@
if strings.HasPrefix(v.Name.Dump(), "call inherit-product,") {
args := v.Name.Clone()
args.ReplaceLiteral("call inherit-product,", "")
- ctx.handleInheritModule(v, args, true)
- return
+ return ctx.handleInheritModule(v, args, true)
}
if strings.HasPrefix(v.Name.Dump(), "call inherit-product-if-exists,") {
args := v.Name.Clone()
args.ReplaceLiteral("call inherit-product-if-exists,", "")
- ctx.handleInheritModule(v, args, false)
- return
+ return ctx.handleInheritModule(v, args, false)
}
- expr := ctx.parseReference(v, v.Name)
- switch x := expr.(type) {
- case *callExpr:
- ctx.receiver.newNode(&exprNode{expr})
- case *badExpr:
- ctx.wrapBadExpr(x)
- default:
- ctx.errorf(v, "cannot handle %s", v.Dump())
- }
+ return []starlarkNode{&exprNode{expr: ctx.parseReference(v, v.Name)}}
}
-func (ctx *parseContext) handleDefine(directive *mkparser.Directive) {
+func (ctx *parseContext) maybeHandleDefine(directive *mkparser.Directive) starlarkNode {
macro_name := strings.Fields(directive.Args.Strings[0])[0]
// Ignore the macros that we handle
_, ignored := ignoredDefines[macro_name]
_, known := knownFunctions[macro_name]
if !ignored && !known {
- ctx.errorf(directive, "define is not supported: %s", macro_name)
+ return ctx.newBadNode(directive, "define is not supported: %s", macro_name)
}
+ return nil
}
-func (ctx *parseContext) handleIfBlock(ifDirective *mkparser.Directive) {
- ssSwitch := &switchNode{}
- ctx.pushReceiver(ssSwitch)
- for ctx.processBranch(ifDirective); ctx.hasNodes() && ctx.fatalError == nil; {
+func (ctx *parseContext) handleIfBlock(ifDirective *mkparser.Directive) starlarkNode {
+ ssSwitch := &switchNode{
+ ssCases: []*switchCase{ctx.processBranch(ifDirective)},
+ }
+ for ctx.hasNodes() && ctx.fatalError == nil {
node := ctx.getNode()
switch x := node.(type) {
case *mkparser.Directive:
switch x.Name {
case "else", "elifdef", "elifndef", "elifeq", "elifneq":
- ctx.processBranch(x)
+ ssSwitch.ssCases = append(ssSwitch.ssCases, ctx.processBranch(x))
case "endif":
- ctx.popReceiver()
- ctx.receiver.newNode(ssSwitch)
- return
+ return ssSwitch
default:
- ctx.errorf(node, "unexpected directive %s", x.Name)
+ return ctx.newBadNode(node, "unexpected directive %s", x.Name)
}
default:
- ctx.errorf(ifDirective, "unexpected statement")
+ return ctx.newBadNode(ifDirective, "unexpected statement")
}
}
if ctx.fatalError == nil {
ctx.fatalError = fmt.Errorf("no matching endif for %s", ifDirective.Dump())
}
- ctx.popReceiver()
+ return ctx.newBadNode(ifDirective, "no matching endif for %s", ifDirective.Dump())
}
// processBranch processes a single branch (if/elseif/else) until the next directive
// on the same level.
-func (ctx *parseContext) processBranch(check *mkparser.Directive) {
- block := switchCase{gate: ctx.parseCondition(check)}
+func (ctx *parseContext) processBranch(check *mkparser.Directive) *switchCase {
+ block := &switchCase{gate: ctx.parseCondition(check)}
defer func() {
ctx.popVarAssignments()
ctx.ifNestLevel--
@@ -985,37 +942,29 @@
ctx.pushVarAssignments()
ctx.ifNestLevel++
- ctx.pushReceiver(&block)
for ctx.hasNodes() {
node := ctx.getNode()
if d, ok := node.(*mkparser.Directive); ok {
switch d.Name {
case "else", "elifdef", "elifndef", "elifeq", "elifneq", "endif":
- ctx.popReceiver()
- ctx.receiver.newNode(&block)
ctx.backNode()
- return
+ return block
}
}
- ctx.handleSimpleStatement(node)
+ block.nodes = append(block.nodes, ctx.handleSimpleStatement(node)...)
}
ctx.fatalError = fmt.Errorf("no matching endif for %s", check.Dump())
- ctx.popReceiver()
-}
-
-func (ctx *parseContext) newIfDefinedNode(check *mkparser.Directive) (starlarkExpr, bool) {
- if !check.Args.Const() {
- return ctx.newBadExpr(check, "ifdef variable ref too complex: %s", check.Args.Dump()), false
- }
- v := ctx.addVariable(check.Args.Strings[0])
- return &variableDefinedExpr{v}, true
+ return block
}
func (ctx *parseContext) parseCondition(check *mkparser.Directive) starlarkNode {
switch check.Name {
case "ifdef", "ifndef", "elifdef", "elifndef":
- v, ok := ctx.newIfDefinedNode(check)
- if ok && strings.HasSuffix(check.Name, "ndef") {
+ if !check.Args.Const() {
+ return ctx.newBadNode(check, "ifdef variable ref too complex: %s", check.Args.Dump())
+ }
+ v := NewVariableRefExpr(ctx.addVariable(check.Args.Strings[0]), false)
+ if strings.HasSuffix(check.Name, "ndef") {
v = ¬Expr{v}
}
return &ifNode{
@@ -1035,12 +984,16 @@
}
func (ctx *parseContext) newBadExpr(node mkparser.Node, text string, args ...interface{}) starlarkExpr {
- message := fmt.Sprintf(text, args...)
if ctx.errorLogger != nil {
ctx.errorLogger.NewError(ctx.errorLocation(node), node, text, args...)
}
ctx.script.hasErrors = true
- return &badExpr{errorLocation: ctx.errorLocation(node), message: message}
+ return &badExpr{errorLocation: ctx.errorLocation(node), message: fmt.Sprintf(text, args...)}
+}
+
+// records that the given node failed to be converted and includes an explanatory message
+func (ctx *parseContext) newBadNode(failedNode mkparser.Node, message string, args ...interface{}) starlarkNode {
+ return &exprNode{ctx.newBadExpr(failedNode, message, args...)}
}
func (ctx *parseContext) parseCompare(cond *mkparser.Directive) starlarkExpr {
@@ -1733,28 +1686,34 @@
// Handles the statements whose treatment is the same in all contexts: comment,
// assignment, variable (which is a macro call in reality) and all constructs that
// do not handle in any context ('define directive and any unrecognized stuff).
-func (ctx *parseContext) handleSimpleStatement(node mkparser.Node) {
+func (ctx *parseContext) handleSimpleStatement(node mkparser.Node) []starlarkNode {
+ var result []starlarkNode
switch x := node.(type) {
case *mkparser.Comment:
- ctx.maybeHandleAnnotation(x)
- ctx.insertComment("#" + x.Comment)
+ if n, handled := ctx.maybeHandleAnnotation(x); handled && n != nil {
+ result = []starlarkNode{n}
+ } else if !handled {
+ result = []starlarkNode{&commentNode{strings.TrimSpace("#" + x.Comment)}}
+ }
case *mkparser.Assignment:
- ctx.handleAssignment(x)
+ result = ctx.handleAssignment(x)
case *mkparser.Variable:
- ctx.handleVariable(x)
+ result = ctx.handleVariable(x)
case *mkparser.Directive:
switch x.Name {
case "define":
- ctx.handleDefine(x)
+ if res := ctx.maybeHandleDefine(x); res != nil {
+ result = []starlarkNode{res}
+ }
case "include", "-include":
- ctx.handleInclude(node, ctx.parseMakeString(node, x.Args), x.Name[0] != '-')
+ result = ctx.handleInclude(node, ctx.parseMakeString(node, x.Args), x.Name[0] != '-')
case "ifeq", "ifneq", "ifdef", "ifndef":
- ctx.handleIfBlock(x)
+ result = []starlarkNode{ctx.handleIfBlock(x)}
default:
- ctx.errorf(x, "unexpected directive %s", x.Name)
+ result = []starlarkNode{ctx.newBadNode(x, "unexpected directive %s", x.Name)}
}
default:
- ctx.errorf(x, "unsupported line %s", strings.ReplaceAll(x.Dump(), "\n", "\n#"))
+ result = []starlarkNode{ctx.newBadNode(x, "unsupported line %s", strings.ReplaceAll(x.Dump(), "\n", "\n#"))}
}
// Clear the includeTops after each non-comment statement
@@ -1763,12 +1722,17 @@
if _, wasComment := node.(*mkparser.Comment); !wasComment && len(ctx.includeTops) > 0 {
ctx.includeTops = []string{}
}
+
+ if result == nil {
+ result = []starlarkNode{}
+ }
+ return result
}
// Processes annotation. An annotation is a comment that starts with #RBC# and provides
// a conversion hint -- say, where to look for the dynamically calculated inherit/include
-// paths.
-func (ctx *parseContext) maybeHandleAnnotation(cnode *mkparser.Comment) {
+// paths. Returns true if the comment was a successfully-handled annotation.
+func (ctx *parseContext) maybeHandleAnnotation(cnode *mkparser.Comment) (starlarkNode, bool) {
maybeTrim := func(s, prefix string) (string, bool) {
if strings.HasPrefix(s, prefix) {
return strings.TrimSpace(strings.TrimPrefix(s, prefix)), true
@@ -1777,44 +1741,20 @@
}
annotation, ok := maybeTrim(cnode.Comment, annotationCommentPrefix)
if !ok {
- return
+ return nil, false
}
if p, ok := maybeTrim(annotation, "include_top"); ok {
// Don't allow duplicate include tops, because then we will generate
// invalid starlark code. (duplicate keys in the _entry dictionary)
for _, top := range ctx.includeTops {
if top == p {
- return
+ return nil, true
}
}
ctx.includeTops = append(ctx.includeTops, p)
- return
+ return nil, true
}
- ctx.errorf(cnode, "unsupported annotation %s", cnode.Comment)
-
-}
-
-func (ctx *parseContext) insertComment(s string) {
- ctx.receiver.newNode(&commentNode{strings.TrimSpace(s)})
-}
-
-func (ctx *parseContext) carryAsComment(failedNode mkparser.Node) {
- for _, line := range strings.Split(failedNode.Dump(), "\n") {
- ctx.insertComment("# " + line)
- }
-}
-
-// records that the given node failed to be converted and includes an explanatory message
-func (ctx *parseContext) errorf(failedNode mkparser.Node, message string, args ...interface{}) {
- if ctx.errorLogger != nil {
- ctx.errorLogger.NewError(ctx.errorLocation(failedNode), failedNode, message, args...)
- }
- ctx.receiver.newNode(&exprNode{ctx.newBadExpr(failedNode, message, args...)})
- ctx.script.hasErrors = true
-}
-
-func (ctx *parseContext) wrapBadExpr(xBad *badExpr) {
- ctx.receiver.newNode(&exprNode{xBad})
+ return ctx.newBadNode(cnode, "unsupported annotation %s", cnode.Comment), true
}
func (ctx *parseContext) loadedModulePath(path string) string {
@@ -1929,6 +1869,7 @@
sourceFS: req.SourceFS,
makefileFinder: req.MakefileFinder,
nodeLocator: func(pos mkparser.Pos) int { return parser.Unpack(pos).Line },
+ nodes: make([]starlarkNode, 0),
}
ctx := newParseContext(starScript, nodes)
ctx.outputSuffix = req.OutputSuffix
@@ -1940,9 +1881,8 @@
ctx.tracedVariables[v] = true
}
}
- ctx.pushReceiver(starScript)
for ctx.hasNodes() && ctx.fatalError == nil {
- ctx.handleSimpleStatement(ctx.getNode())
+ starScript.nodes = append(starScript.nodes, ctx.handleSimpleStatement(ctx.getNode())...)
}
if ctx.fatalError != nil {
return nil, ctx.fatalError
diff --git a/mk2rbc/mk2rbc_test.go b/mk2rbc/mk2rbc_test.go
index c4f7da3..c499398 100644
--- a/mk2rbc/mk2rbc_test.go
+++ b/mk2rbc/mk2rbc_test.go
@@ -131,7 +131,7 @@
def init(g, handle):
cfg = rblf.cfg(handle)
rblf.inherit(handle, "part", _part_init)
- if g.get("PRODUCT_NAME") != None:
+ if cfg.get("PRODUCT_NAME", ""):
if not _part1_init:
rblf.mkerror("product.mk", "Cannot find %s" % (":part1.star"))
rblf.inherit(handle, "part1", _part1_init)
@@ -174,7 +174,7 @@
def init(g, handle):
cfg = rblf.cfg(handle)
_part_init(g, handle)
- if g.get("PRODUCT_NAME") != None:
+ if cfg.get("PRODUCT_NAME", ""):
if not _part1_init:
rblf.mkerror("product.mk", "Cannot find %s" % (":part1.star"))
_part1_init(g, handle)
@@ -231,7 +231,7 @@
def init(g, handle):
cfg = rblf.cfg(handle)
- if g.get("PRODUCT_NAME") != None:
+ if cfg.get("PRODUCT_NAME", ""):
cfg["PRODUCT_NAME"] = "gizmo"
else:
pass
@@ -275,7 +275,7 @@
def init(g, handle):
cfg = rblf.cfg(handle)
- if g.get("PRODUCT_NAME") != None:
+ if cfg.get("PRODUCT_NAME", ""):
# Comment
pass
else:
@@ -296,7 +296,7 @@
def init(g, handle):
cfg = rblf.cfg(handle)
- if not g.get("PRODUCT_NAME") != None:
+ if not cfg.get("PRODUCT_NAME", ""):
cfg["PRODUCT_NAME"] = "gizmo1"
else:
cfg["PRODUCT_NAME"] = "gizmo2"
@@ -315,9 +315,9 @@
def init(g, handle):
cfg = rblf.cfg(handle)
- if g.get("PRODUCT_NAME") != None:
+ if cfg.get("PRODUCT_NAME", ""):
cfg["PRODUCT_NAME"] = "gizmo"
- elif not g.get("PRODUCT_PACKAGES") != None:
+ elif not cfg.get("PRODUCT_PACKAGES", []):
# Comment
pass
`,
@@ -509,11 +509,11 @@
def init(g, handle):
cfg = rblf.cfg(handle)
- if g.get("PRODUCT_NAME") != None:
+ if cfg.get("PRODUCT_NAME", ""):
cfg["PRODUCT_PACKAGES"] = ["pack-if0"]
- if g.get("PRODUCT_MODEL") != None:
+ if cfg.get("PRODUCT_MODEL", ""):
cfg["PRODUCT_PACKAGES"] = ["pack-if-if"]
- elif g.get("PRODUCT_NAME") != None:
+ elif cfg.get("PRODUCT_NAME", ""):
cfg["PRODUCT_PACKAGES"] = ["pack-if-elif"]
else:
cfg["PRODUCT_PACKAGES"] = ["pack-if-else"]
@@ -1071,14 +1071,7 @@
def init(g, handle):
cfg = rblf.cfg(handle)
g["MY_PATH"] = "foo"
- #RBC# include_top vendor/foo1
- _entry = {
- "vendor/foo1/cfg.mk": ("vendor/foo1/cfg", _cfg_init),
- }.get("%s/cfg.mk" % g["MY_PATH"])
- (_varmod, _varmod_init) = _entry if _entry else (None, None)
- if not _varmod_init:
- rblf.mkerror("product.mk", "Cannot find %s" % ("%s/cfg.mk" % g["MY_PATH"]))
- rblf.inherit(handle, _varmod, _varmod_init)
+ rblf.inherit(handle, "vendor/foo1/cfg", _cfg_init)
`,
},
{
@@ -1089,6 +1082,7 @@
#RBC# include_top vendor/foo1
$(call inherit-product,$(MY_PATH)/cfg.mk)
#RBC# include_top vendor/foo1
+#RBC# include_top vendor/foo1
$(call inherit-product,$(MY_PATH)/cfg.mk)
`,
expected: `load("//build/make/core:product_config.rbc", "rblf")
@@ -1097,26 +1091,12 @@
def init(g, handle):
cfg = rblf.cfg(handle)
g["MY_PATH"] = "foo"
- #RBC# include_top vendor/foo1
- _entry = {
- "vendor/foo1/cfg.mk": ("vendor/foo1/cfg", _cfg_init),
- }.get("%s/cfg.mk" % g["MY_PATH"])
- (_varmod, _varmod_init) = _entry if _entry else (None, None)
- if not _varmod_init:
- rblf.mkerror("product.mk", "Cannot find %s" % ("%s/cfg.mk" % g["MY_PATH"]))
- rblf.inherit(handle, _varmod, _varmod_init)
- #RBC# include_top vendor/foo1
- _entry = {
- "vendor/foo1/cfg.mk": ("vendor/foo1/cfg", _cfg_init),
- }.get("%s/cfg.mk" % g["MY_PATH"])
- (_varmod, _varmod_init) = _entry if _entry else (None, None)
- if not _varmod_init:
- rblf.mkerror("product.mk", "Cannot find %s" % ("%s/cfg.mk" % g["MY_PATH"]))
- rblf.inherit(handle, _varmod, _varmod_init)
+ rblf.inherit(handle, "vendor/foo1/cfg", _cfg_init)
+ rblf.inherit(handle, "vendor/foo1/cfg", _cfg_init)
`,
},
{
- desc: "Dynamic inherit path that lacks necessary hint",
+ desc: "Dynamic inherit path that lacks hint",
mkname: "product.mk",
in: `
#RBC# include_top foo
@@ -1130,29 +1110,24 @@
$(call inherit-product,$(MY_VAR)/font.mk)
`,
- expected: `#RBC# include_top foo
-load("//build/make/core:product_config.rbc", "rblf")
+ expected: `load("//build/make/core:product_config.rbc", "rblf")
load("//foo:font.star|init", _font_init = "init")
+load("//bar:font.star|init", _font1_init = "init")
def init(g, handle):
cfg = rblf.cfg(handle)
- _entry = {
- "foo/font.mk": ("foo/font", _font_init),
- }.get("%s/font.mk" % g.get("MY_VAR", ""))
- (_varmod, _varmod_init) = _entry if _entry else (None, None)
- if not _varmod_init:
- rblf.mkerror("product.mk", "Cannot find %s" % ("%s/font.mk" % g.get("MY_VAR", "")))
- rblf.inherit(handle, _varmod, _varmod_init)
- #RBC# include_top foo
+ rblf.inherit(handle, "foo/font", _font_init)
# There's some space and even this comment between the include_top and the inherit-product
+ rblf.inherit(handle, "foo/font", _font_init)
+ rblf.mkwarning("product.mk:11", "Including a path with a non-constant prefix, please convert this to a simple literal to generate cleaner starlark.")
_entry = {
"foo/font.mk": ("foo/font", _font_init),
+ "bar/font.mk": ("bar/font", _font1_init),
}.get("%s/font.mk" % g.get("MY_VAR", ""))
(_varmod, _varmod_init) = _entry if _entry else (None, None)
if not _varmod_init:
rblf.mkerror("product.mk", "Cannot find %s" % ("%s/font.mk" % g.get("MY_VAR", "")))
rblf.inherit(handle, _varmod, _varmod_init)
- rblf.mk2rbc_error("product.mk:11", "inherit-product/include statements must not be prefixed with a variable, or must include a #RBC# include_top comment beforehand giving a root directory to search.")
`,
},
{
@@ -1178,7 +1153,6 @@
def init(g, handle):
cfg = rblf.cfg(handle)
rblf.mk2rbc_error("product.mk:2", "cannot handle override directive")
- g["override FOO"] = ""
`,
},
{
diff --git a/mk2rbc/node.go b/mk2rbc/node.go
index 4f7c4f0..61aaf91 100644
--- a/mk2rbc/node.go
+++ b/mk2rbc/node.go
@@ -86,6 +86,8 @@
path interpolateExpr
candidateModules []*moduleInfo
loadAlways bool
+ location ErrorLocation
+ needsWarning bool
}
func (i inheritedDynamicModule) name() string {
@@ -97,6 +99,10 @@
}
func (i inheritedDynamicModule) emitSelect(gctx *generationContext) {
+ if i.needsWarning {
+ gctx.newLine()
+ gctx.writef("%s.mkwarning(%q, %q)", baseName, i.location, "Including a path with a non-constant prefix, please convert this to a simple literal to generate cleaner starlark.")
+ }
gctx.newLine()
gctx.writef("_entry = {")
gctx.indentLevel++
@@ -249,29 +255,17 @@
nodes []starlarkNode
}
-func (cb *switchCase) newNode(node starlarkNode) {
- cb.nodes = append(cb.nodes, node)
-}
-
func (cb *switchCase) emit(gctx *generationContext) {
cb.gate.emit(gctx)
gctx.indentLevel++
hasStatements := false
- emitNode := func(node starlarkNode) {
+ for _, node := range cb.nodes {
if _, ok := node.(*commentNode); !ok {
hasStatements = true
}
node.emit(gctx)
}
- if len(cb.nodes) > 0 {
- emitNode(cb.nodes[0])
- for _, node := range cb.nodes[1:] {
- emitNode(node)
- }
- if !hasStatements {
- gctx.emitPass()
- }
- } else {
+ if !hasStatements {
gctx.emitPass()
}
gctx.indentLevel--
@@ -282,22 +276,8 @@
ssCases []*switchCase
}
-func (ssw *switchNode) newNode(node starlarkNode) {
- switch br := node.(type) {
- case *switchCase:
- ssw.ssCases = append(ssw.ssCases, br)
- default:
- panic(fmt.Errorf("expected switchCase node, got %t", br))
- }
-}
-
func (ssw *switchNode) emit(gctx *generationContext) {
- if len(ssw.ssCases) == 0 {
- gctx.emitPass()
- } else {
- ssw.ssCases[0].emit(gctx)
- for _, ssCase := range ssw.ssCases[1:] {
- ssCase.emit(gctx)
- }
+ for _, ssCase := range ssw.ssCases {
+ ssCase.emit(gctx)
}
}
diff --git a/scripts/manifest_fixer.py b/scripts/manifest_fixer.py
index d80a617..2d3103b 100755
--- a/scripts/manifest_fixer.py
+++ b/scripts/manifest_fixer.py
@@ -65,6 +65,9 @@
parser.add_argument('--has-no-code', dest='has_no_code', action='store_true',
help=('adds hasCode="false" attribute to application. Ignored if application elem '
'already has a hasCode attribute.'))
+ parser.add_argument('--test-only', dest='test_only', action='store_true',
+ help=('adds testOnly="true" attribute to application. Assign true value if application elem '
+ 'already has a testOnly attribute.'))
parser.add_argument('input', help='input AndroidManifest.xml file')
parser.add_argument('output', help='output AndroidManifest.xml file')
return parser.parse_args()
@@ -318,6 +321,26 @@
attr.value = 'false'
application.setAttributeNode(attr)
+def set_test_only_flag_to_true(doc):
+ manifest = parse_manifest(doc)
+ elems = get_children_with_tag(manifest, 'application')
+ application = elems[0] if len(elems) == 1 else None
+ if len(elems) > 1:
+ raise RuntimeError('found multiple <application> tags')
+ elif not elems:
+ application = doc.createElement('application')
+ indent = get_indent(manifest.firstChild, 1)
+ first = manifest.firstChild
+ manifest.insertBefore(doc.createTextNode(indent), first)
+ manifest.insertBefore(application, first)
+
+ attr = application.getAttributeNodeNS(android_ns, 'testOnly')
+ if attr is not None:
+ # Do nothing If the application already has a testOnly attribute.
+ return
+ attr = doc.createAttributeNS(android_ns, 'android:testOnly')
+ attr.value = 'true'
+ application.setAttributeNode(attr)
def main():
"""Program entry point."""
@@ -349,6 +372,9 @@
if args.has_no_code:
set_has_code_to_false(doc)
+ if args.test_only:
+ set_test_only_flag_to_true(doc)
+
if args.extract_native_libs is not None:
add_extract_native_libs(doc, args.extract_native_libs)
diff --git a/scripts/manifest_fixer_test.py b/scripts/manifest_fixer_test.py
index f6fcaaf..199b279 100755
--- a/scripts/manifest_fixer_test.py
+++ b/scripts/manifest_fixer_test.py
@@ -521,12 +521,55 @@
self.assert_xml_equal(output, manifest_input)
def test_has_application_has_code_true(self):
- """ Do nothing if there's already an application elemeent even if its
+ """ Do nothing if there's already an application element even if its
hasCode attribute is true. """
manifest_input = self.manifest_tmpl % ' <application android:hasCode="true"/>\n'
output = self.run_test(manifest_input)
self.assert_xml_equal(output, manifest_input)
+class AddTestOnlyApplicationTest(unittest.TestCase):
+ """Unit tests for set_test_only_flag_to_true function."""
+
+ def assert_xml_equal(self, output, expected):
+ self.assertEqual(ET.canonicalize(output), ET.canonicalize(expected))
+
+ def run_test(self, input_manifest):
+ doc = minidom.parseString(input_manifest)
+ manifest_fixer.set_test_only_flag_to_true(doc)
+ output = io.StringIO()
+ manifest_fixer.write_xml(output, doc)
+ return output.getvalue()
+
+ manifest_tmpl = (
+ '<?xml version="1.0" encoding="utf-8"?>\n'
+ '<manifest xmlns:android="http://schemas.android.com/apk/res/android">\n'
+ '%s'
+ '</manifest>\n')
+
+ def test_no_application(self):
+ manifest_input = self.manifest_tmpl % ''
+ expected = self.manifest_tmpl % ' <application android:testOnly="true"/>\n'
+ output = self.run_test(manifest_input)
+ self.assert_xml_equal(output, expected)
+
+ def test_has_application_no_test_only(self):
+ manifest_input = self.manifest_tmpl % ' <application/>\n'
+ expected = self.manifest_tmpl % ' <application android:testOnly="true"/>\n'
+ output = self.run_test(manifest_input)
+ self.assert_xml_equal(output, expected)
+
+ def test_has_application_test_only_true(self):
+ """ If there's already an application element."""
+ manifest_input = self.manifest_tmpl % ' <application android:testOnly="true"/>\n'
+ output = self.run_test(manifest_input)
+ self.assert_xml_equal(output, manifest_input)
+
+ def test_has_application_test_only_false(self):
+ """ If there's already an application element with the testOnly attribute as false."""
+ manifest_input = self.manifest_tmpl % ' <application android:testOnly="false"/>\n'
+ output = self.run_test(manifest_input)
+ self.assert_xml_equal(output, manifest_input)
+
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/sdk/build_release.go b/sdk/build_release.go
index a3f0899..2bcdc6f 100644
--- a/sdk/build_release.go
+++ b/sdk/build_release.go
@@ -230,51 +230,108 @@
return container.Field(fieldIndex)
}
- zeroValue := reflect.Zero(field.Type)
- fieldPruner := func(container reflect.Value) {
- if containingStructAccessor != nil {
- // This is an embedded structure so first access the field for the embedded
- // structure.
- container = containingStructAccessor(container)
+ fieldType := field.Type
+ if selector(name, field) {
+ zeroValue := reflect.Zero(fieldType)
+ fieldPruner := func(container reflect.Value) {
+ if containingStructAccessor != nil {
+ // This is an embedded structure so first access the field for the embedded
+ // structure.
+ container = containingStructAccessor(container)
+ }
+
+ // Skip through interface and pointer values to find the structure.
+ container = getStructValue(container)
+
+ defer func() {
+ if r := recover(); r != nil {
+ panic(fmt.Errorf("%s\n\tfor field (index %d, name %s)", r, fieldIndex, name))
+ }
+ }()
+
+ // Set the field.
+ container.Field(fieldIndex).Set(zeroValue)
}
- // Skip through interface and pointer values to find the structure.
- container = getStructValue(container)
-
- defer func() {
- if r := recover(); r != nil {
- panic(fmt.Errorf("%s for fieldIndex %d of field %s of container %#v", r, fieldIndex, name, container.Interface()))
- }
- }()
-
- // Set the field.
- container.Field(fieldIndex).Set(zeroValue)
- }
-
- if selector(name, field) {
property := prunerProperty{
name,
fieldPruner,
}
p.properties = append(p.properties, property)
- } else if field.Type.Kind() == reflect.Struct {
- // Gather fields from the nested or embedded structure.
- var subNamePrefix string
- if field.Anonymous {
- subNamePrefix = namePrefix
- } else {
- subNamePrefix = name + "."
+ } else {
+ switch fieldType.Kind() {
+ case reflect.Struct:
+ // Gather fields from the nested or embedded structure.
+ var subNamePrefix string
+ if field.Anonymous {
+ subNamePrefix = namePrefix
+ } else {
+ subNamePrefix = name + "."
+ }
+ p.gatherFields(fieldType, fieldGetter, subNamePrefix, selector)
+
+ case reflect.Map:
+ // Get the type of the values stored in the map.
+ valueType := fieldType.Elem()
+ // Skip over * types.
+ if valueType.Kind() == reflect.Ptr {
+ valueType = valueType.Elem()
+ }
+ if valueType.Kind() == reflect.Struct {
+ // If this is not referenced by a pointer then it is an error as it is impossible to
+ // modify a struct that is stored directly as a value in a map.
+ if fieldType.Elem().Kind() != reflect.Ptr {
+ panic(fmt.Errorf("Cannot prune struct %s stored by value in map %s, map values must"+
+ " be pointers to structs",
+ fieldType.Elem(), name))
+ }
+
+ // Create a new pruner for the values of the map.
+ valuePruner := newPropertyPrunerForStructType(valueType, selector)
+
+ // Create a new fieldPruner that will iterate over all the items in the map and call the
+ // pruner on them.
+ fieldPruner := func(container reflect.Value) {
+ mapValue := fieldGetter(container)
+
+ for _, keyValue := range mapValue.MapKeys() {
+ itemValue := mapValue.MapIndex(keyValue)
+
+ defer func() {
+ if r := recover(); r != nil {
+ panic(fmt.Errorf("%s\n\tfor key %q", r, keyValue))
+ }
+ }()
+
+ valuePruner.pruneProperties(itemValue.Interface())
+ }
+ }
+
+ // Add the map field pruner to the list of property pruners.
+ property := prunerProperty{
+ name + "[*]",
+ fieldPruner,
+ }
+ p.properties = append(p.properties, property)
+ }
}
- p.gatherFields(field.Type, fieldGetter, subNamePrefix, selector)
}
}
}
-// pruneProperties will prune (set to zero value) any properties in the supplied struct.
+// pruneProperties will prune (set to zero value) any properties in the struct referenced by the
+// supplied struct pointer.
//
// The struct must be of the same type as was originally passed to newPropertyPruner to create this
// propertyPruner.
func (p *propertyPruner) pruneProperties(propertiesStruct interface{}) {
+
+ defer func() {
+ if r := recover(); r != nil {
+ panic(fmt.Errorf("%s\n\tof container %#v", r, propertiesStruct))
+ }
+ }()
+
structValue := reflect.ValueOf(propertiesStruct)
for _, property := range p.properties {
property.prunerFunc(structValue)
@@ -292,6 +349,13 @@
// of properties.
func newPropertyPruner(propertiesStruct interface{}, selector fieldSelectorFunc) *propertyPruner {
structType := getStructValue(reflect.ValueOf(propertiesStruct)).Type()
+ return newPropertyPrunerForStructType(structType, selector)
+}
+
+// newPropertyPruner creates a new property pruner for the supplied properties struct type.
+//
+// The returned pruner can be used on any properties structure of the supplied type.
+func newPropertyPrunerForStructType(structType reflect.Type, selector fieldSelectorFunc) *propertyPruner {
pruner := &propertyPruner{}
pruner.gatherFields(structType, nil, "", selector)
return pruner
diff --git a/sdk/build_release_test.go b/sdk/build_release_test.go
index dff276d..6608be4 100644
--- a/sdk/build_release_test.go
+++ b/sdk/build_release_test.go
@@ -15,6 +15,7 @@
package sdk
import (
+ "encoding/json"
"fmt"
"testing"
@@ -125,61 +126,102 @@
F1_only string `supported_build_releases:"F1"`
}
+ type mapped struct {
+ Default string
+ T_only string `supported_build_releases:"T"`
+ }
+
type testBuildReleasePruner struct {
Default string
S_and_T_only string `supported_build_releases:"S-T"`
T_later string `supported_build_releases:"T+"`
Nested nested
+ Mapped map[string]*mapped
}
- input := testBuildReleasePruner{
- Default: "Default",
- S_and_T_only: "S_and_T_only",
- T_later: "T_later",
- Nested: nested{
- F1_only: "F1_only",
- },
+ inputFactory := func() testBuildReleasePruner {
+ return testBuildReleasePruner{
+ Default: "Default",
+ S_and_T_only: "S_and_T_only",
+ T_later: "T_later",
+ Nested: nested{
+ F1_only: "F1_only",
+ },
+ Mapped: map[string]*mapped{
+ "one": {
+ Default: "one-default",
+ T_only: "one-t-only",
+ },
+ "two": {
+ Default: "two-default",
+ T_only: "two-t-only",
+ },
+ },
+ }
+ }
+
+ marshal := func(t interface{}) string {
+ bytes, err := json.MarshalIndent(t, "", " ")
+ if err != nil {
+ panic(err)
+ }
+ return string(bytes)
+ }
+
+ assertJsonEquals := func(t *testing.T, expected, actual interface{}) {
+ t.Helper()
+ expectedJson := marshal(expected)
+ actualJson := marshal(actual)
+ if actualJson != expectedJson {
+ t.Errorf("test struct: expected:\n%s\n got:\n%s", expectedJson, actualJson)
+ }
}
t.Run("target S", func(t *testing.T) {
- testStruct := input
+ testStruct := inputFactory()
pruner := newPropertyPrunerByBuildRelease(&testStruct, buildReleaseS)
pruner.pruneProperties(&testStruct)
- expected := input
+ expected := inputFactory()
expected.T_later = ""
expected.Nested.F1_only = ""
- android.AssertDeepEquals(t, "test struct", expected, testStruct)
+ expected.Mapped["one"].T_only = ""
+ expected.Mapped["two"].T_only = ""
+ assertJsonEquals(t, expected, testStruct)
})
t.Run("target T", func(t *testing.T) {
- testStruct := input
+ testStruct := inputFactory()
pruner := newPropertyPrunerByBuildRelease(&testStruct, buildReleaseT)
pruner.pruneProperties(&testStruct)
- expected := input
+ expected := inputFactory()
expected.Nested.F1_only = ""
- android.AssertDeepEquals(t, "test struct", expected, testStruct)
+ assertJsonEquals(t, expected, testStruct)
})
t.Run("target F1", func(t *testing.T) {
- testStruct := input
+ testStruct := inputFactory()
pruner := newPropertyPrunerByBuildRelease(&testStruct, buildReleaseFuture1)
pruner.pruneProperties(&testStruct)
- expected := input
+ expected := inputFactory()
expected.S_and_T_only = ""
- android.AssertDeepEquals(t, "test struct", expected, testStruct)
+ expected.Mapped["one"].T_only = ""
+ expected.Mapped["two"].T_only = ""
+ assertJsonEquals(t, expected, testStruct)
})
t.Run("target F2", func(t *testing.T) {
- testStruct := input
+ testStruct := inputFactory()
pruner := newPropertyPrunerByBuildRelease(&testStruct, buildReleaseFuture2)
pruner.pruneProperties(&testStruct)
- expected := input
+ expected := inputFactory()
expected.S_and_T_only = ""
expected.Nested.F1_only = ""
- android.AssertDeepEquals(t, "test struct", expected, testStruct)
+ expected.Mapped["one"].T_only = ""
+ expected.Mapped["two"].T_only = ""
+ assertJsonEquals(t, expected, testStruct)
})
}
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index 0d9b4a0..f0d3b35 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -1319,6 +1319,58 @@
)
}
+func TestSnapshotWithJavaSdkLibrary_AnnotationsZip_PreT(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForSdkTestWithJavaSdkLibrary,
+ android.FixtureMergeEnv(map[string]string{
+ "SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE": "S",
+ }),
+ ).RunTestWithBp(t, `
+ sdk {
+ name: "mysdk",
+ java_sdk_libs: ["myjavalib"],
+ }
+
+ java_sdk_library {
+ name: "myjavalib",
+ srcs: ["Test.java"],
+ sdk_version: "current",
+ shared_library: false,
+ annotations_enabled: true,
+ public: {
+ enabled: true,
+ },
+ }
+ `)
+
+ CheckSnapshot(t, result, "mysdk", "",
+ checkUnversionedAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+java_sdk_library_import {
+ name: "myjavalib",
+ prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
+ shared_library: false,
+ public: {
+ jars: ["sdk_library/public/myjavalib-stubs.jar"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
+ current_api: "sdk_library/public/myjavalib.txt",
+ removed_api: "sdk_library/public/myjavalib-removed.txt",
+ sdk_version: "current",
+ },
+}
+ `),
+ checkAllCopyRules(`
+.intermediates/myjavalib.stubs/android_common/javac/myjavalib.stubs.jar -> sdk_library/public/myjavalib-stubs.jar
+.intermediates/myjavalib.stubs.source/android_common/metalava/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib.txt
+.intermediates/myjavalib.stubs.source/android_common/metalava/myjavalib.stubs.source_removed.txt -> sdk_library/public/myjavalib-removed.txt
+ `),
+ checkMergeZips(".intermediates/mysdk/common_os/tmp/sdk_library/public/myjavalib_stub_sources.zip"),
+ )
+}
+
func TestSnapshotWithJavaSdkLibrary_CompileDex(t *testing.T) {
result := android.GroupFixturePreparers(prepareForSdkTestWithJavaSdkLibrary).RunTestWithBp(t, `
sdk {
diff --git a/ui/build/cleanbuild.go b/ui/build/cleanbuild.go
index a3a1aaf..1c80cff 100644
--- a/ui/build/cleanbuild.go
+++ b/ui/build/cleanbuild.go
@@ -171,6 +171,7 @@
productOut("recovery"),
productOut("root"),
productOut("system"),
+ productOut("system_dlkm"),
productOut("system_other"),
productOut("vendor"),
productOut("vendor_dlkm"),