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