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 cc_config "android/soong/cc/config" 29) 30 31var ( 32 RlibStdlibSuffix = ".rlib-std" 33) 34 35func init() { 36 android.RegisterModuleType("rust_library", RustLibraryFactory) 37 android.RegisterModuleType("rust_library_dylib", RustLibraryDylibFactory) 38 android.RegisterModuleType("rust_library_rlib", RustLibraryRlibFactory) 39 android.RegisterModuleType("rust_library_host", RustLibraryHostFactory) 40 android.RegisterModuleType("rust_library_host_dylib", RustLibraryDylibHostFactory) 41 android.RegisterModuleType("rust_library_host_rlib", RustLibraryRlibHostFactory) 42 android.RegisterModuleType("rust_ffi", RustFFIFactory) 43 android.RegisterModuleType("rust_ffi_shared", RustFFISharedFactory) 44 android.RegisterModuleType("rust_ffi_host", RustFFIHostFactory) 45 android.RegisterModuleType("rust_ffi_host_shared", RustFFISharedHostFactory) 46 android.RegisterModuleType("rust_ffi_static", RustLibraryRlibFactory) 47 android.RegisterModuleType("rust_ffi_host_static", RustLibraryRlibHostFactory) 48} 49 50type VariantLibraryProperties struct { 51 Enabled *bool `android:"arch_variant"` 52 Srcs []string `android:"path,arch_variant"` 53} 54 55type LibraryCompilerProperties struct { 56 Rlib VariantLibraryProperties `android:"arch_variant"` 57 Dylib VariantLibraryProperties `android:"arch_variant"` 58 Shared VariantLibraryProperties `android:"arch_variant"` 59 Static VariantLibraryProperties `android:"arch_variant"` 60 61 // TODO: Remove this when all instances of Include_dirs have been removed from rust_ffi modules. 62 // path to include directories to pass to cc_* modules, only relevant for static/shared variants (deprecated, use export_include_dirs instead). 63 Include_dirs []string `android:"path,arch_variant"` 64 65 // path to include directories to export to cc_* modules, only relevant for static/shared variants. 66 Export_include_dirs []string `android:"path,arch_variant"` 67 68 // Version script to pass to the linker. By default this will replace the 69 // implicit rustc emitted version script to mirror expected behavior in CC. 70 // This is only relevant for rust_ffi_shared modules which are exposing a 71 // versioned C API. 72 Version_script *string `android:"path,arch_variant"` 73 74 // A version_script formatted text file with additional symbols to export 75 // for rust shared or dylibs which the rustc compiler does not automatically 76 // export, e.g. additional symbols from whole_static_libs. Unlike 77 // Version_script, this is not meant to imply a stable API. 78 Extra_exported_symbols *string `android:"path,arch_variant"` 79 80 // Whether this library is part of the Rust toolchain sysroot. 81 Sysroot *bool 82 83 // Deprecated - exclude this rust_ffi target from being included in APEXes. 84 // TODO(b/362509506): remove this once all apex_exclude uses are switched to stubs. 85 Apex_exclude *bool 86 87 // Generate stubs to make this library accessible to APEXes. 88 // Can only be set for modules producing shared libraries. 89 Stubs cc.StubsProperties `android:"arch_variant"` 90} 91 92type LibraryMutatedProperties struct { 93 // Build a dylib variant 94 BuildDylib bool `blueprint:"mutated"` 95 // Build an rlib variant 96 BuildRlib bool `blueprint:"mutated"` 97 // Build a shared library variant 98 BuildShared bool `blueprint:"mutated"` 99 // Build a static library variant 100 BuildStatic bool `blueprint:"mutated"` 101 102 // This variant is a dylib 103 VariantIsDylib bool `blueprint:"mutated"` 104 // This variant is an rlib 105 VariantIsRlib bool `blueprint:"mutated"` 106 // This variant is a shared library 107 VariantIsShared bool `blueprint:"mutated"` 108 // This variant is a source provider 109 VariantIsSource bool `blueprint:"mutated"` 110 111 // This variant is disabled and should not be compiled 112 // (used for SourceProvider variants that produce only source) 113 VariantIsDisabled bool `blueprint:"mutated"` 114 115 // Whether this library variant should be link libstd via rlibs 116 VariantIsStaticStd bool `blueprint:"mutated"` 117 118 // This variant is a stubs lib 119 BuildStubs bool `blueprint:"mutated"` 120 // This variant is the latest version 121 IsLatestVersion bool `blueprint:"mutated"` 122 // Version of the stubs lib 123 StubsVersion string `blueprint:"mutated"` 124 // List of all stubs versions associated with an implementation lib 125 AllStubsVersions []string `blueprint:"mutated"` 126} 127 128type libraryDecorator struct { 129 *baseCompiler 130 *flagExporter 131 stripper Stripper 132 133 Properties LibraryCompilerProperties 134 MutatedProperties LibraryMutatedProperties 135 includeDirs android.Paths 136 sourceProvider SourceProvider 137 138 // table-of-contents file for cdylib crates to optimize out relinking when possible 139 tocFile android.OptionalPath 140 141 // Path to the file containing the APIs exported by this library 142 stubsSymbolFilePath android.Path 143 apiListCoverageXmlPath android.ModuleOutPath 144 versionScriptPath android.OptionalPath 145} 146 147func (library *libraryDecorator) stubs() bool { 148 return library.MutatedProperties.BuildStubs 149} 150 151func (library *libraryDecorator) setAPIListCoverageXMLPath(xml android.ModuleOutPath) { 152 library.apiListCoverageXmlPath = xml 153} 154 155func (library *libraryDecorator) libraryProperties() LibraryCompilerProperties { 156 return library.Properties 157} 158 159type libraryInterface interface { 160 cc.VersionedInterface 161 162 rlib() bool 163 dylib() bool 164 static() bool 165 shared() bool 166 sysroot() bool 167 source() bool 168 apexExclude() bool 169 170 // Returns true if the build options for the module have selected a particular build type 171 buildRlib() bool 172 buildDylib() bool 173 buildShared() bool 174 buildStatic() bool 175 176 // Sets a particular variant type 177 setRlib() 178 setDylib() 179 setShared() 180 setStatic() 181 setSource() 182 183 // libstd linkage functions 184 rlibStd() bool 185 setRlibStd() 186 setDylibStd() 187 188 // Build a specific library variant 189 BuildOnlyFFI() 190 BuildOnlyRust() 191 BuildOnlyRlib() 192 BuildOnlyDylib() 193 BuildOnlyStatic() 194 BuildOnlyShared() 195 196 toc() android.OptionalPath 197 198 IsStubsImplementationRequired() bool 199 setAPIListCoverageXMLPath(out android.ModuleOutPath) 200 201 libraryProperties() LibraryCompilerProperties 202} 203 204func (library *libraryDecorator) nativeCoverage() bool { 205 if library.BuildStubs() { 206 return false 207 } 208 return true 209} 210 211func (library *libraryDecorator) toc() android.OptionalPath { 212 return library.tocFile 213} 214 215func (library *libraryDecorator) rlib() bool { 216 return library.MutatedProperties.VariantIsRlib 217} 218 219func (library *libraryDecorator) sysroot() bool { 220 return Bool(library.Properties.Sysroot) 221} 222 223func (library *libraryDecorator) dylib() bool { 224 return library.MutatedProperties.VariantIsDylib 225} 226 227func (library *libraryDecorator) shared() bool { 228 return library.MutatedProperties.VariantIsShared 229} 230 231func (library *libraryDecorator) static() bool { 232 return false 233} 234 235func (library *libraryDecorator) source() bool { 236 return library.MutatedProperties.VariantIsSource 237} 238 239func (library *libraryDecorator) apexExclude() bool { 240 return Bool(library.Properties.Apex_exclude) 241} 242 243func (library *libraryDecorator) buildRlib() bool { 244 return library.MutatedProperties.BuildRlib && BoolDefault(library.Properties.Rlib.Enabled, true) 245} 246 247func (library *libraryDecorator) buildDylib() bool { 248 return library.MutatedProperties.BuildDylib && BoolDefault(library.Properties.Dylib.Enabled, true) 249} 250 251func (library *libraryDecorator) buildShared() bool { 252 return library.MutatedProperties.BuildShared && BoolDefault(library.Properties.Shared.Enabled, true) 253} 254 255func (library *libraryDecorator) buildStatic() bool { 256 return library.MutatedProperties.BuildStatic && BoolDefault(library.Properties.Static.Enabled, true) 257} 258 259func (library *libraryDecorator) setRlib() { 260 library.MutatedProperties.VariantIsRlib = true 261 library.MutatedProperties.VariantIsDylib = false 262 library.MutatedProperties.VariantIsShared = false 263} 264 265func (library *libraryDecorator) setDylib() { 266 library.MutatedProperties.VariantIsRlib = false 267 library.MutatedProperties.VariantIsDylib = true 268 library.MutatedProperties.VariantIsShared = false 269} 270 271func (library *libraryDecorator) rlibStd() bool { 272 return library.MutatedProperties.VariantIsStaticStd 273} 274 275func (library *libraryDecorator) setRlibStd() { 276 library.MutatedProperties.VariantIsStaticStd = true 277} 278 279func (library *libraryDecorator) setDylibStd() { 280 library.MutatedProperties.VariantIsStaticStd = false 281} 282 283func (library *libraryDecorator) setShared() { 284 library.MutatedProperties.VariantIsShared = true 285 library.MutatedProperties.VariantIsRlib = false 286 library.MutatedProperties.VariantIsDylib = false 287} 288 289func (library *libraryDecorator) setStatic() { 290 panic(fmt.Errorf("static variant is not supported for rust modules, use the rlib variant instead")) 291} 292 293func (library *libraryDecorator) setSource() { 294 library.MutatedProperties.VariantIsSource = true 295} 296 297func (library *libraryDecorator) autoDep(ctx android.BottomUpMutatorContext) autoDep { 298 if library.preferRlib() { 299 return rlibAutoDep 300 } else if library.rlib() || library.static() { 301 return rlibAutoDep 302 } else if library.dylib() || library.shared() { 303 return dylibAutoDep 304 } else { 305 panic(fmt.Errorf("autoDep called on library %q that has no enabled variants.", ctx.ModuleName())) 306 } 307} 308 309func (library *libraryDecorator) stdLinkage(device bool) RustLinkage { 310 if library.static() || library.MutatedProperties.VariantIsStaticStd { 311 return RlibLinkage 312 } else if library.baseCompiler.preferRlib() { 313 return RlibLinkage 314 } 315 return DylibLinkage 316} 317 318var _ compiler = (*libraryDecorator)(nil) 319var _ libraryInterface = (*libraryDecorator)(nil) 320var _ cc.VersionedInterface = (*libraryDecorator)(nil) 321var _ exportedFlagsProducer = (*libraryDecorator)(nil) 322var _ cc.VersionedInterface = (*libraryDecorator)(nil) 323 324func (library *libraryDecorator) HasLLNDKStubs() bool { 325 // Rust LLNDK is currently unsupported 326 return false 327} 328 329func (library *libraryDecorator) HasVendorPublicLibrary() bool { 330 // Rust does not support vendor_public_library yet. 331 return false 332} 333 334func (library *libraryDecorator) HasLLNDKHeaders() bool { 335 // Rust LLNDK is currently unsupported 336 return false 337} 338 339func (library *libraryDecorator) HasStubsVariants() bool { 340 // Just having stubs.symbol_file is enough to create a stub variant. In that case 341 // the stub for the future API level is created. 342 return library.Properties.Stubs.Symbol_file != nil || 343 len(library.Properties.Stubs.Versions) > 0 344} 345 346func (library *libraryDecorator) IsStubsImplementationRequired() bool { 347 return BoolDefault(library.Properties.Stubs.Implementation_installable, true) 348} 349 350func (library *libraryDecorator) GetAPIListCoverageXMLPath() android.ModuleOutPath { 351 return library.apiListCoverageXmlPath 352} 353 354func (library *libraryDecorator) AllStubsVersions() []string { 355 return library.MutatedProperties.AllStubsVersions 356} 357 358func (library *libraryDecorator) SetAllStubsVersions(versions []string) { 359 library.MutatedProperties.AllStubsVersions = versions 360} 361 362func (library *libraryDecorator) SetStubsVersion(version string) { 363 library.MutatedProperties.StubsVersion = version 364} 365 366func (library *libraryDecorator) SetBuildStubs(isLatest bool) { 367 library.MutatedProperties.BuildStubs = true 368 library.MutatedProperties.IsLatestVersion = isLatest 369} 370 371func (library *libraryDecorator) BuildStubs() bool { 372 return library.MutatedProperties.BuildStubs 373} 374 375func (library *libraryDecorator) ImplementationModuleName(name string) string { 376 return name 377} 378 379func (library *libraryDecorator) IsLLNDKMovedToApex() bool { 380 // Rust does not support LLNDK. 381 return false 382} 383 384func (library *libraryDecorator) StubsVersion() string { 385 return library.MutatedProperties.StubsVersion 386} 387 388// stubsVersions implements cc.VersionedInterface. 389func (library *libraryDecorator) StubsVersions(ctx android.BaseModuleContext) []string { 390 if !library.HasStubsVariants() { 391 return nil 392 } 393 394 // Future API level is implicitly added if there isn't 395 versions := cc.AddCurrentVersionIfNotPresent(library.Properties.Stubs.Versions) 396 cc.NormalizeVersions(ctx, versions) 397 return versions 398} 399 400// rust_library produces all Rust variants (rust_library_dylib and 401// rust_library_rlib). 402func RustLibraryFactory() android.Module { 403 module, library := NewRustLibrary(android.HostAndDeviceSupported) 404 library.BuildOnlyRust() 405 return module.Init() 406} 407 408// rust_ffi produces all FFI variants (rust_ffi_shared, rust_ffi_static). 409func RustFFIFactory() android.Module { 410 module, library := NewRustLibrary(android.HostAndDeviceSupported) 411 library.BuildOnlyFFI() 412 return module.Init() 413} 414 415// rust_library_dylib produces a Rust dylib (Rust crate type "dylib"). 416func RustLibraryDylibFactory() android.Module { 417 module, library := NewRustLibrary(android.HostAndDeviceSupported) 418 library.BuildOnlyDylib() 419 return module.Init() 420} 421 422// rust_library_rlib and rust_ffi_static produces an rlib (Rust crate type "rlib"). 423func RustLibraryRlibFactory() android.Module { 424 module, library := NewRustLibrary(android.HostAndDeviceSupported) 425 library.BuildOnlyRlib() 426 return module.Init() 427} 428 429// rust_ffi_shared produces a shared library (Rust crate type 430// "cdylib"). 431func RustFFISharedFactory() android.Module { 432 module, library := NewRustLibrary(android.HostAndDeviceSupported) 433 library.BuildOnlyShared() 434 return module.Init() 435} 436 437// rust_library_host produces all Rust variants for the host 438// (rust_library_dylib_host and rust_library_rlib_host). 439func RustLibraryHostFactory() android.Module { 440 module, library := NewRustLibrary(android.HostSupported) 441 library.BuildOnlyRust() 442 return module.Init() 443} 444 445// rust_ffi_host produces all FFI variants for the host 446// (rust_ffi_static_host and rust_ffi_shared_host). 447func RustFFIHostFactory() android.Module { 448 module, library := NewRustLibrary(android.HostSupported) 449 library.BuildOnlyFFI() 450 return module.Init() 451} 452 453// rust_library_dylib_host produces a dylib for the host (Rust crate 454// type "dylib"). 455func RustLibraryDylibHostFactory() android.Module { 456 module, library := NewRustLibrary(android.HostSupported) 457 library.BuildOnlyDylib() 458 return module.Init() 459} 460 461// rust_library_rlib_host and rust_ffi_static_host produces an rlib for the host 462// (Rust crate type "rlib"). 463func RustLibraryRlibHostFactory() android.Module { 464 module, library := NewRustLibrary(android.HostSupported) 465 library.BuildOnlyRlib() 466 return module.Init() 467} 468 469// rust_ffi_shared_host produces an shared library for the host (Rust 470// crate type "cdylib"). 471func RustFFISharedHostFactory() android.Module { 472 module, library := NewRustLibrary(android.HostSupported) 473 library.BuildOnlyShared() 474 return module.Init() 475} 476 477func CheckRustLibraryProperties(mctx android.DefaultableHookContext) { 478 lib := mctx.Module().(*Module).compiler.(libraryInterface) 479 if !lib.buildShared() { 480 if lib.libraryProperties().Stubs.Symbol_file != nil || 481 lib.libraryProperties().Stubs.Implementation_installable != nil || 482 len(lib.libraryProperties().Stubs.Versions) > 0 { 483 484 mctx.PropertyErrorf("stubs", "stubs properties can only be set for rust_ffi or rust_ffi_shared modules") 485 } 486 } 487} 488 489func (library *libraryDecorator) BuildOnlyFFI() { 490 library.MutatedProperties.BuildDylib = false 491 // we build rlibs for later static ffi linkage. 492 library.MutatedProperties.BuildRlib = true 493 library.MutatedProperties.BuildShared = true 494 library.MutatedProperties.BuildStatic = false 495} 496 497func (library *libraryDecorator) BuildOnlyRust() { 498 library.MutatedProperties.BuildDylib = true 499 library.MutatedProperties.BuildRlib = true 500 library.MutatedProperties.BuildShared = false 501 library.MutatedProperties.BuildStatic = false 502} 503 504func (library *libraryDecorator) BuildOnlyDylib() { 505 library.MutatedProperties.BuildDylib = true 506 library.MutatedProperties.BuildRlib = false 507 library.MutatedProperties.BuildShared = false 508 library.MutatedProperties.BuildStatic = false 509} 510 511func (library *libraryDecorator) BuildOnlyRlib() { 512 library.MutatedProperties.BuildDylib = false 513 library.MutatedProperties.BuildRlib = true 514 library.MutatedProperties.BuildShared = false 515 library.MutatedProperties.BuildStatic = false 516} 517 518func (library *libraryDecorator) BuildOnlyStatic() { 519 library.MutatedProperties.BuildRlib = false 520 library.MutatedProperties.BuildDylib = false 521 library.MutatedProperties.BuildShared = false 522 library.MutatedProperties.BuildStatic = true 523} 524 525func (library *libraryDecorator) BuildOnlyShared() { 526 library.MutatedProperties.BuildRlib = false 527 library.MutatedProperties.BuildDylib = false 528 library.MutatedProperties.BuildStatic = false 529 library.MutatedProperties.BuildShared = true 530} 531 532func NewRustLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorator) { 533 module := newModule(hod, android.MultilibBoth) 534 535 library := &libraryDecorator{ 536 MutatedProperties: LibraryMutatedProperties{ 537 BuildDylib: false, 538 BuildRlib: false, 539 BuildShared: false, 540 BuildStatic: false, 541 }, 542 baseCompiler: NewBaseCompiler("lib", "lib64", InstallInSystem), 543 flagExporter: NewFlagExporter(), 544 } 545 546 module.compiler = library 547 548 module.SetDefaultableHook(CheckRustLibraryProperties) 549 return module, library 550} 551 552func (library *libraryDecorator) compilerProps() []interface{} { 553 return append(library.baseCompiler.compilerProps(), 554 &library.Properties, 555 &library.MutatedProperties, 556 &library.stripper.StripProperties) 557} 558 559func (library *libraryDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps { 560 deps = library.baseCompiler.compilerDeps(ctx, deps) 561 562 if library.dylib() || library.shared() { 563 if ctx.toolchain().Bionic() { 564 deps = bionicDeps(ctx, deps, false) 565 deps.CrtBegin = []string{"crtbegin_so"} 566 deps.CrtEnd = []string{"crtend_so"} 567 } else if ctx.Os() == android.LinuxMusl { 568 deps = muslDeps(ctx, deps, false) 569 deps.CrtBegin = []string{"libc_musl_crtbegin_so"} 570 deps.CrtEnd = []string{"libc_musl_crtend_so"} 571 } 572 } 573 574 return deps 575} 576 577func (library *libraryDecorator) sharedLibFilename(ctx ModuleContext) string { 578 return library.getStem(ctx) + ctx.toolchain().SharedLibSuffix() 579} 580 581// Library cfg flags common to all variants 582func CommonLibraryCfgFlags(ctx android.ModuleContext, flags Flags) Flags { 583 return flags 584} 585 586func (library *libraryDecorator) cfgFlags(ctx ModuleContext, flags Flags) Flags { 587 flags = library.baseCompiler.cfgFlags(ctx, flags) 588 flags = CommonLibraryCfgFlags(ctx, flags) 589 590 cfgs := library.baseCompiler.Properties.Cfgs.GetOrDefault(ctx, nil) 591 592 cfgFlags := cfgsToFlags(cfgs) 593 594 flags.RustFlags = append(flags.RustFlags, cfgFlags...) 595 flags.RustdocFlags = append(flags.RustdocFlags, cfgFlags...) 596 597 return flags 598} 599 600// Common flags applied to all libraries irrespective of properties or variant should be included here 601func CommonLibraryCompilerFlags(ctx android.ModuleContext, flags Flags) Flags { 602 flags.RustFlags = append(flags.RustFlags, "-C metadata="+ctx.ModuleName()) 603 604 return flags 605} 606 607func (library *libraryDecorator) compilerFlags(ctx ModuleContext, flags Flags) Flags { 608 flags = library.baseCompiler.compilerFlags(ctx, flags) 609 610 flags = CommonLibraryCompilerFlags(ctx, flags) 611 612 if library.rlib() || library.shared() { 613 // rlibs collect include dirs as well since they are used to 614 // produce staticlibs in the final C linkages 615 library.includeDirs = append(library.includeDirs, android.PathsForModuleSrc(ctx, library.Properties.Include_dirs)...) 616 library.includeDirs = append(library.includeDirs, android.PathsForModuleSrc(ctx, library.Properties.Export_include_dirs)...) 617 } 618 619 if library.shared() { 620 if ctx.Darwin() { 621 flags.LinkFlags = append( 622 flags.LinkFlags, 623 "-dynamic_lib", 624 "-install_name @rpath/"+library.sharedLibFilename(ctx), 625 ) 626 } else { 627 flags.LinkFlags = append(flags.LinkFlags, "-Wl,-soname="+library.sharedLibFilename(ctx)) 628 } 629 } 630 631 return flags 632} 633 634func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) buildOutput { 635 var outputFile android.ModuleOutPath 636 var ret buildOutput 637 var fileName string 638 crateRootPath := crateRootPath(ctx, library) 639 640 if library.sourceProvider != nil { 641 deps.srcProviderFiles = append(deps.srcProviderFiles, library.sourceProvider.Srcs()...) 642 } 643 644 // Ensure link dirs are not duplicated 645 deps.linkDirs = android.FirstUniqueStrings(deps.linkDirs) 646 647 // Calculate output filename 648 if library.rlib() { 649 fileName = library.getStem(ctx) + ctx.toolchain().RlibSuffix() 650 outputFile = android.PathForModuleOut(ctx, fileName) 651 ret.outputFile = outputFile 652 } else if library.dylib() { 653 fileName = library.getStem(ctx) + ctx.toolchain().DylibSuffix() 654 outputFile = android.PathForModuleOut(ctx, fileName) 655 ret.outputFile = outputFile 656 } else if library.static() { 657 fileName = library.getStem(ctx) + ctx.toolchain().StaticLibSuffix() 658 outputFile = android.PathForModuleOut(ctx, fileName) 659 ret.outputFile = outputFile 660 } else if library.shared() { 661 fileName = library.sharedLibFilename(ctx) 662 outputFile = android.PathForModuleOut(ctx, fileName) 663 ret.outputFile = outputFile 664 } 665 666 if !library.rlib() && !library.static() && library.stripper.NeedsStrip(ctx) { 667 strippedOutputFile := outputFile 668 outputFile = android.PathForModuleOut(ctx, "unstripped", fileName) 669 library.stripper.StripExecutableOrSharedLib(ctx, outputFile, strippedOutputFile) 670 671 library.baseCompiler.strippedOutputFile = android.OptionalPathForPath(strippedOutputFile) 672 } 673 library.baseCompiler.unstrippedOutputFile = outputFile 674 675 flags.RustFlags = append(flags.RustFlags, deps.depFlags...) 676 flags.LinkFlags = append(flags.LinkFlags, deps.depLinkFlags...) 677 flags.LinkFlags = append(flags.LinkFlags, deps.rustLibObjects...) 678 flags.LinkFlags = append(flags.LinkFlags, deps.sharedLibObjects...) 679 flags.LinkFlags = append(flags.LinkFlags, deps.staticLibObjects...) 680 flags.LinkFlags = append(flags.LinkFlags, deps.wholeStaticLibObjects...) 681 682 if String(library.Properties.Version_script) != "" { 683 if String(library.Properties.Extra_exported_symbols) != "" { 684 ctx.ModuleErrorf("version_script and extra_exported_symbols cannot both be set.") 685 } 686 687 if library.shared() { 688 // "-Wl,--android-version-script" signals to the rustcLinker script 689 // that the default version script should be removed. 690 flags.LinkFlags = append(flags.LinkFlags, "-Wl,--android-version-script="+android.PathForModuleSrc(ctx, String(library.Properties.Version_script)).String()) 691 deps.LinkerDeps = append(deps.LinkerDeps, android.PathForModuleSrc(ctx, String(library.Properties.Version_script))) 692 } else if !library.static() && !library.rlib() { 693 // We include rlibs here because rust_ffi produces rlib variants 694 ctx.PropertyErrorf("version_script", "can only be set for rust_ffi modules") 695 } 696 } 697 698 if String(library.Properties.Extra_exported_symbols) != "" { 699 // Passing a second version script (rustc calculates and emits a 700 // default version script) will concatenate the first version script. 701 flags.LinkFlags = append(flags.LinkFlags, "-Wl,--version-script="+android.PathForModuleSrc(ctx, String(library.Properties.Extra_exported_symbols)).String()) 702 deps.LinkerDeps = append(deps.LinkerDeps, android.PathForModuleSrc(ctx, String(library.Properties.Extra_exported_symbols))) 703 } 704 705 if library.dylib() { 706 707 // We need prefer-dynamic for now to avoid linking in the static stdlib. See: 708 // https://github.com/rust-lang/rust/issues/19680 709 // https://github.com/rust-lang/rust/issues/34909 710 flags.RustFlags = append(flags.RustFlags, "-C prefer-dynamic") 711 } 712 713 // Call the appropriate builder for this library type 714 if library.stubs() { 715 ccFlags := library.getApiStubsCcFlags(ctx) 716 stubObjs := library.compileModuleLibApiStubs(ctx, ccFlags) 717 cc.BuildRustStubs(ctx, outputFile, stubObjs, ccFlags) 718 } else if library.rlib() { 719 ret.kytheFile = TransformSrctoRlib(ctx, crateRootPath, deps, flags, outputFile).kytheFile 720 } else if library.dylib() { 721 ret.kytheFile = TransformSrctoDylib(ctx, crateRootPath, deps, flags, outputFile).kytheFile 722 } else if library.static() { 723 ret.kytheFile = TransformSrctoStatic(ctx, crateRootPath, deps, flags, outputFile).kytheFile 724 } else if library.shared() { 725 ret.kytheFile = TransformSrctoShared(ctx, crateRootPath, deps, flags, outputFile).kytheFile 726 } 727 728 // rlibs and dylibs propagate their shared, whole static, and rustlib dependencies 729 if library.rlib() || library.dylib() { 730 library.flagExporter.exportLinkDirs(deps.linkDirs...) 731 library.flagExporter.exportRustLibs(deps.rustLibObjects...) 732 library.flagExporter.exportSharedLibs(deps.sharedLibObjects...) 733 library.flagExporter.exportWholeStaticLibs(deps.wholeStaticLibObjects...) 734 } 735 736 // rlibs also propagate their staticlibs dependencies 737 if library.rlib() { 738 library.flagExporter.exportStaticLibs(deps.staticLibObjects...) 739 } 740 // Since we have FFI rlibs, we need to collect their includes as well 741 if library.static() || library.shared() || library.rlib() || library.stubs() { 742 ccExporter := cc.FlagExporterInfo{ 743 IncludeDirs: android.FirstUniquePaths(library.includeDirs), 744 } 745 if library.rlib() { 746 ccExporter.RustRlibDeps = append(ccExporter.RustRlibDeps, deps.reexportedCcRlibDeps...) 747 ccExporter.RustRlibDeps = append(ccExporter.RustRlibDeps, deps.reexportedWholeCcRlibDeps...) 748 } 749 android.SetProvider(ctx, cc.FlagExporterInfoProvider, ccExporter) 750 } 751 752 if library.dylib() { 753 // reexport whole-static'd dependencies for dylibs. 754 library.flagExporter.wholeRustRlibDeps = append(library.flagExporter.wholeRustRlibDeps, deps.reexportedWholeCcRlibDeps...) 755 } 756 757 if library.shared() || library.stubs() { 758 // Optimize out relinking against shared libraries whose interface hasn't changed by 759 // depending on a table of contents file instead of the library itself. 760 tocFile := outputFile.ReplaceExtension(ctx, flags.Toolchain.SharedLibSuffix()[1:]+".toc") 761 library.tocFile = android.OptionalPathForPath(tocFile) 762 cc.TransformSharedObjectToToc(ctx, outputFile, tocFile) 763 764 android.SetProvider(ctx, cc.SharedLibraryInfoProvider, cc.SharedLibraryInfo{ 765 TableOfContents: android.OptionalPathForPath(tocFile), 766 SharedLibrary: outputFile, 767 Target: ctx.Target(), 768 IsStubs: library.BuildStubs(), 769 }) 770 } 771 772 if library.static() { 773 depSet := depset.NewBuilder[android.Path](depset.TOPOLOGICAL).Direct(outputFile).Build() 774 android.SetProvider(ctx, cc.StaticLibraryInfoProvider, cc.StaticLibraryInfo{ 775 StaticLibrary: outputFile, 776 777 TransitiveStaticLibrariesForOrdering: depSet, 778 }) 779 } 780 cc.AddStubDependencyProviders(ctx) 781 782 // Set our flagexporter provider to export relevant Rust flags 783 library.flagExporter.setRustProvider(ctx) 784 785 return ret 786} 787 788func (library *libraryDecorator) checkedCrateRootPath() (android.Path, error) { 789 if library.sourceProvider != nil { 790 srcs := library.sourceProvider.Srcs() 791 if len(srcs) == 0 { 792 return nil, errors.New("Source provider generated 0 sources") 793 } 794 // Assume the first source from the source provider is the library entry point. 795 return srcs[0], nil 796 } else { 797 return library.baseCompiler.checkedCrateRootPath() 798 } 799} 800 801func (library *libraryDecorator) getApiStubsCcFlags(ctx ModuleContext) cc.Flags { 802 ccFlags := cc.Flags{} 803 toolchain := cc_config.FindToolchain(ctx.Os(), ctx.Arch()) 804 805 platformSdkVersion := "" 806 if ctx.Device() { 807 platformSdkVersion = ctx.Config().PlatformSdkVersion().String() 808 } 809 minSdkVersion := cc.MinSdkVersion(ctx.RustModule(), cc.CtxIsForPlatform(ctx), ctx.Device(), platformSdkVersion) 810 811 // Collect common CC compilation flags 812 ccFlags = cc.CommonLinkerFlags(ctx, ccFlags, true, toolchain, false) 813 ccFlags = cc.CommonLibraryLinkerFlags(ctx, ccFlags, toolchain, library.getStem(ctx)) 814 ccFlags = cc.AddStubLibraryCompilerFlags(ccFlags) 815 ccFlags = cc.AddTargetFlags(ctx, ccFlags, toolchain, minSdkVersion, false) 816 817 return ccFlags 818} 819 820func (library *libraryDecorator) compileModuleLibApiStubs(ctx ModuleContext, ccFlags cc.Flags) cc.Objects { 821 mod := ctx.RustModule() 822 823 symbolFile := String(library.Properties.Stubs.Symbol_file) 824 library.stubsSymbolFilePath = android.PathForModuleSrc(ctx, symbolFile) 825 826 apiParams := cc.ApiStubsParams{ 827 NotInPlatform: mod.NotInPlatform(), 828 IsNdk: mod.IsNdk(ctx.Config()), 829 BaseModuleName: mod.BaseModuleName(), 830 ModuleName: ctx.ModuleName(), 831 } 832 flag := cc.GetApiStubsFlags(apiParams) 833 834 nativeAbiResult := cc.ParseNativeAbiDefinition(ctx, symbolFile, 835 android.ApiLevelOrPanic(ctx, library.MutatedProperties.StubsVersion), flag) 836 objs := cc.CompileStubLibrary(ctx, ccFlags, nativeAbiResult.StubSrc, mod.getSharedFlags()) 837 838 library.versionScriptPath = android.OptionalPathForPath(nativeAbiResult.VersionScript) 839 840 // Parse symbol file to get API list for coverage 841 if library.StubsVersion() == "current" && ctx.PrimaryArch() && !mod.InRecovery() && !mod.InProduct() && !mod.InVendor() { 842 library.apiListCoverageXmlPath = cc.ParseSymbolFileForAPICoverage(ctx, symbolFile) 843 } 844 845 return objs 846} 847 848func (library *libraryDecorator) rustdoc(ctx ModuleContext, flags Flags, 849 deps PathDeps) android.OptionalPath { 850 // rustdoc has builtin support for documenting config specific information 851 // regardless of the actual config it was given 852 // (https://doc.rust-lang.org/rustdoc/advanced-features.html#cfgdoc-documenting-platform-specific-or-feature-specific-information), 853 // so we generate the rustdoc for only the primary module so that we have a 854 // single set of docs to refer to. 855 if ctx.Module() != ctx.PrimaryModule() { 856 return android.OptionalPath{} 857 } 858 859 return android.OptionalPathForPath(Rustdoc(ctx, crateRootPath(ctx, library), 860 deps, flags)) 861} 862 863func (library *libraryDecorator) getStem(ctx ModuleContext) string { 864 stem := library.baseCompiler.getStemWithoutSuffix(ctx) 865 validateLibraryStem(ctx, stem, library.crateName()) 866 867 return stem + String(library.baseCompiler.Properties.Suffix) 868} 869 870func (library *libraryDecorator) install(ctx ModuleContext) { 871 // Only shared and dylib variants make sense to install. 872 if library.shared() || library.dylib() { 873 library.baseCompiler.install(ctx) 874 } 875} 876 877func (library *libraryDecorator) Disabled() bool { 878 return library.MutatedProperties.VariantIsDisabled 879} 880 881func (library *libraryDecorator) SetDisabled() { 882 library.MutatedProperties.VariantIsDisabled = true 883} 884 885func (library *libraryDecorator) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON) { 886 library.baseCompiler.moduleInfoJSON(ctx, moduleInfoJSON) 887 888 if library.rlib() { 889 moduleInfoJSON.Class = []string{"RLIB_LIBRARIES"} 890 } else if library.dylib() { 891 moduleInfoJSON.Class = []string{"DYLIB_LIBRARIES"} 892 } else if library.static() { 893 moduleInfoJSON.Class = []string{"STATIC_LIBRARIES"} 894 } else if library.shared() { 895 moduleInfoJSON.Class = []string{"SHARED_LIBRARIES"} 896 } 897} 898 899var validCrateName = regexp.MustCompile("[^a-zA-Z0-9_]+") 900 901func validateLibraryStem(ctx BaseModuleContext, filename string, crate_name string) { 902 if crate_name == "" { 903 ctx.PropertyErrorf("crate_name", "crate_name must be defined.") 904 } 905 906 // crate_names are used for the library output file, and rustc expects these 907 // to be alphanumeric with underscores allowed. 908 if validCrateName.MatchString(crate_name) { 909 ctx.PropertyErrorf("crate_name", 910 "library crate_names must be alphanumeric with underscores allowed") 911 } 912 913 // Libraries are expected to begin with "lib" followed by the crate_name 914 if !strings.HasPrefix(filename, "lib"+crate_name) { 915 ctx.ModuleErrorf("Invalid name or stem property; library filenames must start with lib<crate_name>") 916 } 917} 918 919type libraryTransitionMutator struct{} 920 921func (libraryTransitionMutator) Split(ctx android.BaseModuleContext) []string { 922 m, ok := ctx.Module().(*Module) 923 if !ok || m.compiler == nil { 924 return []string{""} 925 } 926 library, ok := m.compiler.(libraryInterface) 927 if !ok { 928 return []string{""} 929 } 930 931 // Don't produce rlib/dylib/source variants for shared or static variants 932 if library.shared() || library.static() { 933 return []string{""} 934 } 935 936 var variants []string 937 // The source variant is used for SourceProvider modules. The other variants (i.e. rlib and dylib) 938 // depend on this variant. It must be the first variant to be declared. 939 if m.sourceProvider != nil { 940 variants = append(variants, sourceVariation) 941 } 942 if library.buildRlib() { 943 variants = append(variants, rlibVariation) 944 } 945 if library.buildDylib() { 946 variants = append(variants, dylibVariation) 947 } 948 949 if len(variants) == 0 { 950 return []string{""} 951 } 952 953 return variants 954} 955 956func (libraryTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string { 957 if ctx.DepTag() == android.PrebuiltDepTag { 958 return sourceVariation 959 } 960 return "" 961} 962 963func (libraryTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string { 964 m, ok := ctx.Module().(*Module) 965 if !ok || m.compiler == nil { 966 return "" 967 } 968 library, ok := m.compiler.(libraryInterface) 969 if !ok { 970 return "" 971 } 972 973 if incomingVariation == "" { 974 if m.sourceProvider != nil { 975 return sourceVariation 976 } 977 if library.shared() { 978 return "" 979 } 980 if library.buildRlib() { 981 return rlibVariation 982 } 983 if library.buildDylib() { 984 return dylibVariation 985 } 986 } 987 return incomingVariation 988} 989 990func (libraryTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) { 991 m, ok := ctx.Module().(*Module) 992 if !ok || m.compiler == nil { 993 return 994 } 995 library, ok := m.compiler.(libraryInterface) 996 if !ok { 997 return 998 } 999 1000 switch variation { 1001 case rlibVariation: 1002 library.setRlib() 1003 case dylibVariation: 1004 library.setDylib() 1005 if m.ModuleBase.ImageVariation().Variation == android.VendorRamdiskVariation { 1006 // TODO(b/165791368) 1007 // Disable dylib Vendor Ramdisk variations until we support these. 1008 m.Disable() 1009 } 1010 1011 case sourceVariation: 1012 library.setSource() 1013 // The source variant does not produce any library. 1014 // Disable the compilation steps. 1015 m.compiler.SetDisabled() 1016 } 1017 1018 // If a source variant is created, add an inter-variant dependency 1019 // between the other variants and the source variant. 1020 if m.sourceProvider != nil && variation != sourceVariation { 1021 ctx.AddVariationDependencies( 1022 []blueprint.Variation{ 1023 {"rust_libraries", sourceVariation}, 1024 }, 1025 sourceDepTag, ctx.ModuleName()) 1026 } 1027 1028 if prebuilt, ok := m.compiler.(*prebuiltLibraryDecorator); ok { 1029 if Bool(prebuilt.Properties.Force_use_prebuilt) && len(prebuilt.prebuiltSrcs()) > 0 { 1030 m.Prebuilt().SetUsePrebuilt(true) 1031 } 1032 } 1033} 1034 1035type libstdTransitionMutator struct{} 1036 1037func (libstdTransitionMutator) Split(ctx android.BaseModuleContext) []string { 1038 if m, ok := ctx.Module().(*Module); ok && m.compiler != nil && !m.compiler.Disabled() { 1039 // Only create a variant if a library is actually being built. 1040 if library, ok := m.compiler.(libraryInterface); ok { 1041 if library.rlib() && !library.sysroot() { 1042 return []string{"rlib-std", "dylib-std"} 1043 } 1044 } 1045 } 1046 return []string{""} 1047} 1048 1049func (libstdTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string { 1050 if ctx.DepTag() == android.PrebuiltDepTag { 1051 return sourceVariation 1052 } 1053 return "" 1054} 1055 1056func (libstdTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string { 1057 if m, ok := ctx.Module().(*Module); ok && m.compiler != nil && !m.compiler.Disabled() { 1058 if library, ok := m.compiler.(libraryInterface); ok { 1059 if library.shared() { 1060 return "" 1061 } 1062 if library.rlib() && !library.sysroot() { 1063 if incomingVariation != "" { 1064 return incomingVariation 1065 } 1066 return "rlib-std" 1067 } 1068 } 1069 } 1070 return "" 1071} 1072 1073func (libstdTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) { 1074 if variation == "rlib-std" { 1075 rlib := ctx.Module().(*Module) 1076 rlib.compiler.(libraryInterface).setRlibStd() 1077 rlib.Properties.RustSubName += RlibStdlibSuffix 1078 } else if variation == "dylib-std" { 1079 dylib := ctx.Module().(*Module) 1080 dylib.compiler.(libraryInterface).setDylibStd() 1081 if dylib.ModuleBase.ImageVariation().Variation == android.VendorRamdiskVariation { 1082 // TODO(b/165791368) 1083 // Disable rlibs that link against dylib-std on vendor ramdisk variations until those dylib 1084 // variants are properly supported. 1085 dylib.Disable() 1086 } 1087 } 1088} 1089