| // Copyright 2019 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 rust |
| |
| import ( |
| "fmt" |
| "strconv" |
| "strings" |
| |
| "android/soong/bloaty" |
| |
| "github.com/google/blueprint" |
| "github.com/google/blueprint/depset" |
| "github.com/google/blueprint/proptools" |
| |
| "android/soong/android" |
| "android/soong/cc" |
| cc_config "android/soong/cc/config" |
| "android/soong/fuzz" |
| "android/soong/rust/config" |
| ) |
| |
| var pctx = android.NewPackageContext("android/soong/rust") |
| |
| type LibraryInfo struct { |
| Rlib bool |
| Dylib bool |
| } |
| |
| type CompilerInfo struct { |
| StdLinkageForDevice RustLinkage |
| StdLinkageForNonDevice RustLinkage |
| NoStdlibs bool |
| LibraryInfo *LibraryInfo |
| } |
| |
| type ProtobufDecoratorInfo struct{} |
| |
| type SourceProviderInfo struct { |
| Srcs android.Paths |
| ProtobufDecoratorInfo *ProtobufDecoratorInfo |
| } |
| |
| type RustInfo struct { |
| AndroidMkSuffix string |
| RustSubName string |
| TransitiveAndroidMkSharedLibs depset.DepSet[string] |
| CompilerInfo *CompilerInfo |
| SnapshotInfo *cc.SnapshotInfo |
| SourceProviderInfo *SourceProviderInfo |
| XrefRustFiles android.Paths |
| DocTimestampFile android.OptionalPath |
| } |
| |
| var RustInfoProvider = blueprint.NewProvider[*RustInfo]() |
| |
| func init() { |
| android.RegisterModuleType("rust_defaults", defaultsFactory) |
| android.PreDepsMutators(registerPreDepsMutators) |
| android.PostDepsMutators(registerPostDepsMutators) |
| pctx.Import("android/soong/android") |
| pctx.Import("android/soong/rust/config") |
| pctx.ImportAs("cc_config", "android/soong/cc/config") |
| android.InitRegistrationContext.RegisterParallelSingletonType("kythe_rust_extract", kytheExtractRustFactory) |
| } |
| |
| func registerPreDepsMutators(ctx android.RegisterMutatorsContext) { |
| ctx.Transition("rust_libraries", &libraryTransitionMutator{}) |
| ctx.Transition("rust_stdlinkage", &libstdTransitionMutator{}) |
| ctx.BottomUp("rust_begin", BeginMutator) |
| } |
| |
| func registerPostDepsMutators(ctx android.RegisterMutatorsContext) { |
| ctx.BottomUp("rust_sanitizers", rustSanitizerRuntimeMutator) |
| } |
| |
| type Flags struct { |
| GlobalRustFlags []string // Flags that apply globally to rust |
| GlobalLinkFlags []string // Flags that apply globally to linker |
| RustFlags []string // Flags that apply to rust |
| LinkFlags []string // Flags that apply to linker |
| ClippyFlags []string // Flags that apply to clippy-driver, during the linting |
| RustdocFlags []string // Flags that apply to rustdoc |
| Toolchain config.Toolchain |
| Coverage bool |
| Clippy bool |
| EmitXrefs bool // If true, emit rules to aid cross-referencing |
| } |
| |
| type BaseProperties struct { |
| AndroidMkRlibs []string `blueprint:"mutated"` |
| AndroidMkDylibs []string `blueprint:"mutated"` |
| AndroidMkProcMacroLibs []string `blueprint:"mutated"` |
| AndroidMkStaticLibs []string `blueprint:"mutated"` |
| AndroidMkHeaderLibs []string `blueprint:"mutated"` |
| |
| ImageVariation string `blueprint:"mutated"` |
| VndkVersion string `blueprint:"mutated"` |
| SubName string `blueprint:"mutated"` |
| |
| // SubName is used by CC for tracking image variants / SDK versions. RustSubName is used for Rust-specific |
| // subnaming which shouldn't be visible to CC modules (such as the rlib stdlinkage subname). This should be |
| // appended before SubName. |
| RustSubName string `blueprint:"mutated"` |
| |
| // Set by imageMutator |
| ProductVariantNeeded bool `blueprint:"mutated"` |
| VendorVariantNeeded bool `blueprint:"mutated"` |
| CoreVariantNeeded bool `blueprint:"mutated"` |
| VendorRamdiskVariantNeeded bool `blueprint:"mutated"` |
| RamdiskVariantNeeded bool `blueprint:"mutated"` |
| RecoveryVariantNeeded bool `blueprint:"mutated"` |
| ExtraVariants []string `blueprint:"mutated"` |
| |
| // Allows this module to use non-APEX version of libraries. Useful |
| // for building binaries that are started before APEXes are activated. |
| Bootstrap *bool |
| |
| // Used by vendor snapshot to record dependencies from snapshot modules. |
| SnapshotSharedLibs []string `blueprint:"mutated"` |
| SnapshotStaticLibs []string `blueprint:"mutated"` |
| SnapshotRlibs []string `blueprint:"mutated"` |
| SnapshotDylibs []string `blueprint:"mutated"` |
| |
| // Make this module available when building for ramdisk. |
| // On device without a dedicated recovery partition, the module is only |
| // available after switching root into |
| // /first_stage_ramdisk. To expose the module before switching root, install |
| // the recovery variant instead. |
| Ramdisk_available *bool |
| |
| // Make this module available when building for vendor ramdisk. |
| // On device without a dedicated recovery partition, the module is only |
| // available after switching root into |
| // /first_stage_ramdisk. To expose the module before switching root, install |
| // the recovery variant instead |
| Vendor_ramdisk_available *bool |
| |
| // Normally Soong uses the directory structure to decide which modules |
| // should be included (framework) or excluded (non-framework) from the |
| // different snapshots (vendor, recovery, etc.), but this property |
| // allows a partner to exclude a module normally thought of as a |
| // framework module from the vendor snapshot. |
| Exclude_from_vendor_snapshot *bool |
| |
| // Normally Soong uses the directory structure to decide which modules |
| // should be included (framework) or excluded (non-framework) from the |
| // different snapshots (vendor, recovery, etc.), but this property |
| // allows a partner to exclude a module normally thought of as a |
| // framework module from the recovery snapshot. |
| Exclude_from_recovery_snapshot *bool |
| |
| // Make this module available when building for recovery |
| Recovery_available *bool |
| |
| // The API level that this module is built against. The APIs of this API level will be |
| // visible at build time, but use of any APIs newer than min_sdk_version will render the |
| // module unloadable on older devices. In the future it will be possible to weakly-link new |
| // APIs, making the behavior match Java: such modules will load on older devices, but |
| // calling new APIs on devices that do not support them will result in a crash. |
| // |
| // This property has the same behavior as sdk_version does for Java modules. For those |
| // familiar with Android Gradle, the property behaves similarly to how compileSdkVersion |
| // does for Java code. |
| // |
| // In addition, setting this property causes two variants to be built, one for the platform |
| // and one for apps. |
| Sdk_version *string |
| |
| // Minimum OS API level supported by this C or C++ module. This property becomes the value |
| // of the __ANDROID_API__ macro. When the C or C++ module is included in an APEX or an APK, |
| // this property is also used to ensure that the min_sdk_version of the containing module is |
| // not older (i.e. less) than this module's min_sdk_version. When not set, this property |
| // defaults to the value of sdk_version. When this is set to "apex_inherit", this tracks |
| // min_sdk_version of the containing APEX. When the module |
| // is not built for an APEX, "apex_inherit" defaults to sdk_version. |
| Min_sdk_version *string |
| |
| // Variant is an SDK variant created by sdkMutator |
| IsSdkVariant bool `blueprint:"mutated"` |
| |
| // Set by factories of module types that can only be referenced from variants compiled against |
| // the SDK. |
| AlwaysSdk bool `blueprint:"mutated"` |
| |
| HideFromMake bool `blueprint:"mutated"` |
| PreventInstall bool `blueprint:"mutated"` |
| |
| Installable *bool |
| } |
| |
| type Module struct { |
| fuzz.FuzzModule |
| |
| VendorProperties cc.VendorProperties |
| |
| Properties BaseProperties |
| |
| hod android.HostOrDeviceSupported |
| multilib android.Multilib |
| testModule bool |
| |
| makeLinkType string |
| |
| afdo *afdo |
| compiler compiler |
| coverage *coverage |
| clippy *clippy |
| sanitize *sanitize |
| cachedToolchain config.Toolchain |
| sourceProvider SourceProvider |
| subAndroidMkOnce map[SubAndroidMkProvider]bool |
| |
| exportedLinkDirs []string |
| |
| // Output file to be installed, may be stripped or unstripped. |
| outputFile android.OptionalPath |
| |
| // Cross-reference input file |
| kytheFiles android.Paths |
| |
| docTimestampFile android.OptionalPath |
| |
| hideApexVariantFromMake bool |
| |
| // For apex variants, this is set as apex.min_sdk_version |
| apexSdkVersion android.ApiLevel |
| |
| transitiveAndroidMkSharedLibs depset.DepSet[string] |
| |
| // Shared flags among stubs build rules of this module |
| sharedFlags cc.SharedFlags |
| } |
| |
| func (mod *Module) Header() bool { |
| //TODO: If Rust libraries provide header variants, this needs to be updated. |
| return false |
| } |
| |
| func (mod *Module) SetPreventInstall() { |
| mod.Properties.PreventInstall = true |
| } |
| |
| func (mod *Module) SetHideFromMake() { |
| mod.Properties.HideFromMake = true |
| } |
| |
| func (mod *Module) HiddenFromMake() bool { |
| return mod.Properties.HideFromMake |
| } |
| |
| func (mod *Module) SanitizePropDefined() bool { |
| // Because compiler is not set for some Rust modules where sanitize might be set, check that compiler is also not |
| // nil since we need compiler to actually sanitize. |
| return mod.sanitize != nil && mod.compiler != nil |
| } |
| |
| func (mod *Module) IsPrebuilt() bool { |
| if _, ok := mod.compiler.(*prebuiltLibraryDecorator); ok { |
| return true |
| } |
| return false |
| } |
| |
| func (mod *Module) SelectedStl() string { |
| return "" |
| } |
| |
| func (mod *Module) NonCcVariants() bool { |
| if mod.compiler != nil { |
| if library, ok := mod.compiler.(libraryInterface); ok { |
| return library.buildRlib() || library.buildDylib() |
| } |
| } |
| panic(fmt.Errorf("NonCcVariants called on non-library module: %q", mod.BaseModuleName())) |
| } |
| |
| func (mod *Module) Static() bool { |
| if mod.compiler != nil { |
| if library, ok := mod.compiler.(libraryInterface); ok { |
| return library.static() |
| } |
| } |
| return false |
| } |
| |
| func (mod *Module) Shared() bool { |
| if mod.compiler != nil { |
| if library, ok := mod.compiler.(libraryInterface); ok { |
| return library.shared() |
| } |
| } |
| return false |
| } |
| |
| func (mod *Module) Dylib() bool { |
| if mod.compiler != nil { |
| if library, ok := mod.compiler.(libraryInterface); ok { |
| return library.dylib() |
| } |
| } |
| return false |
| } |
| |
| func (mod *Module) Source() bool { |
| if mod.compiler != nil { |
| if library, ok := mod.compiler.(libraryInterface); ok && mod.sourceProvider != nil { |
| return library.source() |
| } |
| } |
| return false |
| } |
| |
| func (mod *Module) RlibStd() bool { |
| if mod.compiler != nil { |
| if library, ok := mod.compiler.(libraryInterface); ok && library.rlib() { |
| return library.rlibStd() |
| } |
| } |
| panic(fmt.Errorf("RlibStd() called on non-rlib module: %q", mod.BaseModuleName())) |
| } |
| |
| func (mod *Module) Rlib() bool { |
| if mod.compiler != nil { |
| if library, ok := mod.compiler.(libraryInterface); ok { |
| return library.rlib() |
| } |
| } |
| return false |
| } |
| |
| func (mod *Module) Binary() bool { |
| if binary, ok := mod.compiler.(binaryInterface); ok { |
| return binary.binary() |
| } |
| return false |
| } |
| |
| func (mod *Module) StaticExecutable() bool { |
| if !mod.Binary() { |
| return false |
| } |
| return mod.StaticallyLinked() |
| } |
| |
| func (mod *Module) ApexExclude() bool { |
| if mod.compiler != nil { |
| if library, ok := mod.compiler.(libraryInterface); ok { |
| return library.apexExclude() |
| } |
| } |
| return false |
| } |
| |
| func (mod *Module) Object() bool { |
| // Rust has no modules which produce only object files. |
| return false |
| } |
| |
| func (mod *Module) Toc() android.OptionalPath { |
| if mod.compiler != nil { |
| if lib, ok := mod.compiler.(libraryInterface); ok { |
| return lib.toc() |
| } |
| } |
| panic(fmt.Errorf("Toc() called on non-library module: %q", mod.BaseModuleName())) |
| } |
| |
| func (mod *Module) UseSdk() bool { |
| return false |
| } |
| |
| func (mod *Module) RelativeInstallPath() string { |
| if mod.compiler != nil { |
| return mod.compiler.relativeInstallPath() |
| } |
| return "" |
| } |
| |
| func (mod *Module) UseVndk() bool { |
| return mod.Properties.VndkVersion != "" |
| } |
| |
| func (mod *Module) Bootstrap() bool { |
| return Bool(mod.Properties.Bootstrap) |
| } |
| |
| func (mod *Module) SubName() string { |
| return mod.Properties.SubName |
| } |
| |
| func (mod *Module) IsVndkPrebuiltLibrary() bool { |
| // Rust modules do not provide VNDK prebuilts |
| return false |
| } |
| |
| func (mod *Module) IsVendorPublicLibrary() bool { |
| // Rust modules do not currently support vendor_public_library |
| return false |
| } |
| |
| func (mod *Module) SdkAndPlatformVariantVisibleToMake() bool { |
| // Rust modules to not provide Sdk variants |
| return false |
| } |
| |
| func (c *Module) IsVndkPrivate() bool { |
| // Rust modules do not currently support VNDK variants |
| return false |
| } |
| |
| func (c *Module) IsLlndk() bool { |
| // Rust modules do not currently support LLNDK variants |
| return false |
| } |
| |
| func (mod *Module) KernelHeadersDecorator() bool { |
| return false |
| } |
| |
| func (m *Module) NeedsLlndkVariants() bool { |
| // Rust modules do not currently support LLNDK variants |
| return false |
| } |
| |
| func (m *Module) NeedsVendorPublicLibraryVariants() bool { |
| // Rust modules do not currently support vendor_public_library |
| return false |
| } |
| |
| func (mod *Module) HasLlndkStubs() bool { |
| // Rust modules do not currently support LLNDK stubs |
| return false |
| } |
| |
| func (mod *Module) SdkVersion() string { |
| return String(mod.Properties.Sdk_version) |
| } |
| |
| func (mod *Module) AlwaysSdk() bool { |
| return mod.Properties.AlwaysSdk |
| } |
| |
| func (mod *Module) IsSdkVariant() bool { |
| return mod.Properties.IsSdkVariant |
| } |
| |
| func (mod *Module) SplitPerApiLevel() bool { |
| return cc.CanUseSdk(mod) && mod.IsCrt() |
| } |
| |
| func (mod *Module) XrefRustFiles() android.Paths { |
| return mod.kytheFiles |
| } |
| |
| type Deps struct { |
| Dylibs []string |
| Rlibs []string |
| Rustlibs []string |
| Stdlibs []string |
| ProcMacros []string |
| SharedLibs []string |
| StaticLibs []string |
| WholeStaticLibs []string |
| HeaderLibs []string |
| |
| // Used for data dependencies adjacent to tests |
| DataLibs []string |
| DataBins []string |
| |
| CrtBegin, CrtEnd []string |
| } |
| |
| type PathDeps struct { |
| DyLibs RustLibraries |
| RLibs RustLibraries |
| SharedLibs android.Paths |
| SharedLibDeps android.Paths |
| StaticLibs android.Paths |
| ProcMacros RustLibraries |
| AfdoProfiles android.Paths |
| LinkerDeps android.Paths |
| |
| // depFlags and depLinkFlags are rustc and linker (clang) flags. |
| depFlags []string |
| depLinkFlags []string |
| |
| // track cc static-libs that have Rlib dependencies |
| reexportedCcRlibDeps []cc.RustRlibDep |
| reexportedWholeCcRlibDeps []cc.RustRlibDep |
| ccRlibDeps []cc.RustRlibDep |
| |
| // linkDirs are link paths passed via -L to rustc. linkObjects are objects passed directly to the linker |
| // Both of these are exported and propagate to dependencies. |
| linkDirs []string |
| rustLibObjects []string |
| staticLibObjects []string |
| wholeStaticLibObjects []string |
| sharedLibObjects []string |
| |
| // exportedLinkDirs are exported linkDirs for direct rlib dependencies to |
| // cc_library_static dependants of rlibs. |
| // Track them separately from linkDirs so superfluous -L flags don't get emitted. |
| exportedLinkDirs []string |
| |
| // Used by bindgen modules which call clang |
| depClangFlags []string |
| depIncludePaths android.Paths |
| depGeneratedHeaders android.Paths |
| depSystemIncludePaths android.Paths |
| |
| CrtBegin android.Paths |
| CrtEnd android.Paths |
| |
| // Paths to generated source files |
| SrcDeps android.Paths |
| srcProviderFiles android.Paths |
| |
| directImplementationDeps android.Paths |
| transitiveImplementationDeps []depset.DepSet[android.Path] |
| } |
| |
| type RustLibraries []RustLibrary |
| |
| type RustLibrary struct { |
| Path android.Path |
| CrateName string |
| } |
| |
| type exportedFlagsProducer interface { |
| exportLinkDirs(...string) |
| exportRustLibs(...string) |
| exportStaticLibs(...string) |
| exportWholeStaticLibs(...string) |
| exportSharedLibs(...string) |
| } |
| |
| type xref interface { |
| XrefRustFiles() android.Paths |
| } |
| |
| type flagExporter struct { |
| linkDirs []string |
| ccLinkDirs []string |
| rustLibPaths []string |
| staticLibObjects []string |
| sharedLibObjects []string |
| wholeStaticLibObjects []string |
| wholeRustRlibDeps []cc.RustRlibDep |
| } |
| |
| func (flagExporter *flagExporter) exportLinkDirs(dirs ...string) { |
| flagExporter.linkDirs = android.FirstUniqueStrings(append(flagExporter.linkDirs, dirs...)) |
| } |
| |
| func (flagExporter *flagExporter) exportRustLibs(flags ...string) { |
| flagExporter.rustLibPaths = android.FirstUniqueStrings(append(flagExporter.rustLibPaths, flags...)) |
| } |
| |
| func (flagExporter *flagExporter) exportStaticLibs(flags ...string) { |
| flagExporter.staticLibObjects = android.FirstUniqueStrings(append(flagExporter.staticLibObjects, flags...)) |
| } |
| |
| func (flagExporter *flagExporter) exportSharedLibs(flags ...string) { |
| flagExporter.sharedLibObjects = android.FirstUniqueStrings(append(flagExporter.sharedLibObjects, flags...)) |
| } |
| |
| func (flagExporter *flagExporter) exportWholeStaticLibs(flags ...string) { |
| flagExporter.wholeStaticLibObjects = android.FirstUniqueStrings(append(flagExporter.wholeStaticLibObjects, flags...)) |
| } |
| |
| func (flagExporter *flagExporter) setRustProvider(ctx ModuleContext) { |
| android.SetProvider(ctx, RustFlagExporterInfoProvider, RustFlagExporterInfo{ |
| LinkDirs: flagExporter.linkDirs, |
| RustLibObjects: flagExporter.rustLibPaths, |
| StaticLibObjects: flagExporter.staticLibObjects, |
| WholeStaticLibObjects: flagExporter.wholeStaticLibObjects, |
| SharedLibPaths: flagExporter.sharedLibObjects, |
| WholeRustRlibDeps: flagExporter.wholeRustRlibDeps, |
| }) |
| } |
| |
| var _ exportedFlagsProducer = (*flagExporter)(nil) |
| |
| func NewFlagExporter() *flagExporter { |
| return &flagExporter{} |
| } |
| |
| type RustFlagExporterInfo struct { |
| Flags []string |
| LinkDirs []string |
| RustLibObjects []string |
| StaticLibObjects []string |
| WholeStaticLibObjects []string |
| SharedLibPaths []string |
| WholeRustRlibDeps []cc.RustRlibDep |
| } |
| |
| var RustFlagExporterInfoProvider = blueprint.NewProvider[RustFlagExporterInfo]() |
| |
| func (mod *Module) isCoverageVariant() bool { |
| return mod.coverage.Properties.IsCoverageVariant |
| } |
| |
| var _ cc.Coverage = (*Module)(nil) |
| |
| func (mod *Module) IsNativeCoverageNeeded(ctx cc.IsNativeCoverageNeededContext) bool { |
| return mod.coverage != nil && mod.coverage.Properties.NeedCoverageVariant |
| } |
| |
| func (mod *Module) VndkVersion() string { |
| return mod.Properties.VndkVersion |
| } |
| |
| func (mod *Module) ExportedCrateLinkDirs() []string { |
| return mod.exportedLinkDirs |
| } |
| |
| func (mod *Module) PreventInstall() bool { |
| return mod.Properties.PreventInstall |
| } |
| func (c *Module) ForceDisableSanitizers() { |
| c.sanitize.Properties.ForceDisable = true |
| } |
| |
| func (mod *Module) MarkAsCoverageVariant(coverage bool) { |
| mod.coverage.Properties.IsCoverageVariant = coverage |
| } |
| |
| func (mod *Module) EnableCoverageIfNeeded() { |
| mod.coverage.Properties.CoverageEnabled = mod.coverage.Properties.NeedCoverageBuild |
| } |
| |
| func defaultsFactory() android.Module { |
| return DefaultsFactory() |
| } |
| |
| type Defaults struct { |
| android.ModuleBase |
| android.DefaultsModuleBase |
| } |
| |
| func DefaultsFactory(props ...interface{}) android.Module { |
| module := &Defaults{} |
| |
| module.AddProperties(props...) |
| module.AddProperties( |
| &BaseProperties{}, |
| &cc.AfdoProperties{}, |
| &cc.VendorProperties{}, |
| &BenchmarkProperties{}, |
| &BindgenProperties{}, |
| &BaseCompilerProperties{}, |
| &BinaryCompilerProperties{}, |
| &LibraryCompilerProperties{}, |
| &ProcMacroCompilerProperties{}, |
| &PrebuiltProperties{}, |
| &SourceProviderProperties{}, |
| &TestProperties{}, |
| &cc.CoverageProperties{}, |
| &cc.RustBindgenClangProperties{}, |
| &ClippyProperties{}, |
| &SanitizeProperties{}, |
| &fuzz.FuzzProperties{}, |
| ) |
| |
| android.InitDefaultsModule(module) |
| return module |
| } |
| |
| func (mod *Module) CrateName() string { |
| return mod.compiler.crateName() |
| } |
| |
| func (mod *Module) CcLibrary() bool { |
| if mod.compiler != nil { |
| if _, ok := mod.compiler.(libraryInterface); ok { |
| return true |
| } |
| } |
| return false |
| } |
| |
| func (mod *Module) CcLibraryInterface() bool { |
| if mod.compiler != nil { |
| // use build{Static,Shared}() instead of {static,shared}() here because this might be called before |
| // VariantIs{Static,Shared} is set. |
| if lib, ok := mod.compiler.(libraryInterface); ok && (lib.buildShared() || lib.buildStatic() || lib.buildRlib()) { |
| return true |
| } |
| } |
| return false |
| } |
| |
| func (mod *Module) RustLibraryInterface() bool { |
| if mod.compiler != nil { |
| if _, ok := mod.compiler.(libraryInterface); ok { |
| return true |
| } |
| } |
| return false |
| } |
| |
| func (mod *Module) IsFuzzModule() bool { |
| if _, ok := mod.compiler.(*fuzzDecorator); ok { |
| return true |
| } |
| return false |
| } |
| |
| func (mod *Module) FuzzModuleStruct() fuzz.FuzzModule { |
| return mod.FuzzModule |
| } |
| |
| func (mod *Module) FuzzPackagedModule() fuzz.FuzzPackagedModule { |
| if fuzzer, ok := mod.compiler.(*fuzzDecorator); ok { |
| return fuzzer.fuzzPackagedModule |
| } |
| panic(fmt.Errorf("FuzzPackagedModule called on non-fuzz module: %q", mod.BaseModuleName())) |
| } |
| |
| func (mod *Module) FuzzSharedLibraries() android.RuleBuilderInstalls { |
| if fuzzer, ok := mod.compiler.(*fuzzDecorator); ok { |
| return fuzzer.sharedLibraries |
| } |
| panic(fmt.Errorf("FuzzSharedLibraries called on non-fuzz module: %q", mod.BaseModuleName())) |
| } |
| |
| func (mod *Module) UnstrippedOutputFile() android.Path { |
| if mod.compiler != nil { |
| return mod.compiler.unstrippedOutputFilePath() |
| } |
| return nil |
| } |
| |
| func (mod *Module) SetStatic() { |
| if mod.compiler != nil { |
| if library, ok := mod.compiler.(libraryInterface); ok { |
| library.setStatic() |
| return |
| } |
| } |
| panic(fmt.Errorf("SetStatic called on non-library module: %q", mod.BaseModuleName())) |
| } |
| |
| func (mod *Module) SetShared() { |
| if mod.compiler != nil { |
| if library, ok := mod.compiler.(libraryInterface); ok { |
| library.setShared() |
| return |
| } |
| } |
| panic(fmt.Errorf("SetShared called on non-library module: %q", mod.BaseModuleName())) |
| } |
| |
| func (mod *Module) BuildStaticVariant() bool { |
| if mod.compiler != nil { |
| if library, ok := mod.compiler.(libraryInterface); ok { |
| return library.buildStatic() |
| } |
| } |
| panic(fmt.Errorf("BuildStaticVariant called on non-library module: %q", mod.BaseModuleName())) |
| } |
| |
| func (mod *Module) BuildRlibVariant() bool { |
| if mod.compiler != nil { |
| if library, ok := mod.compiler.(libraryInterface); ok { |
| return library.buildRlib() |
| } |
| } |
| panic(fmt.Errorf("BuildRlibVariant called on non-library module: %q", mod.BaseModuleName())) |
| } |
| |
| func (mod *Module) BuildSharedVariant() bool { |
| if mod.compiler != nil { |
| if library, ok := mod.compiler.(libraryInterface); ok { |
| return library.buildShared() |
| } |
| } |
| panic(fmt.Errorf("BuildSharedVariant called on non-library module: %q", mod.BaseModuleName())) |
| } |
| |
| func (mod *Module) Module() android.Module { |
| return mod |
| } |
| |
| func (mod *Module) OutputFile() android.OptionalPath { |
| return mod.outputFile |
| } |
| |
| func (mod *Module) CoverageFiles() android.Paths { |
| if mod.compiler != nil { |
| return android.Paths{} |
| } |
| panic(fmt.Errorf("CoverageFiles called on non-library module: %q", mod.BaseModuleName())) |
| } |
| |
| // Rust does not produce gcno files, and therefore does not produce a coverage archive. |
| func (mod *Module) CoverageOutputFile() android.OptionalPath { |
| return android.OptionalPath{} |
| } |
| |
| func (mod *Module) IsNdk(config android.Config) bool { |
| return false |
| } |
| |
| func (mod *Module) IsStubs() bool { |
| if lib, ok := mod.compiler.(libraryInterface); ok { |
| return lib.BuildStubs() |
| } |
| return false |
| } |
| |
| func (mod *Module) HasStubsVariants() bool { |
| if lib, ok := mod.compiler.(libraryInterface); ok { |
| return lib.HasStubsVariants() |
| } |
| return false |
| } |
| |
| func (mod *Module) ApexSdkVersion() android.ApiLevel { |
| return mod.apexSdkVersion |
| } |
| |
| func (mod *Module) RustApexExclude() bool { |
| return mod.ApexExclude() |
| } |
| |
| func (mod *Module) getSharedFlags() *cc.SharedFlags { |
| shared := &mod.sharedFlags |
| if shared.FlagsMap == nil { |
| shared.NumSharedFlags = 0 |
| shared.FlagsMap = make(map[string]string) |
| } |
| return shared |
| } |
| |
| func (mod *Module) ImplementationModuleNameForMake() string { |
| name := mod.BaseModuleName() |
| if versioned, ok := mod.compiler.(cc.VersionedInterface); ok { |
| name = versioned.ImplementationModuleName(name) |
| } |
| return name |
| } |
| |
| func (mod *Module) Multilib() string { |
| return mod.Arch().ArchType.Multilib |
| } |
| |
| func (mod *Module) IsCrt() bool { |
| // Rust does not currently provide any crt modules. |
| return false |
| } |
| |
| func (mod *Module) installable(apexInfo android.ApexInfo) bool { |
| if !proptools.BoolDefault(mod.Installable(), mod.EverInstallable()) { |
| return false |
| } |
| |
| // The apex variant is not installable because it is included in the APEX and won't appear |
| // in the system partition as a standalone file. |
| if !apexInfo.IsForPlatform() { |
| return false |
| } |
| |
| return mod.OutputFile().Valid() && !mod.Properties.PreventInstall |
| } |
| |
| func (ctx moduleContext) apexVariationName() string { |
| apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider) |
| return apexInfo.ApexVariationName |
| } |
| |
| var _ cc.LinkableInterface = (*Module)(nil) |
| var _ cc.VersionedLinkableInterface = (*Module)(nil) |
| |
| func (mod *Module) Init() android.Module { |
| mod.AddProperties(&mod.Properties) |
| mod.AddProperties(&mod.VendorProperties) |
| |
| if mod.afdo != nil { |
| mod.AddProperties(mod.afdo.props()...) |
| } |
| if mod.compiler != nil { |
| mod.AddProperties(mod.compiler.compilerProps()...) |
| } |
| if mod.coverage != nil { |
| mod.AddProperties(mod.coverage.props()...) |
| } |
| if mod.clippy != nil { |
| mod.AddProperties(mod.clippy.props()...) |
| } |
| if mod.sourceProvider != nil { |
| mod.AddProperties(mod.sourceProvider.SourceProviderProps()...) |
| } |
| if mod.sanitize != nil { |
| mod.AddProperties(mod.sanitize.props()...) |
| } |
| |
| android.InitAndroidArchModule(mod, mod.hod, mod.multilib) |
| android.InitApexModule(mod) |
| |
| android.InitDefaultableModule(mod) |
| return mod |
| } |
| |
| func newBaseModule(hod android.HostOrDeviceSupported, multilib android.Multilib) *Module { |
| return &Module{ |
| hod: hod, |
| multilib: multilib, |
| } |
| } |
| func newModule(hod android.HostOrDeviceSupported, multilib android.Multilib) *Module { |
| module := newBaseModule(hod, multilib) |
| module.afdo = &afdo{} |
| module.coverage = &coverage{} |
| module.clippy = &clippy{} |
| module.sanitize = &sanitize{} |
| return module |
| } |
| |
| type ModuleContext interface { |
| android.ModuleContext |
| ModuleContextIntf |
| } |
| |
| type BaseModuleContext interface { |
| android.BaseModuleContext |
| ModuleContextIntf |
| } |
| |
| type DepsContext interface { |
| android.BottomUpMutatorContext |
| ModuleContextIntf |
| } |
| |
| type ModuleContextIntf interface { |
| RustModule() *Module |
| toolchain() config.Toolchain |
| } |
| |
| type depsContext struct { |
| android.BottomUpMutatorContext |
| } |
| |
| type moduleContext struct { |
| android.ModuleContext |
| } |
| |
| type baseModuleContext struct { |
| android.BaseModuleContext |
| } |
| |
| func (ctx *moduleContext) RustModule() *Module { |
| return ctx.Module().(*Module) |
| } |
| |
| func (ctx *moduleContext) toolchain() config.Toolchain { |
| return ctx.RustModule().toolchain(ctx) |
| } |
| |
| func (ctx *depsContext) RustModule() *Module { |
| return ctx.Module().(*Module) |
| } |
| |
| func (ctx *depsContext) toolchain() config.Toolchain { |
| return ctx.RustModule().toolchain(ctx) |
| } |
| |
| func (ctx *baseModuleContext) RustModule() *Module { |
| return ctx.Module().(*Module) |
| } |
| |
| func (ctx *baseModuleContext) toolchain() config.Toolchain { |
| return ctx.RustModule().toolchain(ctx) |
| } |
| |
| func (mod *Module) nativeCoverage() bool { |
| // Bug: http://b/137883967 - native-bridge modules do not currently work with coverage |
| if mod.Target().NativeBridge == android.NativeBridgeEnabled { |
| return false |
| } |
| return mod.compiler != nil && mod.compiler.nativeCoverage() |
| } |
| |
| func (mod *Module) SetStl(s string) { |
| // STL is a CC concept; do nothing for Rust |
| } |
| |
| func (mod *Module) SetSdkVersion(s string) { |
| mod.Properties.Sdk_version = StringPtr(s) |
| } |
| |
| func (mod *Module) SetMinSdkVersion(s string) { |
| mod.Properties.Min_sdk_version = StringPtr(s) |
| } |
| |
| func (mod *Module) VersionedInterface() cc.VersionedInterface { |
| if _, ok := mod.compiler.(cc.VersionedInterface); ok { |
| return mod.compiler.(cc.VersionedInterface) |
| } |
| return nil |
| } |
| |
| func (mod *Module) EverInstallable() bool { |
| return mod.compiler != nil && |
| // Check to see whether the module is actually ever installable. |
| mod.compiler.everInstallable() |
| } |
| |
| func (mod *Module) Installable() *bool { |
| return mod.Properties.Installable |
| } |
| |
| func (mod *Module) ProcMacro() bool { |
| if pm, ok := mod.compiler.(procMacroInterface); ok { |
| return pm.ProcMacro() |
| } |
| return false |
| } |
| |
| func (mod *Module) toolchain(ctx android.BaseModuleContext) config.Toolchain { |
| if mod.cachedToolchain == nil { |
| mod.cachedToolchain = config.FindToolchain(ctx.Os(), ctx.Arch()) |
| } |
| return mod.cachedToolchain |
| } |
| |
| func (mod *Module) ccToolchain(ctx android.BaseModuleContext) cc_config.Toolchain { |
| return cc_config.FindToolchain(ctx.Os(), ctx.Arch()) |
| } |
| |
| func (d *Defaults) GenerateAndroidBuildActions(ctx android.ModuleContext) { |
| } |
| |
| func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { |
| ctx := &moduleContext{ |
| ModuleContext: actx, |
| } |
| |
| apexInfo, _ := android.ModuleProvider(actx, android.ApexInfoProvider) |
| if !apexInfo.IsForPlatform() { |
| mod.hideApexVariantFromMake = true |
| } |
| |
| toolchain := mod.toolchain(ctx) |
| mod.makeLinkType = cc.GetMakeLinkType(actx, mod) |
| |
| mod.Properties.SubName = cc.GetSubnameProperty(actx, mod) |
| |
| if !toolchain.Supported() { |
| // This toolchain's unsupported, there's nothing to do for this mod. |
| return |
| } |
| |
| deps := mod.depsToPaths(ctx) |
| // Export linkDirs for CC rust generatedlibs |
| mod.exportedLinkDirs = append(mod.exportedLinkDirs, deps.exportedLinkDirs...) |
| mod.exportedLinkDirs = append(mod.exportedLinkDirs, deps.linkDirs...) |
| |
| flags := Flags{ |
| Toolchain: toolchain, |
| } |
| |
| // Calculate rustc flags |
| if mod.afdo != nil { |
| flags, deps = mod.afdo.flags(actx, flags, deps) |
| } |
| if mod.compiler != nil { |
| flags = mod.compiler.compilerFlags(ctx, flags) |
| flags = mod.compiler.cfgFlags(ctx, flags) |
| flags = mod.compiler.featureFlags(ctx, mod, flags) |
| } |
| if mod.coverage != nil { |
| flags, deps = mod.coverage.flags(ctx, flags, deps) |
| } |
| if mod.clippy != nil { |
| flags, deps = mod.clippy.flags(ctx, flags, deps) |
| } |
| if mod.sanitize != nil { |
| flags, deps = mod.sanitize.flags(ctx, flags, deps) |
| } |
| |
| // SourceProvider needs to call GenerateSource() before compiler calls |
| // compile() so it can provide the source. A SourceProvider has |
| // multiple variants (e.g. source, rlib, dylib). Only the "source" |
| // variant is responsible for effectively generating the source. The |
| // remaining variants relies on the "source" variant output. |
| if mod.sourceProvider != nil { |
| if mod.compiler.(libraryInterface).source() { |
| mod.sourceProvider.GenerateSource(ctx, deps) |
| mod.sourceProvider.setSubName(ctx.ModuleSubDir()) |
| } else { |
| sourceMod := actx.GetDirectDepProxyWithTag(mod.Name(), sourceDepTag) |
| sourceLib := android.OtherModuleProviderOrDefault(ctx, sourceMod, RustInfoProvider).SourceProviderInfo |
| mod.sourceProvider.setOutputFiles(sourceLib.Srcs) |
| } |
| ctx.CheckbuildFile(mod.sourceProvider.Srcs()...) |
| } |
| |
| if mod.compiler != nil && !mod.compiler.Disabled() { |
| mod.compiler.initialize(ctx) |
| buildOutput := mod.compiler.compile(ctx, flags, deps) |
| if ctx.Failed() { |
| return |
| } |
| mod.outputFile = android.OptionalPathForPath(buildOutput.outputFile) |
| ctx.CheckbuildFile(buildOutput.outputFile) |
| if buildOutput.kytheFile != nil { |
| mod.kytheFiles = append(mod.kytheFiles, buildOutput.kytheFile) |
| } |
| bloaty.MeasureSizeForPaths(ctx, mod.compiler.strippedOutputFilePath(), android.OptionalPathForPath(mod.compiler.unstrippedOutputFilePath())) |
| |
| mod.docTimestampFile = mod.compiler.rustdoc(ctx, flags, deps) |
| |
| apexInfo, _ := android.ModuleProvider(actx, android.ApexInfoProvider) |
| if !proptools.BoolDefault(mod.Installable(), mod.EverInstallable()) && !mod.ProcMacro() { |
| // If the module has been specifically configure to not be installed then |
| // hide from make as otherwise it will break when running inside make as the |
| // output path to install will not be specified. Not all uninstallable |
| // modules can be hidden from make as some are needed for resolving make |
| // side dependencies. In particular, proc-macros need to be captured in the |
| // host snapshot. |
| mod.HideFromMake() |
| mod.SkipInstall() |
| } else if !mod.installable(apexInfo) { |
| mod.SkipInstall() |
| } |
| |
| // Still call install though, the installs will be stored as PackageSpecs to allow |
| // using the outputs in a genrule. |
| if mod.OutputFile().Valid() { |
| mod.compiler.install(ctx) |
| if ctx.Failed() { |
| return |
| } |
| // Export your own directory as a linkDir |
| mod.exportedLinkDirs = append(mod.exportedLinkDirs, linkPathFromFilePath(mod.OutputFile().Path())) |
| |
| } |
| |
| android.SetProvider(ctx, cc.ImplementationDepInfoProvider, &cc.ImplementationDepInfo{ |
| ImplementationDeps: depset.New(depset.PREORDER, deps.directImplementationDeps, deps.transitiveImplementationDeps), |
| }) |
| |
| ctx.Phony("rust", ctx.RustModule().OutputFile().Path()) |
| } |
| |
| linkableInfo := cc.CreateCommonLinkableInfo(ctx, mod) |
| linkableInfo.Static = mod.Static() |
| linkableInfo.Shared = mod.Shared() |
| linkableInfo.CrateName = mod.CrateName() |
| linkableInfo.ExportedCrateLinkDirs = mod.ExportedCrateLinkDirs() |
| if lib, ok := mod.compiler.(cc.VersionedInterface); ok { |
| linkableInfo.StubsVersion = lib.StubsVersion() |
| } |
| |
| android.SetProvider(ctx, cc.LinkableInfoProvider, linkableInfo) |
| |
| rustInfo := &RustInfo{ |
| AndroidMkSuffix: mod.AndroidMkSuffix(), |
| RustSubName: mod.Properties.RustSubName, |
| TransitiveAndroidMkSharedLibs: mod.transitiveAndroidMkSharedLibs, |
| XrefRustFiles: mod.XrefRustFiles(), |
| DocTimestampFile: mod.docTimestampFile, |
| } |
| if mod.compiler != nil { |
| rustInfo.CompilerInfo = &CompilerInfo{ |
| NoStdlibs: mod.compiler.noStdlibs(), |
| StdLinkageForDevice: mod.compiler.stdLinkage(true), |
| StdLinkageForNonDevice: mod.compiler.stdLinkage(false), |
| } |
| if lib, ok := mod.compiler.(libraryInterface); ok { |
| rustInfo.CompilerInfo.LibraryInfo = &LibraryInfo{ |
| Dylib: lib.dylib(), |
| Rlib: lib.rlib(), |
| } |
| } |
| if lib, ok := mod.compiler.(cc.SnapshotInterface); ok { |
| rustInfo.SnapshotInfo = &cc.SnapshotInfo{ |
| SnapshotAndroidMkSuffix: lib.SnapshotAndroidMkSuffix(), |
| } |
| } |
| } |
| if mod.sourceProvider != nil { |
| rustInfo.SourceProviderInfo = &SourceProviderInfo{ |
| Srcs: mod.sourceProvider.Srcs(), |
| } |
| if _, ok := mod.sourceProvider.(*protobufDecorator); ok { |
| rustInfo.SourceProviderInfo.ProtobufDecoratorInfo = &ProtobufDecoratorInfo{} |
| } |
| } |
| android.SetProvider(ctx, RustInfoProvider, rustInfo) |
| |
| ccInfo := &cc.CcInfo{ |
| IsPrebuilt: mod.IsPrebuilt(), |
| } |
| |
| // Define the linker info if compiler != nil because Rust currently |
| // does compilation and linking in one step. If this changes in the future, |
| // move this as appropriate. |
| baseCompilerProps := mod.compiler.baseCompilerProps() |
| ccInfo.LinkerInfo = &cc.LinkerInfo{ |
| WholeStaticLibs: baseCompilerProps.Whole_static_libs.GetOrDefault(ctx, nil), |
| StaticLibs: baseCompilerProps.Static_libs.GetOrDefault(ctx, nil), |
| SharedLibs: baseCompilerProps.Shared_libs.GetOrDefault(ctx, nil), |
| } |
| |
| android.SetProvider(ctx, cc.CcInfoProvider, ccInfo) |
| |
| mod.setOutputFiles(ctx) |
| |
| buildComplianceMetadataInfo(ctx, mod, deps) |
| |
| moduleInfoJSON := ctx.ModuleInfoJSON() |
| if mod.compiler != nil { |
| mod.compiler.moduleInfoJSON(ctx, moduleInfoJSON) |
| } |
| } |
| |
| func (mod *Module) setOutputFiles(ctx ModuleContext) { |
| if mod.sourceProvider != nil && (mod.compiler == nil || mod.compiler.Disabled()) { |
| ctx.SetOutputFiles(mod.sourceProvider.Srcs(), "") |
| } else if mod.OutputFile().Valid() { |
| ctx.SetOutputFiles(android.Paths{mod.OutputFile().Path()}, "") |
| } else { |
| ctx.SetOutputFiles(android.Paths{}, "") |
| } |
| if mod.compiler != nil { |
| ctx.SetOutputFiles(android.PathsIfNonNil(mod.compiler.unstrippedOutputFilePath()), "unstripped") |
| } |
| } |
| |
| func buildComplianceMetadataInfo(ctx *moduleContext, mod *Module, deps PathDeps) { |
| // Dump metadata that can not be done in android/compliance-metadata.go |
| metadataInfo := ctx.ComplianceMetadataInfo() |
| metadataInfo.SetStringValue(android.ComplianceMetadataProp.IS_STATIC_LIB, strconv.FormatBool(mod.Static())) |
| metadataInfo.SetStringValue(android.ComplianceMetadataProp.BUILT_FILES, mod.outputFile.String()) |
| |
| // Static libs |
| staticDeps := ctx.GetDirectDepsProxyWithTag(rlibDepTag) |
| staticDepNames := make([]string, 0, len(staticDeps)) |
| for _, dep := range staticDeps { |
| staticDepNames = append(staticDepNames, dep.Name()) |
| } |
| ccStaticDeps := ctx.GetDirectDepsProxyWithTag(cc.StaticDepTag(false)) |
| for _, dep := range ccStaticDeps { |
| staticDepNames = append(staticDepNames, dep.Name()) |
| } |
| |
| staticDepPaths := make([]string, 0, len(deps.StaticLibs)+len(deps.RLibs)) |
| // C static libraries |
| for _, dep := range deps.StaticLibs { |
| staticDepPaths = append(staticDepPaths, dep.String()) |
| } |
| // Rust static libraries |
| for _, dep := range deps.RLibs { |
| staticDepPaths = append(staticDepPaths, dep.Path.String()) |
| } |
| metadataInfo.SetListValue(android.ComplianceMetadataProp.STATIC_DEPS, android.FirstUniqueStrings(staticDepNames)) |
| metadataInfo.SetListValue(android.ComplianceMetadataProp.STATIC_DEP_FILES, android.FirstUniqueStrings(staticDepPaths)) |
| |
| // C Whole static libs |
| ccWholeStaticDeps := ctx.GetDirectDepsProxyWithTag(cc.StaticDepTag(true)) |
| wholeStaticDepNames := make([]string, 0, len(ccWholeStaticDeps)) |
| for _, dep := range ccStaticDeps { |
| wholeStaticDepNames = append(wholeStaticDepNames, dep.Name()) |
| } |
| metadataInfo.SetListValue(android.ComplianceMetadataProp.STATIC_DEPS, android.FirstUniqueStrings(staticDepNames)) |
| } |
| |
| func (mod *Module) deps(ctx DepsContext) Deps { |
| deps := Deps{} |
| |
| if mod.compiler != nil { |
| deps = mod.compiler.compilerDeps(ctx, deps) |
| } |
| if mod.sourceProvider != nil { |
| deps = mod.sourceProvider.SourceProviderDeps(ctx, deps) |
| } |
| |
| if mod.coverage != nil { |
| deps = mod.coverage.deps(ctx, deps) |
| } |
| |
| if mod.sanitize != nil { |
| deps = mod.sanitize.deps(ctx, deps) |
| } |
| |
| deps.Rlibs = android.LastUniqueStrings(deps.Rlibs) |
| deps.Dylibs = android.LastUniqueStrings(deps.Dylibs) |
| deps.Rustlibs = android.LastUniqueStrings(deps.Rustlibs) |
| deps.ProcMacros = android.LastUniqueStrings(deps.ProcMacros) |
| deps.SharedLibs = android.LastUniqueStrings(deps.SharedLibs) |
| deps.StaticLibs = android.LastUniqueStrings(deps.StaticLibs) |
| deps.Stdlibs = android.LastUniqueStrings(deps.Stdlibs) |
| deps.WholeStaticLibs = android.LastUniqueStrings(deps.WholeStaticLibs) |
| return deps |
| |
| } |
| |
| type dependencyTag struct { |
| blueprint.BaseDependencyTag |
| name string |
| library bool |
| procMacro bool |
| dynamic bool |
| } |
| |
| // InstallDepNeeded returns true for rlibs, dylibs, and proc macros so that they or their transitive |
| // dependencies (especially C/C++ shared libs) are installed as dependencies of a rust binary. |
| func (d dependencyTag) InstallDepNeeded() bool { |
| return d.library || d.procMacro |
| } |
| |
| var _ android.InstallNeededDependencyTag = dependencyTag{} |
| |
| func (d dependencyTag) LicenseAnnotations() []android.LicenseAnnotation { |
| if d.library && d.dynamic { |
| return []android.LicenseAnnotation{android.LicenseAnnotationSharedDependency} |
| } |
| return nil |
| } |
| |
| func (d dependencyTag) PropagateAconfigValidation() bool { |
| return d == rlibDepTag || d == sourceDepTag |
| } |
| |
| var _ android.PropagateAconfigValidationDependencyTag = dependencyTag{} |
| |
| var _ android.LicenseAnnotationsDependencyTag = dependencyTag{} |
| |
| var ( |
| customBindgenDepTag = dependencyTag{name: "customBindgenTag"} |
| rlibDepTag = dependencyTag{name: "rlibTag", library: true} |
| dylibDepTag = dependencyTag{name: "dylib", library: true, dynamic: true} |
| procMacroDepTag = dependencyTag{name: "procMacro", procMacro: true} |
| sourceDepTag = dependencyTag{name: "source"} |
| dataLibDepTag = dependencyTag{name: "data lib"} |
| dataBinDepTag = dependencyTag{name: "data bin"} |
| ) |
| |
| func IsDylibDepTag(depTag blueprint.DependencyTag) bool { |
| tag, ok := depTag.(dependencyTag) |
| return ok && tag == dylibDepTag |
| } |
| |
| func IsRlibDepTag(depTag blueprint.DependencyTag) bool { |
| tag, ok := depTag.(dependencyTag) |
| return ok && tag == rlibDepTag |
| } |
| |
| type autoDep struct { |
| variation string |
| depTag dependencyTag |
| } |
| |
| var ( |
| sourceVariation = "source" |
| rlibVariation = "rlib" |
| dylibVariation = "dylib" |
| rlibAutoDep = autoDep{variation: rlibVariation, depTag: rlibDepTag} |
| dylibAutoDep = autoDep{variation: dylibVariation, depTag: dylibDepTag} |
| ) |
| |
| type autoDeppable interface { |
| autoDep(ctx android.BottomUpMutatorContext) autoDep |
| } |
| |
| func (mod *Module) begin(ctx BaseModuleContext) { |
| if mod.coverage != nil { |
| mod.coverage.begin(ctx) |
| } |
| if mod.sanitize != nil { |
| mod.sanitize.begin(ctx) |
| } |
| |
| if mod.UseSdk() && mod.IsSdkVariant() { |
| sdkVersion := "" |
| if ctx.Device() { |
| sdkVersion = mod.SdkVersion() |
| } |
| version, err := cc.NativeApiLevelFromUser(ctx, sdkVersion) |
| if err != nil { |
| ctx.PropertyErrorf("sdk_version", err.Error()) |
| mod.Properties.Sdk_version = nil |
| } else { |
| mod.Properties.Sdk_version = StringPtr(version.String()) |
| } |
| } |
| |
| } |
| |
| func (mod *Module) Prebuilt() *android.Prebuilt { |
| if p, ok := mod.compiler.(rustPrebuilt); ok { |
| return p.prebuilt() |
| } |
| return nil |
| } |
| |
| func (mod *Module) Symlinks() []string { |
| // TODO update this to return the list of symlinks when Rust supports defining symlinks |
| return nil |
| } |
| |
| func rustMakeLibName(rustInfo *RustInfo, linkableInfo *cc.LinkableInfo, commonInfo *android.CommonModuleInfo, depName string) string { |
| if rustInfo != nil { |
| // Use base module name for snapshots when exporting to Makefile. |
| if rustInfo.SnapshotInfo != nil { |
| baseName := commonInfo.BaseModuleName |
| return baseName + rustInfo.SnapshotInfo.SnapshotAndroidMkSuffix + rustInfo.AndroidMkSuffix |
| } |
| } |
| return cc.MakeLibName(nil, linkableInfo, commonInfo, depName) |
| } |
| |
| func collectIncludedProtos(mod *Module, rustInfo *RustInfo, linkableInfo *cc.LinkableInfo) { |
| if protoMod, ok := mod.sourceProvider.(*protobufDecorator); ok { |
| if rustInfo.SourceProviderInfo.ProtobufDecoratorInfo != nil { |
| protoMod.additionalCrates = append(protoMod.additionalCrates, linkableInfo.CrateName) |
| } |
| } |
| } |
| |
| func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { |
| var depPaths PathDeps |
| |
| directRlibDeps := []*cc.LinkableInfo{} |
| directDylibDeps := []*cc.LinkableInfo{} |
| directProcMacroDeps := []*cc.LinkableInfo{} |
| directSharedLibDeps := []cc.SharedLibraryInfo{} |
| directStaticLibDeps := [](*cc.LinkableInfo){} |
| directSrcProvidersDeps := []*android.ModuleProxy{} |
| directSrcDeps := []android.SourceFilesInfo{} |
| |
| // For the dependency from platform to apex, use the latest stubs |
| mod.apexSdkVersion = android.FutureApiLevel |
| apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider) |
| if !apexInfo.IsForPlatform() { |
| mod.apexSdkVersion = apexInfo.MinSdkVersion |
| } |
| |
| if android.InList("hwaddress", ctx.Config().SanitizeDevice()) { |
| // In hwasan build, we override apexSdkVersion to the FutureApiLevel(10000) |
| // so that even Q(29/Android10) apexes could use the dynamic unwinder by linking the newer stubs(e.g libc(R+)). |
| // (b/144430859) |
| mod.apexSdkVersion = android.FutureApiLevel |
| } |
| |
| skipModuleList := map[string]bool{} |
| |
| var transitiveAndroidMkSharedLibs []depset.DepSet[string] |
| var directAndroidMkSharedLibs []string |
| |
| ctx.VisitDirectDepsProxy(func(dep android.ModuleProxy) { |
| depName := ctx.OtherModuleName(dep) |
| depTag := ctx.OtherModuleDependencyTag(dep) |
| modStdLinkage := mod.compiler.stdLinkage(ctx.Device()) |
| |
| if _, exists := skipModuleList[depName]; exists { |
| return |
| } |
| |
| if depTag == android.DarwinUniversalVariantTag { |
| return |
| } |
| |
| rustInfo, hasRustInfo := android.OtherModuleProvider(ctx, dep, RustInfoProvider) |
| ccInfo, _ := android.OtherModuleProvider(ctx, dep, cc.CcInfoProvider) |
| linkableInfo, hasLinkableInfo := android.OtherModuleProvider(ctx, dep, cc.LinkableInfoProvider) |
| commonInfo := android.OtherModulePointerProviderOrDefault(ctx, dep, android.CommonModuleInfoProvider) |
| if hasRustInfo && !linkableInfo.Static && !linkableInfo.Shared { |
| //Handle Rust Modules |
| makeLibName := rustMakeLibName(rustInfo, linkableInfo, commonInfo, depName+rustInfo.RustSubName) |
| |
| switch { |
| case depTag == dylibDepTag: |
| dylib := rustInfo.CompilerInfo.LibraryInfo |
| if dylib == nil || !dylib.Dylib { |
| ctx.ModuleErrorf("mod %q not an dylib library", depName) |
| return |
| } |
| directDylibDeps = append(directDylibDeps, linkableInfo) |
| mod.Properties.AndroidMkDylibs = append(mod.Properties.AndroidMkDylibs, makeLibName) |
| mod.Properties.SnapshotDylibs = append(mod.Properties.SnapshotDylibs, cc.BaseLibName(depName)) |
| |
| depPaths.directImplementationDeps = append(depPaths.directImplementationDeps, android.OutputFileForModule(ctx, dep, "")) |
| if info, ok := android.OtherModuleProvider(ctx, dep, cc.ImplementationDepInfoProvider); ok { |
| depPaths.transitiveImplementationDeps = append(depPaths.transitiveImplementationDeps, info.ImplementationDeps) |
| } |
| |
| if !rustInfo.CompilerInfo.NoStdlibs { |
| rustDepStdLinkage := rustInfo.CompilerInfo.StdLinkageForNonDevice |
| if ctx.Device() { |
| rustDepStdLinkage = rustInfo.CompilerInfo.StdLinkageForDevice |
| } |
| if rustDepStdLinkage != modStdLinkage { |
| ctx.ModuleErrorf("Rust dependency %q has the wrong StdLinkage; expected %#v, got %#v", depName, modStdLinkage, rustDepStdLinkage) |
| return |
| } |
| } |
| |
| case depTag == rlibDepTag: |
| rlib := rustInfo.CompilerInfo.LibraryInfo |
| if rlib == nil || !rlib.Rlib { |
| ctx.ModuleErrorf("mod %q not an rlib library", makeLibName) |
| return |
| } |
| directRlibDeps = append(directRlibDeps, linkableInfo) |
| mod.Properties.AndroidMkRlibs = append(mod.Properties.AndroidMkRlibs, makeLibName) |
| mod.Properties.SnapshotRlibs = append(mod.Properties.SnapshotRlibs, cc.BaseLibName(depName)) |
| |
| // rust_ffi rlibs may export include dirs, so collect those here. |
| exportedInfo, _ := android.OtherModuleProvider(ctx, dep, cc.FlagExporterInfoProvider) |
| depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...) |
| depPaths.exportedLinkDirs = append(depPaths.exportedLinkDirs, linkPathFromFilePath(linkableInfo.OutputFile.Path())) |
| |
| // rlibs are not installed, so don't add the output file to directImplementationDeps |
| if info, ok := android.OtherModuleProvider(ctx, dep, cc.ImplementationDepInfoProvider); ok { |
| depPaths.transitiveImplementationDeps = append(depPaths.transitiveImplementationDeps, info.ImplementationDeps) |
| } |
| |
| if !rustInfo.CompilerInfo.NoStdlibs { |
| rustDepStdLinkage := rustInfo.CompilerInfo.StdLinkageForNonDevice |
| if ctx.Device() { |
| rustDepStdLinkage = rustInfo.CompilerInfo.StdLinkageForDevice |
| } |
| if rustDepStdLinkage != modStdLinkage { |
| ctx.ModuleErrorf("Rust dependency %q has the wrong StdLinkage; expected %#v, got %#v", depName, modStdLinkage, rustDepStdLinkage) |
| return |
| } |
| } |
| |
| if !mod.Rlib() { |
| depPaths.ccRlibDeps = append(depPaths.ccRlibDeps, exportedInfo.RustRlibDeps...) |
| } else { |
| // rlibs need to reexport these |
| depPaths.reexportedCcRlibDeps = append(depPaths.reexportedCcRlibDeps, exportedInfo.RustRlibDeps...) |
| } |
| |
| case depTag == procMacroDepTag: |
| directProcMacroDeps = append(directProcMacroDeps, linkableInfo) |
| mod.Properties.AndroidMkProcMacroLibs = append(mod.Properties.AndroidMkProcMacroLibs, makeLibName) |
| // proc_macro link dirs need to be exported, so collect those here. |
| depPaths.exportedLinkDirs = append(depPaths.exportedLinkDirs, linkPathFromFilePath(linkableInfo.OutputFile.Path())) |
| |
| case depTag == sourceDepTag: |
| if _, ok := mod.sourceProvider.(*protobufDecorator); ok { |
| collectIncludedProtos(mod, rustInfo, linkableInfo) |
| } |
| case cc.IsStaticDepTag(depTag): |
| // Rust FFI rlibs should not be declared in a Rust modules |
| // "static_libs" list as we can't handle them properly at the |
| // moment (for example, they only produce an rlib-std variant). |
| // Instead, a normal rust_library variant should be used. |
| ctx.PropertyErrorf("static_libs", |
| "found '%s' in static_libs; use a rust_library module in rustlibs instead of a rust_ffi module in static_libs", |
| depName) |
| |
| } |
| |
| transitiveAndroidMkSharedLibs = append(transitiveAndroidMkSharedLibs, rustInfo.TransitiveAndroidMkSharedLibs) |
| |
| if android.IsSourceDepTagWithOutputTag(depTag, "") { |
| // Since these deps are added in path_properties.go via AddDependencies, we need to ensure the correct |
| // OS/Arch variant is used. |
| var helper string |
| if ctx.Host() { |
| helper = "missing 'host_supported'?" |
| } else { |
| helper = "device module defined?" |
| } |
| |
| if commonInfo.Target.Os != ctx.Os() { |
| ctx.ModuleErrorf("OS mismatch on dependency %q (%s)", dep.Name(), helper) |
| return |
| } else if commonInfo.Target.Arch.ArchType != ctx.Arch().ArchType { |
| ctx.ModuleErrorf("Arch mismatch on dependency %q (%s)", dep.Name(), helper) |
| return |
| } |
| directSrcProvidersDeps = append(directSrcProvidersDeps, &dep) |
| } |
| |
| exportedRustInfo, _ := android.OtherModuleProvider(ctx, dep, RustFlagExporterInfoProvider) |
| exportedInfo, _ := android.OtherModuleProvider(ctx, dep, RustFlagExporterInfoProvider) |
| //Append the dependencies exported objects, except for proc-macros which target a different arch/OS |
| if depTag != procMacroDepTag { |
| depPaths.depFlags = append(depPaths.depFlags, exportedInfo.Flags...) |
| depPaths.rustLibObjects = append(depPaths.rustLibObjects, exportedInfo.RustLibObjects...) |
| depPaths.sharedLibObjects = append(depPaths.sharedLibObjects, exportedInfo.SharedLibPaths...) |
| depPaths.staticLibObjects = append(depPaths.staticLibObjects, exportedInfo.StaticLibObjects...) |
| depPaths.wholeStaticLibObjects = append(depPaths.wholeStaticLibObjects, exportedInfo.WholeStaticLibObjects...) |
| depPaths.linkDirs = append(depPaths.linkDirs, exportedInfo.LinkDirs...) |
| |
| depPaths.reexportedWholeCcRlibDeps = append(depPaths.reexportedWholeCcRlibDeps, exportedRustInfo.WholeRustRlibDeps...) |
| if !mod.Rlib() { |
| depPaths.ccRlibDeps = append(depPaths.ccRlibDeps, exportedRustInfo.WholeRustRlibDeps...) |
| } |
| } |
| |
| if depTag == dylibDepTag || depTag == rlibDepTag || depTag == procMacroDepTag { |
| linkFile := linkableInfo.UnstrippedOutputFile |
| linkDir := linkPathFromFilePath(linkFile) |
| if lib, ok := mod.compiler.(exportedFlagsProducer); ok { |
| lib.exportLinkDirs(linkDir) |
| } |
| } |
| |
| if depTag == sourceDepTag { |
| if _, ok := mod.sourceProvider.(*protobufDecorator); ok && mod.Source() { |
| if rustInfo.SourceProviderInfo.ProtobufDecoratorInfo != nil { |
| exportedInfo, _ := android.OtherModuleProvider(ctx, dep, cc.FlagExporterInfoProvider) |
| depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...) |
| } |
| } |
| } |
| } else if hasLinkableInfo { |
| //Handle C dependencies |
| makeLibName := cc.MakeLibName(ccInfo, linkableInfo, commonInfo, depName) |
| if !hasRustInfo { |
| if commonInfo.Target.Os != ctx.Os() { |
| ctx.ModuleErrorf("OS mismatch between %q and %q", ctx.ModuleName(), depName) |
| return |
| } |
| if commonInfo.Target.Arch.ArchType != ctx.Arch().ArchType { |
| ctx.ModuleErrorf("Arch mismatch between %q and %q", ctx.ModuleName(), depName) |
| return |
| } |
| } |
| ccLibPath := linkableInfo.OutputFile |
| if !ccLibPath.Valid() { |
| if !ctx.Config().AllowMissingDependencies() { |
| ctx.ModuleErrorf("Invalid output file when adding dep %q to %q", depName, ctx.ModuleName()) |
| } else { |
| ctx.AddMissingDependencies([]string{depName}) |
| } |
| return |
| } |
| |
| linkPath := linkPathFromFilePath(ccLibPath.Path()) |
| |
| exportDep := false |
| switch { |
| case cc.IsStaticDepTag(depTag): |
| if cc.IsWholeStaticLib(depTag) { |
| // rustc will bundle static libraries when they're passed with "-lstatic=<lib>". This will fail |
| // if the library is not prefixed by "lib". |
| if mod.Binary() { |
| // Since binaries don't need to 'rebundle' these like libraries and only use these for the |
| // final linkage, pass the args directly to the linker to handle these cases. |
| depPaths.depLinkFlags = append(depPaths.depLinkFlags, []string{"-Wl,--whole-archive", ccLibPath.Path().String(), "-Wl,--no-whole-archive"}...) |
| } else if libName, ok := libNameFromFilePath(ccLibPath.Path()); ok { |
| depPaths.depFlags = append(depPaths.depFlags, "-lstatic:+whole-archive="+libName) |
| depPaths.depLinkFlags = append(depPaths.depLinkFlags, ccLibPath.Path().String()) |
| } else { |
| ctx.ModuleErrorf("'%q' cannot be listed as a whole_static_library in Rust modules unless the output is prefixed by 'lib'", depName, ctx.ModuleName()) |
| } |
| } |
| |
| exportedInfo, _ := android.OtherModuleProvider(ctx, dep, cc.FlagExporterInfoProvider) |
| if cc.IsWholeStaticLib(depTag) { |
| // Add whole staticlibs to wholeStaticLibObjects to propagate to Rust all dependents. |
| depPaths.wholeStaticLibObjects = append(depPaths.wholeStaticLibObjects, ccLibPath.String()) |
| |
| // We also propagate forward whole-static'd cc staticlibs with rust_ffi_rlib dependencies |
| // We don't need to check a hypothetical exportedRustInfo.WholeRustRlibDeps because we |
| // wouldn't expect a rust_ffi_rlib to be listed in `static_libs` (Soong explicitly disallows this) |
| depPaths.reexportedWholeCcRlibDeps = append(depPaths.reexportedWholeCcRlibDeps, exportedInfo.RustRlibDeps...) |
| } else { |
| // If not whole_static, add to staticLibObjects, which only propagate through rlibs to their dependents. |
| depPaths.staticLibObjects = append(depPaths.staticLibObjects, ccLibPath.String()) |
| |
| if mod.Rlib() { |
| // rlibs propagate their inherited rust_ffi_rlibs forward. |
| depPaths.reexportedCcRlibDeps = append(depPaths.reexportedCcRlibDeps, exportedInfo.RustRlibDeps...) |
| } |
| } |
| |
| depPaths.linkDirs = append(depPaths.linkDirs, linkPath) |
| depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...) |
| depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...) |
| depPaths.depClangFlags = append(depPaths.depClangFlags, exportedInfo.Flags...) |
| depPaths.depGeneratedHeaders = append(depPaths.depGeneratedHeaders, exportedInfo.GeneratedHeaders...) |
| |
| if !mod.Rlib() { |
| // rlibs don't need to build the generated static library, so they don't need to track these. |
| depPaths.ccRlibDeps = append(depPaths.ccRlibDeps, exportedInfo.RustRlibDeps...) |
| } |
| |
| directStaticLibDeps = append(directStaticLibDeps, linkableInfo) |
| |
| // Record baseLibName for snapshots. |
| mod.Properties.SnapshotStaticLibs = append(mod.Properties.SnapshotStaticLibs, cc.BaseLibName(depName)) |
| |
| mod.Properties.AndroidMkStaticLibs = append(mod.Properties.AndroidMkStaticLibs, makeLibName) |
| case cc.IsSharedDepTag(depTag): |
| // For the shared lib dependencies, we may link to the stub variant |
| // of the dependency depending on the context (e.g. if this |
| // dependency crosses the APEX boundaries). |
| sharedLibraryInfo, exportedInfo := cc.ChooseStubOrImpl(ctx, dep) |
| |
| if !sharedLibraryInfo.IsStubs { |
| // TODO(b/362509506): remove this additional check once all apex_exclude uses are switched to stubs. |
| if !linkableInfo.RustApexExclude { |
| depPaths.directImplementationDeps = append(depPaths.directImplementationDeps, android.OutputFileForModule(ctx, dep, "")) |
| if info, ok := android.OtherModuleProvider(ctx, dep, cc.ImplementationDepInfoProvider); ok { |
| depPaths.transitiveImplementationDeps = append(depPaths.transitiveImplementationDeps, info.ImplementationDeps) |
| } |
| } |
| } |
| |
| // Re-get linkObject as ChooseStubOrImpl actually tells us which |
| // object (either from stub or non-stub) to use. |
| ccLibPath = android.OptionalPathForPath(sharedLibraryInfo.SharedLibrary) |
| if !ccLibPath.Valid() { |
| if !ctx.Config().AllowMissingDependencies() { |
| ctx.ModuleErrorf("Invalid output file when adding dep %q to %q", depName, ctx.ModuleName()) |
| } else { |
| ctx.AddMissingDependencies([]string{depName}) |
| } |
| return |
| } |
| linkPath = linkPathFromFilePath(ccLibPath.Path()) |
| |
| depPaths.linkDirs = append(depPaths.linkDirs, linkPath) |
| depPaths.sharedLibObjects = append(depPaths.sharedLibObjects, ccLibPath.String()) |
| depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...) |
| depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...) |
| depPaths.depClangFlags = append(depPaths.depClangFlags, exportedInfo.Flags...) |
| depPaths.depGeneratedHeaders = append(depPaths.depGeneratedHeaders, exportedInfo.GeneratedHeaders...) |
| directSharedLibDeps = append(directSharedLibDeps, sharedLibraryInfo) |
| |
| // Record baseLibName for snapshots. |
| mod.Properties.SnapshotSharedLibs = append(mod.Properties.SnapshotSharedLibs, cc.BaseLibName(depName)) |
| |
| directAndroidMkSharedLibs = append(directAndroidMkSharedLibs, makeLibName) |
| exportDep = true |
| case cc.IsHeaderDepTag(depTag): |
| exportedInfo, _ := android.OtherModuleProvider(ctx, dep, cc.FlagExporterInfoProvider) |
| depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...) |
| depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...) |
| depPaths.depGeneratedHeaders = append(depPaths.depGeneratedHeaders, exportedInfo.GeneratedHeaders...) |
| mod.Properties.AndroidMkHeaderLibs = append(mod.Properties.AndroidMkHeaderLibs, makeLibName) |
| case depTag == cc.CrtBeginDepTag: |
| depPaths.CrtBegin = append(depPaths.CrtBegin, ccLibPath.Path()) |
| case depTag == cc.CrtEndDepTag: |
| depPaths.CrtEnd = append(depPaths.CrtEnd, ccLibPath.Path()) |
| } |
| |
| // Make sure shared dependencies are propagated |
| if lib, ok := mod.compiler.(exportedFlagsProducer); ok && exportDep { |
| lib.exportLinkDirs(linkPath) |
| lib.exportSharedLibs(ccLibPath.String()) |
| } |
| } else { |
| switch { |
| case depTag == cc.CrtBeginDepTag: |
| depPaths.CrtBegin = append(depPaths.CrtBegin, android.OutputFileForModule(ctx, dep, "")) |
| case depTag == cc.CrtEndDepTag: |
| depPaths.CrtEnd = append(depPaths.CrtEnd, android.OutputFileForModule(ctx, dep, "")) |
| } |
| } |
| |
| if srcDep, ok := android.OtherModuleProvider(ctx, dep, android.SourceFilesInfoProvider); ok { |
| if android.IsSourceDepTagWithOutputTag(depTag, "") { |
| // These are usually genrules which don't have per-target variants. |
| directSrcDeps = append(directSrcDeps, srcDep) |
| } |
| } |
| }) |
| |
| mod.transitiveAndroidMkSharedLibs = depset.New[string](depset.PREORDER, directAndroidMkSharedLibs, transitiveAndroidMkSharedLibs) |
| |
| var rlibDepFiles RustLibraries |
| aliases := mod.compiler.Aliases() |
| for _, dep := range directRlibDeps { |
| crateName := dep.CrateName |
| if alias, aliased := aliases[crateName]; aliased { |
| crateName = alias |
| } |
| rlibDepFiles = append(rlibDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile, CrateName: crateName}) |
| } |
| var dylibDepFiles RustLibraries |
| for _, dep := range directDylibDeps { |
| crateName := dep.CrateName |
| if alias, aliased := aliases[crateName]; aliased { |
| crateName = alias |
| } |
| dylibDepFiles = append(dylibDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile, CrateName: crateName}) |
| } |
| var procMacroDepFiles RustLibraries |
| for _, dep := range directProcMacroDeps { |
| crateName := dep.CrateName |
| if alias, aliased := aliases[crateName]; aliased { |
| crateName = alias |
| } |
| procMacroDepFiles = append(procMacroDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile, CrateName: crateName}) |
| } |
| |
| var staticLibDepFiles android.Paths |
| for _, dep := range directStaticLibDeps { |
| staticLibDepFiles = append(staticLibDepFiles, dep.OutputFile.Path()) |
| } |
| |
| var sharedLibFiles android.Paths |
| var sharedLibDepFiles android.Paths |
| for _, dep := range directSharedLibDeps { |
| sharedLibFiles = append(sharedLibFiles, dep.SharedLibrary) |
| if dep.TableOfContents.Valid() { |
| sharedLibDepFiles = append(sharedLibDepFiles, dep.TableOfContents.Path()) |
| } else { |
| sharedLibDepFiles = append(sharedLibDepFiles, dep.SharedLibrary) |
| } |
| } |
| |
| var srcProviderDepFiles android.Paths |
| for _, dep := range directSrcProvidersDeps { |
| srcs := android.OutputFilesForModule(ctx, *dep, "") |
| srcProviderDepFiles = append(srcProviderDepFiles, srcs...) |
| } |
| for _, dep := range directSrcDeps { |
| srcs := dep.Srcs |
| srcProviderDepFiles = append(srcProviderDepFiles, srcs...) |
| } |
| |
| depPaths.RLibs = append(depPaths.RLibs, rlibDepFiles...) |
| depPaths.DyLibs = append(depPaths.DyLibs, dylibDepFiles...) |
| depPaths.SharedLibs = append(depPaths.SharedLibs, sharedLibFiles...) |
| depPaths.SharedLibDeps = append(depPaths.SharedLibDeps, sharedLibDepFiles...) |
| depPaths.StaticLibs = append(depPaths.StaticLibs, staticLibDepFiles...) |
| depPaths.ProcMacros = append(depPaths.ProcMacros, procMacroDepFiles...) |
| depPaths.SrcDeps = append(depPaths.SrcDeps, srcProviderDepFiles...) |
| |
| // Dedup exported flags from dependencies |
| depPaths.linkDirs = android.FirstUniqueStrings(depPaths.linkDirs) |
| depPaths.rustLibObjects = android.FirstUniqueStrings(depPaths.rustLibObjects) |
| depPaths.staticLibObjects = android.FirstUniqueStrings(depPaths.staticLibObjects) |
| depPaths.wholeStaticLibObjects = android.FirstUniqueStrings(depPaths.wholeStaticLibObjects) |
| depPaths.sharedLibObjects = android.FirstUniqueStrings(depPaths.sharedLibObjects) |
| depPaths.depFlags = android.FirstUniqueStrings(depPaths.depFlags) |
| depPaths.depClangFlags = android.FirstUniqueStrings(depPaths.depClangFlags) |
| depPaths.depIncludePaths = android.FirstUniquePaths(depPaths.depIncludePaths) |
| depPaths.depSystemIncludePaths = android.FirstUniquePaths(depPaths.depSystemIncludePaths) |
| depPaths.depLinkFlags = android.FirstUniqueStrings(depPaths.depLinkFlags) |
| depPaths.reexportedCcRlibDeps = android.FirstUniqueFunc(depPaths.reexportedCcRlibDeps, cc.EqRustRlibDeps) |
| depPaths.reexportedWholeCcRlibDeps = android.FirstUniqueFunc(depPaths.reexportedWholeCcRlibDeps, cc.EqRustRlibDeps) |
| depPaths.ccRlibDeps = android.FirstUniqueFunc(depPaths.ccRlibDeps, cc.EqRustRlibDeps) |
| |
| return depPaths |
| } |
| |
| func (mod *Module) InstallInData() bool { |
| if mod.compiler == nil { |
| return false |
| } |
| return mod.compiler.inData() |
| } |
| |
| func (mod *Module) InstallInRamdisk() bool { |
| return mod.InRamdisk() |
| } |
| |
| func (mod *Module) InstallInVendorRamdisk() bool { |
| return mod.InVendorRamdisk() |
| } |
| |
| func (mod *Module) InstallInRecovery() bool { |
| return mod.InRecovery() |
| } |
| |
| func linkPathFromFilePath(filepath android.Path) string { |
| return strings.Split(filepath.String(), filepath.Base())[0] |
| } |
| |
| // usePublicApi returns true if the rust variant should link against NDK (publicapi) |
| func (r *Module) usePublicApi() bool { |
| return r.Device() && r.UseSdk() |
| } |
| |
| // useVendorApi returns true if the rust variant should link against LLNDK (vendorapi) |
| func (r *Module) useVendorApi() bool { |
| return r.Device() && (r.InVendor() || r.InProduct()) |
| } |
| |
| func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) { |
| ctx := &depsContext{ |
| BottomUpMutatorContext: actx, |
| } |
| |
| deps := mod.deps(ctx) |
| var commonDepVariations []blueprint.Variation |
| |
| if ctx.Os() == android.Android { |
| deps.SharedLibs, _ = cc.FilterNdkLibs(mod, ctx.Config(), deps.SharedLibs) |
| } |
| |
| stdLinkage := "dylib-std" |
| if mod.compiler.stdLinkage(ctx.Device()) == RlibLinkage { |
| stdLinkage = "rlib-std" |
| } |
| |
| rlibDepVariations := commonDepVariations |
| |
| if lib, ok := mod.compiler.(libraryInterface); !ok || !lib.sysroot() { |
| rlibDepVariations = append(rlibDepVariations, |
| blueprint.Variation{Mutator: "rust_stdlinkage", Variation: stdLinkage}) |
| } |
| |
| // rlibs |
| rlibDepVariations = append(rlibDepVariations, blueprint.Variation{Mutator: "rust_libraries", Variation: rlibVariation}) |
| for _, lib := range deps.Rlibs { |
| depTag := rlibDepTag |
| actx.AddVariationDependencies(rlibDepVariations, depTag, lib) |
| } |
| |
| // dylibs |
| dylibDepVariations := append(commonDepVariations, blueprint.Variation{Mutator: "rust_libraries", Variation: dylibVariation}) |
| |
| for _, lib := range deps.Dylibs { |
| actx.AddVariationDependencies(dylibDepVariations, dylibDepTag, lib) |
| } |
| |
| // rustlibs |
| if deps.Rustlibs != nil { |
| if !mod.compiler.Disabled() { |
| for _, lib := range deps.Rustlibs { |
| autoDep := mod.compiler.(autoDeppable).autoDep(ctx) |
| if autoDep.depTag == rlibDepTag { |
| // Handle the rlib deptag case |
| actx.AddVariationDependencies(rlibDepVariations, rlibDepTag, lib) |
| |
| } else { |
| // autoDep.depTag is a dylib depTag. Not all rustlibs may be available as a dylib however. |
| // Check for the existence of the dylib deptag variant. Select it if available, |
| // otherwise select the rlib variant. |
| autoDepVariations := append(commonDepVariations, |
| blueprint.Variation{Mutator: "rust_libraries", Variation: autoDep.variation}) |
| if actx.OtherModuleDependencyVariantExists(autoDepVariations, lib) { |
| actx.AddVariationDependencies(autoDepVariations, autoDep.depTag, lib) |
| |
| } else { |
| // If there's no dylib dependency available, try to add the rlib dependency instead. |
| actx.AddVariationDependencies(rlibDepVariations, rlibDepTag, lib) |
| |
| } |
| } |
| } |
| } else if _, ok := mod.sourceProvider.(*protobufDecorator); ok { |
| for _, lib := range deps.Rustlibs { |
| srcProviderVariations := append(commonDepVariations, |
| blueprint.Variation{Mutator: "rust_libraries", Variation: sourceVariation}) |
| |
| // Only add rustlib dependencies if they're source providers themselves. |
| // This is used to track which crate names need to be added to the source generated |
| // in the rust_protobuf mod.rs. |
| if actx.OtherModuleDependencyVariantExists(srcProviderVariations, lib) { |
| actx.AddVariationDependencies(srcProviderVariations, sourceDepTag, lib) |
| } |
| } |
| } |
| } |
| |
| // stdlibs |
| if deps.Stdlibs != nil { |
| if mod.compiler.stdLinkage(ctx.Device()) == RlibLinkage { |
| for _, lib := range deps.Stdlibs { |
| actx.AddVariationDependencies(append(commonDepVariations, []blueprint.Variation{{Mutator: "rust_libraries", Variation: "rlib"}}...), |
| rlibDepTag, lib) |
| } |
| } else { |
| for _, lib := range deps.Stdlibs { |
| actx.AddVariationDependencies(dylibDepVariations, dylibDepTag, lib) |
| |
| } |
| } |
| } |
| |
| for _, lib := range deps.SharedLibs { |
| depTag := cc.SharedDepTag() |
| name, version := cc.StubsLibNameAndVersion(lib) |
| |
| variations := []blueprint.Variation{ |
| {Mutator: "link", Variation: "shared"}, |
| } |
| cc.AddSharedLibDependenciesWithVersions(ctx, mod, variations, depTag, name, version, false) |
| } |
| |
| for _, lib := range deps.WholeStaticLibs { |
| depTag := cc.StaticDepTag(true) |
| |
| actx.AddVariationDependencies([]blueprint.Variation{ |
| {Mutator: "link", Variation: "static"}, |
| }, depTag, lib) |
| } |
| |
| for _, lib := range deps.StaticLibs { |
| depTag := cc.StaticDepTag(false) |
| |
| actx.AddVariationDependencies([]blueprint.Variation{ |
| {Mutator: "link", Variation: "static"}, |
| }, depTag, lib) |
| } |
| |
| actx.AddVariationDependencies(nil, cc.HeaderDepTag(), deps.HeaderLibs...) |
| |
| crtVariations := cc.GetCrtVariations(ctx, mod) |
| for _, crt := range deps.CrtBegin { |
| actx.AddVariationDependencies(crtVariations, cc.CrtBeginDepTag, crt) |
| } |
| for _, crt := range deps.CrtEnd { |
| actx.AddVariationDependencies(crtVariations, cc.CrtEndDepTag, crt) |
| } |
| |
| if mod.sourceProvider != nil { |
| if bindgen, ok := mod.sourceProvider.(*bindgenDecorator); ok && |
| bindgen.Properties.Custom_bindgen != "" { |
| actx.AddFarVariationDependencies(ctx.Config().BuildOSTarget.Variations(), customBindgenDepTag, |
| bindgen.Properties.Custom_bindgen) |
| } |
| } |
| |
| actx.AddVariationDependencies([]blueprint.Variation{ |
| {Mutator: "link", Variation: "shared"}, |
| }, dataLibDepTag, deps.DataLibs...) |
| |
| actx.AddVariationDependencies(nil, dataBinDepTag, deps.DataBins...) |
| |
| // proc_macros are compiler plugins, and so we need the host arch variant as a dependendcy. |
| actx.AddFarVariationDependencies(ctx.Config().BuildOSTarget.Variations(), procMacroDepTag, deps.ProcMacros...) |
| |
| mod.afdo.addDep(ctx, actx) |
| } |
| |
| func BeginMutator(ctx android.BottomUpMutatorContext) { |
| if mod, ok := ctx.Module().(*Module); ok && mod.Enabled(ctx) { |
| mod.beginMutator(ctx) |
| } |
| } |
| |
| func (mod *Module) beginMutator(actx android.BottomUpMutatorContext) { |
| ctx := &baseModuleContext{ |
| BaseModuleContext: actx, |
| } |
| |
| mod.begin(ctx) |
| } |
| |
| func (mod *Module) Name() string { |
| name := mod.ModuleBase.Name() |
| if p, ok := mod.compiler.(interface { |
| Name(string) string |
| }); ok { |
| name = p.Name(name) |
| } |
| return name |
| } |
| |
| func (mod *Module) disableClippy() { |
| if mod.clippy != nil { |
| mod.clippy.Properties.Clippy_lints = proptools.StringPtr("none") |
| } |
| } |
| |
| var _ android.HostToolProvider = (*Module)(nil) |
| |
| func (mod *Module) HostToolPath() android.OptionalPath { |
| if !mod.Host() { |
| return android.OptionalPath{} |
| } |
| if binary, ok := mod.compiler.(*binaryDecorator); ok { |
| return android.OptionalPathForPath(binary.baseCompiler.path) |
| } else if pm, ok := mod.compiler.(*procMacroDecorator); ok { |
| // Even though proc-macros aren't strictly "tools", since they target the compiler |
| // and act as compiler plugins, we treat them similarly. |
| return android.OptionalPathForPath(pm.baseCompiler.path) |
| } |
| return android.OptionalPath{} |
| } |
| |
| var _ android.ApexModule = (*Module)(nil) |
| |
| // If a module is marked for exclusion from apexes, don't provide apex variants. |
| // TODO(b/362509506): remove this once all apex_exclude usages are removed. |
| func (m *Module) CanHaveApexVariants() bool { |
| if m.ApexExclude() { |
| return false |
| } else { |
| return m.ApexModuleBase.CanHaveApexVariants() |
| } |
| } |
| |
| func (mod *Module) MinSdkVersion() string { |
| return String(mod.Properties.Min_sdk_version) |
| } |
| |
| // Implements android.ApexModule |
| func (mod *Module) MinSdkVersionSupported(ctx android.BaseModuleContext) android.ApiLevel { |
| minSdkVersion := mod.MinSdkVersion() |
| if minSdkVersion == "apex_inherit" { |
| return android.MinApiLevel |
| } |
| |
| if minSdkVersion == "" { |
| return android.NoneApiLevel |
| } |
| // Not using nativeApiLevelFromUser because the context here is not |
| // necessarily a native context. |
| ver, err := android.ApiLevelFromUserWithConfig(ctx.Config(), minSdkVersion) |
| if err != nil { |
| return android.NoneApiLevel |
| } |
| |
| return ver |
| } |
| |
| // Implements android.ApexModule |
| func (mod *Module) AlwaysRequiresPlatformApexVariant() bool { |
| // stub libraries and native bridge libraries are always available to platform |
| // TODO(b/362509506): remove the ApexExclude() check once all apex_exclude uses are switched to stubs. |
| return mod.IsStubs() || mod.Target().NativeBridge == android.NativeBridgeEnabled || mod.ApexExclude() |
| } |
| |
| // Implements android.ApexModule |
| type RustDepInSameApexChecker struct { |
| Static bool |
| HasStubsVariants bool |
| ApexExclude bool |
| Host bool |
| } |
| |
| func (mod *Module) GetDepInSameApexChecker() android.DepInSameApexChecker { |
| return RustDepInSameApexChecker{ |
| Static: mod.Static(), |
| HasStubsVariants: mod.HasStubsVariants(), |
| ApexExclude: mod.ApexExclude(), |
| Host: mod.Host(), |
| } |
| } |
| |
| func (r RustDepInSameApexChecker) OutgoingDepIsInSameApex(depTag blueprint.DependencyTag) bool { |
| if depTag == procMacroDepTag || depTag == customBindgenDepTag { |
| return false |
| } |
| |
| if r.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 == cc.StubImplDepTag { |
| // We don't track from an implementation library to its stubs. |
| return false |
| } |
| |
| if cc.ExcludeInApexDepTag(depTag) { |
| return false |
| } |
| |
| // TODO(b/362509506): remove once all apex_exclude uses are switched to stubs. |
| if r.ApexExclude { |
| return false |
| } |
| |
| return true |
| } |
| |
| func (r RustDepInSameApexChecker) IncomingDepIsInSameApex(depTag blueprint.DependencyTag) bool { |
| if r.Host { |
| return false |
| } |
| // TODO(b/362509506): remove once all apex_exclude uses are switched to stubs. |
| if r.ApexExclude { |
| return false |
| } |
| |
| if r.HasStubsVariants { |
| if cc.IsSharedDepTag(depTag) && !cc.IsExplicitImplSharedDepTag(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 |
| } |
| } |
| return true |
| } |
| |
| // Overrides ApexModule.IsInstallabeToApex() |
| func (mod *Module) IsInstallableToApex() bool { |
| // TODO(b/362509506): remove once all apex_exclude uses are switched to stubs. |
| if mod.ApexExclude() { |
| return false |
| } |
| |
| if mod.compiler != nil { |
| if lib, ok := mod.compiler.(libraryInterface); ok { |
| return (lib.shared() || lib.dylib()) && !lib.BuildStubs() |
| } |
| if _, ok := mod.compiler.(*binaryDecorator); ok { |
| return true |
| } |
| } |
| return false |
| } |
| |
| // If a library file has a "lib" prefix, extract the library name without the prefix. |
| func libNameFromFilePath(filepath android.Path) (string, bool) { |
| libName := strings.TrimSuffix(filepath.Base(), filepath.Ext()) |
| if strings.HasPrefix(libName, "lib") { |
| libName = libName[3:] |
| return libName, true |
| } |
| return "", false |
| } |
| |
| func kytheExtractRustFactory() android.Singleton { |
| return &kytheExtractRustSingleton{} |
| } |
| |
| type kytheExtractRustSingleton struct { |
| } |
| |
| func (k kytheExtractRustSingleton) GenerateBuildActions(ctx android.SingletonContext) { |
| var xrefTargets android.Paths |
| ctx.VisitAllModuleProxies(func(module android.ModuleProxy) { |
| if rustModule, ok := android.OtherModuleProvider(ctx, module, RustInfoProvider); ok { |
| xrefTargets = append(xrefTargets, rustModule.XrefRustFiles...) |
| } |
| }) |
| if len(xrefTargets) > 0 { |
| ctx.Phony("xref_rust", xrefTargets...) |
| } |
| } |
| |
| func (c *Module) Partition() string { |
| return "" |
| } |
| |
| var Bool = proptools.Bool |
| var BoolDefault = proptools.BoolDefault |
| var String = proptools.String |
| var StringPtr = proptools.StringPtr |