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) { 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 372 useCoreVariant := m.VndkVersion() == mctx.DeviceConfig().PlatformVndkVersion() && 373 mctx.DeviceConfig().VndkUseCoreVariant() && !m.MustUseVendorVariant() 374 return lib.shared() && m.InVendor() && m.IsVndk() && !m.IsVndkExt() && !useCoreVariant 375 } 376 return false 377} 378 379// gather list of vndk-core, vndk-sp, and ll-ndk libs 380func VndkMutator(mctx android.BottomUpMutatorContext) { 381 m, ok := mctx.Module().(*Module) 382 if !ok { 383 return 384 } 385 386 if shouldSkipVndkMutator(m) { 387 return 388 } 389 390 lib, isLib := m.linker.(*libraryDecorator) 391 prebuiltLib, isPrebuiltLib := m.linker.(*prebuiltLibraryLinker) 392 393 if m.UseVndk() && isLib && lib.hasLLNDKStubs() { 394 m.VendorProperties.IsLLNDK = true 395 m.VendorProperties.IsVNDKPrivate = Bool(lib.Properties.Llndk.Private) 396 } 397 if m.UseVndk() && isPrebuiltLib && prebuiltLib.hasLLNDKStubs() { 398 m.VendorProperties.IsLLNDK = true 399 m.VendorProperties.IsVNDKPrivate = Bool(prebuiltLib.Properties.Llndk.Private) 400 } 401 402 if (isLib && lib.buildShared()) || (isPrebuiltLib && prebuiltLib.buildShared()) { 403 if m.vndkdep != nil && m.vndkdep.isVndk() && !m.vndkdep.isVndkExt() { 404 processVndkLibrary(mctx, m) 405 return 406 } 407 } 408} 409 410func init() { 411 RegisterVndkLibraryTxtTypes(android.InitRegistrationContext) 412 android.RegisterSingletonType("vndk-snapshot", VndkSnapshotSingleton) 413} 414 415func RegisterVndkLibraryTxtTypes(ctx android.RegistrationContext) { 416 ctx.RegisterSingletonModuleType("llndk_libraries_txt", llndkLibrariesTxtFactory) 417 ctx.RegisterSingletonModuleType("vndksp_libraries_txt", vndkSPLibrariesTxtFactory) 418 ctx.RegisterSingletonModuleType("vndkcore_libraries_txt", vndkCoreLibrariesTxtFactory) 419 ctx.RegisterSingletonModuleType("vndkprivate_libraries_txt", vndkPrivateLibrariesTxtFactory) 420 ctx.RegisterSingletonModuleType("vndkproduct_libraries_txt", vndkProductLibrariesTxtFactory) 421 ctx.RegisterSingletonModuleType("vndkcorevariant_libraries_txt", vndkUsingCoreVariantLibrariesTxtFactory) 422} 423 424type vndkLibrariesTxt struct { 425 android.SingletonModuleBase 426 427 lister moduleListerFunc 428 makeVarName string 429 filterOutFromMakeVar string 430 431 properties VndkLibrariesTxtProperties 432 433 outputFile android.OutputPath 434 moduleNames []string 435 fileNames []string 436} 437 438type VndkLibrariesTxtProperties struct { 439 Insert_vndk_version *bool 440} 441 442var _ etc.PrebuiltEtcModule = &vndkLibrariesTxt{} 443var _ android.OutputFileProducer = &vndkLibrariesTxt{} 444 445// llndk_libraries_txt is a singleton module whose content is a list of LLNDK libraries 446// generated by Soong but can be referenced by other modules. 447// For example, apex_vndk can depend on these files as prebuilt. 448// Make uses LLNDK_LIBRARIES to determine which libraries to install. 449// HWASAN is only part of the LL-NDK in builds in which libc depends on HWASAN. 450// Therefore, by removing the library here, we cause it to only be installed if libc 451// depends on it. 452func llndkLibrariesTxtFactory() android.SingletonModule { 453 return newVndkLibrariesWithMakeVarFilter(llndkLibraries, "LLNDK_LIBRARIES", "libclang_rt.hwasan") 454} 455 456// vndksp_libraries_txt is a singleton module whose content is a list of VNDKSP libraries 457// generated by Soong but can be referenced by other modules. 458// For example, apex_vndk can depend on these files as prebuilt. 459func vndkSPLibrariesTxtFactory() android.SingletonModule { 460 return newVndkLibrariesTxt(vndkSPLibraries, "VNDK_SAMEPROCESS_LIBRARIES") 461} 462 463// vndkcore_libraries_txt is a singleton module whose content is a list of VNDK core libraries 464// generated by Soong but can be referenced by other modules. 465// For example, apex_vndk can depend on these files as prebuilt. 466func vndkCoreLibrariesTxtFactory() android.SingletonModule { 467 return newVndkLibrariesTxt(vndkCoreLibraries, "VNDK_CORE_LIBRARIES") 468} 469 470// vndkprivate_libraries_txt is a singleton module whose content is a list of VNDK private libraries 471// generated by Soong but can be referenced by other modules. 472// For example, apex_vndk can depend on these files as prebuilt. 473func vndkPrivateLibrariesTxtFactory() android.SingletonModule { 474 return newVndkLibrariesTxt(vndkPrivateLibraries, "VNDK_PRIVATE_LIBRARIES") 475} 476 477// vndkproduct_libraries_txt is a singleton module whose content is a list of VNDK product libraries 478// generated by Soong but can be referenced by other modules. 479// For example, apex_vndk can depend on these files as prebuilt. 480func vndkProductLibrariesTxtFactory() android.SingletonModule { 481 return newVndkLibrariesTxt(vndkProductLibraries, "VNDK_PRODUCT_LIBRARIES") 482} 483 484// vndkcorevariant_libraries_txt is a singleton module whose content is a list of VNDK libraries 485// that are using the core variant, generated by Soong but can be referenced by other modules. 486// For example, apex_vndk can depend on these files as prebuilt. 487func vndkUsingCoreVariantLibrariesTxtFactory() android.SingletonModule { 488 return newVndkLibrariesTxt(vndkUsingCoreVariantLibraries, "VNDK_USING_CORE_VARIANT_LIBRARIES") 489} 490 491func newVndkLibrariesWithMakeVarFilter(lister moduleListerFunc, makeVarName string, filter string) android.SingletonModule { 492 m := &vndkLibrariesTxt{ 493 lister: lister, 494 makeVarName: makeVarName, 495 filterOutFromMakeVar: filter, 496 } 497 m.AddProperties(&m.properties) 498 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon) 499 return m 500} 501 502func newVndkLibrariesTxt(lister moduleListerFunc, makeVarName string) android.SingletonModule { 503 return newVndkLibrariesWithMakeVarFilter(lister, makeVarName, "") 504} 505 506func insertVndkVersion(filename string, vndkVersion string) string { 507 if index := strings.LastIndex(filename, "."); index != -1 { 508 return filename[:index] + "." + vndkVersion + filename[index:] 509 } 510 return filename 511} 512 513func (txt *vndkLibrariesTxt) GenerateAndroidBuildActions(ctx android.ModuleContext) { 514 var filename string 515 if BoolDefault(txt.properties.Insert_vndk_version, true) { 516 filename = insertVndkVersion(txt.Name(), ctx.DeviceConfig().PlatformVndkVersion()) 517 } else { 518 filename = txt.Name() 519 } 520 521 txt.outputFile = android.PathForModuleOut(ctx, filename).OutputPath 522 523 installPath := android.PathForModuleInstall(ctx, "etc") 524 ctx.InstallFile(installPath, filename, txt.outputFile) 525} 526 527func (txt *vndkLibrariesTxt) GenerateSingletonBuildActions(ctx android.SingletonContext) { 528 txt.moduleNames, txt.fileNames = txt.lister(ctx) 529 android.WriteFileRule(ctx, txt.outputFile, strings.Join(txt.fileNames, "\n")) 530} 531 532func (txt *vndkLibrariesTxt) AndroidMkEntries() []android.AndroidMkEntries { 533 return []android.AndroidMkEntries{android.AndroidMkEntries{ 534 Class: "ETC", 535 OutputFile: android.OptionalPathForPath(txt.outputFile), 536 ExtraEntries: []android.AndroidMkExtraEntriesFunc{ 537 func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { 538 entries.SetString("LOCAL_MODULE_STEM", txt.outputFile.Base()) 539 }, 540 }, 541 }} 542} 543 544func (txt *vndkLibrariesTxt) MakeVars(ctx android.MakeVarsContext) { 545 filter := func(modules []string, prefix string) []string { 546 if prefix == "" { 547 return modules 548 } 549 var result []string 550 for _, module := range modules { 551 if strings.HasPrefix(module, prefix) { 552 continue 553 } else { 554 result = append(result, module) 555 } 556 } 557 return result 558 } 559 ctx.Strict(txt.makeVarName, strings.Join(filter(txt.moduleNames, txt.filterOutFromMakeVar), " ")) 560} 561 562// PrebuiltEtcModule interface 563func (txt *vndkLibrariesTxt) OutputFile() android.OutputPath { 564 return txt.outputFile 565} 566 567// PrebuiltEtcModule interface 568func (txt *vndkLibrariesTxt) BaseDir() string { 569 return "etc" 570} 571 572// PrebuiltEtcModule interface 573func (txt *vndkLibrariesTxt) SubDir() string { 574 return "" 575} 576 577func (txt *vndkLibrariesTxt) OutputFiles(tag string) (android.Paths, error) { 578 return android.Paths{txt.outputFile}, nil 579} 580 581func VndkSnapshotSingleton() android.Singleton { 582 return &vndkSnapshotSingleton{} 583} 584 585type vndkSnapshotSingleton struct { 586 vndkLibrariesFile android.OutputPath 587 vndkSnapshotZipFile android.OptionalPath 588} 589 590func isVndkSnapshotAware(config android.DeviceConfig, m LinkableInterface, 591 apexInfo android.ApexInfo) (vndkType string, isVndkSnapshotLib bool) { 592 593 if m.Target().NativeBridge == android.NativeBridgeEnabled { 594 return "", false 595 } 596 // !inVendor: There's product/vendor variants for VNDK libs. We only care about vendor variants. 597 // !installable: Snapshot only cares about "installable" modules. 598 // !m.IsLlndk: llndk stubs are required for building against snapshots. 599 // IsSnapshotPrebuilt: Snapshotting a snapshot doesn't make sense. 600 // !outputFile.Valid: Snapshot requires valid output file. 601 if !m.InVendor() || (!installable(m, apexInfo) && !m.IsLlndk()) || m.IsSnapshotPrebuilt() || !m.OutputFile().Valid() { 602 return "", false 603 } 604 if !m.IsSnapshotLibrary() || !m.Shared() { 605 return "", false 606 } 607 if m.VndkVersion() == config.PlatformVndkVersion() { 608 if m.IsVndk() && !m.IsVndkExt() { 609 if m.IsVndkSp() { 610 return "vndk-sp", true 611 } else { 612 return "vndk-core", true 613 } 614 } else if m.HasLlndkStubs() && m.StubsVersion() == "" { 615 // Use default version for the snapshot. 616 return "llndk-stub", true 617 } 618 } 619 620 return "", false 621} 622 623func (c *vndkSnapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) { 624 // build these files even if PlatformVndkVersion or BoardVndkVersion is not set 625 c.buildVndkLibrariesTxtFiles(ctx) 626 627 // BOARD_VNDK_VERSION must be set to 'current' in order to generate a VNDK snapshot. 628 if ctx.DeviceConfig().VndkVersion() != "current" { 629 return 630 } 631 632 if ctx.DeviceConfig().PlatformVndkVersion() == "" { 633 return 634 } 635 636 var snapshotOutputs android.Paths 637 638 /* 639 VNDK snapshot zipped artifacts directory structure: 640 {SNAPSHOT_ARCH}/ 641 arch-{TARGET_ARCH}-{TARGET_ARCH_VARIANT}/ 642 shared/ 643 vndk-core/ 644 (VNDK-core libraries, e.g. libbinder.so) 645 vndk-sp/ 646 (VNDK-SP libraries, e.g. libc++.so) 647 llndk-stub/ 648 (LLNDK stub libraries) 649 arch-{TARGET_2ND_ARCH}-{TARGET_2ND_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 binder32/ 658 (This directory is newly introduced in v28 (Android P) to hold 659 prebuilts built for 32-bit binder interface.) 660 arch-{TARGET_ARCH}-{TARGE_ARCH_VARIANT}/ 661 ... 662 configs/ 663 (various *.txt configuration files) 664 include/ 665 (header files of same directory structure with source tree) 666 NOTICE_FILES/ 667 (notice files of libraries, e.g. libcutils.so.txt) 668 */ 669 670 snapshotDir := "vndk-snapshot" 671 snapshotArchDir := filepath.Join(snapshotDir, ctx.DeviceConfig().DeviceArch()) 672 673 configsDir := filepath.Join(snapshotArchDir, "configs") 674 noticeDir := filepath.Join(snapshotArchDir, "NOTICE_FILES") 675 includeDir := filepath.Join(snapshotArchDir, "include") 676 677 // set of notice files copied. 678 noticeBuilt := make(map[string]bool) 679 680 // paths of VNDK modules for GPL license checking 681 modulePaths := make(map[string]string) 682 683 // actual module names of .so files 684 // e.g. moduleNames["libprotobuf-cpp-full-3.9.1.so"] = "libprotobuf-cpp-full" 685 moduleNames := make(map[string]string) 686 687 var headers android.Paths 688 689 // installVndkSnapshotLib copies built .so file from the module. 690 // Also, if the build artifacts is on, write a json file which contains all exported flags 691 // with FlagExporterInfo. 692 installVndkSnapshotLib := func(m *Module, vndkType string) (android.Paths, bool) { 693 var ret android.Paths 694 695 targetArch := "arch-" + m.Target().Arch.ArchType.String() 696 if m.Target().Arch.ArchVariant != "" { 697 targetArch += "-" + m.Target().Arch.ArchVariant 698 } 699 700 libPath := m.outputFile.Path() 701 snapshotLibOut := filepath.Join(snapshotArchDir, targetArch, "shared", vndkType, libPath.Base()) 702 ret = append(ret, snapshot.CopyFileRule(pctx, ctx, libPath, snapshotLibOut)) 703 704 if ctx.Config().VndkSnapshotBuildArtifacts() { 705 prop := struct { 706 ExportedDirs []string `json:",omitempty"` 707 ExportedSystemDirs []string `json:",omitempty"` 708 ExportedFlags []string `json:",omitempty"` 709 RelativeInstallPath string `json:",omitempty"` 710 }{} 711 exportedInfo := ctx.ModuleProvider(m, FlagExporterInfoProvider).(FlagExporterInfo) 712 prop.ExportedFlags = exportedInfo.Flags 713 prop.ExportedDirs = exportedInfo.IncludeDirs.Strings() 714 prop.ExportedSystemDirs = exportedInfo.SystemIncludeDirs.Strings() 715 prop.RelativeInstallPath = m.RelativeInstallPath() 716 717 propOut := snapshotLibOut + ".json" 718 719 j, err := json.Marshal(prop) 720 if err != nil { 721 ctx.Errorf("json marshal to %q failed: %#v", propOut, err) 722 return nil, false 723 } 724 ret = append(ret, snapshot.WriteStringToFileRule(ctx, string(j), propOut)) 725 } 726 return ret, true 727 } 728 729 ctx.VisitAllModules(func(module android.Module) { 730 m, ok := module.(*Module) 731 if !ok || !m.Enabled() { 732 return 733 } 734 735 apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo) 736 737 vndkType, ok := isVndkSnapshotAware(ctx.DeviceConfig(), m, apexInfo) 738 if !ok { 739 return 740 } 741 742 // For all snapshot candidates, the followings are captured. 743 // - .so files 744 // - notice files 745 // 746 // The followings are also captured if VNDK_SNAPSHOT_BUILD_ARTIFACTS. 747 // - .json files containing exported flags 748 // - exported headers from collectHeadersForSnapshot() 749 // 750 // Headers are deduplicated after visiting all modules. 751 752 // install .so files for appropriate modules. 753 // Also install .json files if VNDK_SNAPSHOT_BUILD_ARTIFACTS 754 libs, ok := installVndkSnapshotLib(m, vndkType) 755 if !ok { 756 return 757 } 758 snapshotOutputs = append(snapshotOutputs, libs...) 759 760 // These are for generating module_names.txt and module_paths.txt 761 stem := m.outputFile.Path().Base() 762 moduleNames[stem] = ctx.ModuleName(m) 763 modulePaths[stem] = ctx.ModuleDir(m) 764 765 if len(m.NoticeFiles()) > 0 { 766 noticeName := stem + ".txt" 767 // skip already copied notice file 768 if _, ok := noticeBuilt[noticeName]; !ok { 769 noticeBuilt[noticeName] = true 770 snapshotOutputs = append(snapshotOutputs, combineNoticesRule( 771 ctx, m.NoticeFiles(), filepath.Join(noticeDir, noticeName))) 772 } 773 } 774 775 if ctx.Config().VndkSnapshotBuildArtifacts() { 776 headers = append(headers, m.SnapshotHeaders()...) 777 } 778 }) 779 780 // install all headers after removing duplicates 781 for _, header := range android.FirstUniquePaths(headers) { 782 snapshotOutputs = append(snapshotOutputs, snapshot.CopyFileRule( 783 pctx, ctx, header, filepath.Join(includeDir, header.String()))) 784 } 785 786 // install *.libraries.txt except vndkcorevariant.libraries.txt 787 ctx.VisitAllModules(func(module android.Module) { 788 m, ok := module.(*vndkLibrariesTxt) 789 if !ok || !m.Enabled() || m.Name() == vndkUsingCoreVariantLibrariesTxt { 790 return 791 } 792 snapshotOutputs = append(snapshotOutputs, snapshot.CopyFileRule( 793 pctx, ctx, m.OutputFile(), filepath.Join(configsDir, m.Name()))) 794 }) 795 796 /* 797 module_paths.txt contains paths on which VNDK modules are defined. 798 e.g., 799 libbase.so system/libbase 800 libc.so bionic/libc 801 ... 802 */ 803 snapshotOutputs = append(snapshotOutputs, installMapListFileRule(ctx, modulePaths, filepath.Join(configsDir, "module_paths.txt"))) 804 805 /* 806 module_names.txt contains names as which VNDK modules are defined, 807 because output filename and module name can be different with stem and suffix properties. 808 809 e.g., 810 libcutils.so libcutils 811 libprotobuf-cpp-full-3.9.2.so libprotobuf-cpp-full 812 ... 813 */ 814 snapshotOutputs = append(snapshotOutputs, installMapListFileRule(ctx, moduleNames, filepath.Join(configsDir, "module_names.txt"))) 815 816 // All artifacts are ready. Sort them to normalize ninja and then zip. 817 sort.Slice(snapshotOutputs, func(i, j int) bool { 818 return snapshotOutputs[i].String() < snapshotOutputs[j].String() 819 }) 820 821 zipPath := android.PathForOutput(ctx, snapshotDir, "android-vndk-"+ctx.DeviceConfig().DeviceArch()+".zip") 822 zipRule := android.NewRuleBuilder(pctx, ctx) 823 824 // filenames in rspfile from FlagWithRspFileInputList might be single-quoted. Remove it with tr 825 snapshotOutputList := android.PathForOutput(ctx, snapshotDir, "android-vndk-"+ctx.DeviceConfig().DeviceArch()+"_list") 826 rspFile := snapshotOutputList.ReplaceExtension(ctx, "rsp") 827 zipRule.Command(). 828 Text("tr"). 829 FlagWithArg("-d ", "\\'"). 830 FlagWithRspFileInputList("< ", rspFile, snapshotOutputs). 831 FlagWithOutput("> ", snapshotOutputList) 832 833 zipRule.Temporary(snapshotOutputList) 834 835 zipRule.Command(). 836 BuiltTool("soong_zip"). 837 FlagWithOutput("-o ", zipPath). 838 FlagWithArg("-C ", android.PathForOutput(ctx, snapshotDir).String()). 839 FlagWithInput("-l ", snapshotOutputList) 840 841 zipRule.Build(zipPath.String(), "vndk snapshot "+zipPath.String()) 842 zipRule.DeleteTemporaryFiles() 843 c.vndkSnapshotZipFile = android.OptionalPathForPath(zipPath) 844} 845 846func getVndkFileName(m *Module) (string, error) { 847 if library, ok := m.linker.(*libraryDecorator); ok { 848 return library.getLibNameHelper(m.BaseModuleName(), true, false) + ".so", nil 849 } 850 if prebuilt, ok := m.linker.(*prebuiltLibraryLinker); ok { 851 return prebuilt.libraryDecorator.getLibNameHelper(m.BaseModuleName(), true, false) + ".so", nil 852 } 853 return "", fmt.Errorf("VNDK library should have libraryDecorator or prebuiltLibraryLinker as linker: %T", m.linker) 854} 855 856func (c *vndkSnapshotSingleton) buildVndkLibrariesTxtFiles(ctx android.SingletonContext) { 857 // Build list of vndk libs as merged & tagged & filter-out(libclang_rt): 858 // Since each target have different set of libclang_rt.* files, 859 // keep the common set of files in vndk.libraries.txt 860 _, llndk := vndkModuleListRemover(llndkLibraries, "libclang_rt.")(ctx) 861 _, vndkcore := vndkModuleListRemover(vndkCoreLibraries, "libclang_rt.")(ctx) 862 _, vndksp := vndkSPLibraries(ctx) 863 _, vndkprivate := vndkPrivateLibraries(ctx) 864 _, vndkproduct := vndkModuleListRemover(vndkProductLibraries, "libclang_rt.")(ctx) 865 var merged []string 866 merged = append(merged, addPrefix(llndk, "LLNDK: ")...) 867 merged = append(merged, addPrefix(vndksp, "VNDK-SP: ")...) 868 merged = append(merged, addPrefix(vndkcore, "VNDK-core: ")...) 869 merged = append(merged, addPrefix(vndkprivate, "VNDK-private: ")...) 870 merged = append(merged, addPrefix(vndkproduct, "VNDK-product: ")...) 871 c.vndkLibrariesFile = android.PathForOutput(ctx, "vndk", "vndk.libraries.txt") 872 android.WriteFileRule(ctx, c.vndkLibrariesFile, strings.Join(merged, "\n")) 873} 874 875func (c *vndkSnapshotSingleton) MakeVars(ctx android.MakeVarsContext) { 876 // Make uses LLNDK_MOVED_TO_APEX_LIBRARIES to avoid installing libraries on /system if 877 // they been moved to an apex. 878 movedToApexLlndkLibraries := make(map[string]bool) 879 ctx.VisitAllModules(func(module android.Module) { 880 if library := moduleLibraryInterface(module); library != nil && library.hasLLNDKStubs() { 881 // Skip bionic libs, they are handled in different manner 882 name := library.implementationModuleName(module.(*Module).BaseModuleName()) 883 if module.(android.ApexModule).DirectlyInAnyApex() && !isBionic(name) { 884 movedToApexLlndkLibraries[name] = true 885 } 886 } 887 }) 888 889 ctx.Strict("LLNDK_MOVED_TO_APEX_LIBRARIES", 890 strings.Join(android.SortedStringKeys(movedToApexLlndkLibraries), " ")) 891 892 ctx.Strict("VNDK_LIBRARIES_FILE", c.vndkLibrariesFile.String()) 893 ctx.Strict("SOONG_VNDK_SNAPSHOT_ZIP", c.vndkSnapshotZipFile.String()) 894} 895