| // 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") | |
| 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 | |
| // Minimum sdk version that the artifact should support when it runs as part of mainline modules(APEX). | |
| Min_sdk_version *string | |
| 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] | |
| } | |
| 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 { | |
| return mod.VendorProperties.IsVendorPublicLibrary | |
| } | |
| func (mod *Module) SdkAndPlatformVariantVisibleToMake() bool { | |
| // Rust modules to not provide Sdk variants | |
| return false | |
| } | |
| func (c *Module) IsVndkPrivate() bool { | |
| return false | |
| } | |
| func (c *Module) IsLlndk() bool { | |
| return false | |
| } | |
| func (mod *Module) KernelHeadersDecorator() bool { | |
| return false | |
| } | |
| func (m *Module) NeedsLlndkVariants() bool { | |
| return false | |
| } | |
| func (m *Module) NeedsVendorPublicLibraryVariants() bool { | |
| return false | |
| } | |
| func (mod *Module) HasLlndkStubs() bool { | |
| return false | |
| } | |
| func (mod *Module) StubsVersion() string { | |
| panic(fmt.Errorf("StubsVersion called on non-versioned module: %q", mod.BaseModuleName())) | |
| } | |
| func (mod *Module) SdkVersion() string { | |
| return "" | |
| } | |
| func (mod *Module) AlwaysSdk() bool { | |
| return false | |
| } | |
| func (mod *Module) IsSdkVariant() bool { | |
| return false | |
| } | |
| func (mod *Module) SplitPerApiLevel() bool { | |
| return false | |
| } | |
| 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 | |
| // 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 | |
| linkObjects []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) | |
| exportLinkObjects(...string) | |
| } | |
| type xref interface { | |
| XrefRustFiles() android.Paths | |
| } | |
| type flagExporter struct { | |
| linkDirs []string | |
| ccLinkDirs []string | |
| linkObjects []string | |
| } | |
| func (flagExporter *flagExporter) exportLinkDirs(dirs ...string) { | |
| flagExporter.linkDirs = android.FirstUniqueStrings(append(flagExporter.linkDirs, dirs...)) | |
| } | |
| func (flagExporter *flagExporter) exportLinkObjects(flags ...string) { | |
| flagExporter.linkObjects = android.FirstUniqueStrings(append(flagExporter.linkObjects, flags...)) | |
| } | |
| func (flagExporter *flagExporter) setProvider(ctx ModuleContext) { | |
| android.SetProvider(ctx, FlagExporterInfoProvider, FlagExporterInfo{ | |
| LinkDirs: flagExporter.linkDirs, | |
| LinkObjects: flagExporter.linkObjects, | |
| }) | |
| } | |
| var _ exportedFlagsProducer = (*flagExporter)(nil) | |
| func NewFlagExporter() *flagExporter { | |
| return &flagExporter{} | |
| } | |
| type FlagExporterInfo struct { | |
| Flags []string | |
| LinkDirs []string // TODO: this should be android.Paths | |
| LinkObjects []string // TODO: this should be android.Paths | |
| } | |
| var FlagExporterInfoProvider = blueprint.NewProvider[FlagExporterInfo]() | |
| 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 (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()) { | |
| 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) IsRustFFI() bool { | |
| if mod.compiler != nil { | |
| if library, ok := mod.compiler.(libraryInterface); ok { | |
| return library.isFFILibrary() | |
| } | |
| } | |
| return false | |
| } | |
| 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) HasStubsVariants() bool { | |
| return false | |
| } | |
| func (mod *Module) IsStubs() bool { | |
| 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) | |
| 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) 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.GetDirectDepWithTag(mod.Name(), sourceDepTag) | |
| sourceLib := sourceMod.(*Module).compiler.(*libraryDecorator) | |
| mod.sourceProvider.setOutputFiles(sourceLib.sourceProvider.Srcs()) | |
| } | |
| ctx.CheckbuildFile(mod.sourceProvider.Srcs()...) | |
| android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: mod.sourceProvider.Srcs().Strings()}) | |
| } | |
| 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()) | |
| } | |
| android.SetProvider(ctx, cc.LinkableInfoKey, cc.LinkableInfo{ | |
| StaticExecutable: mod.StaticExecutable(), | |
| }) | |
| mod.setOutputFiles(ctx) | |
| buildComplianceMetadataInfo(ctx, mod, deps) | |
| } | |
| 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.GetDirectDepsWithTag(rlibDepTag) | |
| staticDepNames := make([]string, 0, len(staticDeps)) | |
| for _, dep := range staticDeps { | |
| staticDepNames = append(staticDepNames, dep.Name()) | |
| } | |
| ccStaticDeps := ctx.GetDirectDepsWithTag(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.GetDirectDepsWithTag(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) | |
| } | |
| } | |
| 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(ctx android.ModuleContext, c cc.LinkableInterface, dep cc.LinkableInterface, depName string) string { | |
| if rustDep, ok := dep.(*Module); ok { | |
| // Use base module name for snapshots when exporting to Makefile. | |
| if snapshotPrebuilt, ok := rustDep.compiler.(cc.SnapshotInterface); ok { | |
| baseName := rustDep.BaseModuleName() | |
| return baseName + snapshotPrebuilt.SnapshotAndroidMkSuffix() + rustDep.AndroidMkSuffix() | |
| } | |
| } | |
| return cc.MakeLibName(ctx, c, dep, depName) | |
| } | |
| func collectIncludedProtos(mod *Module, dep *Module) { | |
| if protoMod, ok := mod.sourceProvider.(*protobufDecorator); ok { | |
| if _, ok := dep.sourceProvider.(*protobufDecorator); ok { | |
| protoMod.additionalCrates = append(protoMod.additionalCrates, dep.CrateName()) | |
| } | |
| } | |
| } | |
| func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { | |
| var depPaths PathDeps | |
| directRlibDeps := []*Module{} | |
| directDylibDeps := []*Module{} | |
| directProcMacroDeps := []*Module{} | |
| directSharedLibDeps := []cc.SharedLibraryInfo{} | |
| directStaticLibDeps := [](cc.LinkableInterface){} | |
| directSrcProvidersDeps := []*Module{} | |
| directSrcDeps := [](android.SourceFileProducer){} | |
| // 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.VisitDirectDeps(func(dep android.Module) { | |
| depName := ctx.OtherModuleName(dep) | |
| depTag := ctx.OtherModuleDependencyTag(dep) | |
| if _, exists := skipModuleList[depName]; exists { | |
| return | |
| } | |
| if depTag == android.DarwinUniversalVariantTag { | |
| return | |
| } | |
| if rustDep, ok := dep.(*Module); ok && !rustDep.Static() && !rustDep.Shared() { | |
| //Handle Rust Modules | |
| makeLibName := rustMakeLibName(ctx, mod, rustDep, depName+rustDep.Properties.RustSubName) | |
| switch { | |
| case depTag == dylibDepTag: | |
| dylib, ok := rustDep.compiler.(libraryInterface) | |
| if !ok || !dylib.dylib() { | |
| ctx.ModuleErrorf("mod %q not an dylib library", depName) | |
| return | |
| } | |
| directDylibDeps = append(directDylibDeps, rustDep) | |
| 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) | |
| } | |
| case depTag == rlibDepTag: | |
| rlib, ok := rustDep.compiler.(libraryInterface) | |
| if !ok || !rlib.rlib() { | |
| ctx.ModuleErrorf("mod %q not an rlib library", makeLibName) | |
| return | |
| } | |
| directRlibDeps = append(directRlibDeps, rustDep) | |
| 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(rustDep.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) | |
| } | |
| case depTag == procMacroDepTag: | |
| directProcMacroDeps = append(directProcMacroDeps, rustDep) | |
| 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(rustDep.OutputFile().Path())) | |
| case depTag == sourceDepTag: | |
| if _, ok := mod.sourceProvider.(*protobufDecorator); ok { | |
| collectIncludedProtos(mod, rustDep) | |
| } | |
| 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, rustDep.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 dep.Target().Os != ctx.Os() { | |
| ctx.ModuleErrorf("OS mismatch on dependency %q (%s)", dep.Name(), helper) | |
| return | |
| } else if dep.Target().Arch.ArchType != ctx.Arch().ArchType { | |
| ctx.ModuleErrorf("Arch mismatch on dependency %q (%s)", dep.Name(), helper) | |
| return | |
| } | |
| directSrcProvidersDeps = append(directSrcProvidersDeps, rustDep) | |
| } | |
| exportedInfo, _ := android.OtherModuleProvider(ctx, dep, FlagExporterInfoProvider) | |
| //Append the dependencies exportedDirs, except for proc-macros which target a different arch/OS | |
| if depTag != procMacroDepTag { | |
| depPaths.depFlags = append(depPaths.depFlags, exportedInfo.Flags...) | |
| depPaths.linkObjects = append(depPaths.linkObjects, exportedInfo.LinkObjects...) | |
| depPaths.linkDirs = append(depPaths.linkDirs, exportedInfo.LinkDirs...) | |
| } | |
| if depTag == dylibDepTag || depTag == rlibDepTag || depTag == procMacroDepTag { | |
| linkFile := rustDep.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 _, ok := rustDep.sourceProvider.(*protobufDecorator); ok { | |
| exportedInfo, _ := android.OtherModuleProvider(ctx, dep, cc.FlagExporterInfoProvider) | |
| depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...) | |
| } | |
| } | |
| } | |
| } else if ccDep, ok := dep.(cc.LinkableInterface); ok { | |
| //Handle C dependencies | |
| makeLibName := cc.MakeLibName(ctx, mod, ccDep, depName) | |
| if _, ok := ccDep.(*Module); !ok { | |
| if ccDep.Module().Target().Os != ctx.Os() { | |
| ctx.ModuleErrorf("OS mismatch between %q and %q", ctx.ModuleName(), depName) | |
| return | |
| } | |
| if ccDep.Module().Target().Arch.ArchType != ctx.Arch().ArchType { | |
| ctx.ModuleErrorf("Arch mismatch between %q and %q", ctx.ModuleName(), depName) | |
| return | |
| } | |
| } | |
| linkObject := ccDep.OutputFile() | |
| if !linkObject.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(linkObject.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() { | |
| // Binaries may sometimes need to link whole static libraries that don't start with 'lib'. | |
| // 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", linkObject.Path().String(), "-Wl,--no-whole-archive"}...) | |
| } else if libName, ok := libNameFromFilePath(linkObject.Path()); ok { | |
| depPaths.depFlags = append(depPaths.depFlags, "-lstatic="+libName) | |
| } 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()) | |
| } | |
| } | |
| // Add this to linkObjects to pass the library directly to the linker as well. This propagates | |
| // to dependencies to avoid having to redeclare static libraries for dependents of the dylib variant. | |
| depPaths.linkObjects = append(depPaths.linkObjects, linkObject.String()) | |
| depPaths.linkDirs = append(depPaths.linkDirs, linkPath) | |
| exportedInfo, _ := android.OtherModuleProvider(ctx, dep, cc.FlagExporterInfoProvider) | |
| 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...) | |
| directStaticLibDeps = append(directStaticLibDeps, ccDep) | |
| // 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 { | |
| 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. | |
| linkObject = android.OptionalPathForPath(sharedLibraryInfo.SharedLibrary) | |
| if !linkObject.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(linkObject.Path()) | |
| depPaths.linkDirs = append(depPaths.linkDirs, linkPath) | |
| depPaths.linkObjects = append(depPaths.linkObjects, linkObject.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, linkObject.Path()) | |
| case depTag == cc.CrtEndDepTag: | |
| depPaths.CrtEnd = append(depPaths.CrtEnd, linkObject.Path()) | |
| } | |
| // Make sure these dependencies are propagated | |
| if lib, ok := mod.compiler.(exportedFlagsProducer); ok && exportDep { | |
| lib.exportLinkDirs(linkPath) | |
| lib.exportLinkObjects(linkObject.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 := dep.(android.SourceFileProducer); 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.linkObjects = android.FirstUniqueStrings(depPaths.linkObjects) | |
| depPaths.depFlags = android.FirstUniqueStrings(depPaths.depFlags) | |
| depPaths.depClangFlags = android.FirstUniqueStrings(depPaths.depClangFlags) | |
| depPaths.depIncludePaths = android.FirstUniquePaths(depPaths.depIncludePaths) | |
| depPaths.depSystemIncludePaths = android.FirstUniquePaths(depPaths.depSystemIncludePaths) | |
| 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) == 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) == 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 stubs are properly supported by rust_ffi targets. | |
| 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) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion android.ApiLevel) error { | |
| minSdkVersion := mod.MinSdkVersion() | |
| if minSdkVersion == "apex_inherit" { | |
| return nil | |
| } | |
| if minSdkVersion == "" { | |
| return fmt.Errorf("min_sdk_version is not specificed") | |
| } | |
| // Not using nativeApiLevelFromUser because the context here is not | |
| // necessarily a native context. | |
| ver, err := android.ApiLevelFromUser(ctx, minSdkVersion) | |
| if err != nil { | |
| return err | |
| } | |
| if ver.GreaterThan(sdkVersion) { | |
| return fmt.Errorf("newer SDK(%v)", ver) | |
| } | |
| return nil | |
| } | |
| // Implements android.ApexModule | |
| func (mod *Module) OutgoingDepIsInSameApex(depTag blueprint.DependencyTag) bool { | |
| if depTag == procMacroDepTag || depTag == customBindgenDepTag { | |
| 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 | |
| } | |
| return true | |
| } | |
| func (mod *Module) IncomingDepIsInSameApex(depTag blueprint.DependencyTag) bool { | |
| return !mod.ApexExclude() | |
| } | |
| // Overrides ApexModule.IsInstallabeToApex() | |
| func (mod *Module) IsInstallableToApex() bool { | |
| if mod.compiler != nil { | |
| if lib, ok := mod.compiler.(libraryInterface); ok && (lib.shared() || lib.dylib()) { | |
| return true | |
| } | |
| 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.VisitAllModules(func(module android.Module) { | |
| if rustModule, ok := module.(xref); 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 |