rust modules can be included in apex
We will have some APEXes having rust binaries and libraries. So, adding the support for the types of modules. rust.Module now inherits from android.ApexModuleBase and implements the android.ApexModule interface. Bug: 172414324 Test: m Exempt-From-Owner-Approval: rebased after +2 from the owner Change-Id: I356ef4c45f782a6460f001e83af96d1710642d80
This commit is contained in:
parent
d35d92a7b5
commit
99644e92c8
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
|
||||
|
||||
|
@ -513,13 +517,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
|
||||
|
@ -529,6 +535,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) {
|
||||
|
@ -1264,6 +1271,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()
|
||||
|
@ -1501,8 +1537,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) {
|
||||
|
@ -1663,6 +1702,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