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