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