3576e769a4
Every module belonging to a single mainline module family will be hidden from make, except the one which has been flagged using apex_contributions Details - Introduce a new `source_apex_name` property to prebuilt_apex and override_apex. This property will be used to identify the source equivalent of a prebuilt soong apex module. - Create an N-ary tree from source to prebuilt(s). The tree wil be rooted at the source module. - In a subsequent mutator, visit every node in the tree(s). Query apex_contributions and store the handle of the node which is "active" (if any) - In the same mutator, do another pass over the tree. Invoke `HideFromMake` on every node which is not "active". The two-pass approach is needed PrebuiltSelectionInfoProvider does not know about the inter source-prebuilt dependency, this dependency can only be known by doing a graph walk of the N-ary tree. Some tangential implementation details - Each prebuilt apex has an internal deapxer module that is responsible for generating the deapex ninja rules. The name of this internal module uses the BaseModuleName (without the prebuilt_ prefix). Since we can have multiple prebuilt soong modules in trunk stable, change this to follow the name of the prebuilt module in order to avoid name collisions. Update existing unit tests accordingly Bug: 316179314 Test: go test ./apex -run TestInstallationRulesForMultipleApexPrebuilts Test: m nothing --no-skip-soong-tests Test: presubmits Change-Id: I58aa99d5e6a9859954614e6db9a8e9e2e581642d
454 lines
10 KiB
Go
454 lines
10 KiB
Go
// Copyright (C) 2021 The Android Open Source Project
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package apex
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
|
|
"android/soong/android"
|
|
"android/soong/dexpreopt"
|
|
"android/soong/java"
|
|
)
|
|
|
|
var prepareForTestWithSystemserverclasspathFragment = android.GroupFixturePreparers(
|
|
java.PrepareForTestWithDexpreopt,
|
|
PrepareForTestWithApexBuildComponents,
|
|
)
|
|
|
|
func TestSystemserverclasspathFragmentContents(t *testing.T) {
|
|
result := android.GroupFixturePreparers(
|
|
prepareForTestWithSystemserverclasspathFragment,
|
|
prepareForTestWithMyapex,
|
|
dexpreopt.FixtureSetApexSystemServerJars("myapex:foo", "myapex:bar", "myapex:baz"),
|
|
).RunTestWithBp(t, `
|
|
apex {
|
|
name: "myapex",
|
|
key: "myapex.key",
|
|
systemserverclasspath_fragments: [
|
|
"mysystemserverclasspathfragment",
|
|
],
|
|
updatable: false,
|
|
}
|
|
|
|
apex_key {
|
|
name: "myapex.key",
|
|
public_key: "testkey.avbpubkey",
|
|
private_key: "testkey.pem",
|
|
}
|
|
|
|
java_library {
|
|
name: "foo",
|
|
srcs: ["b.java"],
|
|
installable: true,
|
|
apex_available: [
|
|
"myapex",
|
|
],
|
|
}
|
|
|
|
java_library {
|
|
name: "bar",
|
|
srcs: ["c.java"],
|
|
installable: true,
|
|
dex_preopt: {
|
|
profile: "bar-art-profile",
|
|
},
|
|
apex_available: [
|
|
"myapex",
|
|
],
|
|
}
|
|
|
|
java_library {
|
|
name: "baz",
|
|
srcs: ["d.java"],
|
|
installable: true,
|
|
dex_preopt: {
|
|
profile_guided: true, // ignored
|
|
},
|
|
apex_available: [
|
|
"myapex",
|
|
],
|
|
}
|
|
|
|
systemserverclasspath_fragment {
|
|
name: "mysystemserverclasspathfragment",
|
|
contents: [
|
|
"foo",
|
|
"bar",
|
|
"baz",
|
|
],
|
|
apex_available: [
|
|
"myapex",
|
|
],
|
|
}
|
|
`)
|
|
|
|
ctx := result.TestContext
|
|
|
|
ensureExactContents(t, ctx, "myapex", "android_common_myapex", []string{
|
|
"etc/classpaths/systemserverclasspath.pb",
|
|
"javalib/foo.jar",
|
|
"javalib/bar.jar",
|
|
"javalib/bar.jar.prof",
|
|
"javalib/baz.jar",
|
|
})
|
|
|
|
java.CheckModuleDependencies(t, ctx, "myapex", "android_common_myapex", []string{
|
|
`myapex.key`,
|
|
`mysystemserverclasspathfragment`,
|
|
})
|
|
|
|
assertProfileGuided(t, ctx, "foo", "android_common_apex10000", false)
|
|
assertProfileGuided(t, ctx, "bar", "android_common_apex10000", true)
|
|
assertProfileGuided(t, ctx, "baz", "android_common_apex10000", false)
|
|
}
|
|
|
|
func TestSystemserverclasspathFragmentNoGeneratedProto(t *testing.T) {
|
|
result := android.GroupFixturePreparers(
|
|
prepareForTestWithSystemserverclasspathFragment,
|
|
prepareForTestWithMyapex,
|
|
dexpreopt.FixtureSetApexSystemServerJars("myapex:foo"),
|
|
).RunTestWithBp(t, `
|
|
apex {
|
|
name: "myapex",
|
|
key: "myapex.key",
|
|
systemserverclasspath_fragments: [
|
|
"mysystemserverclasspathfragment",
|
|
],
|
|
updatable: false,
|
|
}
|
|
|
|
apex_key {
|
|
name: "myapex.key",
|
|
public_key: "testkey.avbpubkey",
|
|
private_key: "testkey.pem",
|
|
}
|
|
|
|
java_library {
|
|
name: "foo",
|
|
srcs: ["b.java"],
|
|
installable: true,
|
|
apex_available: [
|
|
"myapex",
|
|
],
|
|
}
|
|
|
|
systemserverclasspath_fragment {
|
|
name: "mysystemserverclasspathfragment",
|
|
generate_classpaths_proto: false,
|
|
contents: [
|
|
"foo",
|
|
],
|
|
apex_available: [
|
|
"myapex",
|
|
],
|
|
}
|
|
`)
|
|
|
|
ensureExactContents(t, result.TestContext, "myapex", "android_common_myapex", []string{
|
|
"javalib/foo.jar",
|
|
})
|
|
|
|
java.CheckModuleDependencies(t, result.TestContext, "myapex", "android_common_myapex", []string{
|
|
`myapex.key`,
|
|
`mysystemserverclasspathfragment`,
|
|
})
|
|
}
|
|
|
|
func TestSystemServerClasspathFragmentWithContentNotInMake(t *testing.T) {
|
|
android.GroupFixturePreparers(
|
|
prepareForTestWithSystemserverclasspathFragment,
|
|
prepareForTestWithMyapex,
|
|
dexpreopt.FixtureSetApexSystemServerJars("myapex:foo"),
|
|
).
|
|
ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
|
|
`in contents must also be declared in PRODUCT_APEX_SYSTEM_SERVER_JARS`)).
|
|
RunTestWithBp(t, `
|
|
apex {
|
|
name: "myapex",
|
|
key: "myapex.key",
|
|
systemserverclasspath_fragments: [
|
|
"mysystemserverclasspathfragment",
|
|
],
|
|
updatable: false,
|
|
}
|
|
|
|
apex_key {
|
|
name: "myapex.key",
|
|
public_key: "testkey.avbpubkey",
|
|
private_key: "testkey.pem",
|
|
}
|
|
|
|
java_library {
|
|
name: "foo",
|
|
srcs: ["b.java"],
|
|
installable: true,
|
|
apex_available: ["myapex"],
|
|
}
|
|
|
|
java_library {
|
|
name: "bar",
|
|
srcs: ["b.java"],
|
|
installable: true,
|
|
apex_available: ["myapex"],
|
|
}
|
|
|
|
systemserverclasspath_fragment {
|
|
name: "mysystemserverclasspathfragment",
|
|
contents: [
|
|
"foo",
|
|
"bar",
|
|
],
|
|
apex_available: [
|
|
"myapex",
|
|
],
|
|
}
|
|
`)
|
|
}
|
|
|
|
func TestPrebuiltSystemserverclasspathFragmentContents(t *testing.T) {
|
|
result := android.GroupFixturePreparers(
|
|
prepareForTestWithSystemserverclasspathFragment,
|
|
prepareForTestWithMyapex,
|
|
dexpreopt.FixtureSetApexSystemServerJars("myapex:foo", "myapex:bar"),
|
|
).RunTestWithBp(t, `
|
|
prebuilt_apex {
|
|
name: "myapex",
|
|
arch: {
|
|
arm64: {
|
|
src: "myapex-arm64.apex",
|
|
},
|
|
arm: {
|
|
src: "myapex-arm.apex",
|
|
},
|
|
},
|
|
exported_systemserverclasspath_fragments: ["mysystemserverclasspathfragment"],
|
|
}
|
|
|
|
java_import {
|
|
name: "foo",
|
|
jars: ["foo.jar"],
|
|
apex_available: [
|
|
"myapex",
|
|
],
|
|
}
|
|
|
|
java_import {
|
|
name: "bar",
|
|
jars: ["bar.jar"],
|
|
dex_preopt: {
|
|
profile_guided: true,
|
|
},
|
|
apex_available: [
|
|
"myapex",
|
|
],
|
|
}
|
|
|
|
prebuilt_systemserverclasspath_fragment {
|
|
name: "mysystemserverclasspathfragment",
|
|
prefer: true,
|
|
contents: [
|
|
"foo",
|
|
"bar",
|
|
],
|
|
apex_available: [
|
|
"myapex",
|
|
],
|
|
}
|
|
`)
|
|
|
|
ctx := result.TestContext
|
|
|
|
java.CheckModuleDependencies(t, ctx, "myapex", "android_common_myapex", []string{
|
|
`dex2oatd`,
|
|
`prebuilt_myapex.apex.selector`,
|
|
`prebuilt_myapex.deapexer`,
|
|
`prebuilt_mysystemserverclasspathfragment`,
|
|
})
|
|
|
|
java.CheckModuleDependencies(t, ctx, "mysystemserverclasspathfragment", "android_common_myapex", []string{
|
|
`prebuilt_bar`,
|
|
`prebuilt_foo`,
|
|
`prebuilt_myapex.deapexer`,
|
|
})
|
|
|
|
ensureExactDeapexedContents(t, ctx, "prebuilt_myapex", "android_common", []string{
|
|
"javalib/foo.jar",
|
|
"javalib/bar.jar",
|
|
"javalib/bar.jar.prof",
|
|
})
|
|
|
|
assertProfileGuided(t, ctx, "foo", "android_common_myapex", false)
|
|
assertProfileGuided(t, ctx, "bar", "android_common_myapex", true)
|
|
}
|
|
|
|
func TestSystemserverclasspathFragmentStandaloneContents(t *testing.T) {
|
|
result := android.GroupFixturePreparers(
|
|
prepareForTestWithSystemserverclasspathFragment,
|
|
prepareForTestWithMyapex,
|
|
dexpreopt.FixtureSetApexStandaloneSystemServerJars("myapex:foo", "myapex:bar", "myapex:baz"),
|
|
).RunTestWithBp(t, `
|
|
apex {
|
|
name: "myapex",
|
|
key: "myapex.key",
|
|
systemserverclasspath_fragments: [
|
|
"mysystemserverclasspathfragment",
|
|
],
|
|
updatable: false,
|
|
}
|
|
|
|
apex_key {
|
|
name: "myapex.key",
|
|
public_key: "testkey.avbpubkey",
|
|
private_key: "testkey.pem",
|
|
}
|
|
|
|
java_library {
|
|
name: "foo",
|
|
srcs: ["b.java"],
|
|
installable: true,
|
|
apex_available: [
|
|
"myapex",
|
|
],
|
|
}
|
|
|
|
java_library {
|
|
name: "bar",
|
|
srcs: ["c.java"],
|
|
dex_preopt: {
|
|
profile: "bar-art-profile",
|
|
},
|
|
installable: true,
|
|
apex_available: [
|
|
"myapex",
|
|
],
|
|
}
|
|
|
|
java_library {
|
|
name: "baz",
|
|
srcs: ["d.java"],
|
|
dex_preopt: {
|
|
profile_guided: true, // ignored
|
|
},
|
|
installable: true,
|
|
apex_available: [
|
|
"myapex",
|
|
],
|
|
}
|
|
|
|
systemserverclasspath_fragment {
|
|
name: "mysystemserverclasspathfragment",
|
|
standalone_contents: [
|
|
"foo",
|
|
"bar",
|
|
"baz",
|
|
],
|
|
apex_available: [
|
|
"myapex",
|
|
],
|
|
}
|
|
`)
|
|
|
|
ctx := result.TestContext
|
|
|
|
ensureExactContents(t, ctx, "myapex", "android_common_myapex", []string{
|
|
"etc/classpaths/systemserverclasspath.pb",
|
|
"javalib/foo.jar",
|
|
"javalib/bar.jar",
|
|
"javalib/bar.jar.prof",
|
|
"javalib/baz.jar",
|
|
})
|
|
|
|
assertProfileGuided(t, ctx, "foo", "android_common_apex10000", false)
|
|
assertProfileGuided(t, ctx, "bar", "android_common_apex10000", true)
|
|
assertProfileGuided(t, ctx, "baz", "android_common_apex10000", false)
|
|
}
|
|
|
|
func TestPrebuiltStandaloneSystemserverclasspathFragmentContents(t *testing.T) {
|
|
result := android.GroupFixturePreparers(
|
|
prepareForTestWithSystemserverclasspathFragment,
|
|
prepareForTestWithMyapex,
|
|
dexpreopt.FixtureSetApexStandaloneSystemServerJars("myapex:foo", "myapex:bar"),
|
|
).RunTestWithBp(t, `
|
|
prebuilt_apex {
|
|
name: "myapex",
|
|
arch: {
|
|
arm64: {
|
|
src: "myapex-arm64.apex",
|
|
},
|
|
arm: {
|
|
src: "myapex-arm.apex",
|
|
},
|
|
},
|
|
exported_systemserverclasspath_fragments: ["mysystemserverclasspathfragment"],
|
|
}
|
|
|
|
java_import {
|
|
name: "foo",
|
|
jars: ["foo.jar"],
|
|
apex_available: [
|
|
"myapex",
|
|
],
|
|
}
|
|
|
|
java_import {
|
|
name: "bar",
|
|
jars: ["bar.jar"],
|
|
dex_preopt: {
|
|
profile_guided: true,
|
|
},
|
|
apex_available: [
|
|
"myapex",
|
|
],
|
|
}
|
|
|
|
prebuilt_systemserverclasspath_fragment {
|
|
name: "mysystemserverclasspathfragment",
|
|
prefer: true,
|
|
standalone_contents: [
|
|
"foo",
|
|
"bar",
|
|
],
|
|
apex_available: [
|
|
"myapex",
|
|
],
|
|
}
|
|
`)
|
|
|
|
ctx := result.TestContext
|
|
|
|
java.CheckModuleDependencies(t, ctx, "mysystemserverclasspathfragment", "android_common_myapex", []string{
|
|
`prebuilt_bar`,
|
|
`prebuilt_foo`,
|
|
`prebuilt_myapex.deapexer`,
|
|
})
|
|
|
|
ensureExactDeapexedContents(t, ctx, "prebuilt_myapex", "android_common", []string{
|
|
"javalib/foo.jar",
|
|
"javalib/bar.jar",
|
|
"javalib/bar.jar.prof",
|
|
})
|
|
|
|
assertProfileGuided(t, ctx, "foo", "android_common_myapex", false)
|
|
assertProfileGuided(t, ctx, "bar", "android_common_myapex", true)
|
|
}
|
|
|
|
func assertProfileGuided(t *testing.T, ctx *android.TestContext, moduleName string, variant string, expected bool) {
|
|
dexpreopt := ctx.ModuleForTests(moduleName, variant).Rule("dexpreopt")
|
|
actual := strings.Contains(dexpreopt.RuleParams.Command, "--profile-file=")
|
|
if expected != actual {
|
|
t.Fatalf("Expected profile-guided to be %v, got %v", expected, actual)
|
|
}
|
|
}
|