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 "errors" 19 "fmt" 20 "regexp" 21 "strings" 22 23 "github.com/google/blueprint" 24 "github.com/google/blueprint/depset" 25 26 "android/soong/android" 27 "android/soong/cc" 28) 29 30var ( 31 RlibStdlibSuffix = ".rlib-std" 32) 33 34func init() { 35 android.RegisterModuleType("rust_library", RustLibraryFactory) 36 android.RegisterModuleType("rust_library_dylib", RustLibraryDylibFactory) 37 android.RegisterModuleType("rust_library_rlib", RustLibraryRlibFactory) 38 android.RegisterModuleType("rust_library_host", RustLibraryHostFactory) 39 android.RegisterModuleType("rust_library_host_dylib", RustLibraryDylibHostFactory) 40 android.RegisterModuleType("rust_library_host_rlib", RustLibraryRlibHostFactory) 41 android.RegisterModuleType("rust_ffi", RustFFIFactory) 42 android.RegisterModuleType("rust_ffi_shared", RustFFISharedFactory) 43 android.RegisterModuleType("rust_ffi_rlib", RustFFIRlibFactory) 44 android.RegisterModuleType("rust_ffi_host", RustFFIHostFactory) 45 android.RegisterModuleType("rust_ffi_host_shared", RustFFISharedHostFactory) 46 android.RegisterModuleType("rust_ffi_host_rlib", RustFFIRlibHostFactory) 47 48 // TODO: Remove when all instances of rust_ffi_static have been switched to rust_ffi_rlib 49 // Alias rust_ffi_static to the rust_ffi_rlib factory 50 android.RegisterModuleType("rust_ffi_static", RustFFIRlibFactory) 51 android.RegisterModuleType("rust_ffi_host_static", RustFFIRlibHostFactory) 52} 53 54type VariantLibraryProperties struct { 55 Enabled *bool `android:"arch_variant"` 56 Srcs []string `android:"path,arch_variant"` 57} 58 59type LibraryCompilerProperties struct { 60 Rlib VariantLibraryProperties `android:"arch_variant"` 61 Dylib VariantLibraryProperties `android:"arch_variant"` 62 Shared VariantLibraryProperties `android:"arch_variant"` 63 Static VariantLibraryProperties `android:"arch_variant"` 64 65 // TODO: Remove this when all instances of Include_dirs have been removed from rust_ffi modules. 66 // path to include directories to pass to cc_* modules, only relevant for static/shared variants (deprecated, use export_include_dirs instead). 67 Include_dirs []string `android:"path,arch_variant"` 68 69 // path to include directories to export to cc_* modules, only relevant for static/shared variants. 70 Export_include_dirs []string `android:"path,arch_variant"` 71 72 // Whether this library is part of the Rust toolchain sysroot. 73 Sysroot *bool 74 75 // Exclude this rust_ffi target from being included in APEXes. 76 // TODO(b/362509506): remove this once stubs are properly supported by rust_ffi targets. 77 Apex_exclude *bool 78} 79 80type LibraryMutatedProperties struct { 81 // Build a dylib variant 82 BuildDylib bool `blueprint:"mutated"` 83 // Build an rlib variant 84 BuildRlib bool `blueprint:"mutated"` 85 // Build a shared library variant 86 BuildShared bool `blueprint:"mutated"` 87 // Build a static library variant 88 BuildStatic bool `blueprint:"mutated"` 89 90 // This variant is a dylib 91 VariantIsDylib bool `blueprint:"mutated"` 92 // This variant is an rlib 93 VariantIsRlib bool `blueprint:"mutated"` 94 // This variant is a shared library 95 VariantIsShared bool `blueprint:"mutated"` 96 // This variant is a source provider 97 VariantIsSource bool `blueprint:"mutated"` 98 99 // This variant is disabled and should not be compiled 100 // (used for SourceProvider variants that produce only source) 101 VariantIsDisabled bool `blueprint:"mutated"` 102 103 // Whether this library variant should be link libstd via rlibs 104 VariantIsStaticStd bool `blueprint:"mutated"` 105} 106 107type libraryDecorator struct { 108 *baseCompiler 109 *flagExporter 110 stripper Stripper 111 112 Properties LibraryCompilerProperties 113 MutatedProperties LibraryMutatedProperties 114 includeDirs android.Paths 115 sourceProvider SourceProvider 116 117 isFFI bool 118 119 // table-of-contents file for cdylib crates to optimize out relinking when possible 120 tocFile android.OptionalPath 121} 122 123type libraryInterface interface { 124 rlib() bool 125 dylib() bool 126 static() bool 127 shared() bool 128 sysroot() bool 129 source() bool 130 apexExclude() bool 131 132 // Returns true if the build options for the module have selected a particular build type 133 buildRlib() bool 134 buildDylib() bool 135 buildShared() bool 136 buildStatic() bool 137 138 // Sets a particular variant type 139 setRlib() 140 setDylib() 141 setShared() 142 setStatic() 143 setSource() 144 145 // libstd linkage functions 146 rlibStd() bool 147 setRlibStd() 148 setDylibStd() 149 150 // Build a specific library variant 151 BuildOnlyFFI() 152 BuildOnlyRust() 153 BuildOnlyRlib() 154 BuildOnlyDylib() 155 BuildOnlyStatic() 156 BuildOnlyShared() 157 158 toc() android.OptionalPath 159 160 isFFILibrary() bool 161} 162 163func (library *libraryDecorator) nativeCoverage() bool { 164 return true 165} 166 167func (library *libraryDecorator) toc() android.OptionalPath { 168 return library.tocFile 169} 170 171func (library *libraryDecorator) rlib() bool { 172 return library.MutatedProperties.VariantIsRlib 173} 174 175func (library *libraryDecorator) sysroot() bool { 176 return Bool(library.Properties.Sysroot) 177} 178 179func (library *libraryDecorator) dylib() bool { 180 return library.MutatedProperties.VariantIsDylib 181} 182 183func (library *libraryDecorator) shared() bool { 184 return library.MutatedProperties.VariantIsShared 185} 186 187func (library *libraryDecorator) static() bool { 188 return false 189} 190 191func (library *libraryDecorator) source() bool { 192 return library.MutatedProperties.VariantIsSource 193} 194 195func (library *libraryDecorator) apexExclude() bool { 196 return Bool(library.Properties.Apex_exclude) 197} 198 199func (library *libraryDecorator) buildRlib() bool { 200 return library.MutatedProperties.BuildRlib && BoolDefault(library.Properties.Rlib.Enabled, true) 201} 202 203func (library *libraryDecorator) buildDylib() bool { 204 return library.MutatedProperties.BuildDylib && BoolDefault(library.Properties.Dylib.Enabled, true) 205} 206 207func (library *libraryDecorator) buildShared() bool { 208 return library.MutatedProperties.BuildShared && BoolDefault(library.Properties.Shared.Enabled, true) 209} 210 211func (library *libraryDecorator) buildStatic() bool { 212 return library.MutatedProperties.BuildStatic && BoolDefault(library.Properties.Static.Enabled, true) 213} 214 215func (library *libraryDecorator) setRlib() { 216 library.MutatedProperties.VariantIsRlib = true 217 library.MutatedProperties.VariantIsDylib = false 218 library.MutatedProperties.VariantIsShared = false 219} 220 221func (library *libraryDecorator) setDylib() { 222 library.MutatedProperties.VariantIsRlib = false 223 library.MutatedProperties.VariantIsDylib = true 224 library.MutatedProperties.VariantIsShared = false 225} 226 227func (library *libraryDecorator) rlibStd() bool { 228 return library.MutatedProperties.VariantIsStaticStd 229} 230 231func (library *libraryDecorator) setRlibStd() { 232 library.MutatedProperties.VariantIsStaticStd = true 233} 234 235func (library *libraryDecorator) setDylibStd() { 236 library.MutatedProperties.VariantIsStaticStd = false 237} 238 239func (library *libraryDecorator) setShared() { 240 library.MutatedProperties.VariantIsShared = true 241 library.MutatedProperties.VariantIsRlib = false 242 library.MutatedProperties.VariantIsDylib = false 243} 244 245func (library *libraryDecorator) setStatic() { 246 panic(fmt.Errorf("static variant is not supported for rust modules, use the rlib variant instead")) 247} 248 249func (library *libraryDecorator) setSource() { 250 library.MutatedProperties.VariantIsSource = true 251} 252 253func (library *libraryDecorator) autoDep(ctx android.BottomUpMutatorContext) autoDep { 254 if library.preferRlib() { 255 return rlibAutoDep 256 } else if library.rlib() || library.static() { 257 return rlibAutoDep 258 } else if library.dylib() || library.shared() { 259 return dylibAutoDep 260 } else { 261 panic(fmt.Errorf("autoDep called on library %q that has no enabled variants.", ctx.ModuleName())) 262 } 263} 264 265func (library *libraryDecorator) stdLinkage(ctx *depsContext) RustLinkage { 266 if library.static() || library.MutatedProperties.VariantIsStaticStd || (library.rlib() && library.isFFILibrary()) { 267 return RlibLinkage 268 } else if library.baseCompiler.preferRlib() { 269 return RlibLinkage 270 } 271 return DefaultLinkage 272} 273 274var _ compiler = (*libraryDecorator)(nil) 275var _ libraryInterface = (*libraryDecorator)(nil) 276var _ exportedFlagsProducer = (*libraryDecorator)(nil) 277 278// rust_library produces all Rust variants (rust_library_dylib and 279// rust_library_rlib). 280func RustLibraryFactory() android.Module { 281 module, library := NewRustLibrary(android.HostAndDeviceSupported) 282 library.BuildOnlyRust() 283 return module.Init() 284} 285 286// rust_ffi produces all FFI variants (rust_ffi_shared, rust_ffi_static, and 287// rust_ffi_rlib). 288func RustFFIFactory() android.Module { 289 module, library := NewRustLibrary(android.HostAndDeviceSupported) 290 library.BuildOnlyFFI() 291 return module.Init() 292} 293 294// rust_library_dylib produces a Rust dylib (Rust crate type "dylib"). 295func RustLibraryDylibFactory() android.Module { 296 module, library := NewRustLibrary(android.HostAndDeviceSupported) 297 library.BuildOnlyDylib() 298 return module.Init() 299} 300 301// rust_library_rlib produces an rlib (Rust crate type "rlib"). 302func RustLibraryRlibFactory() android.Module { 303 module, library := NewRustLibrary(android.HostAndDeviceSupported) 304 library.BuildOnlyRlib() 305 return module.Init() 306} 307 308// rust_ffi_shared produces a shared library (Rust crate type 309// "cdylib"). 310func RustFFISharedFactory() android.Module { 311 module, library := NewRustLibrary(android.HostAndDeviceSupported) 312 library.BuildOnlyShared() 313 return module.Init() 314} 315 316// rust_library_host produces all Rust variants for the host 317// (rust_library_dylib_host and rust_library_rlib_host). 318func RustLibraryHostFactory() android.Module { 319 module, library := NewRustLibrary(android.HostSupported) 320 library.BuildOnlyRust() 321 return module.Init() 322} 323 324// rust_ffi_host produces all FFI variants for the host 325// (rust_ffi_rlib_host, rust_ffi_static_host, and rust_ffi_shared_host). 326func RustFFIHostFactory() android.Module { 327 module, library := NewRustLibrary(android.HostSupported) 328 library.BuildOnlyFFI() 329 return module.Init() 330} 331 332// rust_library_dylib_host produces a dylib for the host (Rust crate 333// type "dylib"). 334func RustLibraryDylibHostFactory() android.Module { 335 module, library := NewRustLibrary(android.HostSupported) 336 library.BuildOnlyDylib() 337 return module.Init() 338} 339 340// rust_library_rlib_host produces an rlib for the host (Rust crate 341// type "rlib"). 342func RustLibraryRlibHostFactory() android.Module { 343 module, library := NewRustLibrary(android.HostSupported) 344 library.BuildOnlyRlib() 345 return module.Init() 346} 347 348// rust_ffi_shared_host produces an shared library for the host (Rust 349// crate type "cdylib"). 350func RustFFISharedHostFactory() android.Module { 351 module, library := NewRustLibrary(android.HostSupported) 352 library.BuildOnlyShared() 353 return module.Init() 354} 355 356// rust_ffi_rlib_host produces an rlib for the host (Rust crate 357// type "rlib"). 358func RustFFIRlibHostFactory() android.Module { 359 module, library := NewRustLibrary(android.HostSupported) 360 library.BuildOnlyRlib() 361 362 library.isFFI = true 363 return module.Init() 364} 365 366// rust_ffi_rlib produces an rlib (Rust crate type "rlib"). 367func RustFFIRlibFactory() android.Module { 368 module, library := NewRustLibrary(android.HostAndDeviceSupported) 369 library.BuildOnlyRlib() 370 371 library.isFFI = true 372 return module.Init() 373} 374 375func (library *libraryDecorator) BuildOnlyFFI() { 376 library.MutatedProperties.BuildDylib = false 377 // we build rlibs for later static ffi linkage. 378 library.MutatedProperties.BuildRlib = true 379 library.MutatedProperties.BuildShared = true 380 library.MutatedProperties.BuildStatic = false 381 382 library.isFFI = true 383} 384 385func (library *libraryDecorator) BuildOnlyRust() { 386 library.MutatedProperties.BuildDylib = true 387 library.MutatedProperties.BuildRlib = true 388 library.MutatedProperties.BuildShared = false 389 library.MutatedProperties.BuildStatic = false 390} 391 392func (library *libraryDecorator) BuildOnlyDylib() { 393 library.MutatedProperties.BuildDylib = true 394 library.MutatedProperties.BuildRlib = false 395 library.MutatedProperties.BuildShared = false 396 library.MutatedProperties.BuildStatic = false 397} 398 399func (library *libraryDecorator) BuildOnlyRlib() { 400 library.MutatedProperties.BuildDylib = false 401 library.MutatedProperties.BuildRlib = true 402 library.MutatedProperties.BuildShared = false 403 library.MutatedProperties.BuildStatic = false 404} 405 406func (library *libraryDecorator) BuildOnlyStatic() { 407 library.MutatedProperties.BuildRlib = false 408 library.MutatedProperties.BuildDylib = false 409 library.MutatedProperties.BuildShared = false 410 library.MutatedProperties.BuildStatic = true 411 412 library.isFFI = true 413} 414 415func (library *libraryDecorator) BuildOnlyShared() { 416 library.MutatedProperties.BuildRlib = false 417 library.MutatedProperties.BuildDylib = false 418 library.MutatedProperties.BuildStatic = false 419 library.MutatedProperties.BuildShared = true 420 421 library.isFFI = true 422} 423 424func (library *libraryDecorator) isFFILibrary() bool { 425 return library.isFFI 426} 427 428func NewRustLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorator) { 429 module := newModule(hod, android.MultilibBoth) 430 431 library := &libraryDecorator{ 432 MutatedProperties: LibraryMutatedProperties{ 433 BuildDylib: false, 434 BuildRlib: false, 435 BuildShared: false, 436 BuildStatic: false, 437 }, 438 baseCompiler: NewBaseCompiler("lib", "lib64", InstallInSystem), 439 flagExporter: NewFlagExporter(), 440 } 441 442 module.compiler = library 443 444 return module, library 445} 446 447func (library *libraryDecorator) compilerProps() []interface{} { 448 return append(library.baseCompiler.compilerProps(), 449 &library.Properties, 450 &library.MutatedProperties, 451 &library.stripper.StripProperties) 452} 453 454func (library *libraryDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps { 455 deps = library.baseCompiler.compilerDeps(ctx, deps) 456 457 if library.dylib() || library.shared() { 458 if ctx.toolchain().Bionic() { 459 deps = bionicDeps(ctx, deps, false) 460 deps.CrtBegin = []string{"crtbegin_so"} 461 deps.CrtEnd = []string{"crtend_so"} 462 } else if ctx.Os() == android.LinuxMusl { 463 deps = muslDeps(ctx, deps, false) 464 deps.CrtBegin = []string{"libc_musl_crtbegin_so"} 465 deps.CrtEnd = []string{"libc_musl_crtend_so"} 466 } 467 } 468 469 return deps 470} 471 472func (library *libraryDecorator) sharedLibFilename(ctx ModuleContext) string { 473 return library.getStem(ctx) + ctx.toolchain().SharedLibSuffix() 474} 475 476// Library cfg flags common to all variants 477func CommonLibraryCfgFlags(ctx android.ModuleContext, flags Flags) Flags { 478 return flags 479} 480 481func (library *libraryDecorator) cfgFlags(ctx ModuleContext, flags Flags) Flags { 482 flags = library.baseCompiler.cfgFlags(ctx, flags) 483 flags = CommonLibraryCfgFlags(ctx, flags) 484 485 cfgs := library.baseCompiler.Properties.Cfgs.GetOrDefault(ctx, nil) 486 487 if library.dylib() { 488 // We need to add a dependency on std in order to link crates as dylibs. 489 // The hack to add this dependency is guarded by the following cfg so 490 // that we don't force a dependency when it isn't needed. 491 cfgs = append(cfgs, "android_dylib") 492 } 493 494 cfgFlags := cfgsToFlags(cfgs) 495 496 flags.RustFlags = append(flags.RustFlags, cfgFlags...) 497 flags.RustdocFlags = append(flags.RustdocFlags, cfgFlags...) 498 499 return flags 500} 501 502// Common flags applied to all libraries irrespective of properties or variant should be included here 503func CommonLibraryCompilerFlags(ctx android.ModuleContext, flags Flags) Flags { 504 flags.RustFlags = append(flags.RustFlags, "-C metadata="+ctx.ModuleName()) 505 506 return flags 507} 508 509func (library *libraryDecorator) compilerFlags(ctx ModuleContext, flags Flags) Flags { 510 flags = library.baseCompiler.compilerFlags(ctx, flags) 511 512 flags = CommonLibraryCompilerFlags(ctx, flags) 513 514 if library.isFFI { 515 library.includeDirs = append(library.includeDirs, android.PathsForModuleSrc(ctx, library.Properties.Include_dirs)...) 516 library.includeDirs = append(library.includeDirs, android.PathsForModuleSrc(ctx, library.Properties.Export_include_dirs)...) 517 } 518 519 if library.shared() { 520 if ctx.Darwin() { 521 flags.LinkFlags = append( 522 flags.LinkFlags, 523 "-dynamic_lib", 524 "-install_name @rpath/"+library.sharedLibFilename(ctx), 525 ) 526 } else { 527 flags.LinkFlags = append(flags.LinkFlags, "-Wl,-soname="+library.sharedLibFilename(ctx)) 528 } 529 } 530 531 return flags 532} 533 534func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) buildOutput { 535 var outputFile android.ModuleOutPath 536 var ret buildOutput 537 var fileName string 538 crateRootPath := crateRootPath(ctx, library) 539 540 if library.sourceProvider != nil { 541 deps.srcProviderFiles = append(deps.srcProviderFiles, library.sourceProvider.Srcs()...) 542 } 543 544 // Ensure link dirs are not duplicated 545 deps.linkDirs = android.FirstUniqueStrings(deps.linkDirs) 546 547 // Calculate output filename 548 if library.rlib() { 549 fileName = library.getStem(ctx) + ctx.toolchain().RlibSuffix() 550 outputFile = android.PathForModuleOut(ctx, fileName) 551 ret.outputFile = outputFile 552 } else if library.dylib() { 553 fileName = library.getStem(ctx) + ctx.toolchain().DylibSuffix() 554 outputFile = android.PathForModuleOut(ctx, fileName) 555 ret.outputFile = outputFile 556 } else if library.static() { 557 fileName = library.getStem(ctx) + ctx.toolchain().StaticLibSuffix() 558 outputFile = android.PathForModuleOut(ctx, fileName) 559 ret.outputFile = outputFile 560 } else if library.shared() { 561 fileName = library.sharedLibFilename(ctx) 562 outputFile = android.PathForModuleOut(ctx, fileName) 563 ret.outputFile = outputFile 564 } 565 566 if !library.rlib() && !library.static() && library.stripper.NeedsStrip(ctx) { 567 strippedOutputFile := outputFile 568 outputFile = android.PathForModuleOut(ctx, "unstripped", fileName) 569 library.stripper.StripExecutableOrSharedLib(ctx, outputFile, strippedOutputFile) 570 571 library.baseCompiler.strippedOutputFile = android.OptionalPathForPath(strippedOutputFile) 572 } 573 library.baseCompiler.unstrippedOutputFile = outputFile 574 575 flags.RustFlags = append(flags.RustFlags, deps.depFlags...) 576 flags.LinkFlags = append(flags.LinkFlags, deps.depLinkFlags...) 577 flags.LinkFlags = append(flags.LinkFlags, deps.linkObjects...) 578 579 if library.dylib() { 580 // We need prefer-dynamic for now to avoid linking in the static stdlib. See: 581 // https://github.com/rust-lang/rust/issues/19680 582 // https://github.com/rust-lang/rust/issues/34909 583 flags.RustFlags = append(flags.RustFlags, "-C prefer-dynamic") 584 } 585 586 // Call the appropriate builder for this library type 587 if library.rlib() { 588 ret.kytheFile = TransformSrctoRlib(ctx, crateRootPath, deps, flags, outputFile).kytheFile 589 } else if library.dylib() { 590 ret.kytheFile = TransformSrctoDylib(ctx, crateRootPath, deps, flags, outputFile).kytheFile 591 } else if library.static() { 592 ret.kytheFile = TransformSrctoStatic(ctx, crateRootPath, deps, flags, outputFile).kytheFile 593 } else if library.shared() { 594 ret.kytheFile = TransformSrctoShared(ctx, crateRootPath, deps, flags, outputFile).kytheFile 595 } 596 597 if library.rlib() || library.dylib() { 598 library.flagExporter.exportLinkDirs(deps.linkDirs...) 599 library.flagExporter.exportLinkObjects(deps.linkObjects...) 600 } 601 602 // Since we have FFI rlibs, we need to collect their includes as well 603 if library.static() || library.shared() || library.rlib() { 604 android.SetProvider(ctx, cc.FlagExporterInfoProvider, cc.FlagExporterInfo{ 605 IncludeDirs: android.FirstUniquePaths(library.includeDirs), 606 }) 607 } 608 609 if library.shared() { 610 // Optimize out relinking against shared libraries whose interface hasn't changed by 611 // depending on a table of contents file instead of the library itself. 612 tocFile := outputFile.ReplaceExtension(ctx, flags.Toolchain.SharedLibSuffix()[1:]+".toc") 613 library.tocFile = android.OptionalPathForPath(tocFile) 614 cc.TransformSharedObjectToToc(ctx, outputFile, tocFile) 615 616 android.SetProvider(ctx, cc.SharedLibraryInfoProvider, cc.SharedLibraryInfo{ 617 TableOfContents: android.OptionalPathForPath(tocFile), 618 SharedLibrary: outputFile, 619 Target: ctx.Target(), 620 // TODO: when rust supports stubs uses the stubs state rather than inferring it from 621 // apex_exclude. 622 IsStubs: Bool(library.Properties.Apex_exclude), 623 }) 624 } 625 626 if library.static() { 627 depSet := depset.NewBuilder[android.Path](depset.TOPOLOGICAL).Direct(outputFile).Build() 628 android.SetProvider(ctx, cc.StaticLibraryInfoProvider, cc.StaticLibraryInfo{ 629 StaticLibrary: outputFile, 630 631 TransitiveStaticLibrariesForOrdering: depSet, 632 }) 633 } 634 635 library.flagExporter.setProvider(ctx) 636 637 return ret 638} 639 640func (library *libraryDecorator) checkedCrateRootPath() (android.Path, error) { 641 if library.sourceProvider != nil { 642 srcs := library.sourceProvider.Srcs() 643 if len(srcs) == 0 { 644 return nil, errors.New("Source provider generated 0 sources") 645 } 646 // Assume the first source from the source provider is the library entry point. 647 return srcs[0], nil 648 } else { 649 return library.baseCompiler.checkedCrateRootPath() 650 } 651} 652 653func (library *libraryDecorator) rustdoc(ctx ModuleContext, flags Flags, 654 deps PathDeps) android.OptionalPath { 655 // rustdoc has builtin support for documenting config specific information 656 // regardless of the actual config it was given 657 // (https://doc.rust-lang.org/rustdoc/advanced-features.html#cfgdoc-documenting-platform-specific-or-feature-specific-information), 658 // so we generate the rustdoc for only the primary module so that we have a 659 // single set of docs to refer to. 660 if ctx.Module() != ctx.PrimaryModule() { 661 return android.OptionalPath{} 662 } 663 664 return android.OptionalPathForPath(Rustdoc(ctx, crateRootPath(ctx, library), 665 deps, flags)) 666} 667 668func (library *libraryDecorator) getStem(ctx ModuleContext) string { 669 stem := library.baseCompiler.getStemWithoutSuffix(ctx) 670 validateLibraryStem(ctx, stem, library.crateName()) 671 672 return stem + String(library.baseCompiler.Properties.Suffix) 673} 674 675func (library *libraryDecorator) install(ctx ModuleContext) { 676 // Only shared and dylib variants make sense to install. 677 if library.shared() || library.dylib() { 678 library.baseCompiler.install(ctx) 679 } 680} 681 682func (library *libraryDecorator) Disabled() bool { 683 return library.MutatedProperties.VariantIsDisabled 684} 685 686func (library *libraryDecorator) SetDisabled() { 687 library.MutatedProperties.VariantIsDisabled = true 688} 689 690var validCrateName = regexp.MustCompile("[^a-zA-Z0-9_]+") 691 692func validateLibraryStem(ctx BaseModuleContext, filename string, crate_name string) { 693 if crate_name == "" { 694 ctx.PropertyErrorf("crate_name", "crate_name must be defined.") 695 } 696 697 // crate_names are used for the library output file, and rustc expects these 698 // to be alphanumeric with underscores allowed. 699 if validCrateName.MatchString(crate_name) { 700 ctx.PropertyErrorf("crate_name", 701 "library crate_names must be alphanumeric with underscores allowed") 702 } 703 704 // Libraries are expected to begin with "lib" followed by the crate_name 705 if !strings.HasPrefix(filename, "lib"+crate_name) { 706 ctx.ModuleErrorf("Invalid name or stem property; library filenames must start with lib<crate_name>") 707 } 708} 709 710type libraryTransitionMutator struct{} 711 712func (libraryTransitionMutator) Split(ctx android.BaseModuleContext) []string { 713 m, ok := ctx.Module().(*Module) 714 if !ok || m.compiler == nil { 715 return []string{""} 716 } 717 library, ok := m.compiler.(libraryInterface) 718 if !ok { 719 return []string{""} 720 } 721 722 // Don't produce rlib/dylib/source variants for shared or static variants 723 if library.shared() || library.static() { 724 return []string{""} 725 } 726 727 var variants []string 728 // The source variant is used for SourceProvider modules. The other variants (i.e. rlib and dylib) 729 // depend on this variant. It must be the first variant to be declared. 730 if m.sourceProvider != nil { 731 variants = append(variants, sourceVariation) 732 } 733 if library.buildRlib() { 734 variants = append(variants, rlibVariation) 735 } 736 if library.buildDylib() { 737 variants = append(variants, dylibVariation) 738 } 739 740 if len(variants) == 0 { 741 return []string{""} 742 } 743 744 return variants 745} 746 747func (libraryTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string { 748 return "" 749} 750 751func (libraryTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string { 752 m, ok := ctx.Module().(*Module) 753 if !ok || m.compiler == nil { 754 return "" 755 } 756 library, ok := m.compiler.(libraryInterface) 757 if !ok { 758 return "" 759 } 760 761 if incomingVariation == "" { 762 if m.sourceProvider != nil { 763 return sourceVariation 764 } 765 if library.shared() { 766 return "" 767 } 768 if library.buildRlib() { 769 return rlibVariation 770 } 771 if library.buildDylib() { 772 return dylibVariation 773 } 774 } 775 return incomingVariation 776} 777 778func (libraryTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) { 779 m, ok := ctx.Module().(*Module) 780 if !ok || m.compiler == nil { 781 return 782 } 783 library, ok := m.compiler.(libraryInterface) 784 if !ok { 785 return 786 } 787 788 switch variation { 789 case rlibVariation: 790 library.setRlib() 791 case dylibVariation: 792 library.setDylib() 793 if m.ModuleBase.ImageVariation().Variation == android.VendorRamdiskVariation { 794 // TODO(b/165791368) 795 // Disable dylib Vendor Ramdisk variations until we support these. 796 m.Disable() 797 } 798 799 case sourceVariation: 800 library.setSource() 801 // The source variant does not produce any library. 802 // Disable the compilation steps. 803 m.compiler.SetDisabled() 804 } 805 806 // If a source variant is created, add an inter-variant dependency 807 // between the other variants and the source variant. 808 if m.sourceProvider != nil && variation != sourceVariation { 809 ctx.AddVariationDependencies( 810 []blueprint.Variation{ 811 {"rust_libraries", sourceVariation}, 812 }, 813 sourceDepTag, ctx.ModuleName()) 814 } 815} 816 817type libstdTransitionMutator struct{} 818 819func (libstdTransitionMutator) Split(ctx android.BaseModuleContext) []string { 820 if m, ok := ctx.Module().(*Module); ok && m.compiler != nil && !m.compiler.Disabled() { 821 // Only create a variant if a library is actually being built. 822 if library, ok := m.compiler.(libraryInterface); ok { 823 if library.rlib() && !library.sysroot() { 824 if library.isFFILibrary() { 825 return []string{"rlib-std"} 826 } else { 827 return []string{"rlib-std", "dylib-std"} 828 } 829 } 830 } 831 } 832 return []string{""} 833} 834 835func (libstdTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string { 836 return "" 837} 838 839func (libstdTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string { 840 if m, ok := ctx.Module().(*Module); ok && m.compiler != nil && !m.compiler.Disabled() { 841 if library, ok := m.compiler.(libraryInterface); ok { 842 if library.shared() { 843 return "" 844 } 845 if library.rlib() && !library.sysroot() { 846 if incomingVariation != "" { 847 return incomingVariation 848 } 849 return "rlib-std" 850 } 851 } 852 } 853 return "" 854} 855 856func (libstdTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) { 857 if variation == "rlib-std" { 858 rlib := ctx.Module().(*Module) 859 rlib.compiler.(libraryInterface).setRlibStd() 860 rlib.Properties.RustSubName += RlibStdlibSuffix 861 } else if variation == "dylib-std" { 862 dylib := ctx.Module().(*Module) 863 dylib.compiler.(libraryInterface).setDylibStd() 864 if dylib.ModuleBase.ImageVariation().Variation == android.VendorRamdiskVariation { 865 // TODO(b/165791368) 866 // Disable rlibs that link against dylib-std on vendor ramdisk variations until those dylib 867 // variants are properly supported. 868 dylib.Disable() 869 } 870 } 871} 872