Merge "rust modules can be included in apex" am: fdea25781f
Original change: https://android-review.googlesource.com/c/platform/build/soong/+/1508096 Change-Id: I0e33459ce8207779367bdf6b3abee79718f8adba
This commit is contained in:
commit
88365d1894
11 changed files with 177 additions and 11 deletions
|
@ -75,6 +75,10 @@ toolchain_library {
|
|||
product_available: true,
|
||||
recovery_available: true,
|
||||
native_bridge_supported: true,
|
||||
apex_available: [
|
||||
"//apex_available:platform",
|
||||
"//apex_available:anyapex",
|
||||
],
|
||||
|
||||
arch: {
|
||||
arm: {
|
||||
|
|
|
@ -9,6 +9,7 @@ bootstrap_go_package {
|
|||
"soong-cc",
|
||||
"soong-java",
|
||||
"soong-python",
|
||||
"soong-rust",
|
||||
"soong-sh",
|
||||
],
|
||||
srcs: [
|
||||
|
|
52
apex/apex.go
52
apex/apex.go
|
@ -32,6 +32,7 @@ import (
|
|||
prebuilt_etc "android/soong/etc"
|
||||
"android/soong/java"
|
||||
"android/soong/python"
|
||||
"android/soong/rust"
|
||||
"android/soong/sh"
|
||||
)
|
||||
|
||||
|
@ -179,6 +180,9 @@ type ApexNativeDependencies struct {
|
|||
// List of JNI libraries that are embedded inside this APEX.
|
||||
Jni_libs []string
|
||||
|
||||
// List of rust dyn libraries
|
||||
Rust_dyn_libs []string
|
||||
|
||||
// List of native executables that are embedded inside this APEX.
|
||||
Binaries []string
|
||||
|
||||
|
@ -511,13 +515,15 @@ var (
|
|||
func addDependenciesForNativeModules(ctx android.BottomUpMutatorContext, nativeModules ApexNativeDependencies, target android.Target, imageVariation string) {
|
||||
binVariations := target.Variations()
|
||||
libVariations := append(target.Variations(), blueprint.Variation{Mutator: "link", Variation: "shared"})
|
||||
rustLibVariations := append(target.Variations(), blueprint.Variation{Mutator: "rust_libraries", Variation: "dylib"})
|
||||
|
||||
if ctx.Device() {
|
||||
binVariations = append(binVariations, blueprint.Variation{Mutator: "image", Variation: imageVariation})
|
||||
libVariations = append(libVariations,
|
||||
blueprint.Variation{Mutator: "image", Variation: imageVariation},
|
||||
blueprint.Variation{Mutator: "version", Variation: ""}, // "" is the non-stub variant
|
||||
)
|
||||
blueprint.Variation{Mutator: "version", Variation: ""}) // "" is the non-stub variant
|
||||
rustLibVariations = append(rustLibVariations,
|
||||
blueprint.Variation{Mutator: "image", Variation: imageVariation})
|
||||
}
|
||||
|
||||
// Use *FarVariation* to be able to depend on modules having conflicting variations with
|
||||
|
@ -527,6 +533,7 @@ func addDependenciesForNativeModules(ctx android.BottomUpMutatorContext, nativeM
|
|||
ctx.AddFarVariationDependencies(binVariations, testTag, nativeModules.Tests...)
|
||||
ctx.AddFarVariationDependencies(libVariations, jniLibTag, nativeModules.Jni_libs...)
|
||||
ctx.AddFarVariationDependencies(libVariations, sharedLibTag, nativeModules.Native_shared_libs...)
|
||||
ctx.AddFarVariationDependencies(rustLibVariations, sharedLibTag, nativeModules.Rust_dyn_libs...)
|
||||
}
|
||||
|
||||
func (a *apexBundle) combineProperties(ctx android.BottomUpMutatorContext) {
|
||||
|
@ -1263,6 +1270,35 @@ func apexFileForExecutable(ctx android.BaseModuleContext, cc *cc.Module) apexFil
|
|||
return af
|
||||
}
|
||||
|
||||
func apexFileForRustExecutable(ctx android.BaseModuleContext, rustm *rust.Module) apexFile {
|
||||
dirInApex := "bin"
|
||||
if rustm.Target().NativeBridge == android.NativeBridgeEnabled {
|
||||
dirInApex = filepath.Join(dirInApex, rustm.Target().NativeBridgeRelativePath)
|
||||
}
|
||||
fileToCopy := rustm.OutputFile().Path()
|
||||
androidMkModuleName := rustm.BaseModuleName() + rustm.Properties.SubName
|
||||
af := newApexFile(ctx, fileToCopy, androidMkModuleName, dirInApex, nativeExecutable, rustm)
|
||||
return af
|
||||
}
|
||||
|
||||
func apexFileForRustLibrary(ctx android.BaseModuleContext, rustm *rust.Module) apexFile {
|
||||
// Decide the APEX-local directory by the multilib of the library
|
||||
// In the future, we may query this to the module.
|
||||
var dirInApex string
|
||||
switch rustm.Arch().ArchType.Multilib {
|
||||
case "lib32":
|
||||
dirInApex = "lib"
|
||||
case "lib64":
|
||||
dirInApex = "lib64"
|
||||
}
|
||||
if rustm.Target().NativeBridge == android.NativeBridgeEnabled {
|
||||
dirInApex = filepath.Join(dirInApex, rustm.Target().NativeBridgeRelativePath)
|
||||
}
|
||||
fileToCopy := rustm.OutputFile().Path()
|
||||
androidMkModuleName := rustm.BaseModuleName() + rustm.Properties.SubName
|
||||
return newApexFile(ctx, fileToCopy, androidMkModuleName, dirInApex, nativeSharedLib, rustm)
|
||||
}
|
||||
|
||||
func apexFileForPyBinary(ctx android.BaseModuleContext, py *python.Module) apexFile {
|
||||
dirInApex := "bin"
|
||||
fileToCopy := py.HostToolPath().Path()
|
||||
|
@ -1500,8 +1536,11 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
|||
filesInfo = append(filesInfo, apexFileForPyBinary(ctx, py))
|
||||
} else if gb, ok := child.(bootstrap.GoBinaryTool); ok && a.Host() {
|
||||
filesInfo = append(filesInfo, apexFileForGoBinary(ctx, depName, gb))
|
||||
} else if rust, ok := child.(*rust.Module); ok {
|
||||
filesInfo = append(filesInfo, apexFileForRustExecutable(ctx, rust))
|
||||
return true // track transitive dependencies
|
||||
} else {
|
||||
ctx.PropertyErrorf("binaries", "%q is neither cc_binary, (embedded) py_binary, (host) blueprint_go_binary, (host) bootstrap_go_binary, nor sh_binary", depName)
|
||||
ctx.PropertyErrorf("binaries", "%q is neither cc_binary, rust_binary, (embedded) py_binary, (host) blueprint_go_binary, (host) bootstrap_go_binary, nor sh_binary", depName)
|
||||
}
|
||||
case javaLibTag:
|
||||
switch child.(type) {
|
||||
|
@ -1662,6 +1701,13 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
|||
if prebuilt, ok := child.(prebuilt_etc.PrebuiltEtcModule); ok {
|
||||
filesInfo = append(filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, depName))
|
||||
}
|
||||
} else if rust.IsDylibDepTag(depTag) {
|
||||
if rustm, ok := child.(*rust.Module); ok && rustm.IsInstallableToApex() {
|
||||
af := apexFileForRustLibrary(ctx, rustm)
|
||||
af.transitiveDep = true
|
||||
filesInfo = append(filesInfo, af)
|
||||
return true // track transitive dependencies
|
||||
}
|
||||
} else if _, ok := depTag.(android.CopyDirectlyInAnyApexTag); ok {
|
||||
// nothing
|
||||
} else if am.CanHaveApexVariants() && am.IsInstallableToApex() {
|
||||
|
|
|
@ -32,6 +32,7 @@ import (
|
|||
"android/soong/dexpreopt"
|
||||
prebuilt_etc "android/soong/etc"
|
||||
"android/soong/java"
|
||||
"android/soong/rust"
|
||||
"android/soong/sh"
|
||||
)
|
||||
|
||||
|
@ -136,6 +137,8 @@ func testApexContext(_ *testing.T, bp string, handlers ...testCustomizer) (*andr
|
|||
|
||||
bp = bp + cc.GatherRequiredDepsForTest(android.Android)
|
||||
|
||||
bp = bp + rust.GatherRequiredDepsForTest()
|
||||
|
||||
bp = bp + java.GatherRequiredDepsForTest()
|
||||
|
||||
fs := map[string][]byte{
|
||||
|
@ -185,6 +188,7 @@ func testApexContext(_ *testing.T, bp string, handlers ...testCustomizer) (*andr
|
|||
"bar/baz": nil,
|
||||
"testdata/baz": nil,
|
||||
"AppSet.apks": nil,
|
||||
"foo.rs": nil,
|
||||
}
|
||||
|
||||
cc.GatherRequiredFilesForTest(fs)
|
||||
|
@ -241,6 +245,7 @@ func testApexContext(_ *testing.T, bp string, handlers ...testCustomizer) (*andr
|
|||
ctx.PostDepsMutators(android.RegisterVisibilityRuleEnforcer)
|
||||
|
||||
cc.RegisterRequiredBuildComponentsForTest(ctx)
|
||||
rust.RegisterRequiredBuildComponentsForTest(ctx)
|
||||
|
||||
ctx.RegisterModuleType("cc_test", cc.TestFactory)
|
||||
ctx.RegisterModuleType("vndk_prebuilt_shared", cc.VndkPrebuiltSharedFactory)
|
||||
|
@ -349,10 +354,12 @@ func TestBasicApex(t *testing.T) {
|
|||
manifest: ":myapex.manifest",
|
||||
androidManifest: ":myapex.androidmanifest",
|
||||
key: "myapex.key",
|
||||
binaries: ["foo.rust"],
|
||||
native_shared_libs: ["mylib"],
|
||||
rust_dyn_libs: ["libfoo.dylib.rust"],
|
||||
multilib: {
|
||||
both: {
|
||||
binaries: ["foo",],
|
||||
binaries: ["foo"],
|
||||
}
|
||||
},
|
||||
java_libs: [
|
||||
|
@ -415,6 +422,28 @@ func TestBasicApex(t *testing.T) {
|
|||
apex_available: [ "myapex", "com.android.gki.*" ],
|
||||
}
|
||||
|
||||
rust_binary {
|
||||
name: "foo.rust",
|
||||
srcs: ["foo.rs"],
|
||||
rlibs: ["libfoo.rlib.rust"],
|
||||
dylibs: ["libfoo.dylib.rust"],
|
||||
apex_available: ["myapex"],
|
||||
}
|
||||
|
||||
rust_library_rlib {
|
||||
name: "libfoo.rlib.rust",
|
||||
srcs: ["foo.rs"],
|
||||
crate_name: "foo",
|
||||
apex_available: ["myapex"],
|
||||
}
|
||||
|
||||
rust_library_dylib {
|
||||
name: "libfoo.dylib.rust",
|
||||
srcs: ["foo.rs"],
|
||||
crate_name: "foo",
|
||||
apex_available: ["myapex"],
|
||||
}
|
||||
|
||||
apex {
|
||||
name: "com.android.gki.fake",
|
||||
binaries: ["foo"],
|
||||
|
@ -529,16 +558,20 @@ func TestBasicApex(t *testing.T) {
|
|||
ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_shared_apex10000")
|
||||
ensureListContains(t, ctx.ModuleVariantsForTests("myjar"), "android_common_apex10000")
|
||||
ensureListContains(t, ctx.ModuleVariantsForTests("myjar_dex"), "android_common_apex10000")
|
||||
ensureListContains(t, ctx.ModuleVariantsForTests("foo.rust"), "android_arm64_armv8-a_apex10000")
|
||||
|
||||
// Ensure that apex variant is created for the indirect dep
|
||||
ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_shared_apex10000")
|
||||
ensureListContains(t, ctx.ModuleVariantsForTests("myotherjar"), "android_common_apex10000")
|
||||
ensureListContains(t, ctx.ModuleVariantsForTests("libfoo.rlib.rust"), "android_arm64_armv8-a_rlib_dylib-std_apex10000")
|
||||
ensureListContains(t, ctx.ModuleVariantsForTests("libfoo.dylib.rust"), "android_arm64_armv8-a_dylib_apex10000")
|
||||
|
||||
// Ensure that both direct and indirect deps are copied into apex
|
||||
ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
|
||||
ensureContains(t, copyCmds, "image.apex/lib64/mylib2.so")
|
||||
ensureContains(t, copyCmds, "image.apex/javalib/myjar_stem.jar")
|
||||
ensureContains(t, copyCmds, "image.apex/javalib/myjar_dex.jar")
|
||||
ensureContains(t, copyCmds, "image.apex/lib64/libfoo.dylib.rust.dylib.so")
|
||||
// .. but not for java libs
|
||||
ensureNotContains(t, copyCmds, "image.apex/javalib/myotherjar.jar")
|
||||
ensureNotContains(t, copyCmds, "image.apex/javalib/msharedjar.jar")
|
||||
|
|
|
@ -166,6 +166,10 @@ func GatherRequiredDepsForTest(oses ...android.OsType) string {
|
|||
product_available: true,
|
||||
recovery_available: true,
|
||||
src: "",
|
||||
apex_available: [
|
||||
"//apex_available:platform",
|
||||
"//apex_available:anyapex",
|
||||
],
|
||||
}
|
||||
|
||||
toolchain_library {
|
||||
|
|
|
@ -43,7 +43,7 @@ func (mod *Module) SubAndroidMk(data *android.AndroidMkEntries, obj interface{})
|
|||
}
|
||||
|
||||
func (mod *Module) AndroidMkEntries() []android.AndroidMkEntries {
|
||||
if mod.Properties.HideFromMake {
|
||||
if mod.Properties.HideFromMake || mod.hideApexVariantFromMake {
|
||||
|
||||
return []android.AndroidMkEntries{android.AndroidMkEntries{Disabled: true}}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"android/soong/android"
|
||||
"android/soong/cc"
|
||||
)
|
||||
|
||||
func TestClippy(t *testing.T) {
|
||||
|
@ -45,6 +46,7 @@ func TestClippy(t *testing.T) {
|
|||
}`
|
||||
|
||||
bp = bp + GatherRequiredDepsForTest()
|
||||
bp = bp + cc.GatherRequiredDepsForTest(android.NoOsType)
|
||||
|
||||
fs := map[string][]byte{
|
||||
// Reuse the same blueprint file for subdirectories.
|
||||
|
|
|
@ -19,6 +19,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"android/soong/android"
|
||||
"android/soong/cc"
|
||||
)
|
||||
|
||||
// Test that feature flags are being correctly generated.
|
||||
|
@ -132,6 +133,7 @@ func TestLints(t *testing.T) {
|
|||
}`
|
||||
|
||||
bp = bp + GatherRequiredDepsForTest()
|
||||
bp = bp + cc.GatherRequiredDepsForTest(android.NoOsType)
|
||||
|
||||
fs := map[string][]byte{
|
||||
// Reuse the same blueprint file for subdirectories.
|
||||
|
|
66
rust/rust.go
66
rust/rust.go
|
@ -74,6 +74,7 @@ type BaseProperties struct {
|
|||
type Module struct {
|
||||
android.ModuleBase
|
||||
android.DefaultableModuleBase
|
||||
android.ApexModuleBase
|
||||
|
||||
Properties BaseProperties
|
||||
|
||||
|
@ -88,6 +89,8 @@ type Module struct {
|
|||
subAndroidMkOnce map[SubAndroidMkProvider]bool
|
||||
|
||||
outputFile android.OptionalPath
|
||||
|
||||
hideApexVariantFromMake bool
|
||||
}
|
||||
|
||||
func (mod *Module) OutputFiles(tag string) (android.Paths, error) {
|
||||
|
@ -508,6 +511,7 @@ func (mod *Module) Init() android.Module {
|
|||
}
|
||||
|
||||
android.InitAndroidArchModule(mod, mod.hod, mod.multilib)
|
||||
android.InitApexModule(mod)
|
||||
|
||||
android.InitDefaultableModule(mod)
|
||||
return mod
|
||||
|
@ -605,6 +609,11 @@ func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
|
|||
ModuleContext: actx,
|
||||
}
|
||||
|
||||
apexInfo := actx.Provider(android.ApexInfoProvider).(android.ApexInfo)
|
||||
if !apexInfo.IsForPlatform() {
|
||||
mod.hideApexVariantFromMake = true
|
||||
}
|
||||
|
||||
toolchain := mod.toolchain(ctx)
|
||||
|
||||
if !toolchain.Supported() {
|
||||
|
@ -694,6 +703,11 @@ var (
|
|||
sourceDepTag = dependencyTag{name: "source"}
|
||||
)
|
||||
|
||||
func IsDylibDepTag(depTag blueprint.DependencyTag) bool {
|
||||
tag, ok := depTag.(dependencyTag)
|
||||
return ok && tag == dylibDepTag
|
||||
}
|
||||
|
||||
type autoDep struct {
|
||||
variation string
|
||||
depTag dependencyTag
|
||||
|
@ -1052,6 +1066,58 @@ func (mod *Module) HostToolPath() android.OptionalPath {
|
|||
return android.OptionalPath{}
|
||||
}
|
||||
|
||||
var _ android.ApexModule = (*Module)(nil)
|
||||
|
||||
func (mod *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion android.ApiLevel) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mod *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
|
||||
depTag := ctx.OtherModuleDependencyTag(dep)
|
||||
|
||||
if ccm, ok := dep.(*cc.Module); ok {
|
||||
if ccm.HasStubsVariants() {
|
||||
if cc.IsSharedDepTag(depTag) {
|
||||
// dynamic dep to a stubs lib crosses APEX boundary
|
||||
return false
|
||||
}
|
||||
if cc.IsRuntimeDepTag(depTag) {
|
||||
// runtime dep to a stubs lib also crosses APEX boundary
|
||||
return false
|
||||
}
|
||||
|
||||
if cc.IsHeaderDepTag(depTag) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
if mod.Static() && cc.IsSharedDepTag(depTag) {
|
||||
// shared_lib dependency from a static lib is considered as crossing
|
||||
// the APEX boundary because the dependency doesn't actually is
|
||||
// linked; the dependency is used only during the compilation phase.
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if depTag == procMacroDepTag {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Overrides ApexModule.IsInstallabeToApex()
|
||||
func (mod *Module) IsInstallableToApex() bool {
|
||||
if mod.compiler != nil {
|
||||
if lib, ok := mod.compiler.(*libraryDecorator); ok && (lib.shared() || lib.dylib()) {
|
||||
return true
|
||||
}
|
||||
if _, ok := mod.compiler.(*binaryDecorator); ok {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var Bool = proptools.Bool
|
||||
var BoolDefault = proptools.BoolDefault
|
||||
var String = proptools.String
|
||||
|
|
|
@ -120,6 +120,7 @@ func (tctx *testRustCtx) useMockedFs() {
|
|||
// attributes of the testRustCtx.
|
||||
func (tctx *testRustCtx) generateConfig() {
|
||||
tctx.bp = tctx.bp + GatherRequiredDepsForTest()
|
||||
tctx.bp = tctx.bp + cc.GatherRequiredDepsForTest(android.NoOsType)
|
||||
cc.GatherRequiredFilesForTest(tctx.fs)
|
||||
config := android.TestArchConfig(buildDir, tctx.env, tctx.bp, tctx.fs)
|
||||
tctx.config = &config
|
||||
|
|
|
@ -77,6 +77,7 @@ func GatherRequiredDepsForTest() string {
|
|||
no_libcrt: true,
|
||||
nocrt: true,
|
||||
system_shared_libs: [],
|
||||
apex_available: ["//apex_available:platform", "//apex_available:anyapex"],
|
||||
}
|
||||
cc_library {
|
||||
name: "libprotobuf-cpp-full",
|
||||
|
@ -93,6 +94,7 @@ func GatherRequiredDepsForTest() string {
|
|||
host_supported: true,
|
||||
native_coverage: false,
|
||||
sysroot: true,
|
||||
apex_available: ["//apex_available:platform", "//apex_available:anyapex"],
|
||||
}
|
||||
rust_library {
|
||||
name: "libtest",
|
||||
|
@ -102,6 +104,7 @@ func GatherRequiredDepsForTest() string {
|
|||
host_supported: true,
|
||||
native_coverage: false,
|
||||
sysroot: true,
|
||||
apex_available: ["//apex_available:platform", "//apex_available:anyapex"],
|
||||
}
|
||||
rust_library {
|
||||
name: "libprotobuf",
|
||||
|
@ -122,15 +125,11 @@ func GatherRequiredDepsForTest() string {
|
|||
host_supported: true,
|
||||
}
|
||||
|
||||
` + cc.GatherRequiredDepsForTest(android.NoOsType)
|
||||
`
|
||||
return bp
|
||||
}
|
||||
|
||||
func CreateTestContext(config android.Config) *android.TestContext {
|
||||
ctx := android.NewTestArchContext(config)
|
||||
android.RegisterPrebuiltMutators(ctx)
|
||||
ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
|
||||
cc.RegisterRequiredBuildComponentsForTest(ctx)
|
||||
func RegisterRequiredBuildComponentsForTest(ctx android.RegistrationContext) {
|
||||
ctx.RegisterModuleType("rust_binary", RustBinaryFactory)
|
||||
ctx.RegisterModuleType("rust_binary_host", RustBinaryHostFactory)
|
||||
ctx.RegisterModuleType("rust_bindgen", RustBindgenFactory)
|
||||
|
@ -164,6 +163,14 @@ func CreateTestContext(config android.Config) *android.TestContext {
|
|||
ctx.BottomUp("rust_begin", BeginMutator).Parallel()
|
||||
})
|
||||
ctx.RegisterSingletonType("rust_project_generator", rustProjectGeneratorSingleton)
|
||||
}
|
||||
|
||||
func CreateTestContext(config android.Config) *android.TestContext {
|
||||
ctx := android.NewTestArchContext(config)
|
||||
android.RegisterPrebuiltMutators(ctx)
|
||||
ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
|
||||
cc.RegisterRequiredBuildComponentsForTest(ctx)
|
||||
RegisterRequiredBuildComponentsForTest(ctx)
|
||||
|
||||
return ctx
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue