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