1// Copyright 2020 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. 14package cc 15 16import ( 17 "encoding/json" 18 "path/filepath" 19 "sort" 20 "strings" 21 "sync" 22 23 "github.com/google/blueprint/proptools" 24 25 "android/soong/android" 26) 27 28const ( 29 vendorSnapshotHeaderSuffix = ".vendor_header." 30 vendorSnapshotSharedSuffix = ".vendor_shared." 31 vendorSnapshotStaticSuffix = ".vendor_static." 32 vendorSnapshotBinarySuffix = ".vendor_binary." 33 vendorSnapshotObjectSuffix = ".vendor_object." 34) 35 36var ( 37 vendorSnapshotsLock sync.Mutex 38 vendorSuffixModulesKey = android.NewOnceKey("vendorSuffixModules") 39 vendorSnapshotHeaderLibsKey = android.NewOnceKey("vendorSnapshotHeaderLibs") 40 vendorSnapshotStaticLibsKey = android.NewOnceKey("vendorSnapshotStaticLibs") 41 vendorSnapshotSharedLibsKey = android.NewOnceKey("vendorSnapshotSharedLibs") 42 vendorSnapshotBinariesKey = android.NewOnceKey("vendorSnapshotBinaries") 43 vendorSnapshotObjectsKey = android.NewOnceKey("vendorSnapshotObjects") 44) 45 46// vendor snapshot maps hold names of vendor snapshot modules per arch 47func vendorSuffixModules(config android.Config) map[string]bool { 48 return config.Once(vendorSuffixModulesKey, func() interface{} { 49 return make(map[string]bool) 50 }).(map[string]bool) 51} 52 53func vendorSnapshotHeaderLibs(config android.Config) *snapshotMap { 54 return config.Once(vendorSnapshotHeaderLibsKey, func() interface{} { 55 return newSnapshotMap() 56 }).(*snapshotMap) 57} 58 59func vendorSnapshotSharedLibs(config android.Config) *snapshotMap { 60 return config.Once(vendorSnapshotSharedLibsKey, func() interface{} { 61 return newSnapshotMap() 62 }).(*snapshotMap) 63} 64 65func vendorSnapshotStaticLibs(config android.Config) *snapshotMap { 66 return config.Once(vendorSnapshotStaticLibsKey, func() interface{} { 67 return newSnapshotMap() 68 }).(*snapshotMap) 69} 70 71func vendorSnapshotBinaries(config android.Config) *snapshotMap { 72 return config.Once(vendorSnapshotBinariesKey, func() interface{} { 73 return newSnapshotMap() 74 }).(*snapshotMap) 75} 76 77func vendorSnapshotObjects(config android.Config) *snapshotMap { 78 return config.Once(vendorSnapshotObjectsKey, func() interface{} { 79 return newSnapshotMap() 80 }).(*snapshotMap) 81} 82 83type vendorSnapshotLibraryProperties struct { 84 // snapshot version. 85 Version string 86 87 // Target arch name of the snapshot (e.g. 'arm64' for variant 'aosp_arm64') 88 Target_arch string 89 90 // Prebuilt file for each arch. 91 Src *string `android:"arch_variant"` 92 93 // list of flags that will be used for any module that links against this module. 94 Export_flags []string `android:"arch_variant"` 95 96 // Check the prebuilt ELF files (e.g. DT_SONAME, DT_NEEDED, resolution of undefined symbols, 97 // etc). 98 Check_elf_files *bool 99 100 // Whether this prebuilt needs to depend on sanitize ubsan runtime or not. 101 Sanitize_ubsan_dep *bool `android:"arch_variant"` 102 103 // Whether this prebuilt needs to depend on sanitize minimal runtime or not. 104 Sanitize_minimal_dep *bool `android:"arch_variant"` 105} 106 107type vendorSnapshotLibraryDecorator struct { 108 *libraryDecorator 109 properties vendorSnapshotLibraryProperties 110 androidMkVendorSuffix bool 111} 112 113func (p *vendorSnapshotLibraryDecorator) Name(name string) string { 114 return name + p.NameSuffix() 115} 116 117func (p *vendorSnapshotLibraryDecorator) NameSuffix() string { 118 versionSuffix := p.version() 119 if p.arch() != "" { 120 versionSuffix += "." + p.arch() 121 } 122 123 var linkageSuffix string 124 if p.buildShared() { 125 linkageSuffix = vendorSnapshotSharedSuffix 126 } else if p.buildStatic() { 127 linkageSuffix = vendorSnapshotStaticSuffix 128 } else { 129 linkageSuffix = vendorSnapshotHeaderSuffix 130 } 131 132 return linkageSuffix + versionSuffix 133} 134 135func (p *vendorSnapshotLibraryDecorator) version() string { 136 return p.properties.Version 137} 138 139func (p *vendorSnapshotLibraryDecorator) arch() string { 140 return p.properties.Target_arch 141} 142 143func (p *vendorSnapshotLibraryDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags { 144 p.libraryDecorator.libName = strings.TrimSuffix(ctx.ModuleName(), p.NameSuffix()) 145 return p.libraryDecorator.linkerFlags(ctx, flags) 146} 147 148func (p *vendorSnapshotLibraryDecorator) matchesWithDevice(config android.DeviceConfig) bool { 149 arches := config.Arches() 150 if len(arches) == 0 || arches[0].ArchType.String() != p.arch() { 151 return false 152 } 153 if !p.header() && p.properties.Src == nil { 154 return false 155 } 156 return true 157} 158 159func (p *vendorSnapshotLibraryDecorator) link(ctx ModuleContext, 160 flags Flags, deps PathDeps, objs Objects) android.Path { 161 m := ctx.Module().(*Module) 162 p.androidMkVendorSuffix = vendorSuffixModules(ctx.Config())[m.BaseModuleName()] 163 164 if p.header() { 165 return p.libraryDecorator.link(ctx, flags, deps, objs) 166 } 167 168 if !p.matchesWithDevice(ctx.DeviceConfig()) { 169 return nil 170 } 171 172 p.libraryDecorator.exportIncludes(ctx) 173 p.libraryDecorator.reexportFlags(p.properties.Export_flags...) 174 175 in := android.PathForModuleSrc(ctx, *p.properties.Src) 176 p.unstrippedOutputFile = in 177 178 if p.shared() { 179 libName := in.Base() 180 builderFlags := flagsToBuilderFlags(flags) 181 182 // Optimize out relinking against shared libraries whose interface hasn't changed by 183 // depending on a table of contents file instead of the library itself. 184 tocFile := android.PathForModuleOut(ctx, libName+".toc") 185 p.tocFile = android.OptionalPathForPath(tocFile) 186 TransformSharedObjectToToc(ctx, in, tocFile, builderFlags) 187 } 188 189 return in 190} 191 192func (p *vendorSnapshotLibraryDecorator) nativeCoverage() bool { 193 return false 194} 195 196func (p *vendorSnapshotLibraryDecorator) isSnapshotPrebuilt() bool { 197 return true 198} 199 200func (p *vendorSnapshotLibraryDecorator) install(ctx ModuleContext, file android.Path) { 201 if p.matchesWithDevice(ctx.DeviceConfig()) && (p.shared() || p.static()) { 202 p.baseInstaller.install(ctx, file) 203 } 204} 205 206type vendorSnapshotInterface interface { 207 version() string 208} 209 210func vendorSnapshotLoadHook(ctx android.LoadHookContext, p vendorSnapshotInterface) { 211 if p.version() != ctx.DeviceConfig().VndkVersion() { 212 ctx.Module().Disable() 213 return 214 } 215} 216 217func vendorSnapshotLibrary() (*Module, *vendorSnapshotLibraryDecorator) { 218 module, library := NewLibrary(android.DeviceSupported) 219 220 module.stl = nil 221 module.sanitize = nil 222 library.StripProperties.Strip.None = BoolPtr(true) 223 224 prebuilt := &vendorSnapshotLibraryDecorator{ 225 libraryDecorator: library, 226 } 227 228 prebuilt.baseLinker.Properties.No_libcrt = BoolPtr(true) 229 prebuilt.baseLinker.Properties.Nocrt = BoolPtr(true) 230 231 // Prevent default system libs (libc, libm, and libdl) from being linked 232 if prebuilt.baseLinker.Properties.System_shared_libs == nil { 233 prebuilt.baseLinker.Properties.System_shared_libs = []string{} 234 } 235 236 module.compiler = nil 237 module.linker = prebuilt 238 module.installer = prebuilt 239 240 module.AddProperties( 241 &prebuilt.properties, 242 ) 243 244 return module, prebuilt 245} 246 247func VendorSnapshotSharedFactory() android.Module { 248 module, prebuilt := vendorSnapshotLibrary() 249 prebuilt.libraryDecorator.BuildOnlyShared() 250 android.AddLoadHook(module, func(ctx android.LoadHookContext) { 251 vendorSnapshotLoadHook(ctx, prebuilt) 252 }) 253 return module.Init() 254} 255 256func VendorSnapshotStaticFactory() android.Module { 257 module, prebuilt := vendorSnapshotLibrary() 258 prebuilt.libraryDecorator.BuildOnlyStatic() 259 android.AddLoadHook(module, func(ctx android.LoadHookContext) { 260 vendorSnapshotLoadHook(ctx, prebuilt) 261 }) 262 return module.Init() 263} 264 265func VendorSnapshotHeaderFactory() android.Module { 266 module, prebuilt := vendorSnapshotLibrary() 267 prebuilt.libraryDecorator.HeaderOnly() 268 android.AddLoadHook(module, func(ctx android.LoadHookContext) { 269 vendorSnapshotLoadHook(ctx, prebuilt) 270 }) 271 return module.Init() 272} 273 274type vendorSnapshotBinaryProperties struct { 275 // snapshot version. 276 Version string 277 278 // Target arch name of the snapshot (e.g. 'arm64' for variant 'aosp_arm64_ab') 279 Target_arch string 280 281 // Prebuilt file for each arch. 282 Src *string `android:"arch_variant"` 283} 284 285type vendorSnapshotBinaryDecorator struct { 286 *binaryDecorator 287 properties vendorSnapshotBinaryProperties 288 androidMkVendorSuffix bool 289} 290 291func (p *vendorSnapshotBinaryDecorator) Name(name string) string { 292 return name + p.NameSuffix() 293} 294 295func (p *vendorSnapshotBinaryDecorator) NameSuffix() string { 296 versionSuffix := p.version() 297 if p.arch() != "" { 298 versionSuffix += "." + p.arch() 299 } 300 return vendorSnapshotBinarySuffix + versionSuffix 301} 302 303func (p *vendorSnapshotBinaryDecorator) version() string { 304 return p.properties.Version 305} 306 307func (p *vendorSnapshotBinaryDecorator) arch() string { 308 return p.properties.Target_arch 309} 310 311func (p *vendorSnapshotBinaryDecorator) matchesWithDevice(config android.DeviceConfig) bool { 312 if config.DeviceArch() != p.arch() { 313 return false 314 } 315 if p.properties.Src == nil { 316 return false 317 } 318 return true 319} 320 321func (p *vendorSnapshotBinaryDecorator) link(ctx ModuleContext, 322 flags Flags, deps PathDeps, objs Objects) android.Path { 323 if !p.matchesWithDevice(ctx.DeviceConfig()) { 324 return nil 325 } 326 327 in := android.PathForModuleSrc(ctx, *p.properties.Src) 328 builderFlags := flagsToBuilderFlags(flags) 329 p.unstrippedOutputFile = in 330 binName := in.Base() 331 if p.needsStrip(ctx) { 332 stripped := android.PathForModuleOut(ctx, "stripped", binName) 333 p.stripExecutableOrSharedLib(ctx, in, stripped, builderFlags) 334 in = stripped 335 } 336 337 m := ctx.Module().(*Module) 338 p.androidMkVendorSuffix = vendorSuffixModules(ctx.Config())[m.BaseModuleName()] 339 340 // use cpExecutable to make it executable 341 outputFile := android.PathForModuleOut(ctx, binName) 342 ctx.Build(pctx, android.BuildParams{ 343 Rule: android.CpExecutable, 344 Description: "prebuilt", 345 Output: outputFile, 346 Input: in, 347 }) 348 349 return outputFile 350} 351 352func (p *vendorSnapshotBinaryDecorator) isSnapshotPrebuilt() bool { 353 return true 354} 355 356func VendorSnapshotBinaryFactory() android.Module { 357 module, binary := NewBinary(android.DeviceSupported) 358 binary.baseLinker.Properties.No_libcrt = BoolPtr(true) 359 binary.baseLinker.Properties.Nocrt = BoolPtr(true) 360 361 // Prevent default system libs (libc, libm, and libdl) from being linked 362 if binary.baseLinker.Properties.System_shared_libs == nil { 363 binary.baseLinker.Properties.System_shared_libs = []string{} 364 } 365 366 prebuilt := &vendorSnapshotBinaryDecorator{ 367 binaryDecorator: binary, 368 } 369 370 module.compiler = nil 371 module.sanitize = nil 372 module.stl = nil 373 module.linker = prebuilt 374 375 android.AddLoadHook(module, func(ctx android.LoadHookContext) { 376 vendorSnapshotLoadHook(ctx, prebuilt) 377 }) 378 379 module.AddProperties(&prebuilt.properties) 380 return module.Init() 381} 382 383type vendorSnapshotObjectProperties struct { 384 // snapshot version. 385 Version string 386 387 // Target arch name of the snapshot (e.g. 'arm64' for variant 'aosp_arm64_ab') 388 Target_arch string 389 390 // Prebuilt file for each arch. 391 Src *string `android:"arch_variant"` 392} 393 394type vendorSnapshotObjectLinker struct { 395 objectLinker 396 properties vendorSnapshotObjectProperties 397 androidMkVendorSuffix bool 398} 399 400func (p *vendorSnapshotObjectLinker) Name(name string) string { 401 return name + p.NameSuffix() 402} 403 404func (p *vendorSnapshotObjectLinker) NameSuffix() string { 405 versionSuffix := p.version() 406 if p.arch() != "" { 407 versionSuffix += "." + p.arch() 408 } 409 return vendorSnapshotObjectSuffix + versionSuffix 410} 411 412func (p *vendorSnapshotObjectLinker) version() string { 413 return p.properties.Version 414} 415 416func (p *vendorSnapshotObjectLinker) arch() string { 417 return p.properties.Target_arch 418} 419 420func (p *vendorSnapshotObjectLinker) matchesWithDevice(config android.DeviceConfig) bool { 421 if config.DeviceArch() != p.arch() { 422 return false 423 } 424 if p.properties.Src == nil { 425 return false 426 } 427 return true 428} 429 430func (p *vendorSnapshotObjectLinker) link(ctx ModuleContext, 431 flags Flags, deps PathDeps, objs Objects) android.Path { 432 if !p.matchesWithDevice(ctx.DeviceConfig()) { 433 return nil 434 } 435 436 m := ctx.Module().(*Module) 437 p.androidMkVendorSuffix = vendorSuffixModules(ctx.Config())[m.BaseModuleName()] 438 439 return android.PathForModuleSrc(ctx, *p.properties.Src) 440} 441 442func (p *vendorSnapshotObjectLinker) nativeCoverage() bool { 443 return false 444} 445 446func (p *vendorSnapshotObjectLinker) isSnapshotPrebuilt() bool { 447 return true 448} 449 450func VendorSnapshotObjectFactory() android.Module { 451 module := newObject() 452 453 prebuilt := &vendorSnapshotObjectLinker{ 454 objectLinker: objectLinker{ 455 baseLinker: NewBaseLinker(nil), 456 }, 457 } 458 module.linker = prebuilt 459 460 android.AddLoadHook(module, func(ctx android.LoadHookContext) { 461 vendorSnapshotLoadHook(ctx, prebuilt) 462 }) 463 464 module.AddProperties(&prebuilt.properties) 465 return module.Init() 466} 467 468func init() { 469 android.RegisterSingletonType("vendor-snapshot", VendorSnapshotSingleton) 470 android.RegisterModuleType("vendor_snapshot_shared", VendorSnapshotSharedFactory) 471 android.RegisterModuleType("vendor_snapshot_static", VendorSnapshotStaticFactory) 472 android.RegisterModuleType("vendor_snapshot_header", VendorSnapshotHeaderFactory) 473 android.RegisterModuleType("vendor_snapshot_binary", VendorSnapshotBinaryFactory) 474 android.RegisterModuleType("vendor_snapshot_object", VendorSnapshotObjectFactory) 475} 476 477func VendorSnapshotSingleton() android.Singleton { 478 return &vendorSnapshotSingleton{} 479} 480 481type vendorSnapshotSingleton struct { 482 vendorSnapshotZipFile android.OptionalPath 483} 484 485var ( 486 // Modules under following directories are ignored. They are OEM's and vendor's 487 // proprietary modules(device/, vendor/, and hardware/). 488 // TODO(b/65377115): Clean up these with more maintainable way 489 vendorProprietaryDirs = []string{ 490 "device", 491 "vendor", 492 "hardware", 493 } 494 495 // Modules under following directories are included as they are in AOSP, 496 // although hardware/ is normally for vendor's own. 497 // TODO(b/65377115): Clean up these with more maintainable way 498 aospDirsUnderProprietary = []string{ 499 "hardware/interfaces", 500 "hardware/libhardware", 501 "hardware/libhardware_legacy", 502 "hardware/ril", 503 } 504) 505 506// Determine if a dir under source tree is an SoC-owned proprietary directory, such as 507// device/, vendor/, etc. 508func isVendorProprietaryPath(dir string) bool { 509 for _, p := range vendorProprietaryDirs { 510 if strings.HasPrefix(dir, p) { 511 // filter out AOSP defined directories, e.g. hardware/interfaces/ 512 aosp := false 513 for _, p := range aospDirsUnderProprietary { 514 if strings.HasPrefix(dir, p) { 515 aosp = true 516 break 517 } 518 } 519 if !aosp { 520 return true 521 } 522 } 523 } 524 return false 525} 526 527// Determine if a module is going to be included in vendor snapshot or not. 528// 529// Targets of vendor snapshot are "vendor: true" or "vendor_available: true" modules in 530// AOSP. They are not guaranteed to be compatible with older vendor images. (e.g. might 531// depend on newer VNDK) So they are captured as vendor snapshot To build older vendor 532// image and newer system image altogether. 533func isVendorSnapshotModule(m *Module, moduleDir string) bool { 534 if !m.Enabled() || m.Properties.HideFromMake { 535 return false 536 } 537 // skip proprietary modules, but include all VNDK (static) 538 if isVendorProprietaryPath(moduleDir) && !m.IsVndk() { 539 return false 540 } 541 if m.Target().Os.Class != android.Device { 542 return false 543 } 544 if m.Target().NativeBridge == android.NativeBridgeEnabled { 545 return false 546 } 547 // the module must be installed in /vendor 548 if !m.IsForPlatform() || m.isSnapshotPrebuilt() || !m.inVendor() { 549 return false 550 } 551 // skip kernel_headers which always depend on vendor 552 if _, ok := m.linker.(*kernelHeadersDecorator); ok { 553 return false 554 } 555 556 // Libraries 557 if l, ok := m.linker.(snapshotLibraryInterface); ok { 558 // TODO(b/65377115): add full support for sanitizer 559 if m.sanitize != nil { 560 // cfi, scs and hwasan export both sanitized and unsanitized variants for static and header 561 // Always use unsanitized variants of them. 562 for _, t := range []sanitizerType{cfi, scs, hwasan} { 563 if !l.shared() && m.sanitize.isSanitizerEnabled(t) { 564 return false 565 } 566 } 567 } 568 if l.static() { 569 return m.outputFile.Valid() && proptools.BoolDefault(m.VendorProperties.Vendor_available, true) 570 } 571 if l.shared() { 572 if !m.outputFile.Valid() { 573 return false 574 } 575 if !m.IsVndk() { 576 return true 577 } 578 return m.isVndkExt() 579 } 580 return true 581 } 582 583 // Binaries and Objects 584 if m.binary() || m.object() { 585 return m.outputFile.Valid() && proptools.BoolDefault(m.VendorProperties.Vendor_available, true) 586 } 587 588 return false 589} 590 591func (c *vendorSnapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) { 592 // BOARD_VNDK_VERSION must be set to 'current' in order to generate a vendor snapshot. 593 if ctx.DeviceConfig().VndkVersion() != "current" { 594 return 595 } 596 597 var snapshotOutputs android.Paths 598 599 /* 600 Vendor snapshot zipped artifacts directory structure: 601 {SNAPSHOT_ARCH}/ 602 arch-{TARGET_ARCH}-{TARGET_ARCH_VARIANT}/ 603 shared/ 604 (.so shared libraries) 605 static/ 606 (.a static libraries) 607 header/ 608 (header only libraries) 609 binary/ 610 (executable binaries) 611 object/ 612 (.o object files) 613 arch-{TARGET_2ND_ARCH}-{TARGET_2ND_ARCH_VARIANT}/ 614 shared/ 615 (.so shared libraries) 616 static/ 617 (.a static libraries) 618 header/ 619 (header only libraries) 620 binary/ 621 (executable binaries) 622 object/ 623 (.o object files) 624 NOTICE_FILES/ 625 (notice files, e.g. libbase.txt) 626 configs/ 627 (config files, e.g. init.rc files, vintf_fragments.xml files, etc.) 628 include/ 629 (header files of same directory structure with source tree) 630 */ 631 632 snapshotDir := "vendor-snapshot" 633 snapshotArchDir := filepath.Join(snapshotDir, ctx.DeviceConfig().DeviceArch()) 634 635 includeDir := filepath.Join(snapshotArchDir, "include") 636 configsDir := filepath.Join(snapshotArchDir, "configs") 637 noticeDir := filepath.Join(snapshotArchDir, "NOTICE_FILES") 638 639 installedNotices := make(map[string]bool) 640 installedConfigs := make(map[string]bool) 641 642 var headers android.Paths 643 644 installSnapshot := func(m *Module) android.Paths { 645 targetArch := "arch-" + m.Target().Arch.ArchType.String() 646 if m.Target().Arch.ArchVariant != "" { 647 targetArch += "-" + m.Target().Arch.ArchVariant 648 } 649 650 var ret android.Paths 651 652 prop := struct { 653 ModuleName string `json:",omitempty"` 654 RelativeInstallPath string `json:",omitempty"` 655 656 // library flags 657 ExportedDirs []string `json:",omitempty"` 658 ExportedSystemDirs []string `json:",omitempty"` 659 ExportedFlags []string `json:",omitempty"` 660 SanitizeMinimalDep bool `json:",omitempty"` 661 SanitizeUbsanDep bool `json:",omitempty"` 662 663 // binary flags 664 Symlinks []string `json:",omitempty"` 665 666 // dependencies 667 SharedLibs []string `json:",omitempty"` 668 RuntimeLibs []string `json:",omitempty"` 669 Required []string `json:",omitempty"` 670 671 // extra config files 672 InitRc []string `json:",omitempty"` 673 VintfFragments []string `json:",omitempty"` 674 }{} 675 676 // Common properties among snapshots. 677 prop.ModuleName = ctx.ModuleName(m) 678 if m.isVndkExt() { 679 // vndk exts are installed to /vendor/lib(64)?/vndk(-sp)? 680 if m.isVndkSp() { 681 prop.RelativeInstallPath = "vndk-sp" 682 } else { 683 prop.RelativeInstallPath = "vndk" 684 } 685 } else { 686 prop.RelativeInstallPath = m.RelativeInstallPath() 687 } 688 prop.RuntimeLibs = m.Properties.SnapshotRuntimeLibs 689 prop.Required = m.RequiredModuleNames() 690 for _, path := range m.InitRc() { 691 prop.InitRc = append(prop.InitRc, filepath.Join("configs", path.Base())) 692 } 693 for _, path := range m.VintfFragments() { 694 prop.VintfFragments = append(prop.VintfFragments, filepath.Join("configs", path.Base())) 695 } 696 697 // install config files. ignores any duplicates. 698 for _, path := range append(m.InitRc(), m.VintfFragments()...) { 699 out := filepath.Join(configsDir, path.Base()) 700 if !installedConfigs[out] { 701 installedConfigs[out] = true 702 ret = append(ret, copyFile(ctx, path, out)) 703 } 704 } 705 706 var propOut string 707 708 if l, ok := m.linker.(snapshotLibraryInterface); ok { 709 // library flags 710 prop.ExportedFlags = l.exportedFlags() 711 for _, dir := range l.exportedDirs() { 712 prop.ExportedDirs = append(prop.ExportedDirs, filepath.Join("include", dir.String())) 713 } 714 for _, dir := range l.exportedSystemDirs() { 715 prop.ExportedSystemDirs = append(prop.ExportedSystemDirs, filepath.Join("include", dir.String())) 716 } 717 // shared libs dependencies aren't meaningful on static or header libs 718 if l.shared() { 719 prop.SharedLibs = m.Properties.SnapshotSharedLibs 720 } 721 if l.static() && m.sanitize != nil { 722 prop.SanitizeMinimalDep = m.sanitize.Properties.MinimalRuntimeDep || enableMinimalRuntime(m.sanitize) 723 prop.SanitizeUbsanDep = m.sanitize.Properties.UbsanRuntimeDep || enableUbsanRuntime(m.sanitize) 724 } 725 726 var libType string 727 if l.static() { 728 libType = "static" 729 } else if l.shared() { 730 libType = "shared" 731 } else { 732 libType = "header" 733 } 734 735 var stem string 736 737 // install .a or .so 738 if libType != "header" { 739 libPath := m.outputFile.Path() 740 stem = libPath.Base() 741 snapshotLibOut := filepath.Join(snapshotArchDir, targetArch, libType, stem) 742 ret = append(ret, copyFile(ctx, libPath, snapshotLibOut)) 743 } else { 744 stem = ctx.ModuleName(m) 745 } 746 747 propOut = filepath.Join(snapshotArchDir, targetArch, libType, stem+".json") 748 } else if m.binary() { 749 // binary flags 750 prop.Symlinks = m.Symlinks() 751 prop.SharedLibs = m.Properties.SnapshotSharedLibs 752 753 // install bin 754 binPath := m.outputFile.Path() 755 snapshotBinOut := filepath.Join(snapshotArchDir, targetArch, "binary", binPath.Base()) 756 ret = append(ret, copyFile(ctx, binPath, snapshotBinOut)) 757 propOut = snapshotBinOut + ".json" 758 } else if m.object() { 759 // object files aren't installed to the device, so their names can conflict. 760 // Use module name as stem. 761 objPath := m.outputFile.Path() 762 snapshotObjOut := filepath.Join(snapshotArchDir, targetArch, "object", 763 ctx.ModuleName(m)+filepath.Ext(objPath.Base())) 764 ret = append(ret, copyFile(ctx, objPath, snapshotObjOut)) 765 propOut = snapshotObjOut + ".json" 766 } else { 767 ctx.Errorf("unknown module %q in vendor snapshot", m.String()) 768 return nil 769 } 770 771 j, err := json.Marshal(prop) 772 if err != nil { 773 ctx.Errorf("json marshal to %q failed: %#v", propOut, err) 774 return nil 775 } 776 ret = append(ret, writeStringToFile(ctx, string(j), propOut)) 777 778 return ret 779 } 780 781 ctx.VisitAllModules(func(module android.Module) { 782 m, ok := module.(*Module) 783 if !ok { 784 return 785 } 786 787 moduleDir := ctx.ModuleDir(module) 788 if !isVendorSnapshotModule(m, moduleDir) { 789 return 790 } 791 792 snapshotOutputs = append(snapshotOutputs, installSnapshot(m)...) 793 if l, ok := m.linker.(snapshotLibraryInterface); ok { 794 headers = append(headers, l.snapshotHeaders()...) 795 } 796 797 if m.NoticeFile().Valid() { 798 noticeName := ctx.ModuleName(m) + ".txt" 799 noticeOut := filepath.Join(noticeDir, noticeName) 800 // skip already copied notice file 801 if !installedNotices[noticeOut] { 802 installedNotices[noticeOut] = true 803 snapshotOutputs = append(snapshotOutputs, copyFile( 804 ctx, m.NoticeFile().Path(), noticeOut)) 805 } 806 } 807 }) 808 809 // install all headers after removing duplicates 810 for _, header := range android.FirstUniquePaths(headers) { 811 snapshotOutputs = append(snapshotOutputs, copyFile( 812 ctx, header, filepath.Join(includeDir, header.String()))) 813 } 814 815 // All artifacts are ready. Sort them to normalize ninja and then zip. 816 sort.Slice(snapshotOutputs, func(i, j int) bool { 817 return snapshotOutputs[i].String() < snapshotOutputs[j].String() 818 }) 819 820 zipPath := android.PathForOutput(ctx, snapshotDir, "vendor-"+ctx.Config().DeviceName()+".zip") 821 zipRule := android.NewRuleBuilder() 822 823 // filenames in rspfile from FlagWithRspFileInputList might be single-quoted. Remove it with tr 824 snapshotOutputList := android.PathForOutput(ctx, snapshotDir, "vendor-"+ctx.Config().DeviceName()+"_list") 825 zipRule.Command(). 826 Text("tr"). 827 FlagWithArg("-d ", "\\'"). 828 FlagWithRspFileInputList("< ", snapshotOutputs). 829 FlagWithOutput("> ", snapshotOutputList) 830 831 zipRule.Temporary(snapshotOutputList) 832 833 zipRule.Command(). 834 BuiltTool(ctx, "soong_zip"). 835 FlagWithOutput("-o ", zipPath). 836 FlagWithArg("-C ", android.PathForOutput(ctx, snapshotDir).String()). 837 FlagWithInput("-l ", snapshotOutputList) 838 839 zipRule.Build(pctx, ctx, zipPath.String(), "vendor snapshot "+zipPath.String()) 840 zipRule.DeleteTemporaryFiles() 841 c.vendorSnapshotZipFile = android.OptionalPathForPath(zipPath) 842} 843 844func (c *vendorSnapshotSingleton) MakeVars(ctx android.MakeVarsContext) { 845 ctx.Strict("SOONG_VENDOR_SNAPSHOT_ZIP", c.vendorSnapshotZipFile.String()) 846} 847 848type snapshotInterface interface { 849 matchesWithDevice(config android.DeviceConfig) bool 850} 851 852var _ snapshotInterface = (*vndkPrebuiltLibraryDecorator)(nil) 853var _ snapshotInterface = (*vendorSnapshotLibraryDecorator)(nil) 854var _ snapshotInterface = (*vendorSnapshotBinaryDecorator)(nil) 855var _ snapshotInterface = (*vendorSnapshotObjectLinker)(nil) 856 857// gathers all snapshot modules for vendor, and disable unnecessary snapshots 858// TODO(b/145966707): remove mutator and utilize android.Prebuilt to override source modules 859func VendorSnapshotMutator(ctx android.BottomUpMutatorContext) { 860 vndkVersion := ctx.DeviceConfig().VndkVersion() 861 // don't need snapshot if current 862 if vndkVersion == "current" || vndkVersion == "" { 863 return 864 } 865 866 module, ok := ctx.Module().(*Module) 867 if !ok || !module.Enabled() || module.VndkVersion() != vndkVersion { 868 return 869 } 870 871 if !module.isSnapshotPrebuilt() { 872 return 873 } 874 875 // isSnapshotPrebuilt ensures snapshotInterface 876 if !module.linker.(snapshotInterface).matchesWithDevice(ctx.DeviceConfig()) { 877 // Disable unnecessary snapshot module, but do not disable 878 // vndk_prebuilt_shared because they might be packed into vndk APEX 879 if !module.IsVndk() { 880 module.Disable() 881 } 882 return 883 } 884 885 var snapshotMap *snapshotMap 886 887 if lib, ok := module.linker.(libraryInterface); ok { 888 if lib.static() { 889 snapshotMap = vendorSnapshotStaticLibs(ctx.Config()) 890 } else if lib.shared() { 891 snapshotMap = vendorSnapshotSharedLibs(ctx.Config()) 892 } else { 893 // header 894 snapshotMap = vendorSnapshotHeaderLibs(ctx.Config()) 895 } 896 } else if _, ok := module.linker.(*vendorSnapshotBinaryDecorator); ok { 897 snapshotMap = vendorSnapshotBinaries(ctx.Config()) 898 } else if _, ok := module.linker.(*vendorSnapshotObjectLinker); ok { 899 snapshotMap = vendorSnapshotObjects(ctx.Config()) 900 } else { 901 return 902 } 903 904 vendorSnapshotsLock.Lock() 905 defer vendorSnapshotsLock.Unlock() 906 snapshotMap.add(module.BaseModuleName(), ctx.Arch().ArchType, ctx.ModuleName()) 907} 908 909// Disables source modules which have snapshots 910func VendorSnapshotSourceMutator(ctx android.BottomUpMutatorContext) { 911 if !ctx.Device() { 912 return 913 } 914 915 vndkVersion := ctx.DeviceConfig().VndkVersion() 916 // don't need snapshot if current 917 if vndkVersion == "current" || vndkVersion == "" { 918 return 919 } 920 921 module, ok := ctx.Module().(*Module) 922 if !ok { 923 return 924 } 925 926 // vendor suffix should be added to snapshots if the source module isn't vendor: true. 927 if !module.SocSpecific() { 928 // But we can't just check SocSpecific() since we already passed the image mutator. 929 // Check ramdisk and recovery to see if we are real "vendor: true" module. 930 ramdisk_available := module.InRamdisk() && !module.OnlyInRamdisk() 931 recovery_available := module.InRecovery() && !module.OnlyInRecovery() 932 933 if !ramdisk_available && !recovery_available { 934 vendorSnapshotsLock.Lock() 935 defer vendorSnapshotsLock.Unlock() 936 937 vendorSuffixModules(ctx.Config())[ctx.ModuleName()] = true 938 } 939 } 940 941 if module.isSnapshotPrebuilt() || module.VndkVersion() != ctx.DeviceConfig().VndkVersion() { 942 // only non-snapshot modules with BOARD_VNDK_VERSION 943 return 944 } 945 946 // .. and also filter out llndk library 947 if module.isLlndk(ctx.Config()) { 948 return 949 } 950 951 var snapshotMap *snapshotMap 952 953 if lib, ok := module.linker.(libraryInterface); ok { 954 if lib.static() { 955 snapshotMap = vendorSnapshotStaticLibs(ctx.Config()) 956 } else if lib.shared() { 957 snapshotMap = vendorSnapshotSharedLibs(ctx.Config()) 958 } else { 959 // header 960 snapshotMap = vendorSnapshotHeaderLibs(ctx.Config()) 961 } 962 } else if module.binary() { 963 snapshotMap = vendorSnapshotBinaries(ctx.Config()) 964 } else if module.object() { 965 snapshotMap = vendorSnapshotObjects(ctx.Config()) 966 } else { 967 return 968 } 969 970 if _, ok := snapshotMap.get(ctx.ModuleName(), ctx.Arch().ArchType); !ok { 971 // Corresponding snapshot doesn't exist 972 return 973 } 974 975 // Disables source modules if corresponding snapshot exists. 976 if lib, ok := module.linker.(libraryInterface); ok && lib.buildStatic() && lib.buildShared() { 977 // But do not disable because the shared variant depends on the static variant. 978 module.SkipInstall() 979 module.Properties.HideFromMake = true 980 } else { 981 module.Disable() 982 } 983} 984