1// Copyright 2019 The Android Open Source Project 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package rust 16 17import ( 18 "fmt" 19 "strings" 20 21 "android/soong/bloaty" 22 "android/soong/testing" 23 24 "github.com/google/blueprint" 25 "github.com/google/blueprint/proptools" 26 27 "android/soong/android" 28 "android/soong/cc" 29 cc_config "android/soong/cc/config" 30 "android/soong/fuzz" 31 "android/soong/multitree" 32 "android/soong/rust/config" 33) 34 35var pctx = android.NewPackageContext("android/soong/rust") 36 37func init() { 38 android.RegisterModuleType("rust_defaults", defaultsFactory) 39 android.PreDepsMutators(func(ctx android.RegisterMutatorsContext) { 40 ctx.BottomUp("rust_libraries", LibraryMutator).Parallel() 41 ctx.BottomUp("rust_stdlinkage", LibstdMutator).Parallel() 42 ctx.BottomUp("rust_begin", BeginMutator).Parallel() 43 }) 44 android.PostDepsMutators(func(ctx android.RegisterMutatorsContext) { 45 ctx.BottomUp("rust_sanitizers", rustSanitizerRuntimeMutator).Parallel() 46 }) 47 pctx.Import("android/soong/android") 48 pctx.Import("android/soong/rust/config") 49 pctx.ImportAs("cc_config", "android/soong/cc/config") 50 android.InitRegistrationContext.RegisterParallelSingletonType("kythe_rust_extract", kytheExtractRustFactory) 51} 52 53type Flags struct { 54 GlobalRustFlags []string // Flags that apply globally to rust 55 GlobalLinkFlags []string // Flags that apply globally to linker 56 RustFlags []string // Flags that apply to rust 57 LinkFlags []string // Flags that apply to linker 58 ClippyFlags []string // Flags that apply to clippy-driver, during the linting 59 RustdocFlags []string // Flags that apply to rustdoc 60 Toolchain config.Toolchain 61 Coverage bool 62 Clippy bool 63 EmitXrefs bool // If true, emit rules to aid cross-referencing 64} 65 66type BaseProperties struct { 67 AndroidMkRlibs []string `blueprint:"mutated"` 68 AndroidMkDylibs []string `blueprint:"mutated"` 69 AndroidMkProcMacroLibs []string `blueprint:"mutated"` 70 AndroidMkStaticLibs []string `blueprint:"mutated"` 71 AndroidMkHeaderLibs []string `blueprint:"mutated"` 72 73 ImageVariation string `blueprint:"mutated"` 74 VndkVersion string `blueprint:"mutated"` 75 SubName string `blueprint:"mutated"` 76 77 // SubName is used by CC for tracking image variants / SDK versions. RustSubName is used for Rust-specific 78 // subnaming which shouldn't be visible to CC modules (such as the rlib stdlinkage subname). This should be 79 // appended before SubName. 80 RustSubName string `blueprint:"mutated"` 81 82 // Set by imageMutator 83 CoreVariantNeeded bool `blueprint:"mutated"` 84 VendorRamdiskVariantNeeded bool `blueprint:"mutated"` 85 RamdiskVariantNeeded bool `blueprint:"mutated"` 86 RecoveryVariantNeeded bool `blueprint:"mutated"` 87 ExtraVariants []string `blueprint:"mutated"` 88 89 // Allows this module to use non-APEX version of libraries. Useful 90 // for building binaries that are started before APEXes are activated. 91 Bootstrap *bool 92 93 // Used by vendor snapshot to record dependencies from snapshot modules. 94 SnapshotSharedLibs []string `blueprint:"mutated"` 95 SnapshotStaticLibs []string `blueprint:"mutated"` 96 SnapshotRlibs []string `blueprint:"mutated"` 97 SnapshotDylibs []string `blueprint:"mutated"` 98 99 // Make this module available when building for ramdisk. 100 // On device without a dedicated recovery partition, the module is only 101 // available after switching root into 102 // /first_stage_ramdisk. To expose the module before switching root, install 103 // the recovery variant instead. 104 Ramdisk_available *bool 105 106 // Make this module available when building for vendor ramdisk. 107 // On device without a dedicated recovery partition, the module is only 108 // available after switching root into 109 // /first_stage_ramdisk. To expose the module before switching root, install 110 // the recovery variant instead 111 Vendor_ramdisk_available *bool 112 113 // Normally Soong uses the directory structure to decide which modules 114 // should be included (framework) or excluded (non-framework) from the 115 // different snapshots (vendor, recovery, etc.), but this property 116 // allows a partner to exclude a module normally thought of as a 117 // framework module from the vendor snapshot. 118 Exclude_from_vendor_snapshot *bool 119 120 // Normally Soong uses the directory structure to decide which modules 121 // should be included (framework) or excluded (non-framework) from the 122 // different snapshots (vendor, recovery, etc.), but this property 123 // allows a partner to exclude a module normally thought of as a 124 // framework module from the recovery snapshot. 125 Exclude_from_recovery_snapshot *bool 126 127 // Make this module available when building for recovery 128 Recovery_available *bool 129 130 // Minimum sdk version that the artifact should support when it runs as part of mainline modules(APEX). 131 Min_sdk_version *string 132 133 HideFromMake bool `blueprint:"mutated"` 134 PreventInstall bool `blueprint:"mutated"` 135 136 Installable *bool 137} 138 139type Module struct { 140 fuzz.FuzzModule 141 142 VendorProperties cc.VendorProperties 143 144 Properties BaseProperties 145 146 hod android.HostOrDeviceSupported 147 multilib android.Multilib 148 testModule bool 149 150 makeLinkType string 151 152 afdo *afdo 153 compiler compiler 154 coverage *coverage 155 clippy *clippy 156 sanitize *sanitize 157 cachedToolchain config.Toolchain 158 sourceProvider SourceProvider 159 subAndroidMkOnce map[SubAndroidMkProvider]bool 160 161 exportedLinkDirs []string 162 163 // Output file to be installed, may be stripped or unstripped. 164 outputFile android.OptionalPath 165 166 // Cross-reference input file 167 kytheFiles android.Paths 168 169 docTimestampFile android.OptionalPath 170 171 hideApexVariantFromMake bool 172 173 // For apex variants, this is set as apex.min_sdk_version 174 apexSdkVersion android.ApiLevel 175 176 transitiveAndroidMkSharedLibs *android.DepSet[string] 177} 178 179func (mod *Module) Header() bool { 180 //TODO: If Rust libraries provide header variants, this needs to be updated. 181 return false 182} 183 184func (mod *Module) SetPreventInstall() { 185 mod.Properties.PreventInstall = true 186} 187 188func (mod *Module) SetHideFromMake() { 189 mod.Properties.HideFromMake = true 190} 191 192func (mod *Module) HiddenFromMake() bool { 193 return mod.Properties.HideFromMake 194} 195 196func (mod *Module) SanitizePropDefined() bool { 197 // Because compiler is not set for some Rust modules where sanitize might be set, check that compiler is also not 198 // nil since we need compiler to actually sanitize. 199 return mod.sanitize != nil && mod.compiler != nil 200} 201 202func (mod *Module) IsPrebuilt() bool { 203 if _, ok := mod.compiler.(*prebuiltLibraryDecorator); ok { 204 return true 205 } 206 return false 207} 208 209func (mod *Module) OutputFiles(tag string) (android.Paths, error) { 210 switch tag { 211 case "": 212 if mod.sourceProvider != nil && (mod.compiler == nil || mod.compiler.Disabled()) { 213 return mod.sourceProvider.Srcs(), nil 214 } else { 215 if mod.OutputFile().Valid() { 216 return android.Paths{mod.OutputFile().Path()}, nil 217 } 218 return android.Paths{}, nil 219 } 220 case "unstripped": 221 if mod.compiler != nil { 222 return android.PathsIfNonNil(mod.compiler.unstrippedOutputFilePath()), nil 223 } 224 return nil, nil 225 default: 226 return nil, fmt.Errorf("unsupported module reference tag %q", tag) 227 } 228} 229 230func (mod *Module) SelectedStl() string { 231 return "" 232} 233 234func (mod *Module) NonCcVariants() bool { 235 if mod.compiler != nil { 236 if library, ok := mod.compiler.(libraryInterface); ok { 237 return library.buildRlib() || library.buildDylib() 238 } 239 } 240 panic(fmt.Errorf("NonCcVariants called on non-library module: %q", mod.BaseModuleName())) 241} 242 243func (mod *Module) Static() bool { 244 if mod.compiler != nil { 245 if library, ok := mod.compiler.(libraryInterface); ok { 246 return library.static() 247 } 248 } 249 return false 250} 251 252func (mod *Module) Shared() bool { 253 if mod.compiler != nil { 254 if library, ok := mod.compiler.(libraryInterface); ok { 255 return library.shared() 256 } 257 } 258 return false 259} 260 261func (mod *Module) Dylib() bool { 262 if mod.compiler != nil { 263 if library, ok := mod.compiler.(libraryInterface); ok { 264 return library.dylib() 265 } 266 } 267 return false 268} 269 270func (mod *Module) Source() bool { 271 if mod.compiler != nil { 272 if library, ok := mod.compiler.(libraryInterface); ok && mod.sourceProvider != nil { 273 return library.source() 274 } 275 } 276 return false 277} 278 279func (mod *Module) RlibStd() bool { 280 if mod.compiler != nil { 281 if library, ok := mod.compiler.(libraryInterface); ok && library.rlib() { 282 return library.rlibStd() 283 } 284 } 285 panic(fmt.Errorf("RlibStd() called on non-rlib module: %q", mod.BaseModuleName())) 286} 287 288func (mod *Module) Rlib() bool { 289 if mod.compiler != nil { 290 if library, ok := mod.compiler.(libraryInterface); ok { 291 return library.rlib() 292 } 293 } 294 return false 295} 296 297func (mod *Module) Binary() bool { 298 if binary, ok := mod.compiler.(binaryInterface); ok { 299 return binary.binary() 300 } 301 return false 302} 303 304func (mod *Module) StaticExecutable() bool { 305 if !mod.Binary() { 306 return false 307 } 308 return mod.StaticallyLinked() 309} 310 311func (mod *Module) Object() bool { 312 // Rust has no modules which produce only object files. 313 return false 314} 315 316func (mod *Module) Toc() android.OptionalPath { 317 if mod.compiler != nil { 318 if lib, ok := mod.compiler.(libraryInterface); ok { 319 return lib.toc() 320 } 321 } 322 panic(fmt.Errorf("Toc() called on non-library module: %q", mod.BaseModuleName())) 323} 324 325func (mod *Module) UseSdk() bool { 326 return false 327} 328 329func (mod *Module) RelativeInstallPath() string { 330 if mod.compiler != nil { 331 return mod.compiler.relativeInstallPath() 332 } 333 return "" 334} 335 336func (mod *Module) UseVndk() bool { 337 return mod.Properties.VndkVersion != "" 338} 339 340func (mod *Module) Bootstrap() bool { 341 return Bool(mod.Properties.Bootstrap) 342} 343 344func (mod *Module) SubName() string { 345 return mod.Properties.SubName 346} 347 348func (mod *Module) IsVndkPrebuiltLibrary() bool { 349 // Rust modules do not provide VNDK prebuilts 350 return false 351} 352 353func (mod *Module) IsVendorPublicLibrary() bool { 354 return mod.VendorProperties.IsVendorPublicLibrary 355} 356 357func (mod *Module) SdkAndPlatformVariantVisibleToMake() bool { 358 // Rust modules to not provide Sdk variants 359 return false 360} 361 362func (c *Module) IsVndkPrivate() bool { 363 return false 364} 365 366func (c *Module) IsLlndk() bool { 367 return false 368} 369 370func (mod *Module) KernelHeadersDecorator() bool { 371 return false 372} 373 374func (m *Module) NeedsLlndkVariants() bool { 375 return false 376} 377 378func (m *Module) NeedsVendorPublicLibraryVariants() bool { 379 return false 380} 381 382func (mod *Module) HasLlndkStubs() bool { 383 return false 384} 385 386func (mod *Module) StubsVersion() string { 387 panic(fmt.Errorf("StubsVersion called on non-versioned module: %q", mod.BaseModuleName())) 388} 389 390func (mod *Module) SdkVersion() string { 391 return "" 392} 393 394func (mod *Module) AlwaysSdk() bool { 395 return false 396} 397 398func (mod *Module) IsSdkVariant() bool { 399 return false 400} 401 402func (mod *Module) SplitPerApiLevel() bool { 403 return false 404} 405 406func (mod *Module) XrefRustFiles() android.Paths { 407 return mod.kytheFiles 408} 409 410type Deps struct { 411 Dylibs []string 412 Rlibs []string 413 Rustlibs []string 414 Stdlibs []string 415 ProcMacros []string 416 SharedLibs []string 417 StaticLibs []string 418 WholeStaticLibs []string 419 HeaderLibs []string 420 421 // Used for data dependencies adjacent to tests 422 DataLibs []string 423 DataBins []string 424 425 CrtBegin, CrtEnd []string 426} 427 428type PathDeps struct { 429 DyLibs RustLibraries 430 RLibs RustLibraries 431 SharedLibs android.Paths 432 SharedLibDeps android.Paths 433 StaticLibs android.Paths 434 ProcMacros RustLibraries 435 AfdoProfiles android.Paths 436 437 // depFlags and depLinkFlags are rustc and linker (clang) flags. 438 depFlags []string 439 depLinkFlags []string 440 441 // linkDirs are link paths passed via -L to rustc. linkObjects are objects passed directly to the linker. 442 // Both of these are exported and propagate to dependencies. 443 linkDirs []string 444 linkObjects []string 445 446 // exportedLinkDirs are exported linkDirs for direct rlib dependencies to 447 // cc_library_static dependants of rlibs. 448 // Track them separately from linkDirs so superfluous -L flags don't get emitted. 449 exportedLinkDirs []string 450 451 // Used by bindgen modules which call clang 452 depClangFlags []string 453 depIncludePaths android.Paths 454 depGeneratedHeaders android.Paths 455 depSystemIncludePaths android.Paths 456 457 CrtBegin android.Paths 458 CrtEnd android.Paths 459 460 // Paths to generated source files 461 SrcDeps android.Paths 462 srcProviderFiles android.Paths 463 464 // Used by Generated Libraries 465 depExportedRlibs []cc.RustRlibDep 466} 467 468type RustLibraries []RustLibrary 469 470type RustLibrary struct { 471 Path android.Path 472 CrateName string 473} 474 475type exportedFlagsProducer interface { 476 exportLinkDirs(...string) 477 exportLinkObjects(...string) 478} 479 480type xref interface { 481 XrefRustFiles() android.Paths 482} 483 484type flagExporter struct { 485 linkDirs []string 486 linkObjects []string 487} 488 489func (flagExporter *flagExporter) exportLinkDirs(dirs ...string) { 490 flagExporter.linkDirs = android.FirstUniqueStrings(append(flagExporter.linkDirs, dirs...)) 491} 492 493func (flagExporter *flagExporter) exportLinkObjects(flags ...string) { 494 flagExporter.linkObjects = android.FirstUniqueStrings(append(flagExporter.linkObjects, flags...)) 495} 496 497func (flagExporter *flagExporter) setProvider(ctx ModuleContext) { 498 android.SetProvider(ctx, FlagExporterInfoProvider, FlagExporterInfo{ 499 LinkDirs: flagExporter.linkDirs, 500 LinkObjects: flagExporter.linkObjects, 501 }) 502} 503 504var _ exportedFlagsProducer = (*flagExporter)(nil) 505 506func NewFlagExporter() *flagExporter { 507 return &flagExporter{} 508} 509 510type FlagExporterInfo struct { 511 Flags []string 512 LinkDirs []string // TODO: this should be android.Paths 513 LinkObjects []string // TODO: this should be android.Paths 514} 515 516var FlagExporterInfoProvider = blueprint.NewProvider[FlagExporterInfo]() 517 518func (mod *Module) isCoverageVariant() bool { 519 return mod.coverage.Properties.IsCoverageVariant 520} 521 522var _ cc.Coverage = (*Module)(nil) 523 524func (mod *Module) IsNativeCoverageNeeded(ctx android.IncomingTransitionContext) bool { 525 return mod.coverage != nil && mod.coverage.Properties.NeedCoverageVariant 526} 527 528func (mod *Module) VndkVersion() string { 529 return mod.Properties.VndkVersion 530} 531 532func (mod *Module) ExportedCrateLinkDirs() []string { 533 return mod.exportedLinkDirs 534} 535 536func (mod *Module) PreventInstall() bool { 537 return mod.Properties.PreventInstall 538} 539 540func (mod *Module) MarkAsCoverageVariant(coverage bool) { 541 mod.coverage.Properties.IsCoverageVariant = coverage 542} 543 544func (mod *Module) EnableCoverageIfNeeded() { 545 mod.coverage.Properties.CoverageEnabled = mod.coverage.Properties.NeedCoverageBuild 546} 547 548func defaultsFactory() android.Module { 549 return DefaultsFactory() 550} 551 552type Defaults struct { 553 android.ModuleBase 554 android.DefaultsModuleBase 555} 556 557func DefaultsFactory(props ...interface{}) android.Module { 558 module := &Defaults{} 559 560 module.AddProperties(props...) 561 module.AddProperties( 562 &BaseProperties{}, 563 &cc.AfdoProperties{}, 564 &cc.VendorProperties{}, 565 &BenchmarkProperties{}, 566 &BindgenProperties{}, 567 &BaseCompilerProperties{}, 568 &BinaryCompilerProperties{}, 569 &LibraryCompilerProperties{}, 570 &ProcMacroCompilerProperties{}, 571 &PrebuiltProperties{}, 572 &SourceProviderProperties{}, 573 &TestProperties{}, 574 &cc.CoverageProperties{}, 575 &cc.RustBindgenClangProperties{}, 576 &ClippyProperties{}, 577 &SanitizeProperties{}, 578 &fuzz.FuzzProperties{}, 579 ) 580 581 android.InitDefaultsModule(module) 582 return module 583} 584 585func (mod *Module) CrateName() string { 586 return mod.compiler.crateName() 587} 588 589func (mod *Module) CcLibrary() bool { 590 if mod.compiler != nil { 591 if _, ok := mod.compiler.(libraryInterface); ok { 592 return true 593 } 594 } 595 return false 596} 597 598func (mod *Module) CcLibraryInterface() bool { 599 if mod.compiler != nil { 600 // use build{Static,Shared}() instead of {static,shared}() here because this might be called before 601 // VariantIs{Static,Shared} is set. 602 if lib, ok := mod.compiler.(libraryInterface); ok && (lib.buildShared() || lib.buildStatic()) { 603 return true 604 } 605 } 606 return false 607} 608 609func (mod *Module) RustLibraryInterface() bool { 610 if mod.compiler != nil { 611 if _, ok := mod.compiler.(libraryInterface); ok { 612 return true 613 } 614 } 615 return false 616} 617 618func (mod *Module) IsFuzzModule() bool { 619 if _, ok := mod.compiler.(*fuzzDecorator); ok { 620 return true 621 } 622 return false 623} 624 625func (mod *Module) FuzzModuleStruct() fuzz.FuzzModule { 626 return mod.FuzzModule 627} 628 629func (mod *Module) FuzzPackagedModule() fuzz.FuzzPackagedModule { 630 if fuzzer, ok := mod.compiler.(*fuzzDecorator); ok { 631 return fuzzer.fuzzPackagedModule 632 } 633 panic(fmt.Errorf("FuzzPackagedModule called on non-fuzz module: %q", mod.BaseModuleName())) 634} 635 636func (mod *Module) FuzzSharedLibraries() android.RuleBuilderInstalls { 637 if fuzzer, ok := mod.compiler.(*fuzzDecorator); ok { 638 return fuzzer.sharedLibraries 639 } 640 panic(fmt.Errorf("FuzzSharedLibraries called on non-fuzz module: %q", mod.BaseModuleName())) 641} 642 643func (mod *Module) UnstrippedOutputFile() android.Path { 644 if mod.compiler != nil { 645 return mod.compiler.unstrippedOutputFilePath() 646 } 647 return nil 648} 649 650func (mod *Module) SetStatic() { 651 if mod.compiler != nil { 652 if library, ok := mod.compiler.(libraryInterface); ok { 653 library.setStatic() 654 return 655 } 656 } 657 panic(fmt.Errorf("SetStatic called on non-library module: %q", mod.BaseModuleName())) 658} 659 660func (mod *Module) SetShared() { 661 if mod.compiler != nil { 662 if library, ok := mod.compiler.(libraryInterface); ok { 663 library.setShared() 664 return 665 } 666 } 667 panic(fmt.Errorf("SetShared called on non-library module: %q", mod.BaseModuleName())) 668} 669 670func (mod *Module) BuildStaticVariant() bool { 671 if mod.compiler != nil { 672 if library, ok := mod.compiler.(libraryInterface); ok { 673 return library.buildStatic() 674 } 675 } 676 panic(fmt.Errorf("BuildStaticVariant called on non-library module: %q", mod.BaseModuleName())) 677} 678 679func (mod *Module) BuildSharedVariant() bool { 680 if mod.compiler != nil { 681 if library, ok := mod.compiler.(libraryInterface); ok { 682 return library.buildShared() 683 } 684 } 685 panic(fmt.Errorf("BuildSharedVariant called on non-library module: %q", mod.BaseModuleName())) 686} 687 688func (mod *Module) Module() android.Module { 689 return mod 690} 691 692func (mod *Module) OutputFile() android.OptionalPath { 693 return mod.outputFile 694} 695 696func (mod *Module) CoverageFiles() android.Paths { 697 if mod.compiler != nil { 698 return android.Paths{} 699 } 700 panic(fmt.Errorf("CoverageFiles called on non-library module: %q", mod.BaseModuleName())) 701} 702 703// Rust does not produce gcno files, and therefore does not produce a coverage archive. 704func (mod *Module) CoverageOutputFile() android.OptionalPath { 705 return android.OptionalPath{} 706} 707 708func (mod *Module) IsNdk(config android.Config) bool { 709 return false 710} 711 712func (mod *Module) IsStubs() bool { 713 return false 714} 715 716func (mod *Module) installable(apexInfo android.ApexInfo) bool { 717 if !proptools.BoolDefault(mod.Installable(), mod.EverInstallable()) { 718 return false 719 } 720 721 // The apex variant is not installable because it is included in the APEX and won't appear 722 // in the system partition as a standalone file. 723 if !apexInfo.IsForPlatform() { 724 return false 725 } 726 727 return mod.OutputFile().Valid() && !mod.Properties.PreventInstall 728} 729 730func (ctx moduleContext) apexVariationName() string { 731 apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider) 732 return apexInfo.ApexVariationName 733} 734 735var _ cc.LinkableInterface = (*Module)(nil) 736 737func (mod *Module) Init() android.Module { 738 mod.AddProperties(&mod.Properties) 739 mod.AddProperties(&mod.VendorProperties) 740 741 if mod.afdo != nil { 742 mod.AddProperties(mod.afdo.props()...) 743 } 744 if mod.compiler != nil { 745 mod.AddProperties(mod.compiler.compilerProps()...) 746 } 747 if mod.coverage != nil { 748 mod.AddProperties(mod.coverage.props()...) 749 } 750 if mod.clippy != nil { 751 mod.AddProperties(mod.clippy.props()...) 752 } 753 if mod.sourceProvider != nil { 754 mod.AddProperties(mod.sourceProvider.SourceProviderProps()...) 755 } 756 if mod.sanitize != nil { 757 mod.AddProperties(mod.sanitize.props()...) 758 } 759 760 android.InitAndroidArchModule(mod, mod.hod, mod.multilib) 761 android.InitApexModule(mod) 762 763 android.InitDefaultableModule(mod) 764 return mod 765} 766 767func newBaseModule(hod android.HostOrDeviceSupported, multilib android.Multilib) *Module { 768 return &Module{ 769 hod: hod, 770 multilib: multilib, 771 } 772} 773func newModule(hod android.HostOrDeviceSupported, multilib android.Multilib) *Module { 774 module := newBaseModule(hod, multilib) 775 module.afdo = &afdo{} 776 module.coverage = &coverage{} 777 module.clippy = &clippy{} 778 module.sanitize = &sanitize{} 779 return module 780} 781 782type ModuleContext interface { 783 android.ModuleContext 784 ModuleContextIntf 785} 786 787type BaseModuleContext interface { 788 android.BaseModuleContext 789 ModuleContextIntf 790} 791 792type DepsContext interface { 793 android.BottomUpMutatorContext 794 ModuleContextIntf 795} 796 797type ModuleContextIntf interface { 798 RustModule() *Module 799 toolchain() config.Toolchain 800} 801 802type depsContext struct { 803 android.BottomUpMutatorContext 804} 805 806type moduleContext struct { 807 android.ModuleContext 808} 809 810type baseModuleContext struct { 811 android.BaseModuleContext 812} 813 814func (ctx *moduleContext) RustModule() *Module { 815 return ctx.Module().(*Module) 816} 817 818func (ctx *moduleContext) toolchain() config.Toolchain { 819 return ctx.RustModule().toolchain(ctx) 820} 821 822func (ctx *depsContext) RustModule() *Module { 823 return ctx.Module().(*Module) 824} 825 826func (ctx *depsContext) toolchain() config.Toolchain { 827 return ctx.RustModule().toolchain(ctx) 828} 829 830func (ctx *baseModuleContext) RustModule() *Module { 831 return ctx.Module().(*Module) 832} 833 834func (ctx *baseModuleContext) toolchain() config.Toolchain { 835 return ctx.RustModule().toolchain(ctx) 836} 837 838func (mod *Module) nativeCoverage() bool { 839 // Bug: http://b/137883967 - native-bridge modules do not currently work with coverage 840 if mod.Target().NativeBridge == android.NativeBridgeEnabled { 841 return false 842 } 843 return mod.compiler != nil && mod.compiler.nativeCoverage() 844} 845 846func (mod *Module) EverInstallable() bool { 847 return mod.compiler != nil && 848 // Check to see whether the module is actually ever installable. 849 mod.compiler.everInstallable() 850} 851 852func (mod *Module) Installable() *bool { 853 return mod.Properties.Installable 854} 855 856func (mod *Module) ProcMacro() bool { 857 if pm, ok := mod.compiler.(procMacroInterface); ok { 858 return pm.ProcMacro() 859 } 860 return false 861} 862 863func (mod *Module) toolchain(ctx android.BaseModuleContext) config.Toolchain { 864 if mod.cachedToolchain == nil { 865 mod.cachedToolchain = config.FindToolchain(ctx.Os(), ctx.Arch()) 866 } 867 return mod.cachedToolchain 868} 869 870func (mod *Module) ccToolchain(ctx android.BaseModuleContext) cc_config.Toolchain { 871 return cc_config.FindToolchain(ctx.Os(), ctx.Arch()) 872} 873 874func (d *Defaults) GenerateAndroidBuildActions(ctx android.ModuleContext) { 875} 876 877func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { 878 ctx := &moduleContext{ 879 ModuleContext: actx, 880 } 881 882 apexInfo, _ := android.ModuleProvider(actx, android.ApexInfoProvider) 883 if !apexInfo.IsForPlatform() { 884 mod.hideApexVariantFromMake = true 885 } 886 887 toolchain := mod.toolchain(ctx) 888 mod.makeLinkType = cc.GetMakeLinkType(actx, mod) 889 890 mod.Properties.SubName = cc.GetSubnameProperty(actx, mod) 891 892 if !toolchain.Supported() { 893 // This toolchain's unsupported, there's nothing to do for this mod. 894 return 895 } 896 897 deps := mod.depsToPaths(ctx) 898 // Export linkDirs for CC rust generatedlibs 899 mod.exportedLinkDirs = append(mod.exportedLinkDirs, deps.exportedLinkDirs...) 900 mod.exportedLinkDirs = append(mod.exportedLinkDirs, deps.linkDirs...) 901 902 flags := Flags{ 903 Toolchain: toolchain, 904 } 905 906 // Calculate rustc flags 907 if mod.afdo != nil { 908 flags, deps = mod.afdo.flags(actx, flags, deps) 909 } 910 if mod.compiler != nil { 911 flags = mod.compiler.compilerFlags(ctx, flags) 912 flags = mod.compiler.cfgFlags(ctx, flags) 913 flags = mod.compiler.featureFlags(ctx, flags) 914 } 915 if mod.coverage != nil { 916 flags, deps = mod.coverage.flags(ctx, flags, deps) 917 } 918 if mod.clippy != nil { 919 flags, deps = mod.clippy.flags(ctx, flags, deps) 920 } 921 if mod.sanitize != nil { 922 flags, deps = mod.sanitize.flags(ctx, flags, deps) 923 } 924 925 // SourceProvider needs to call GenerateSource() before compiler calls 926 // compile() so it can provide the source. A SourceProvider has 927 // multiple variants (e.g. source, rlib, dylib). Only the "source" 928 // variant is responsible for effectively generating the source. The 929 // remaining variants relies on the "source" variant output. 930 if mod.sourceProvider != nil { 931 if mod.compiler.(libraryInterface).source() { 932 mod.sourceProvider.GenerateSource(ctx, deps) 933 mod.sourceProvider.setSubName(ctx.ModuleSubDir()) 934 } else { 935 sourceMod := actx.GetDirectDepWithTag(mod.Name(), sourceDepTag) 936 sourceLib := sourceMod.(*Module).compiler.(*libraryDecorator) 937 mod.sourceProvider.setOutputFiles(sourceLib.sourceProvider.Srcs()) 938 } 939 android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: mod.sourceProvider.Srcs().Strings()}) 940 } 941 942 if mod.compiler != nil && !mod.compiler.Disabled() { 943 mod.compiler.initialize(ctx) 944 buildOutput := mod.compiler.compile(ctx, flags, deps) 945 if ctx.Failed() { 946 return 947 } 948 mod.outputFile = android.OptionalPathForPath(buildOutput.outputFile) 949 if buildOutput.kytheFile != nil { 950 mod.kytheFiles = append(mod.kytheFiles, buildOutput.kytheFile) 951 } 952 bloaty.MeasureSizeForPaths(ctx, mod.compiler.strippedOutputFilePath(), android.OptionalPathForPath(mod.compiler.unstrippedOutputFilePath())) 953 954 mod.docTimestampFile = mod.compiler.rustdoc(ctx, flags, deps) 955 if mod.docTimestampFile.Valid() { 956 ctx.CheckbuildFile(mod.docTimestampFile.Path()) 957 } 958 959 apexInfo, _ := android.ModuleProvider(actx, android.ApexInfoProvider) 960 if !proptools.BoolDefault(mod.Installable(), mod.EverInstallable()) && !mod.ProcMacro() { 961 // If the module has been specifically configure to not be installed then 962 // hide from make as otherwise it will break when running inside make as the 963 // output path to install will not be specified. Not all uninstallable 964 // modules can be hidden from make as some are needed for resolving make 965 // side dependencies. In particular, proc-macros need to be captured in the 966 // host snapshot. 967 mod.HideFromMake() 968 } else if !mod.installable(apexInfo) { 969 mod.SkipInstall() 970 } 971 972 // Still call install though, the installs will be stored as PackageSpecs to allow 973 // using the outputs in a genrule. 974 if mod.OutputFile().Valid() { 975 mod.compiler.install(ctx) 976 if ctx.Failed() { 977 return 978 } 979 // Export your own directory as a linkDir 980 mod.exportedLinkDirs = append(mod.exportedLinkDirs, linkPathFromFilePath(mod.OutputFile().Path())) 981 982 } 983 984 ctx.Phony("rust", ctx.RustModule().OutputFile().Path()) 985 } 986 if mod.testModule { 987 android.SetProvider(ctx, testing.TestModuleProviderKey, testing.TestModuleProviderData{}) 988 } 989} 990 991func (mod *Module) deps(ctx DepsContext) Deps { 992 deps := Deps{} 993 994 if mod.compiler != nil { 995 deps = mod.compiler.compilerDeps(ctx, deps) 996 } 997 if mod.sourceProvider != nil { 998 deps = mod.sourceProvider.SourceProviderDeps(ctx, deps) 999 } 1000 1001 if mod.coverage != nil { 1002 deps = mod.coverage.deps(ctx, deps) 1003 } 1004 1005 if mod.sanitize != nil { 1006 deps = mod.sanitize.deps(ctx, deps) 1007 } 1008 1009 deps.Rlibs = android.LastUniqueStrings(deps.Rlibs) 1010 deps.Dylibs = android.LastUniqueStrings(deps.Dylibs) 1011 deps.Rustlibs = android.LastUniqueStrings(deps.Rustlibs) 1012 deps.ProcMacros = android.LastUniqueStrings(deps.ProcMacros) 1013 deps.SharedLibs = android.LastUniqueStrings(deps.SharedLibs) 1014 deps.StaticLibs = android.LastUniqueStrings(deps.StaticLibs) 1015 deps.Stdlibs = android.LastUniqueStrings(deps.Stdlibs) 1016 deps.WholeStaticLibs = android.LastUniqueStrings(deps.WholeStaticLibs) 1017 return deps 1018 1019} 1020 1021type dependencyTag struct { 1022 blueprint.BaseDependencyTag 1023 name string 1024 library bool 1025 procMacro bool 1026 dynamic bool 1027} 1028 1029// InstallDepNeeded returns true for rlibs, dylibs, and proc macros so that they or their transitive 1030// dependencies (especially C/C++ shared libs) are installed as dependencies of a rust binary. 1031func (d dependencyTag) InstallDepNeeded() bool { 1032 return d.library || d.procMacro 1033} 1034 1035var _ android.InstallNeededDependencyTag = dependencyTag{} 1036 1037func (d dependencyTag) LicenseAnnotations() []android.LicenseAnnotation { 1038 if d.library && d.dynamic { 1039 return []android.LicenseAnnotation{android.LicenseAnnotationSharedDependency} 1040 } 1041 return nil 1042} 1043 1044func (d dependencyTag) PropagateAconfigValidation() bool { 1045 return d == rlibDepTag || d == sourceDepTag 1046} 1047 1048var _ android.PropagateAconfigValidationDependencyTag = dependencyTag{} 1049 1050var _ android.LicenseAnnotationsDependencyTag = dependencyTag{} 1051 1052var ( 1053 customBindgenDepTag = dependencyTag{name: "customBindgenTag"} 1054 rlibDepTag = dependencyTag{name: "rlibTag", library: true} 1055 dylibDepTag = dependencyTag{name: "dylib", library: true, dynamic: true} 1056 procMacroDepTag = dependencyTag{name: "procMacro", procMacro: true} 1057 testPerSrcDepTag = dependencyTag{name: "rust_unit_tests"} 1058 sourceDepTag = dependencyTag{name: "source"} 1059 dataLibDepTag = dependencyTag{name: "data lib"} 1060 dataBinDepTag = dependencyTag{name: "data bin"} 1061) 1062 1063func IsDylibDepTag(depTag blueprint.DependencyTag) bool { 1064 tag, ok := depTag.(dependencyTag) 1065 return ok && tag == dylibDepTag 1066} 1067 1068func IsRlibDepTag(depTag blueprint.DependencyTag) bool { 1069 tag, ok := depTag.(dependencyTag) 1070 return ok && tag == rlibDepTag 1071} 1072 1073type autoDep struct { 1074 variation string 1075 depTag dependencyTag 1076} 1077 1078var ( 1079 rlibVariation = "rlib" 1080 dylibVariation = "dylib" 1081 rlibAutoDep = autoDep{variation: rlibVariation, depTag: rlibDepTag} 1082 dylibAutoDep = autoDep{variation: dylibVariation, depTag: dylibDepTag} 1083) 1084 1085type autoDeppable interface { 1086 autoDep(ctx android.BottomUpMutatorContext) autoDep 1087} 1088 1089func (mod *Module) begin(ctx BaseModuleContext) { 1090 if mod.coverage != nil { 1091 mod.coverage.begin(ctx) 1092 } 1093 if mod.sanitize != nil { 1094 mod.sanitize.begin(ctx) 1095 } 1096} 1097 1098func (mod *Module) Prebuilt() *android.Prebuilt { 1099 if p, ok := mod.compiler.(rustPrebuilt); ok { 1100 return p.prebuilt() 1101 } 1102 return nil 1103} 1104 1105func (mod *Module) Symlinks() []string { 1106 // TODO update this to return the list of symlinks when Rust supports defining symlinks 1107 return nil 1108} 1109 1110func rustMakeLibName(ctx android.ModuleContext, c cc.LinkableInterface, dep cc.LinkableInterface, depName string) string { 1111 if rustDep, ok := dep.(*Module); ok { 1112 // Use base module name for snapshots when exporting to Makefile. 1113 if snapshotPrebuilt, ok := rustDep.compiler.(cc.SnapshotInterface); ok { 1114 baseName := rustDep.BaseModuleName() 1115 return baseName + snapshotPrebuilt.SnapshotAndroidMkSuffix() + rustDep.AndroidMkSuffix() 1116 } 1117 } 1118 return cc.MakeLibName(ctx, c, dep, depName) 1119} 1120 1121func collectIncludedProtos(mod *Module, dep *Module) { 1122 if protoMod, ok := mod.sourceProvider.(*protobufDecorator); ok { 1123 if _, ok := dep.sourceProvider.(*protobufDecorator); ok { 1124 protoMod.additionalCrates = append(protoMod.additionalCrates, dep.CrateName()) 1125 } 1126 } 1127} 1128 1129func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { 1130 var depPaths PathDeps 1131 1132 directRlibDeps := []*Module{} 1133 directDylibDeps := []*Module{} 1134 directProcMacroDeps := []*Module{} 1135 directSharedLibDeps := []cc.SharedLibraryInfo{} 1136 directStaticLibDeps := [](cc.LinkableInterface){} 1137 directSrcProvidersDeps := []*Module{} 1138 directSrcDeps := [](android.SourceFileProducer){} 1139 1140 // For the dependency from platform to apex, use the latest stubs 1141 mod.apexSdkVersion = android.FutureApiLevel 1142 apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider) 1143 if !apexInfo.IsForPlatform() { 1144 mod.apexSdkVersion = apexInfo.MinSdkVersion 1145 } 1146 1147 if android.InList("hwaddress", ctx.Config().SanitizeDevice()) { 1148 // In hwasan build, we override apexSdkVersion to the FutureApiLevel(10000) 1149 // so that even Q(29/Android10) apexes could use the dynamic unwinder by linking the newer stubs(e.g libc(R+)). 1150 // (b/144430859) 1151 mod.apexSdkVersion = android.FutureApiLevel 1152 } 1153 1154 skipModuleList := map[string]bool{} 1155 1156 var apiImportInfo multitree.ApiImportInfo 1157 hasApiImportInfo := false 1158 1159 ctx.VisitDirectDeps(func(dep android.Module) { 1160 if dep.Name() == "api_imports" { 1161 apiImportInfo, _ = android.OtherModuleProvider(ctx, dep, multitree.ApiImportsProvider) 1162 hasApiImportInfo = true 1163 } 1164 }) 1165 1166 if hasApiImportInfo { 1167 targetStubModuleList := map[string]string{} 1168 targetOrigModuleList := map[string]string{} 1169 1170 // Search for dependency which both original module and API imported library with APEX stub exists 1171 ctx.VisitDirectDeps(func(dep android.Module) { 1172 depName := ctx.OtherModuleName(dep) 1173 if apiLibrary, ok := apiImportInfo.ApexSharedLibs[depName]; ok { 1174 targetStubModuleList[apiLibrary] = depName 1175 } 1176 }) 1177 ctx.VisitDirectDeps(func(dep android.Module) { 1178 depName := ctx.OtherModuleName(dep) 1179 if origLibrary, ok := targetStubModuleList[depName]; ok { 1180 targetOrigModuleList[origLibrary] = depName 1181 } 1182 }) 1183 1184 // Decide which library should be used between original and API imported library 1185 ctx.VisitDirectDeps(func(dep android.Module) { 1186 depName := ctx.OtherModuleName(dep) 1187 if apiLibrary, ok := targetOrigModuleList[depName]; ok { 1188 if cc.ShouldUseStubForApex(ctx, dep) { 1189 skipModuleList[depName] = true 1190 } else { 1191 skipModuleList[apiLibrary] = true 1192 } 1193 } 1194 }) 1195 } 1196 1197 var transitiveAndroidMkSharedLibs []*android.DepSet[string] 1198 var directAndroidMkSharedLibs []string 1199 1200 ctx.VisitDirectDeps(func(dep android.Module) { 1201 depName := ctx.OtherModuleName(dep) 1202 depTag := ctx.OtherModuleDependencyTag(dep) 1203 1204 if _, exists := skipModuleList[depName]; exists { 1205 return 1206 } 1207 1208 if depTag == android.DarwinUniversalVariantTag { 1209 return 1210 } 1211 1212 if rustDep, ok := dep.(*Module); ok && !rustDep.Static() && !rustDep.Shared() { 1213 //Handle Rust Modules 1214 makeLibName := rustMakeLibName(ctx, mod, rustDep, depName+rustDep.Properties.RustSubName) 1215 1216 switch depTag { 1217 case dylibDepTag: 1218 dylib, ok := rustDep.compiler.(libraryInterface) 1219 if !ok || !dylib.dylib() { 1220 ctx.ModuleErrorf("mod %q not an dylib library", depName) 1221 return 1222 } 1223 directDylibDeps = append(directDylibDeps, rustDep) 1224 mod.Properties.AndroidMkDylibs = append(mod.Properties.AndroidMkDylibs, makeLibName) 1225 mod.Properties.SnapshotDylibs = append(mod.Properties.SnapshotDylibs, cc.BaseLibName(depName)) 1226 1227 case rlibDepTag: 1228 1229 rlib, ok := rustDep.compiler.(libraryInterface) 1230 if !ok || !rlib.rlib() { 1231 ctx.ModuleErrorf("mod %q not an rlib library", makeLibName) 1232 return 1233 } 1234 directRlibDeps = append(directRlibDeps, rustDep) 1235 mod.Properties.AndroidMkRlibs = append(mod.Properties.AndroidMkRlibs, makeLibName) 1236 mod.Properties.SnapshotRlibs = append(mod.Properties.SnapshotRlibs, cc.BaseLibName(depName)) 1237 1238 // rust_ffi rlibs may export include dirs, so collect those here. 1239 exportedInfo, _ := android.OtherModuleProvider(ctx, dep, cc.FlagExporterInfoProvider) 1240 depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...) 1241 depPaths.exportedLinkDirs = append(depPaths.exportedLinkDirs, linkPathFromFilePath(rustDep.OutputFile().Path())) 1242 1243 case procMacroDepTag: 1244 directProcMacroDeps = append(directProcMacroDeps, rustDep) 1245 mod.Properties.AndroidMkProcMacroLibs = append(mod.Properties.AndroidMkProcMacroLibs, makeLibName) 1246 // proc_macro link dirs need to be exported, so collect those here. 1247 depPaths.exportedLinkDirs = append(depPaths.exportedLinkDirs, linkPathFromFilePath(rustDep.OutputFile().Path())) 1248 1249 case sourceDepTag: 1250 if _, ok := mod.sourceProvider.(*protobufDecorator); ok { 1251 collectIncludedProtos(mod, rustDep) 1252 } 1253 } 1254 1255 transitiveAndroidMkSharedLibs = append(transitiveAndroidMkSharedLibs, rustDep.transitiveAndroidMkSharedLibs) 1256 1257 if android.IsSourceDepTagWithOutputTag(depTag, "") { 1258 // Since these deps are added in path_properties.go via AddDependencies, we need to ensure the correct 1259 // OS/Arch variant is used. 1260 var helper string 1261 if ctx.Host() { 1262 helper = "missing 'host_supported'?" 1263 } else { 1264 helper = "device module defined?" 1265 } 1266 1267 if dep.Target().Os != ctx.Os() { 1268 ctx.ModuleErrorf("OS mismatch on dependency %q (%s)", dep.Name(), helper) 1269 return 1270 } else if dep.Target().Arch.ArchType != ctx.Arch().ArchType { 1271 ctx.ModuleErrorf("Arch mismatch on dependency %q (%s)", dep.Name(), helper) 1272 return 1273 } 1274 directSrcProvidersDeps = append(directSrcProvidersDeps, rustDep) 1275 } 1276 1277 exportedInfo, _ := android.OtherModuleProvider(ctx, dep, FlagExporterInfoProvider) 1278 //Append the dependencies exportedDirs, except for proc-macros which target a different arch/OS 1279 if depTag != procMacroDepTag { 1280 depPaths.depFlags = append(depPaths.depFlags, exportedInfo.Flags...) 1281 depPaths.linkObjects = append(depPaths.linkObjects, exportedInfo.LinkObjects...) 1282 depPaths.linkDirs = append(depPaths.linkDirs, exportedInfo.LinkDirs...) 1283 } 1284 1285 if depTag == dylibDepTag || depTag == rlibDepTag || depTag == procMacroDepTag { 1286 linkFile := rustDep.UnstrippedOutputFile() 1287 linkDir := linkPathFromFilePath(linkFile) 1288 if lib, ok := mod.compiler.(exportedFlagsProducer); ok { 1289 lib.exportLinkDirs(linkDir) 1290 } 1291 } 1292 1293 if depTag == sourceDepTag { 1294 if _, ok := mod.sourceProvider.(*protobufDecorator); ok && mod.Source() { 1295 if _, ok := rustDep.sourceProvider.(*protobufDecorator); ok { 1296 exportedInfo, _ := android.OtherModuleProvider(ctx, dep, cc.FlagExporterInfoProvider) 1297 depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...) 1298 } 1299 } 1300 } 1301 } else if ccDep, ok := dep.(cc.LinkableInterface); ok { 1302 //Handle C dependencies 1303 makeLibName := cc.MakeLibName(ctx, mod, ccDep, depName) 1304 if _, ok := ccDep.(*Module); !ok { 1305 if ccDep.Module().Target().Os != ctx.Os() { 1306 ctx.ModuleErrorf("OS mismatch between %q and %q", ctx.ModuleName(), depName) 1307 return 1308 } 1309 if ccDep.Module().Target().Arch.ArchType != ctx.Arch().ArchType { 1310 ctx.ModuleErrorf("Arch mismatch between %q and %q", ctx.ModuleName(), depName) 1311 return 1312 } 1313 } 1314 linkObject := ccDep.OutputFile() 1315 if !linkObject.Valid() { 1316 if !ctx.Config().AllowMissingDependencies() { 1317 ctx.ModuleErrorf("Invalid output file when adding dep %q to %q", depName, ctx.ModuleName()) 1318 } else { 1319 ctx.AddMissingDependencies([]string{depName}) 1320 } 1321 return 1322 } 1323 1324 linkPath := linkPathFromFilePath(linkObject.Path()) 1325 1326 exportDep := false 1327 switch { 1328 case cc.IsStaticDepTag(depTag): 1329 if cc.IsWholeStaticLib(depTag) { 1330 // rustc will bundle static libraries when they're passed with "-lstatic=<lib>". This will fail 1331 // if the library is not prefixed by "lib". 1332 if mod.Binary() { 1333 // Binaries may sometimes need to link whole static libraries that don't start with 'lib'. 1334 // Since binaries don't need to 'rebundle' these like libraries and only use these for the 1335 // final linkage, pass the args directly to the linker to handle these cases. 1336 depPaths.depLinkFlags = append(depPaths.depLinkFlags, []string{"-Wl,--whole-archive", linkObject.Path().String(), "-Wl,--no-whole-archive"}...) 1337 } else if libName, ok := libNameFromFilePath(linkObject.Path()); ok { 1338 depPaths.depFlags = append(depPaths.depFlags, "-lstatic="+libName) 1339 } else { 1340 ctx.ModuleErrorf("'%q' cannot be listed as a whole_static_library in Rust modules unless the output is prefixed by 'lib'", depName, ctx.ModuleName()) 1341 } 1342 } 1343 1344 // Add this to linkObjects to pass the library directly to the linker as well. This propagates 1345 // to dependencies to avoid having to redeclare static libraries for dependents of the dylib variant. 1346 depPaths.linkObjects = append(depPaths.linkObjects, linkObject.String()) 1347 depPaths.linkDirs = append(depPaths.linkDirs, linkPath) 1348 1349 exportedInfo, _ := android.OtherModuleProvider(ctx, dep, cc.FlagExporterInfoProvider) 1350 depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...) 1351 depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...) 1352 depPaths.depClangFlags = append(depPaths.depClangFlags, exportedInfo.Flags...) 1353 depPaths.depGeneratedHeaders = append(depPaths.depGeneratedHeaders, exportedInfo.GeneratedHeaders...) 1354 directStaticLibDeps = append(directStaticLibDeps, ccDep) 1355 1356 // Record baseLibName for snapshots. 1357 mod.Properties.SnapshotStaticLibs = append(mod.Properties.SnapshotStaticLibs, cc.BaseLibName(depName)) 1358 1359 mod.Properties.AndroidMkStaticLibs = append(mod.Properties.AndroidMkStaticLibs, makeLibName) 1360 case cc.IsSharedDepTag(depTag): 1361 // For the shared lib dependencies, we may link to the stub variant 1362 // of the dependency depending on the context (e.g. if this 1363 // dependency crosses the APEX boundaries). 1364 sharedLibraryInfo, exportedInfo := cc.ChooseStubOrImpl(ctx, dep) 1365 1366 // Re-get linkObject as ChooseStubOrImpl actually tells us which 1367 // object (either from stub or non-stub) to use. 1368 linkObject = android.OptionalPathForPath(sharedLibraryInfo.SharedLibrary) 1369 if !linkObject.Valid() { 1370 if !ctx.Config().AllowMissingDependencies() { 1371 ctx.ModuleErrorf("Invalid output file when adding dep %q to %q", depName, ctx.ModuleName()) 1372 } else { 1373 ctx.AddMissingDependencies([]string{depName}) 1374 } 1375 return 1376 } 1377 linkPath = linkPathFromFilePath(linkObject.Path()) 1378 1379 depPaths.linkDirs = append(depPaths.linkDirs, linkPath) 1380 depPaths.linkObjects = append(depPaths.linkObjects, linkObject.String()) 1381 depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...) 1382 depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...) 1383 depPaths.depClangFlags = append(depPaths.depClangFlags, exportedInfo.Flags...) 1384 depPaths.depGeneratedHeaders = append(depPaths.depGeneratedHeaders, exportedInfo.GeneratedHeaders...) 1385 directSharedLibDeps = append(directSharedLibDeps, sharedLibraryInfo) 1386 1387 // Record baseLibName for snapshots. 1388 mod.Properties.SnapshotSharedLibs = append(mod.Properties.SnapshotSharedLibs, cc.BaseLibName(depName)) 1389 1390 directAndroidMkSharedLibs = append(directAndroidMkSharedLibs, makeLibName) 1391 exportDep = true 1392 case cc.IsHeaderDepTag(depTag): 1393 exportedInfo, _ := android.OtherModuleProvider(ctx, dep, cc.FlagExporterInfoProvider) 1394 depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...) 1395 depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...) 1396 depPaths.depGeneratedHeaders = append(depPaths.depGeneratedHeaders, exportedInfo.GeneratedHeaders...) 1397 mod.Properties.AndroidMkHeaderLibs = append(mod.Properties.AndroidMkHeaderLibs, makeLibName) 1398 case depTag == cc.CrtBeginDepTag: 1399 depPaths.CrtBegin = append(depPaths.CrtBegin, linkObject.Path()) 1400 case depTag == cc.CrtEndDepTag: 1401 depPaths.CrtEnd = append(depPaths.CrtEnd, linkObject.Path()) 1402 } 1403 1404 // Make sure these dependencies are propagated 1405 if lib, ok := mod.compiler.(exportedFlagsProducer); ok && exportDep { 1406 lib.exportLinkDirs(linkPath) 1407 lib.exportLinkObjects(linkObject.String()) 1408 } 1409 } else { 1410 switch { 1411 case depTag == cc.CrtBeginDepTag: 1412 depPaths.CrtBegin = append(depPaths.CrtBegin, android.OutputFileForModule(ctx, dep, "")) 1413 case depTag == cc.CrtEndDepTag: 1414 depPaths.CrtEnd = append(depPaths.CrtEnd, android.OutputFileForModule(ctx, dep, "")) 1415 } 1416 } 1417 1418 if srcDep, ok := dep.(android.SourceFileProducer); ok { 1419 if android.IsSourceDepTagWithOutputTag(depTag, "") { 1420 // These are usually genrules which don't have per-target variants. 1421 directSrcDeps = append(directSrcDeps, srcDep) 1422 } 1423 } 1424 }) 1425 1426 mod.transitiveAndroidMkSharedLibs = android.NewDepSet[string](android.PREORDER, directAndroidMkSharedLibs, transitiveAndroidMkSharedLibs) 1427 1428 var rlibDepFiles RustLibraries 1429 aliases := mod.compiler.Aliases() 1430 for _, dep := range directRlibDeps { 1431 crateName := dep.CrateName() 1432 if alias, aliased := aliases[crateName]; aliased { 1433 crateName = alias 1434 } 1435 rlibDepFiles = append(rlibDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile(), CrateName: crateName}) 1436 } 1437 var dylibDepFiles RustLibraries 1438 for _, dep := range directDylibDeps { 1439 crateName := dep.CrateName() 1440 if alias, aliased := aliases[crateName]; aliased { 1441 crateName = alias 1442 } 1443 dylibDepFiles = append(dylibDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile(), CrateName: crateName}) 1444 } 1445 var procMacroDepFiles RustLibraries 1446 for _, dep := range directProcMacroDeps { 1447 crateName := dep.CrateName() 1448 if alias, aliased := aliases[crateName]; aliased { 1449 crateName = alias 1450 } 1451 procMacroDepFiles = append(procMacroDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile(), CrateName: crateName}) 1452 } 1453 1454 var staticLibDepFiles android.Paths 1455 for _, dep := range directStaticLibDeps { 1456 staticLibDepFiles = append(staticLibDepFiles, dep.OutputFile().Path()) 1457 } 1458 1459 var sharedLibFiles android.Paths 1460 var sharedLibDepFiles android.Paths 1461 for _, dep := range directSharedLibDeps { 1462 sharedLibFiles = append(sharedLibFiles, dep.SharedLibrary) 1463 if dep.TableOfContents.Valid() { 1464 sharedLibDepFiles = append(sharedLibDepFiles, dep.TableOfContents.Path()) 1465 } else { 1466 sharedLibDepFiles = append(sharedLibDepFiles, dep.SharedLibrary) 1467 } 1468 } 1469 1470 var srcProviderDepFiles android.Paths 1471 for _, dep := range directSrcProvidersDeps { 1472 srcs, _ := dep.OutputFiles("") 1473 srcProviderDepFiles = append(srcProviderDepFiles, srcs...) 1474 } 1475 for _, dep := range directSrcDeps { 1476 srcs := dep.Srcs() 1477 srcProviderDepFiles = append(srcProviderDepFiles, srcs...) 1478 } 1479 1480 depPaths.RLibs = append(depPaths.RLibs, rlibDepFiles...) 1481 depPaths.DyLibs = append(depPaths.DyLibs, dylibDepFiles...) 1482 depPaths.SharedLibs = append(depPaths.SharedLibs, sharedLibFiles...) 1483 depPaths.SharedLibDeps = append(depPaths.SharedLibDeps, sharedLibDepFiles...) 1484 depPaths.StaticLibs = append(depPaths.StaticLibs, staticLibDepFiles...) 1485 depPaths.ProcMacros = append(depPaths.ProcMacros, procMacroDepFiles...) 1486 depPaths.SrcDeps = append(depPaths.SrcDeps, srcProviderDepFiles...) 1487 1488 // Dedup exported flags from dependencies 1489 depPaths.linkDirs = android.FirstUniqueStrings(depPaths.linkDirs) 1490 depPaths.linkObjects = android.FirstUniqueStrings(depPaths.linkObjects) 1491 depPaths.depFlags = android.FirstUniqueStrings(depPaths.depFlags) 1492 depPaths.depClangFlags = android.FirstUniqueStrings(depPaths.depClangFlags) 1493 depPaths.depIncludePaths = android.FirstUniquePaths(depPaths.depIncludePaths) 1494 depPaths.depSystemIncludePaths = android.FirstUniquePaths(depPaths.depSystemIncludePaths) 1495 1496 return depPaths 1497} 1498 1499func (mod *Module) InstallInData() bool { 1500 if mod.compiler == nil { 1501 return false 1502 } 1503 return mod.compiler.inData() 1504} 1505 1506func (mod *Module) InstallInRamdisk() bool { 1507 return mod.InRamdisk() 1508} 1509 1510func (mod *Module) InstallInVendorRamdisk() bool { 1511 return mod.InVendorRamdisk() 1512} 1513 1514func (mod *Module) InstallInRecovery() bool { 1515 return mod.InRecovery() 1516} 1517 1518func linkPathFromFilePath(filepath android.Path) string { 1519 return strings.Split(filepath.String(), filepath.Base())[0] 1520} 1521 1522// usePublicApi returns true if the rust variant should link against NDK (publicapi) 1523func (r *Module) usePublicApi() bool { 1524 return r.Device() && r.UseSdk() 1525} 1526 1527// useVendorApi returns true if the rust variant should link against LLNDK (vendorapi) 1528func (r *Module) useVendorApi() bool { 1529 return r.Device() && (r.InVendor() || r.InProduct()) 1530} 1531 1532func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) { 1533 ctx := &depsContext{ 1534 BottomUpMutatorContext: actx, 1535 } 1536 1537 deps := mod.deps(ctx) 1538 var commonDepVariations []blueprint.Variation 1539 1540 apiImportInfo := cc.GetApiImports(mod, actx) 1541 if mod.usePublicApi() || mod.useVendorApi() { 1542 for idx, lib := range deps.SharedLibs { 1543 deps.SharedLibs[idx] = cc.GetReplaceModuleName(lib, apiImportInfo.SharedLibs) 1544 } 1545 } 1546 1547 if ctx.Os() == android.Android { 1548 deps.SharedLibs, _ = cc.FilterNdkLibs(mod, ctx.Config(), deps.SharedLibs) 1549 } 1550 1551 stdLinkage := "dylib-std" 1552 if mod.compiler.stdLinkage(ctx) == RlibLinkage { 1553 stdLinkage = "rlib-std" 1554 } 1555 1556 rlibDepVariations := commonDepVariations 1557 rlibDepVariations = append(rlibDepVariations, blueprint.Variation{Mutator: "link", Variation: ""}) 1558 1559 if lib, ok := mod.compiler.(libraryInterface); !ok || !lib.sysroot() { 1560 rlibDepVariations = append(rlibDepVariations, 1561 blueprint.Variation{Mutator: "rust_stdlinkage", Variation: stdLinkage}) 1562 } 1563 1564 // rlibs 1565 rlibDepVariations = append(rlibDepVariations, blueprint.Variation{Mutator: "rust_libraries", Variation: rlibVariation}) 1566 for _, lib := range deps.Rlibs { 1567 depTag := rlibDepTag 1568 actx.AddVariationDependencies(rlibDepVariations, depTag, lib) 1569 } 1570 1571 // dylibs 1572 dylibDepVariations := append(commonDepVariations, blueprint.Variation{Mutator: "rust_libraries", Variation: dylibVariation}) 1573 dylibDepVariations = append(dylibDepVariations, blueprint.Variation{Mutator: "link", Variation: ""}) 1574 1575 for _, lib := range deps.Dylibs { 1576 actx.AddVariationDependencies(dylibDepVariations, dylibDepTag, lib) 1577 } 1578 1579 // rustlibs 1580 if deps.Rustlibs != nil { 1581 if !mod.compiler.Disabled() { 1582 for _, lib := range deps.Rustlibs { 1583 autoDep := mod.compiler.(autoDeppable).autoDep(ctx) 1584 if autoDep.depTag == rlibDepTag { 1585 // Handle the rlib deptag case 1586 actx.AddVariationDependencies(rlibDepVariations, rlibDepTag, lib) 1587 1588 } else { 1589 // autoDep.depTag is a dylib depTag. Not all rustlibs may be available as a dylib however. 1590 // Check for the existence of the dylib deptag variant. Select it if available, 1591 // otherwise select the rlib variant. 1592 autoDepVariations := append(commonDepVariations, 1593 blueprint.Variation{Mutator: "rust_libraries", Variation: autoDep.variation}) 1594 autoDepVariations = append(autoDepVariations, blueprint.Variation{Mutator: "link", Variation: ""}) 1595 if actx.OtherModuleDependencyVariantExists(autoDepVariations, lib) { 1596 actx.AddVariationDependencies(autoDepVariations, autoDep.depTag, lib) 1597 1598 } else { 1599 // If there's no dylib dependency available, try to add the rlib dependency instead. 1600 actx.AddVariationDependencies(rlibDepVariations, rlibDepTag, lib) 1601 1602 } 1603 } 1604 } 1605 } else if _, ok := mod.sourceProvider.(*protobufDecorator); ok { 1606 for _, lib := range deps.Rustlibs { 1607 srcProviderVariations := append(commonDepVariations, 1608 blueprint.Variation{Mutator: "rust_libraries", Variation: "source"}) 1609 srcProviderVariations = append(srcProviderVariations, blueprint.Variation{Mutator: "link", Variation: ""}) 1610 1611 // Only add rustlib dependencies if they're source providers themselves. 1612 // This is used to track which crate names need to be added to the source generated 1613 // in the rust_protobuf mod.rs. 1614 if actx.OtherModuleDependencyVariantExists(srcProviderVariations, lib) { 1615 actx.AddVariationDependencies(srcProviderVariations, sourceDepTag, lib) 1616 } 1617 } 1618 } 1619 } 1620 1621 // stdlibs 1622 if deps.Stdlibs != nil { 1623 if mod.compiler.stdLinkage(ctx) == RlibLinkage { 1624 for _, lib := range deps.Stdlibs { 1625 actx.AddVariationDependencies(append(commonDepVariations, []blueprint.Variation{{Mutator: "rust_libraries", Variation: "rlib"}, {Mutator: "link", Variation: ""}}...), 1626 rlibDepTag, lib) 1627 } 1628 } else { 1629 for _, lib := range deps.Stdlibs { 1630 actx.AddVariationDependencies(dylibDepVariations, dylibDepTag, lib) 1631 1632 } 1633 } 1634 } 1635 1636 for _, lib := range deps.SharedLibs { 1637 depTag := cc.SharedDepTag() 1638 name, version := cc.StubsLibNameAndVersion(lib) 1639 1640 variations := []blueprint.Variation{ 1641 {Mutator: "link", Variation: "shared"}, 1642 } 1643 // For core variant, add a dep on the implementation (if it exists) and its .apiimport (if it exists) 1644 // GenerateAndroidBuildActions will pick the correct impl/stub based on the api_domain boundary 1645 if _, ok := apiImportInfo.ApexSharedLibs[name]; !ok || ctx.OtherModuleExists(name) { 1646 cc.AddSharedLibDependenciesWithVersions(ctx, mod, variations, depTag, name, version, false) 1647 } 1648 1649 if apiLibraryName, ok := apiImportInfo.ApexSharedLibs[name]; ok { 1650 cc.AddSharedLibDependenciesWithVersions(ctx, mod, variations, depTag, apiLibraryName, version, false) 1651 } 1652 } 1653 1654 for _, lib := range deps.WholeStaticLibs { 1655 depTag := cc.StaticDepTag(true) 1656 1657 actx.AddVariationDependencies([]blueprint.Variation{ 1658 {Mutator: "link", Variation: "static"}, 1659 }, depTag, lib) 1660 } 1661 1662 for _, lib := range deps.StaticLibs { 1663 depTag := cc.StaticDepTag(false) 1664 1665 actx.AddVariationDependencies([]blueprint.Variation{ 1666 {Mutator: "link", Variation: "static"}, 1667 }, depTag, lib) 1668 } 1669 1670 actx.AddVariationDependencies(nil, cc.HeaderDepTag(), deps.HeaderLibs...) 1671 1672 crtVariations := cc.GetCrtVariations(ctx, mod) 1673 for _, crt := range deps.CrtBegin { 1674 actx.AddVariationDependencies(crtVariations, cc.CrtBeginDepTag, crt) 1675 } 1676 for _, crt := range deps.CrtEnd { 1677 actx.AddVariationDependencies(crtVariations, cc.CrtEndDepTag, crt) 1678 } 1679 1680 if mod.sourceProvider != nil { 1681 if bindgen, ok := mod.sourceProvider.(*bindgenDecorator); ok && 1682 bindgen.Properties.Custom_bindgen != "" { 1683 actx.AddFarVariationDependencies(ctx.Config().BuildOSTarget.Variations(), customBindgenDepTag, 1684 bindgen.Properties.Custom_bindgen) 1685 } 1686 } 1687 1688 actx.AddVariationDependencies([]blueprint.Variation{ 1689 {Mutator: "link", Variation: "shared"}, 1690 }, dataLibDepTag, deps.DataLibs...) 1691 1692 actx.AddVariationDependencies(nil, dataBinDepTag, deps.DataBins...) 1693 1694 // proc_macros are compiler plugins, and so we need the host arch variant as a dependendcy. 1695 actx.AddFarVariationDependencies(ctx.Config().BuildOSTarget.Variations(), procMacroDepTag, deps.ProcMacros...) 1696 1697 mod.afdo.addDep(ctx, actx) 1698} 1699 1700func BeginMutator(ctx android.BottomUpMutatorContext) { 1701 if mod, ok := ctx.Module().(*Module); ok && mod.Enabled(ctx) { 1702 mod.beginMutator(ctx) 1703 } 1704} 1705 1706func (mod *Module) beginMutator(actx android.BottomUpMutatorContext) { 1707 ctx := &baseModuleContext{ 1708 BaseModuleContext: actx, 1709 } 1710 1711 mod.begin(ctx) 1712} 1713 1714func (mod *Module) Name() string { 1715 name := mod.ModuleBase.Name() 1716 if p, ok := mod.compiler.(interface { 1717 Name(string) string 1718 }); ok { 1719 name = p.Name(name) 1720 } 1721 return name 1722} 1723 1724func (mod *Module) disableClippy() { 1725 if mod.clippy != nil { 1726 mod.clippy.Properties.Clippy_lints = proptools.StringPtr("none") 1727 } 1728} 1729 1730var _ android.HostToolProvider = (*Module)(nil) 1731 1732func (mod *Module) HostToolPath() android.OptionalPath { 1733 if !mod.Host() { 1734 return android.OptionalPath{} 1735 } 1736 if binary, ok := mod.compiler.(*binaryDecorator); ok { 1737 return android.OptionalPathForPath(binary.baseCompiler.path) 1738 } else if pm, ok := mod.compiler.(*procMacroDecorator); ok { 1739 // Even though proc-macros aren't strictly "tools", since they target the compiler 1740 // and act as compiler plugins, we treat them similarly. 1741 return android.OptionalPathForPath(pm.baseCompiler.path) 1742 } 1743 return android.OptionalPath{} 1744} 1745 1746var _ android.ApexModule = (*Module)(nil) 1747 1748func (mod *Module) MinSdkVersion() string { 1749 return String(mod.Properties.Min_sdk_version) 1750} 1751 1752// Implements android.ApexModule 1753func (mod *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion android.ApiLevel) error { 1754 minSdkVersion := mod.MinSdkVersion() 1755 if minSdkVersion == "apex_inherit" { 1756 return nil 1757 } 1758 if minSdkVersion == "" { 1759 return fmt.Errorf("min_sdk_version is not specificed") 1760 } 1761 1762 // Not using nativeApiLevelFromUser because the context here is not 1763 // necessarily a native context. 1764 ver, err := android.ApiLevelFromUser(ctx, minSdkVersion) 1765 if err != nil { 1766 return err 1767 } 1768 1769 if ver.GreaterThan(sdkVersion) { 1770 return fmt.Errorf("newer SDK(%v)", ver) 1771 } 1772 return nil 1773} 1774 1775// Implements android.ApexModule 1776func (mod *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool { 1777 depTag := ctx.OtherModuleDependencyTag(dep) 1778 1779 if ccm, ok := dep.(*cc.Module); ok { 1780 if ccm.HasStubsVariants() { 1781 if cc.IsSharedDepTag(depTag) { 1782 // dynamic dep to a stubs lib crosses APEX boundary 1783 return false 1784 } 1785 if cc.IsRuntimeDepTag(depTag) { 1786 // runtime dep to a stubs lib also crosses APEX boundary 1787 return false 1788 } 1789 1790 if cc.IsHeaderDepTag(depTag) { 1791 return false 1792 } 1793 } 1794 if mod.Static() && cc.IsSharedDepTag(depTag) { 1795 // shared_lib dependency from a static lib is considered as crossing 1796 // the APEX boundary because the dependency doesn't actually is 1797 // linked; the dependency is used only during the compilation phase. 1798 return false 1799 } 1800 } 1801 1802 if depTag == procMacroDepTag || depTag == customBindgenDepTag { 1803 return false 1804 } 1805 1806 return true 1807} 1808 1809// Overrides ApexModule.IsInstallabeToApex() 1810func (mod *Module) IsInstallableToApex() bool { 1811 if mod.compiler != nil { 1812 if lib, ok := mod.compiler.(libraryInterface); ok && (lib.shared() || lib.dylib()) { 1813 return true 1814 } 1815 if _, ok := mod.compiler.(*binaryDecorator); ok { 1816 return true 1817 } 1818 } 1819 return false 1820} 1821 1822// If a library file has a "lib" prefix, extract the library name without the prefix. 1823func libNameFromFilePath(filepath android.Path) (string, bool) { 1824 libName := strings.TrimSuffix(filepath.Base(), filepath.Ext()) 1825 if strings.HasPrefix(libName, "lib") { 1826 libName = libName[3:] 1827 return libName, true 1828 } 1829 return "", false 1830} 1831 1832func kytheExtractRustFactory() android.Singleton { 1833 return &kytheExtractRustSingleton{} 1834} 1835 1836type kytheExtractRustSingleton struct { 1837} 1838 1839func (k kytheExtractRustSingleton) GenerateBuildActions(ctx android.SingletonContext) { 1840 var xrefTargets android.Paths 1841 ctx.VisitAllModules(func(module android.Module) { 1842 if rustModule, ok := module.(xref); ok { 1843 xrefTargets = append(xrefTargets, rustModule.XrefRustFiles()...) 1844 } 1845 }) 1846 if len(xrefTargets) > 0 { 1847 ctx.Phony("xref_rust", xrefTargets...) 1848 } 1849} 1850 1851func (c *Module) Partition() string { 1852 return "" 1853} 1854 1855var Bool = proptools.Bool 1856var BoolDefault = proptools.BoolDefault 1857var String = proptools.String 1858var StringPtr = proptools.StringPtr 1859 1860var _ android.OutputFileProducer = (*Module)(nil) 1861