Loading android/deapexer.go +41 −2 Original line number Diff line number Diff line Loading @@ -15,6 +15,8 @@ package android import ( "strings" "github.com/google/blueprint" ) Loading Loading @@ -148,12 +150,19 @@ type RequiresFilesFromPrebuiltApexTag interface { func FindDeapexerProviderForModule(ctx ModuleContext) *DeapexerInfo { var di *DeapexerInfo ctx.VisitDirectDepsWithTag(DeapexerTag, func(m Module) { p := ctx.OtherModuleProvider(m, DeapexerProvider).(DeapexerInfo) c := ctx.OtherModuleProvider(m, DeapexerProvider).(DeapexerInfo) p := &c if di != nil { // If two DeapexerInfo providers have been found then check if they are // equivalent. If they are then use the selected one, otherwise fail. if selected := equivalentDeapexerInfoProviders(di, p); selected != nil { di = selected return } ctx.ModuleErrorf("Multiple installable prebuilt APEXes provide ambiguous deapexers: %s and %s", di.ApexModuleName(), p.ApexModuleName()) } di = &p di = p }) if di != nil { return di Loading @@ -162,3 +171,33 @@ func FindDeapexerProviderForModule(ctx ModuleContext) *DeapexerInfo { ctx.ModuleErrorf("No prebuilt APEX provides a deapexer module for APEX variant %s", ai.ApexVariationName) return nil } // removeCompressedApexSuffix removes the _compressed suffix from the name if present. func removeCompressedApexSuffix(name string) string { return strings.TrimSuffix(name, "_compressed") } // equivalentDeapexerInfoProviders checks to make sure that the two DeapexerInfo structures are // equivalent. // // At the moment <x> and <x>_compressed APEXes are treated as being equivalent. // // If they are not equivalent then this returns nil, otherwise, this returns the DeapexerInfo that // should be used by the build, which is always the uncompressed one. That ensures that the behavior // of the build is not dependent on which prebuilt APEX is visited first. func equivalentDeapexerInfoProviders(p1 *DeapexerInfo, p2 *DeapexerInfo) *DeapexerInfo { n1 := removeCompressedApexSuffix(p1.ApexModuleName()) n2 := removeCompressedApexSuffix(p2.ApexModuleName()) // If the names don't match then they are not equivalent. if n1 != n2 { return nil } // Select the uncompressed APEX. if n1 == removeCompressedApexSuffix(n1) { return p1 } else { return p2 } } apex/apex_test.go +102 −1 Original line number Diff line number Diff line Loading @@ -7428,7 +7428,7 @@ func testDexpreoptWithApexes(t *testing.T, bp, errmsg string, preparer android.F return result.TestContext } func TestDuplicateDeapexeresFromPrebuiltApexes(t *testing.T) { func TestDuplicateDeapexersFromPrebuiltApexes(t *testing.T) { preparers := android.GroupFixturePreparers( java.PrepareForTestWithJavaDefaultModules, PrepareForTestWithApexBuildComponents, Loading Loading @@ -7497,6 +7497,107 @@ func TestDuplicateDeapexeresFromPrebuiltApexes(t *testing.T) { }) } func TestDuplicateButEquivalentDeapexersFromPrebuiltApexes(t *testing.T) { preparers := android.GroupFixturePreparers( java.PrepareForTestWithJavaDefaultModules, PrepareForTestWithApexBuildComponents, ) bpBase := ` apex_set { name: "com.android.myapex", installable: true, exported_bootclasspath_fragments: ["my-bootclasspath-fragment"], set: "myapex.apks", } apex_set { name: "com.android.myapex_compressed", apex_name: "com.android.myapex", installable: true, exported_bootclasspath_fragments: ["my-bootclasspath-fragment"], set: "myapex_compressed.apks", } prebuilt_bootclasspath_fragment { name: "my-bootclasspath-fragment", apex_available: [ "com.android.myapex", "com.android.myapex_compressed", ], hidden_api: { annotation_flags: "annotation-flags.csv", metadata: "metadata.csv", index: "index.csv", signature_patterns: "signature_patterns.csv", }, %s } ` t.Run("java_import", func(t *testing.T) { result := preparers.RunTestWithBp(t, fmt.Sprintf(bpBase, `contents: ["libfoo"]`)+` java_import { name: "libfoo", jars: ["libfoo.jar"], apex_available: [ "com.android.myapex", "com.android.myapex_compressed", ], } `) module := result.Module("libfoo", "android_common_com.android.myapex") usesLibraryDep := module.(java.UsesLibraryDependency) android.AssertPathRelativeToTopEquals(t, "dex jar path", "out/soong/.intermediates/com.android.myapex.deapexer/android_common/deapexer/javalib/libfoo.jar", usesLibraryDep.DexJarBuildPath().Path()) }) t.Run("java_sdk_library_import", func(t *testing.T) { result := preparers.RunTestWithBp(t, fmt.Sprintf(bpBase, `contents: ["libfoo"]`)+` java_sdk_library_import { name: "libfoo", public: { jars: ["libbar.jar"], }, apex_available: [ "com.android.myapex", "com.android.myapex_compressed", ], compile_dex: true, } `) module := result.Module("libfoo", "android_common_com.android.myapex") usesLibraryDep := module.(java.UsesLibraryDependency) android.AssertPathRelativeToTopEquals(t, "dex jar path", "out/soong/.intermediates/com.android.myapex.deapexer/android_common/deapexer/javalib/libfoo.jar", usesLibraryDep.DexJarBuildPath().Path()) }) t.Run("prebuilt_bootclasspath_fragment", func(t *testing.T) { _ = preparers.RunTestWithBp(t, fmt.Sprintf(bpBase, ` image_name: "art", contents: ["libfoo"], `)+` java_sdk_library_import { name: "libfoo", public: { jars: ["libbar.jar"], }, apex_available: [ "com.android.myapex", "com.android.myapex_compressed", ], compile_dex: true, } `) }) } func TestUpdatable_should_set_min_sdk_version(t *testing.T) { testApexError(t, `"myapex" .*: updatable: updatable APEXes should set min_sdk_version`, ` apex { Loading Loading
android/deapexer.go +41 −2 Original line number Diff line number Diff line Loading @@ -15,6 +15,8 @@ package android import ( "strings" "github.com/google/blueprint" ) Loading Loading @@ -148,12 +150,19 @@ type RequiresFilesFromPrebuiltApexTag interface { func FindDeapexerProviderForModule(ctx ModuleContext) *DeapexerInfo { var di *DeapexerInfo ctx.VisitDirectDepsWithTag(DeapexerTag, func(m Module) { p := ctx.OtherModuleProvider(m, DeapexerProvider).(DeapexerInfo) c := ctx.OtherModuleProvider(m, DeapexerProvider).(DeapexerInfo) p := &c if di != nil { // If two DeapexerInfo providers have been found then check if they are // equivalent. If they are then use the selected one, otherwise fail. if selected := equivalentDeapexerInfoProviders(di, p); selected != nil { di = selected return } ctx.ModuleErrorf("Multiple installable prebuilt APEXes provide ambiguous deapexers: %s and %s", di.ApexModuleName(), p.ApexModuleName()) } di = &p di = p }) if di != nil { return di Loading @@ -162,3 +171,33 @@ func FindDeapexerProviderForModule(ctx ModuleContext) *DeapexerInfo { ctx.ModuleErrorf("No prebuilt APEX provides a deapexer module for APEX variant %s", ai.ApexVariationName) return nil } // removeCompressedApexSuffix removes the _compressed suffix from the name if present. func removeCompressedApexSuffix(name string) string { return strings.TrimSuffix(name, "_compressed") } // equivalentDeapexerInfoProviders checks to make sure that the two DeapexerInfo structures are // equivalent. // // At the moment <x> and <x>_compressed APEXes are treated as being equivalent. // // If they are not equivalent then this returns nil, otherwise, this returns the DeapexerInfo that // should be used by the build, which is always the uncompressed one. That ensures that the behavior // of the build is not dependent on which prebuilt APEX is visited first. func equivalentDeapexerInfoProviders(p1 *DeapexerInfo, p2 *DeapexerInfo) *DeapexerInfo { n1 := removeCompressedApexSuffix(p1.ApexModuleName()) n2 := removeCompressedApexSuffix(p2.ApexModuleName()) // If the names don't match then they are not equivalent. if n1 != n2 { return nil } // Select the uncompressed APEX. if n1 == removeCompressedApexSuffix(n1) { return p1 } else { return p2 } }
apex/apex_test.go +102 −1 Original line number Diff line number Diff line Loading @@ -7428,7 +7428,7 @@ func testDexpreoptWithApexes(t *testing.T, bp, errmsg string, preparer android.F return result.TestContext } func TestDuplicateDeapexeresFromPrebuiltApexes(t *testing.T) { func TestDuplicateDeapexersFromPrebuiltApexes(t *testing.T) { preparers := android.GroupFixturePreparers( java.PrepareForTestWithJavaDefaultModules, PrepareForTestWithApexBuildComponents, Loading Loading @@ -7497,6 +7497,107 @@ func TestDuplicateDeapexeresFromPrebuiltApexes(t *testing.T) { }) } func TestDuplicateButEquivalentDeapexersFromPrebuiltApexes(t *testing.T) { preparers := android.GroupFixturePreparers( java.PrepareForTestWithJavaDefaultModules, PrepareForTestWithApexBuildComponents, ) bpBase := ` apex_set { name: "com.android.myapex", installable: true, exported_bootclasspath_fragments: ["my-bootclasspath-fragment"], set: "myapex.apks", } apex_set { name: "com.android.myapex_compressed", apex_name: "com.android.myapex", installable: true, exported_bootclasspath_fragments: ["my-bootclasspath-fragment"], set: "myapex_compressed.apks", } prebuilt_bootclasspath_fragment { name: "my-bootclasspath-fragment", apex_available: [ "com.android.myapex", "com.android.myapex_compressed", ], hidden_api: { annotation_flags: "annotation-flags.csv", metadata: "metadata.csv", index: "index.csv", signature_patterns: "signature_patterns.csv", }, %s } ` t.Run("java_import", func(t *testing.T) { result := preparers.RunTestWithBp(t, fmt.Sprintf(bpBase, `contents: ["libfoo"]`)+` java_import { name: "libfoo", jars: ["libfoo.jar"], apex_available: [ "com.android.myapex", "com.android.myapex_compressed", ], } `) module := result.Module("libfoo", "android_common_com.android.myapex") usesLibraryDep := module.(java.UsesLibraryDependency) android.AssertPathRelativeToTopEquals(t, "dex jar path", "out/soong/.intermediates/com.android.myapex.deapexer/android_common/deapexer/javalib/libfoo.jar", usesLibraryDep.DexJarBuildPath().Path()) }) t.Run("java_sdk_library_import", func(t *testing.T) { result := preparers.RunTestWithBp(t, fmt.Sprintf(bpBase, `contents: ["libfoo"]`)+` java_sdk_library_import { name: "libfoo", public: { jars: ["libbar.jar"], }, apex_available: [ "com.android.myapex", "com.android.myapex_compressed", ], compile_dex: true, } `) module := result.Module("libfoo", "android_common_com.android.myapex") usesLibraryDep := module.(java.UsesLibraryDependency) android.AssertPathRelativeToTopEquals(t, "dex jar path", "out/soong/.intermediates/com.android.myapex.deapexer/android_common/deapexer/javalib/libfoo.jar", usesLibraryDep.DexJarBuildPath().Path()) }) t.Run("prebuilt_bootclasspath_fragment", func(t *testing.T) { _ = preparers.RunTestWithBp(t, fmt.Sprintf(bpBase, ` image_name: "art", contents: ["libfoo"], `)+` java_sdk_library_import { name: "libfoo", public: { jars: ["libbar.jar"], }, apex_available: [ "com.android.myapex", "com.android.myapex_compressed", ], compile_dex: true, } `) }) } func TestUpdatable_should_set_min_sdk_version(t *testing.T) { testApexError(t, `"myapex" .*: updatable: updatable APEXes should set min_sdk_version`, ` apex { Loading