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 // skip llndk_library and llndk_headers which are backward compatible 556 if _, ok := m.linker.(*llndkStubDecorator); ok { 557 return false 558 } 559 if _, ok := m.linker.(*llndkHeadersDecorator); ok { 560 return false 561 } 562 563 // Libraries 564 if l, ok := m.linker.(snapshotLibraryInterface); ok { 565 // TODO(b/65377115): add full support for sanitizer 566 if m.sanitize != nil { 567 // cfi, scs and hwasan export both sanitized and unsanitized variants for static and header 568 // Always use unsanitized variants of them. 569 for _, t := range []sanitizerType{cfi, scs, hwasan} { 570 if !l.shared() && m.sanitize.isSanitizerEnabled(t) { 571 return false 572 } 573 } 574 } 575 if l.static() { 576 return m.outputFile.Valid() && proptools.BoolDefault(m.VendorProperties.Vendor_available, true) 577 } 578 if l.shared() { 579 if !m.outputFile.Valid() { 580 return false 581 } 582 if !m.IsVndk() { 583 return true 584 } 585 return m.isVndkExt() 586 } 587 return true 588 } 589 590 // Binaries and Objects 591 if m.binary() || m.object() { 592 return m.outputFile.Valid() && proptools.BoolDefault(m.VendorProperties.Vendor_available, true) 593 } 594 595 return false 596} 597 598func (c *vendorSnapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) { 599 // BOARD_VNDK_VERSION must be set to 'current' in order to generate a vendor snapshot. 600 if ctx.DeviceConfig().VndkVersion() != "current" { 601 return 602 } 603 604 var snapshotOutputs android.Paths 605 606 /* 607 Vendor snapshot zipped artifacts directory structure: 608 {SNAPSHOT_ARCH}/ 609 arch-{TARGET_ARCH}-{TARGET_ARCH_VARIANT}/ 610 shared/ 611 (.so shared libraries) 612 static/ 613 (.a static libraries) 614 header/ 615 (header only libraries) 616 binary/ 617 (executable binaries) 618 object/ 619 (.o object files) 620 arch-{TARGET_2ND_ARCH}-{TARGET_2ND_ARCH_VARIANT}/ 621 shared/ 622 (.so shared libraries) 623 static/ 624 (.a static libraries) 625 header/ 626 (header only libraries) 627 binary/ 628 (executable binaries) 629 object/ 630 (.o object files) 631 NOTICE_FILES/ 632 (notice files, e.g. libbase.txt) 633 configs/ 634 (config files, e.g. init.rc files, vintf_fragments.xml files, etc.) 635 include/ 636 (header files of same directory structure with source tree) 637 */ 638 639 snapshotDir := "vendor-snapshot" 640 snapshotArchDir := filepath.Join(snapshotDir, ctx.DeviceConfig().DeviceArch()) 641 642 includeDir := filepath.Join(snapshotArchDir, "include") 643 configsDir := filepath.Join(snapshotArchDir, "configs") 644 noticeDir := filepath.Join(snapshotArchDir, "NOTICE_FILES") 645 646 installedNotices := make(map[string]bool) 647 installedConfigs := make(map[string]bool) 648 649 var headers android.Paths 650 651 installSnapshot := func(m *Module) android.Paths { 652 targetArch := "arch-" + m.Target().Arch.ArchType.String() 653 if m.Target().Arch.ArchVariant != "" { 654 targetArch += "-" + m.Target().Arch.ArchVariant 655 } 656 657 var ret android.Paths 658 659 prop := struct { 660 ModuleName string `json:",omitempty"` 661 RelativeInstallPath string `json:",omitempty"` 662 663 // library flags 664 ExportedDirs []string `json:",omitempty"` 665 ExportedSystemDirs []string `json:",omitempty"` 666 ExportedFlags []string `json:",omitempty"` 667 SanitizeMinimalDep bool `json:",omitempty"` 668 SanitizeUbsanDep bool `json:",omitempty"` 669 670 // binary flags 671 Symlinks []string `json:",omitempty"` 672 673 // dependencies 674 SharedLibs []string `json:",omitempty"` 675 RuntimeLibs []string `json:",omitempty"` 676 Required []string `json:",omitempty"` 677 678 // extra config files 679 InitRc []string `json:",omitempty"` 680 VintfFragments []string `json:",omitempty"` 681 }{} 682 683 // Common properties among snapshots. 684 prop.ModuleName = ctx.ModuleName(m) 685 if m.isVndkExt() { 686 // vndk exts are installed to /vendor/lib(64)?/vndk(-sp)? 687 if m.isVndkSp() { 688 prop.RelativeInstallPath = "vndk-sp" 689 } else { 690 prop.RelativeInstallPath = "vndk" 691 } 692 } else { 693 prop.RelativeInstallPath = m.RelativeInstallPath() 694 } 695 prop.RuntimeLibs = m.Properties.SnapshotRuntimeLibs 696 prop.Required = m.RequiredModuleNames() 697 for _, path := range m.InitRc() { 698 prop.InitRc = append(prop.InitRc, filepath.Join("configs", path.Base())) 699 } 700 for _, path := range m.VintfFragments() { 701 prop.VintfFragments = append(prop.VintfFragments, filepath.Join("configs", path.Base())) 702 } 703 704 // install config files. ignores any duplicates. 705 for _, path := range append(m.InitRc(), m.VintfFragments()...) { 706 out := filepath.Join(configsDir, path.Base()) 707 if !installedConfigs[out] { 708 installedConfigs[out] = true 709 ret = append(ret, copyFile(ctx, path, out)) 710 } 711 } 712 713 var propOut string 714 715 if l, ok := m.linker.(snapshotLibraryInterface); ok { 716 // library flags 717 prop.ExportedFlags = l.exportedFlags() 718 for _, dir := range l.exportedDirs() { 719 prop.ExportedDirs = append(prop.ExportedDirs, filepath.Join("include", dir.String())) 720 } 721 for _, dir := range l.exportedSystemDirs() { 722 prop.ExportedSystemDirs = append(prop.ExportedSystemDirs, filepath.Join("include", dir.String())) 723 } 724 // shared libs dependencies aren't meaningful on static or header libs 725 if l.shared() { 726 prop.SharedLibs = m.Properties.SnapshotSharedLibs 727 } 728 if l.static() && m.sanitize != nil { 729 prop.SanitizeMinimalDep = m.sanitize.Properties.MinimalRuntimeDep || enableMinimalRuntime(m.sanitize) 730 prop.SanitizeUbsanDep = m.sanitize.Properties.UbsanRuntimeDep || enableUbsanRuntime(m.sanitize) 731 } 732 733 var libType string 734 if l.static() { 735 libType = "static" 736 } else if l.shared() { 737 libType = "shared" 738 } else { 739 libType = "header" 740 } 741 742 var stem string 743 744 // install .a or .so 745 if libType != "header" { 746 libPath := m.outputFile.Path() 747 stem = libPath.Base() 748 snapshotLibOut := filepath.Join(snapshotArchDir, targetArch, libType, stem) 749 ret = append(ret, copyFile(ctx, libPath, snapshotLibOut)) 750 } else { 751 stem = ctx.ModuleName(m) 752 } 753 754 propOut = filepath.Join(snapshotArchDir, targetArch, libType, stem+".json") 755 } else if m.binary() { 756 // binary flags 757 prop.Symlinks = m.Symlinks() 758 prop.SharedLibs = m.Properties.SnapshotSharedLibs 759 760 // install bin 761 binPath := m.outputFile.Path() 762 snapshotBinOut := filepath.Join(snapshotArchDir, targetArch, "binary", binPath.Base()) 763 ret = append(ret, copyFile(ctx, binPath, snapshotBinOut)) 764 propOut = snapshotBinOut + ".json" 765 } else if m.object() { 766 // object files aren't installed to the device, so their names can conflict. 767 // Use module name as stem. 768 objPath := m.outputFile.Path() 769 snapshotObjOut := filepath.Join(snapshotArchDir, targetArch, "object", 770 ctx.ModuleName(m)+filepath.Ext(objPath.Base())) 771 ret = append(ret, copyFile(ctx, objPath, snapshotObjOut)) 772 propOut = snapshotObjOut + ".json" 773 } else { 774 ctx.Errorf("unknown module %q in vendor snapshot", m.String()) 775 return nil 776 } 777 778 j, err := json.Marshal(prop) 779 if err != nil { 780 ctx.Errorf("json marshal to %q failed: %#v", propOut, err) 781 return nil 782 } 783 ret = append(ret, writeStringToFile(ctx, string(j), propOut)) 784 785 return ret 786 } 787 788 ctx.VisitAllModules(func(module android.Module) { 789 m, ok := module.(*Module) 790 if !ok { 791 return 792 } 793 794 moduleDir := ctx.ModuleDir(module) 795 if !isVendorSnapshotModule(m, moduleDir) { 796 return 797 } 798 799 snapshotOutputs = append(snapshotOutputs, installSnapshot(m)...) 800 if l, ok := m.linker.(snapshotLibraryInterface); ok { 801 headers = append(headers, l.snapshotHeaders()...) 802 } 803 804 if len(m.NoticeFiles()) > 0 { 805 noticeName := ctx.ModuleName(m) + ".txt" 806 noticeOut := filepath.Join(noticeDir, noticeName) 807 // skip already copied notice file 808 if !installedNotices[noticeOut] { 809 installedNotices[noticeOut] = true 810 snapshotOutputs = append(snapshotOutputs, combineNotices( 811 ctx, m.NoticeFiles(), noticeOut)) 812 } 813 } 814 }) 815 816 // install all headers after removing duplicates 817 for _, header := range android.FirstUniquePaths(headers) { 818 snapshotOutputs = append(snapshotOutputs, copyFile( 819 ctx, header, filepath.Join(includeDir, header.String()))) 820 } 821 822 // All artifacts are ready. Sort them to normalize ninja and then zip. 823 sort.Slice(snapshotOutputs, func(i, j int) bool { 824 return snapshotOutputs[i].String() < snapshotOutputs[j].String() 825 }) 826 827 zipPath := android.PathForOutput(ctx, snapshotDir, "vendor-"+ctx.Config().DeviceName()+".zip") 828 zipRule := android.NewRuleBuilder() 829 830 // filenames in rspfile from FlagWithRspFileInputList might be single-quoted. Remove it with tr 831 snapshotOutputList := android.PathForOutput(ctx, snapshotDir, "vendor-"+ctx.Config().DeviceName()+"_list") 832 zipRule.Command(). 833 Text("tr"). 834 FlagWithArg("-d ", "\\'"). 835 FlagWithRspFileInputList("< ", snapshotOutputs). 836 FlagWithOutput("> ", snapshotOutputList) 837 838 zipRule.Temporary(snapshotOutputList) 839 840 zipRule.Command(). 841 BuiltTool(ctx, "soong_zip"). 842 FlagWithOutput("-o ", zipPath). 843 FlagWithArg("-C ", android.PathForOutput(ctx, snapshotDir).String()). 844 FlagWithInput("-l ", snapshotOutputList) 845 846 zipRule.Build(pctx, ctx, zipPath.String(), "vendor snapshot "+zipPath.String()) 847 zipRule.DeleteTemporaryFiles() 848 c.vendorSnapshotZipFile = android.OptionalPathForPath(zipPath) 849} 850 851func (c *vendorSnapshotSingleton) MakeVars(ctx android.MakeVarsContext) { 852 ctx.Strict("SOONG_VENDOR_SNAPSHOT_ZIP", c.vendorSnapshotZipFile.String()) 853} 854 855type snapshotInterface interface { 856 matchesWithDevice(config android.DeviceConfig) bool 857} 858 859var _ snapshotInterface = (*vndkPrebuiltLibraryDecorator)(nil) 860var _ snapshotInterface = (*vendorSnapshotLibraryDecorator)(nil) 861var _ snapshotInterface = (*vendorSnapshotBinaryDecorator)(nil) 862var _ snapshotInterface = (*vendorSnapshotObjectLinker)(nil) 863 864// gathers all snapshot modules for vendor, and disable unnecessary snapshots 865// TODO(b/145966707): remove mutator and utilize android.Prebuilt to override source modules 866func VendorSnapshotMutator(ctx android.BottomUpMutatorContext) { 867 vndkVersion := ctx.DeviceConfig().VndkVersion() 868 // don't need snapshot if current 869 if vndkVersion == "current" || vndkVersion == "" { 870 return 871 } 872 873 module, ok := ctx.Module().(*Module) 874 if !ok || !module.Enabled() || module.VndkVersion() != vndkVersion { 875 return 876 } 877 878 if !module.isSnapshotPrebuilt() { 879 return 880 } 881 882 // isSnapshotPrebuilt ensures snapshotInterface 883 if !module.linker.(snapshotInterface).matchesWithDevice(ctx.DeviceConfig()) { 884 // Disable unnecessary snapshot module, but do not disable 885 // vndk_prebuilt_shared because they might be packed into vndk APEX 886 if !module.IsVndk() { 887 module.Disable() 888 } 889 return 890 } 891 892 var snapshotMap *snapshotMap 893 894 if lib, ok := module.linker.(libraryInterface); ok { 895 if lib.static() { 896 snapshotMap = vendorSnapshotStaticLibs(ctx.Config()) 897 } else if lib.shared() { 898 snapshotMap = vendorSnapshotSharedLibs(ctx.Config()) 899 } else { 900 // header 901 snapshotMap = vendorSnapshotHeaderLibs(ctx.Config()) 902 } 903 } else if _, ok := module.linker.(*vendorSnapshotBinaryDecorator); ok { 904 snapshotMap = vendorSnapshotBinaries(ctx.Config()) 905 } else if _, ok := module.linker.(*vendorSnapshotObjectLinker); ok { 906 snapshotMap = vendorSnapshotObjects(ctx.Config()) 907 } else { 908 return 909 } 910 911 vendorSnapshotsLock.Lock() 912 defer vendorSnapshotsLock.Unlock() 913 snapshotMap.add(module.BaseModuleName(), ctx.Arch().ArchType, ctx.ModuleName()) 914} 915 916// Disables source modules which have snapshots 917func VendorSnapshotSourceMutator(ctx android.BottomUpMutatorContext) { 918 if !ctx.Device() { 919 return 920 } 921 922 vndkVersion := ctx.DeviceConfig().VndkVersion() 923 // don't need snapshot if current 924 if vndkVersion == "current" || vndkVersion == "" { 925 return 926 } 927 928 module, ok := ctx.Module().(*Module) 929 if !ok { 930 return 931 } 932 933 // vendor suffix should be added to snapshots if the source module isn't vendor: true. 934 if !module.SocSpecific() { 935 // But we can't just check SocSpecific() since we already passed the image mutator. 936 // Check ramdisk and recovery to see if we are real "vendor: true" module. 937 ramdisk_available := module.InRamdisk() && !module.OnlyInRamdisk() 938 recovery_available := module.InRecovery() && !module.OnlyInRecovery() 939 940 if !ramdisk_available && !recovery_available { 941 vendorSnapshotsLock.Lock() 942 defer vendorSnapshotsLock.Unlock() 943 944 vendorSuffixModules(ctx.Config())[ctx.ModuleName()] = true 945 } 946 } 947 948 if module.isSnapshotPrebuilt() || module.VndkVersion() != ctx.DeviceConfig().VndkVersion() { 949 // only non-snapshot modules with BOARD_VNDK_VERSION 950 return 951 } 952 953 // .. and also filter out llndk library 954 if module.isLlndk(ctx.Config()) { 955 return 956 } 957 958 var snapshotMap *snapshotMap 959 960 if lib, ok := module.linker.(libraryInterface); ok { 961 if lib.static() { 962 snapshotMap = vendorSnapshotStaticLibs(ctx.Config()) 963 } else if lib.shared() { 964 snapshotMap = vendorSnapshotSharedLibs(ctx.Config()) 965 } else { 966 // header 967 snapshotMap = vendorSnapshotHeaderLibs(ctx.Config()) 968 } 969 } else if module.binary() { 970 snapshotMap = vendorSnapshotBinaries(ctx.Config()) 971 } else if module.object() { 972 snapshotMap = vendorSnapshotObjects(ctx.Config()) 973 } else { 974 return 975 } 976 977 if _, ok := snapshotMap.get(ctx.ModuleName(), ctx.Arch().ArchType); !ok { 978 // Corresponding snapshot doesn't exist 979 return 980 } 981 982 // Disables source modules if corresponding snapshot exists. 983 if lib, ok := module.linker.(libraryInterface); ok && lib.buildStatic() && lib.buildShared() { 984 // But do not disable because the shared variant depends on the static variant. 985 module.SkipInstall() 986 module.Properties.HideFromMake = true 987 } else { 988 module.Disable() 989 } 990} 991