1// Copyright 2017 Google Inc. All rights reserved. 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 cc 16 17import ( 18 "encoding/json" 19 "errors" 20 "fmt" 21 "path/filepath" 22 "sort" 23 "strings" 24 "sync" 25 26 "android/soong/android" 27 "android/soong/cc/config" 28 "android/soong/etc" 29) 30 31const ( 32 llndkLibrariesTxt = "llndk.libraries.txt" 33 vndkCoreLibrariesTxt = "vndkcore.libraries.txt" 34 vndkSpLibrariesTxt = "vndksp.libraries.txt" 35 vndkPrivateLibrariesTxt = "vndkprivate.libraries.txt" 36 vndkUsingCoreVariantLibrariesTxt = "vndkcorevariant.libraries.txt" 37) 38 39func VndkLibrariesTxtModules(vndkVersion string) []string { 40 if vndkVersion == "current" { 41 return []string{ 42 llndkLibrariesTxt, 43 vndkCoreLibrariesTxt, 44 vndkSpLibrariesTxt, 45 vndkPrivateLibrariesTxt, 46 } 47 } 48 // Snapshot vndks have their own *.libraries.VER.txt files. 49 // Note that snapshots don't have "vndkcorevariant.libraries.VER.txt" 50 return []string{ 51 insertVndkVersion(llndkLibrariesTxt, vndkVersion), 52 insertVndkVersion(vndkCoreLibrariesTxt, vndkVersion), 53 insertVndkVersion(vndkSpLibrariesTxt, vndkVersion), 54 insertVndkVersion(vndkPrivateLibrariesTxt, vndkVersion), 55 } 56} 57 58type VndkProperties struct { 59 Vndk struct { 60 // declared as a VNDK or VNDK-SP module. The vendor variant 61 // will be installed in /system instead of /vendor partition. 62 // 63 // `vendor_available` must be explicitly set to either true or 64 // false together with `vndk: {enabled: true}`. 65 Enabled *bool 66 67 // declared as a VNDK-SP module, which is a subset of VNDK. 68 // 69 // `vndk: { enabled: true }` must set together. 70 // 71 // All these modules are allowed to link to VNDK-SP or LL-NDK 72 // modules only. Other dependency will cause link-type errors. 73 // 74 // If `support_system_process` is not set or set to false, 75 // the module is VNDK-core and can link to other VNDK-core, 76 // VNDK-SP or LL-NDK modules only. 77 Support_system_process *bool 78 79 // Extending another module 80 Extends *string 81 } 82} 83 84type vndkdep struct { 85 Properties VndkProperties 86} 87 88func (vndk *vndkdep) props() []interface{} { 89 return []interface{}{&vndk.Properties} 90} 91 92func (vndk *vndkdep) begin(ctx BaseModuleContext) {} 93 94func (vndk *vndkdep) deps(ctx BaseModuleContext, deps Deps) Deps { 95 return deps 96} 97 98func (vndk *vndkdep) isVndk() bool { 99 return Bool(vndk.Properties.Vndk.Enabled) 100} 101 102func (vndk *vndkdep) isVndkSp() bool { 103 return Bool(vndk.Properties.Vndk.Support_system_process) 104} 105 106func (vndk *vndkdep) isVndkExt() bool { 107 return vndk.Properties.Vndk.Extends != nil 108} 109 110func (vndk *vndkdep) getVndkExtendsModuleName() string { 111 return String(vndk.Properties.Vndk.Extends) 112} 113 114func (vndk *vndkdep) typeName() string { 115 if !vndk.isVndk() { 116 return "native:vendor" 117 } 118 if !vndk.isVndkExt() { 119 if !vndk.isVndkSp() { 120 return "native:vendor:vndk" 121 } 122 return "native:vendor:vndksp" 123 } 124 if !vndk.isVndkSp() { 125 return "native:vendor:vndkext" 126 } 127 return "native:vendor:vndkspext" 128} 129 130func (vndk *vndkdep) vndkCheckLinkType(ctx android.ModuleContext, to *Module, tag DependencyTag) { 131 if to.linker == nil { 132 return 133 } 134 if !vndk.isVndk() { 135 // Non-VNDK modules (those installed to /vendor, /product, or /system/product) can't depend 136 // on modules marked with vendor_available: false. 137 violation := false 138 if lib, ok := to.linker.(*llndkStubDecorator); ok && !Bool(lib.Properties.Vendor_available) { 139 violation = true 140 } else { 141 if _, ok := to.linker.(libraryInterface); ok && to.VendorProperties.Vendor_available != nil && !Bool(to.VendorProperties.Vendor_available) { 142 // Vendor_available == nil && !Bool(Vendor_available) should be okay since 143 // it means a vendor-only, or product-only library which is a valid dependency 144 // for non-VNDK modules. 145 violation = true 146 } 147 } 148 if violation { 149 ctx.ModuleErrorf("Vendor module that is not VNDK should not link to %q which is marked as `vendor_available: false`", to.Name()) 150 } 151 } 152 if lib, ok := to.linker.(*libraryDecorator); !ok || !lib.shared() { 153 // Check only shared libraries. 154 // Other (static and LL-NDK) libraries are allowed to link. 155 return 156 } 157 if !to.UseVndk() { 158 ctx.ModuleErrorf("(%s) should not link to %q which is not a vendor-available library", 159 vndk.typeName(), to.Name()) 160 return 161 } 162 if tag == vndkExtDepTag { 163 // Ensure `extends: "name"` property refers a vndk module that has vendor_available 164 // and has identical vndk properties. 165 if to.vndkdep == nil || !to.vndkdep.isVndk() { 166 ctx.ModuleErrorf("`extends` refers a non-vndk module %q", to.Name()) 167 return 168 } 169 if vndk.isVndkSp() != to.vndkdep.isVndkSp() { 170 ctx.ModuleErrorf( 171 "`extends` refers a module %q with mismatched support_system_process", 172 to.Name()) 173 return 174 } 175 if !Bool(to.VendorProperties.Vendor_available) { 176 ctx.ModuleErrorf( 177 "`extends` refers module %q which does not have `vendor_available: true`", 178 to.Name()) 179 return 180 } 181 } 182 if to.vndkdep == nil { 183 return 184 } 185 186 // Check the dependencies of VNDK shared libraries. 187 if err := vndkIsVndkDepAllowed(vndk, to.vndkdep); err != nil { 188 ctx.ModuleErrorf("(%s) should not link to %q (%s): %v", 189 vndk.typeName(), to.Name(), to.vndkdep.typeName(), err) 190 return 191 } 192} 193 194func vndkIsVndkDepAllowed(from *vndkdep, to *vndkdep) error { 195 // Check the dependencies of VNDK, VNDK-Ext, VNDK-SP, VNDK-SP-Ext and vendor modules. 196 if from.isVndkExt() { 197 if from.isVndkSp() { 198 if to.isVndk() && !to.isVndkSp() { 199 return errors.New("VNDK-SP extensions must not depend on VNDK or VNDK extensions") 200 } 201 return nil 202 } 203 // VNDK-Ext may depend on VNDK, VNDK-Ext, VNDK-SP, VNDK-SP-Ext, or vendor libs. 204 return nil 205 } 206 if from.isVndk() { 207 if to.isVndkExt() { 208 return errors.New("VNDK-core and VNDK-SP must not depend on VNDK extensions") 209 } 210 if from.isVndkSp() { 211 if !to.isVndkSp() { 212 return errors.New("VNDK-SP must only depend on VNDK-SP") 213 } 214 return nil 215 } 216 if !to.isVndk() { 217 return errors.New("VNDK-core must only depend on VNDK-core or VNDK-SP") 218 } 219 return nil 220 } 221 // Vendor modules may depend on VNDK, VNDK-Ext, VNDK-SP, VNDK-SP-Ext, or vendor libs. 222 return nil 223} 224 225var ( 226 vndkCoreLibrariesKey = android.NewOnceKey("vndkCoreLibrarires") 227 vndkSpLibrariesKey = android.NewOnceKey("vndkSpLibrarires") 228 llndkLibrariesKey = android.NewOnceKey("llndkLibrarires") 229 vndkPrivateLibrariesKey = android.NewOnceKey("vndkPrivateLibrarires") 230 vndkUsingCoreVariantLibrariesKey = android.NewOnceKey("vndkUsingCoreVariantLibraries") 231 vndkMustUseVendorVariantListKey = android.NewOnceKey("vndkMustUseVendorVariantListKey") 232 vndkLibrariesLock sync.Mutex 233) 234 235func vndkCoreLibraries(config android.Config) map[string]string { 236 return config.Once(vndkCoreLibrariesKey, func() interface{} { 237 return make(map[string]string) 238 }).(map[string]string) 239} 240 241func vndkSpLibraries(config android.Config) map[string]string { 242 return config.Once(vndkSpLibrariesKey, func() interface{} { 243 return make(map[string]string) 244 }).(map[string]string) 245} 246 247func isLlndkLibrary(baseModuleName string, config android.Config) bool { 248 _, ok := llndkLibraries(config)[baseModuleName] 249 return ok 250} 251 252func llndkLibraries(config android.Config) map[string]string { 253 return config.Once(llndkLibrariesKey, func() interface{} { 254 return make(map[string]string) 255 }).(map[string]string) 256} 257 258func isVndkPrivateLibrary(baseModuleName string, config android.Config) bool { 259 _, ok := vndkPrivateLibraries(config)[baseModuleName] 260 return ok 261} 262 263func vndkPrivateLibraries(config android.Config) map[string]string { 264 return config.Once(vndkPrivateLibrariesKey, func() interface{} { 265 return make(map[string]string) 266 }).(map[string]string) 267} 268 269func vndkUsingCoreVariantLibraries(config android.Config) map[string]string { 270 return config.Once(vndkUsingCoreVariantLibrariesKey, func() interface{} { 271 return make(map[string]string) 272 }).(map[string]string) 273} 274 275func vndkMustUseVendorVariantList(cfg android.Config) []string { 276 return cfg.Once(vndkMustUseVendorVariantListKey, func() interface{} { 277 return config.VndkMustUseVendorVariantList 278 }).([]string) 279} 280 281// test may call this to override global configuration(config.VndkMustUseVendorVariantList) 282// when it is called, it must be before the first call to vndkMustUseVendorVariantList() 283func setVndkMustUseVendorVariantListForTest(config android.Config, mustUseVendorVariantList []string) { 284 config.Once(vndkMustUseVendorVariantListKey, func() interface{} { 285 return mustUseVendorVariantList 286 }) 287} 288 289func processLlndkLibrary(mctx android.BottomUpMutatorContext, m *Module) { 290 lib := m.linker.(*llndkStubDecorator) 291 name := m.BaseModuleName() 292 filename := m.BaseModuleName() + ".so" 293 294 vndkLibrariesLock.Lock() 295 defer vndkLibrariesLock.Unlock() 296 297 llndkLibraries(mctx.Config())[name] = filename 298 if !Bool(lib.Properties.Vendor_available) { 299 vndkPrivateLibraries(mctx.Config())[name] = filename 300 } 301 if mctx.OtherModuleExists(name) { 302 mctx.AddFarVariationDependencies(m.Target().Variations(), llndkImplDep, name) 303 } 304} 305 306func processVndkLibrary(mctx android.BottomUpMutatorContext, m *Module) { 307 name := m.BaseModuleName() 308 filename, err := getVndkFileName(m) 309 if err != nil { 310 panic(err) 311 } 312 313 if m.HasStubsVariants() && name != "libz" { 314 // b/155456180 libz is the ONLY exception here. We don't want to make 315 // libz an LLNDK library because we in general can't guarantee that 316 // libz will behave consistently especially about the compression. 317 // i.e. the compressed output might be different across releases. 318 // As the library is an external one, it's risky to keep the compatibility 319 // promise if it becomes an LLNDK. 320 mctx.PropertyErrorf("vndk.enabled", "This library provides stubs. Shouldn't be VNDK. Consider making it as LLNDK") 321 } 322 323 vndkLibrariesLock.Lock() 324 defer vndkLibrariesLock.Unlock() 325 326 if inList(name, vndkMustUseVendorVariantList(mctx.Config())) { 327 m.Properties.MustUseVendorVariant = true 328 } 329 if mctx.DeviceConfig().VndkUseCoreVariant() && !m.Properties.MustUseVendorVariant { 330 vndkUsingCoreVariantLibraries(mctx.Config())[name] = filename 331 } 332 333 if m.vndkdep.isVndkSp() { 334 vndkSpLibraries(mctx.Config())[name] = filename 335 } else { 336 vndkCoreLibraries(mctx.Config())[name] = filename 337 } 338 if !Bool(m.VendorProperties.Vendor_available) { 339 vndkPrivateLibraries(mctx.Config())[name] = filename 340 } 341} 342 343// Check for modules that mustn't be VNDK 344func shouldSkipVndkMutator(m *Module) bool { 345 if !m.Enabled() { 346 return true 347 } 348 if !m.Device() { 349 // Skip non-device modules 350 return true 351 } 352 if m.Target().NativeBridge == android.NativeBridgeEnabled { 353 // Skip native_bridge modules 354 return true 355 } 356 return false 357} 358 359func IsForVndkApex(mctx android.BottomUpMutatorContext, m *Module) bool { 360 if shouldSkipVndkMutator(m) { 361 return false 362 } 363 364 // prebuilt vndk modules should match with device 365 // TODO(b/142675459): Use enabled: to select target device in vndk_prebuilt_shared 366 // When b/142675459 is landed, remove following check 367 if p, ok := m.linker.(*vndkPrebuiltLibraryDecorator); ok && !p.matchesWithDevice(mctx.DeviceConfig()) { 368 return false 369 } 370 371 if lib, ok := m.linker.(libraryInterface); ok { 372 // VNDK APEX for VNDK-Lite devices will have VNDK-SP libraries from core variants 373 if mctx.DeviceConfig().VndkVersion() == "" { 374 // b/73296261: filter out libz.so because it is considered as LLNDK for VNDK-lite devices 375 if mctx.ModuleName() == "libz" { 376 return false 377 } 378 return m.ImageVariation().Variation == android.CoreVariation && lib.shared() && m.isVndkSp() 379 } 380 381 useCoreVariant := m.VndkVersion() == mctx.DeviceConfig().PlatformVndkVersion() && 382 mctx.DeviceConfig().VndkUseCoreVariant() && !m.MustUseVendorVariant() 383 return lib.shared() && m.inVendor() && m.IsVndk() && !m.isVndkExt() && !useCoreVariant 384 } 385 return false 386} 387 388// gather list of vndk-core, vndk-sp, and ll-ndk libs 389func VndkMutator(mctx android.BottomUpMutatorContext) { 390 m, ok := mctx.Module().(*Module) 391 if !ok { 392 return 393 } 394 395 if shouldSkipVndkMutator(m) { 396 return 397 } 398 399 if _, ok := m.linker.(*llndkStubDecorator); ok { 400 processLlndkLibrary(mctx, m) 401 return 402 } 403 404 lib, is_lib := m.linker.(*libraryDecorator) 405 prebuilt_lib, is_prebuilt_lib := m.linker.(*prebuiltLibraryLinker) 406 407 if (is_lib && lib.buildShared()) || (is_prebuilt_lib && prebuilt_lib.buildShared()) { 408 if m.vndkdep != nil && m.vndkdep.isVndk() && !m.vndkdep.isVndkExt() { 409 processVndkLibrary(mctx, m) 410 return 411 } 412 } 413} 414 415func init() { 416 android.RegisterModuleType("vndk_libraries_txt", VndkLibrariesTxtFactory) 417 android.RegisterSingletonType("vndk-snapshot", VndkSnapshotSingleton) 418} 419 420type vndkLibrariesTxt struct { 421 android.ModuleBase 422 outputFile android.OutputPath 423} 424 425var _ etc.PrebuiltEtcModule = &vndkLibrariesTxt{} 426var _ android.OutputFileProducer = &vndkLibrariesTxt{} 427 428// vndk_libraries_txt is a special kind of module type in that it name is one of 429// - llndk.libraries.txt 430// - vndkcore.libraries.txt 431// - vndksp.libraries.txt 432// - vndkprivate.libraries.txt 433// - vndkcorevariant.libraries.txt 434// A module behaves like a prebuilt_etc but its content is generated by soong. 435// By being a soong module, these files can be referenced by other soong modules. 436// For example, apex_vndk can depend on these files as prebuilt. 437func VndkLibrariesTxtFactory() android.Module { 438 m := &vndkLibrariesTxt{} 439 android.InitAndroidModule(m) 440 return m 441} 442 443func insertVndkVersion(filename string, vndkVersion string) string { 444 if index := strings.LastIndex(filename, "."); index != -1 { 445 return filename[:index] + "." + vndkVersion + filename[index:] 446 } 447 return filename 448} 449 450func (txt *vndkLibrariesTxt) GenerateAndroidBuildActions(ctx android.ModuleContext) { 451 var list []string 452 switch txt.Name() { 453 case llndkLibrariesTxt: 454 for _, filename := range android.SortedStringMapValues(llndkLibraries(ctx.Config())) { 455 if strings.HasPrefix(filename, "libclang_rt.hwasan-") { 456 continue 457 } 458 list = append(list, filename) 459 } 460 case vndkCoreLibrariesTxt: 461 list = android.SortedStringMapValues(vndkCoreLibraries(ctx.Config())) 462 case vndkSpLibrariesTxt: 463 list = android.SortedStringMapValues(vndkSpLibraries(ctx.Config())) 464 case vndkPrivateLibrariesTxt: 465 list = android.SortedStringMapValues(vndkPrivateLibraries(ctx.Config())) 466 case vndkUsingCoreVariantLibrariesTxt: 467 list = android.SortedStringMapValues(vndkUsingCoreVariantLibraries(ctx.Config())) 468 default: 469 ctx.ModuleErrorf("name(%s) is unknown.", txt.Name()) 470 return 471 } 472 473 var filename string 474 if txt.Name() != vndkUsingCoreVariantLibrariesTxt { 475 filename = insertVndkVersion(txt.Name(), ctx.DeviceConfig().PlatformVndkVersion()) 476 } else { 477 filename = txt.Name() 478 } 479 480 txt.outputFile = android.PathForModuleOut(ctx, filename).OutputPath 481 ctx.Build(pctx, android.BuildParams{ 482 Rule: android.WriteFile, 483 Output: txt.outputFile, 484 Description: "Writing " + txt.outputFile.String(), 485 Args: map[string]string{ 486 "content": strings.Join(list, "\\n"), 487 }, 488 }) 489 490 installPath := android.PathForModuleInstall(ctx, "etc") 491 ctx.InstallFile(installPath, filename, txt.outputFile) 492} 493 494func (txt *vndkLibrariesTxt) AndroidMkEntries() []android.AndroidMkEntries { 495 return []android.AndroidMkEntries{android.AndroidMkEntries{ 496 Class: "ETC", 497 OutputFile: android.OptionalPathForPath(txt.outputFile), 498 ExtraEntries: []android.AndroidMkExtraEntriesFunc{ 499 func(entries *android.AndroidMkEntries) { 500 entries.SetString("LOCAL_MODULE_STEM", txt.outputFile.Base()) 501 }, 502 }, 503 }} 504} 505 506func (txt *vndkLibrariesTxt) OutputFile() android.OutputPath { 507 return txt.outputFile 508} 509 510func (txt *vndkLibrariesTxt) OutputFiles(tag string) (android.Paths, error) { 511 return android.Paths{txt.outputFile}, nil 512} 513 514func (txt *vndkLibrariesTxt) SubDir() string { 515 return "" 516} 517 518func VndkSnapshotSingleton() android.Singleton { 519 return &vndkSnapshotSingleton{} 520} 521 522type vndkSnapshotSingleton struct { 523 vndkLibrariesFile android.OutputPath 524 vndkSnapshotZipFile android.OptionalPath 525} 526 527func isVndkSnapshotLibrary(config android.DeviceConfig, m *Module) (i snapshotLibraryInterface, vndkType string, isVndkSnapshotLib bool) { 528 if m.Target().NativeBridge == android.NativeBridgeEnabled { 529 return nil, "", false 530 } 531 if !m.inVendor() || !m.installable() || m.isSnapshotPrebuilt() { 532 return nil, "", false 533 } 534 l, ok := m.linker.(snapshotLibraryInterface) 535 if !ok || !l.shared() { 536 return nil, "", false 537 } 538 if m.VndkVersion() == config.PlatformVndkVersion() && m.IsVndk() && !m.isVndkExt() { 539 if m.isVndkSp() { 540 return l, "vndk-sp", true 541 } else { 542 return l, "vndk-core", true 543 } 544 } 545 546 return nil, "", false 547} 548 549func (c *vndkSnapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) { 550 // build these files even if PlatformVndkVersion or BoardVndkVersion is not set 551 c.buildVndkLibrariesTxtFiles(ctx) 552 553 // BOARD_VNDK_VERSION must be set to 'current' in order to generate a VNDK snapshot. 554 if ctx.DeviceConfig().VndkVersion() != "current" { 555 return 556 } 557 558 if ctx.DeviceConfig().PlatformVndkVersion() == "" { 559 return 560 } 561 562 var snapshotOutputs android.Paths 563 564 /* 565 VNDK snapshot zipped artifacts directory structure: 566 {SNAPSHOT_ARCH}/ 567 arch-{TARGET_ARCH}-{TARGET_ARCH_VARIANT}/ 568 shared/ 569 vndk-core/ 570 (VNDK-core libraries, e.g. libbinder.so) 571 vndk-sp/ 572 (VNDK-SP libraries, e.g. libc++.so) 573 arch-{TARGET_2ND_ARCH}-{TARGET_2ND_ARCH_VARIANT}/ 574 shared/ 575 vndk-core/ 576 (VNDK-core libraries, e.g. libbinder.so) 577 vndk-sp/ 578 (VNDK-SP libraries, e.g. libc++.so) 579 binder32/ 580 (This directory is newly introduced in v28 (Android P) to hold 581 prebuilts built for 32-bit binder interface.) 582 arch-{TARGET_ARCH}-{TARGE_ARCH_VARIANT}/ 583 ... 584 configs/ 585 (various *.txt configuration files) 586 include/ 587 (header files of same directory structure with source tree) 588 NOTICE_FILES/ 589 (notice files of libraries, e.g. libcutils.so.txt) 590 */ 591 592 snapshotDir := "vndk-snapshot" 593 snapshotArchDir := filepath.Join(snapshotDir, ctx.DeviceConfig().DeviceArch()) 594 595 configsDir := filepath.Join(snapshotArchDir, "configs") 596 noticeDir := filepath.Join(snapshotArchDir, "NOTICE_FILES") 597 includeDir := filepath.Join(snapshotArchDir, "include") 598 599 // set of notice files copied. 600 noticeBuilt := make(map[string]bool) 601 602 // paths of VNDK modules for GPL license checking 603 modulePaths := make(map[string]string) 604 605 // actual module names of .so files 606 // e.g. moduleNames["libprotobuf-cpp-full-3.9.1.so"] = "libprotobuf-cpp-full" 607 moduleNames := make(map[string]string) 608 609 var headers android.Paths 610 611 installVndkSnapshotLib := func(m *Module, l snapshotLibraryInterface, vndkType string) (android.Paths, bool) { 612 var ret android.Paths 613 614 targetArch := "arch-" + m.Target().Arch.ArchType.String() 615 if m.Target().Arch.ArchVariant != "" { 616 targetArch += "-" + m.Target().Arch.ArchVariant 617 } 618 619 libPath := m.outputFile.Path() 620 snapshotLibOut := filepath.Join(snapshotArchDir, targetArch, "shared", vndkType, libPath.Base()) 621 ret = append(ret, copyFile(ctx, libPath, snapshotLibOut)) 622 623 if ctx.Config().VndkSnapshotBuildArtifacts() { 624 prop := struct { 625 ExportedDirs []string `json:",omitempty"` 626 ExportedSystemDirs []string `json:",omitempty"` 627 ExportedFlags []string `json:",omitempty"` 628 RelativeInstallPath string `json:",omitempty"` 629 }{} 630 prop.ExportedFlags = l.exportedFlags() 631 prop.ExportedDirs = l.exportedDirs().Strings() 632 prop.ExportedSystemDirs = l.exportedSystemDirs().Strings() 633 prop.RelativeInstallPath = m.RelativeInstallPath() 634 635 propOut := snapshotLibOut + ".json" 636 637 j, err := json.Marshal(prop) 638 if err != nil { 639 ctx.Errorf("json marshal to %q failed: %#v", propOut, err) 640 return nil, false 641 } 642 ret = append(ret, writeStringToFile(ctx, string(j), propOut)) 643 } 644 return ret, true 645 } 646 647 ctx.VisitAllModules(func(module android.Module) { 648 m, ok := module.(*Module) 649 if !ok || !m.Enabled() { 650 return 651 } 652 653 l, vndkType, ok := isVndkSnapshotLibrary(ctx.DeviceConfig(), m) 654 if !ok { 655 return 656 } 657 658 // install .so files for appropriate modules. 659 // Also install .json files if VNDK_SNAPSHOT_BUILD_ARTIFACTS 660 libs, ok := installVndkSnapshotLib(m, l, vndkType) 661 if !ok { 662 return 663 } 664 snapshotOutputs = append(snapshotOutputs, libs...) 665 666 // These are for generating module_names.txt and module_paths.txt 667 stem := m.outputFile.Path().Base() 668 moduleNames[stem] = ctx.ModuleName(m) 669 modulePaths[stem] = ctx.ModuleDir(m) 670 671 if len(m.NoticeFiles()) > 0 { 672 noticeName := stem + ".txt" 673 // skip already copied notice file 674 if _, ok := noticeBuilt[noticeName]; !ok { 675 noticeBuilt[noticeName] = true 676 snapshotOutputs = append(snapshotOutputs, combineNotices( 677 ctx, m.NoticeFiles(), filepath.Join(noticeDir, noticeName))) 678 } 679 } 680 681 if ctx.Config().VndkSnapshotBuildArtifacts() { 682 headers = append(headers, l.snapshotHeaders()...) 683 } 684 }) 685 686 // install all headers after removing duplicates 687 for _, header := range android.FirstUniquePaths(headers) { 688 snapshotOutputs = append(snapshotOutputs, copyFile( 689 ctx, header, filepath.Join(includeDir, header.String()))) 690 } 691 692 // install *.libraries.txt except vndkcorevariant.libraries.txt 693 ctx.VisitAllModules(func(module android.Module) { 694 m, ok := module.(*vndkLibrariesTxt) 695 if !ok || !m.Enabled() || m.Name() == vndkUsingCoreVariantLibrariesTxt { 696 return 697 } 698 snapshotOutputs = append(snapshotOutputs, copyFile( 699 ctx, m.OutputFile(), filepath.Join(configsDir, m.Name()))) 700 }) 701 702 /* 703 Dump a map to a list file as: 704 705 {key1} {value1} 706 {key2} {value2} 707 ... 708 */ 709 installMapListFile := func(m map[string]string, path string) android.OutputPath { 710 var txtBuilder strings.Builder 711 for idx, k := range android.SortedStringKeys(m) { 712 if idx > 0 { 713 txtBuilder.WriteString("\\n") 714 } 715 txtBuilder.WriteString(k) 716 txtBuilder.WriteString(" ") 717 txtBuilder.WriteString(m[k]) 718 } 719 return writeStringToFile(ctx, txtBuilder.String(), path) 720 } 721 722 /* 723 module_paths.txt contains paths on which VNDK modules are defined. 724 e.g., 725 libbase.so system/core/base 726 libc.so bionic/libc 727 ... 728 */ 729 snapshotOutputs = append(snapshotOutputs, installMapListFile(modulePaths, filepath.Join(configsDir, "module_paths.txt"))) 730 731 /* 732 module_names.txt contains names as which VNDK modules are defined, 733 because output filename and module name can be different with stem and suffix properties. 734 735 e.g., 736 libcutils.so libcutils 737 libprotobuf-cpp-full-3.9.2.so libprotobuf-cpp-full 738 ... 739 */ 740 snapshotOutputs = append(snapshotOutputs, installMapListFile(moduleNames, filepath.Join(configsDir, "module_names.txt"))) 741 742 // All artifacts are ready. Sort them to normalize ninja and then zip. 743 sort.Slice(snapshotOutputs, func(i, j int) bool { 744 return snapshotOutputs[i].String() < snapshotOutputs[j].String() 745 }) 746 747 zipPath := android.PathForOutput(ctx, snapshotDir, "android-vndk-"+ctx.DeviceConfig().DeviceArch()+".zip") 748 zipRule := android.NewRuleBuilder() 749 750 // filenames in rspfile from FlagWithRspFileInputList might be single-quoted. Remove it with xargs 751 snapshotOutputList := android.PathForOutput(ctx, snapshotDir, "android-vndk-"+ctx.DeviceConfig().DeviceArch()+"_list") 752 zipRule.Command(). 753 Text("tr"). 754 FlagWithArg("-d ", "\\'"). 755 FlagWithRspFileInputList("< ", snapshotOutputs). 756 FlagWithOutput("> ", snapshotOutputList) 757 758 zipRule.Temporary(snapshotOutputList) 759 760 zipRule.Command(). 761 BuiltTool(ctx, "soong_zip"). 762 FlagWithOutput("-o ", zipPath). 763 FlagWithArg("-C ", android.PathForOutput(ctx, snapshotDir).String()). 764 FlagWithInput("-l ", snapshotOutputList) 765 766 zipRule.Build(pctx, ctx, zipPath.String(), "vndk snapshot "+zipPath.String()) 767 zipRule.DeleteTemporaryFiles() 768 c.vndkSnapshotZipFile = android.OptionalPathForPath(zipPath) 769} 770 771func getVndkFileName(m *Module) (string, error) { 772 if library, ok := m.linker.(*libraryDecorator); ok { 773 return library.getLibNameHelper(m.BaseModuleName(), true) + ".so", nil 774 } 775 if prebuilt, ok := m.linker.(*prebuiltLibraryLinker); ok { 776 return prebuilt.libraryDecorator.getLibNameHelper(m.BaseModuleName(), true) + ".so", nil 777 } 778 return "", fmt.Errorf("VNDK library should have libraryDecorator or prebuiltLibraryLinker as linker: %T", m.linker) 779} 780 781func (c *vndkSnapshotSingleton) buildVndkLibrariesTxtFiles(ctx android.SingletonContext) { 782 llndk := android.SortedStringMapValues(llndkLibraries(ctx.Config())) 783 vndkcore := android.SortedStringMapValues(vndkCoreLibraries(ctx.Config())) 784 vndksp := android.SortedStringMapValues(vndkSpLibraries(ctx.Config())) 785 vndkprivate := android.SortedStringMapValues(vndkPrivateLibraries(ctx.Config())) 786 787 // Build list of vndk libs as merged & tagged & filter-out(libclang_rt): 788 // Since each target have different set of libclang_rt.* files, 789 // keep the common set of files in vndk.libraries.txt 790 var merged []string 791 filterOutLibClangRt := func(libList []string) (filtered []string) { 792 for _, lib := range libList { 793 if !strings.HasPrefix(lib, "libclang_rt.") { 794 filtered = append(filtered, lib) 795 } 796 } 797 return 798 } 799 merged = append(merged, addPrefix(filterOutLibClangRt(llndk), "LLNDK: ")...) 800 merged = append(merged, addPrefix(vndksp, "VNDK-SP: ")...) 801 merged = append(merged, addPrefix(filterOutLibClangRt(vndkcore), "VNDK-core: ")...) 802 merged = append(merged, addPrefix(vndkprivate, "VNDK-private: ")...) 803 c.vndkLibrariesFile = android.PathForOutput(ctx, "vndk", "vndk.libraries.txt") 804 ctx.Build(pctx, android.BuildParams{ 805 Rule: android.WriteFile, 806 Output: c.vndkLibrariesFile, 807 Description: "Writing " + c.vndkLibrariesFile.String(), 808 Args: map[string]string{ 809 "content": strings.Join(merged, "\\n"), 810 }, 811 }) 812} 813 814func (c *vndkSnapshotSingleton) MakeVars(ctx android.MakeVarsContext) { 815 // Make uses LLNDK_MOVED_TO_APEX_LIBRARIES to avoid installing libraries on /system if 816 // they been moved to an apex. 817 movedToApexLlndkLibraries := []string{} 818 for lib := range llndkLibraries(ctx.Config()) { 819 // Skip bionic libs, they are handled in different manner 820 if android.DirectlyInAnyApex(¬OnHostContext{}, lib) && !isBionic(lib) { 821 movedToApexLlndkLibraries = append(movedToApexLlndkLibraries, lib) 822 } 823 } 824 ctx.Strict("LLNDK_MOVED_TO_APEX_LIBRARIES", strings.Join(movedToApexLlndkLibraries, " ")) 825 826 // Make uses LLNDK_LIBRARIES to determine which libraries to install. 827 // HWASAN is only part of the LL-NDK in builds in which libc depends on HWASAN. 828 // Therefore, by removing the library here, we cause it to only be installed if libc 829 // depends on it. 830 installedLlndkLibraries := []string{} 831 for lib := range llndkLibraries(ctx.Config()) { 832 if strings.HasPrefix(lib, "libclang_rt.hwasan-") { 833 continue 834 } 835 installedLlndkLibraries = append(installedLlndkLibraries, lib) 836 } 837 sort.Strings(installedLlndkLibraries) 838 ctx.Strict("LLNDK_LIBRARIES", strings.Join(installedLlndkLibraries, " ")) 839 840 ctx.Strict("VNDK_CORE_LIBRARIES", strings.Join(android.SortedStringKeys(vndkCoreLibraries(ctx.Config())), " ")) 841 ctx.Strict("VNDK_SAMEPROCESS_LIBRARIES", strings.Join(android.SortedStringKeys(vndkSpLibraries(ctx.Config())), " ")) 842 ctx.Strict("VNDK_PRIVATE_LIBRARIES", strings.Join(android.SortedStringKeys(vndkPrivateLibraries(ctx.Config())), " ")) 843 ctx.Strict("VNDK_USING_CORE_VARIANT_LIBRARIES", strings.Join(android.SortedStringKeys(vndkUsingCoreVariantLibraries(ctx.Config())), " ")) 844 845 ctx.Strict("VNDK_LIBRARIES_FILE", c.vndkLibrariesFile.String()) 846 ctx.Strict("SOONG_VNDK_SNAPSHOT_ZIP", c.vndkSnapshotZipFile.String()) 847} 848