1// Copyright 2016 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 etc 16 17// This file implements module types that install prebuilt artifacts. 18// 19// There exist two classes of prebuilt modules in the Android tree. The first class are the ones 20// based on `android.Prebuilt`, such as `cc_prebuilt_library` and `java_import`. This kind of 21// modules may exist both as prebuilts and source at the same time, though only one would be 22// installed and the other would be marked disabled. The `prebuilt_postdeps` mutator would select 23// the actual modules to be installed. More details in android/prebuilt.go. 24// 25// The second class is described in this file. Unlike `android.Prebuilt` based module types, 26// `prebuilt_etc` exist only as prebuilts and cannot have a same-named source module counterpart. 27// This makes the logic of `prebuilt_etc` to be much simpler as they don't need to go through the 28// various `prebuilt_*` mutators. 29 30import ( 31 "encoding/json" 32 "fmt" 33 "path/filepath" 34 "reflect" 35 "strings" 36 37 "github.com/google/blueprint/proptools" 38 39 "android/soong/android" 40 "android/soong/bazel" 41 "android/soong/snapshot" 42) 43 44var pctx = android.NewPackageContext("android/soong/etc") 45 46// TODO(jungw): Now that it handles more than the ones in etc/, consider renaming this file. 47 48func init() { 49 pctx.Import("android/soong/android") 50 RegisterPrebuiltEtcBuildComponents(android.InitRegistrationContext) 51 snapshot.RegisterSnapshotAction(generatePrebuiltSnapshot) 52} 53 54func RegisterPrebuiltEtcBuildComponents(ctx android.RegistrationContext) { 55 ctx.RegisterModuleType("prebuilt_etc", PrebuiltEtcFactory) 56 ctx.RegisterModuleType("prebuilt_etc_host", PrebuiltEtcHostFactory) 57 ctx.RegisterModuleType("prebuilt_etc_cacerts", PrebuiltEtcCaCertsFactory) 58 ctx.RegisterModuleType("prebuilt_root", PrebuiltRootFactory) 59 ctx.RegisterModuleType("prebuilt_root_host", PrebuiltRootHostFactory) 60 ctx.RegisterModuleType("prebuilt_usr_share", PrebuiltUserShareFactory) 61 ctx.RegisterModuleType("prebuilt_usr_share_host", PrebuiltUserShareHostFactory) 62 ctx.RegisterModuleType("prebuilt_font", PrebuiltFontFactory) 63 ctx.RegisterModuleType("prebuilt_firmware", PrebuiltFirmwareFactory) 64 ctx.RegisterModuleType("prebuilt_dsp", PrebuiltDSPFactory) 65 ctx.RegisterModuleType("prebuilt_rfsa", PrebuiltRFSAFactory) 66 67 ctx.RegisterModuleType("prebuilt_defaults", defaultsFactory) 68 69} 70 71var PrepareForTestWithPrebuiltEtc = android.FixtureRegisterWithContext(RegisterPrebuiltEtcBuildComponents) 72 73type prebuiltEtcProperties struct { 74 // Source file of this prebuilt. Can reference a genrule type module with the ":module" syntax. 75 Src *string `android:"path,arch_variant"` 76 77 // Optional name for the installed file. If unspecified, name of the module is used as the file 78 // name. 79 Filename *string `android:"arch_variant"` 80 81 // When set to true, and filename property is not set, the name for the installed file 82 // is the same as the file name of the source file. 83 Filename_from_src *bool `android:"arch_variant"` 84 85 // Make this module available when building for ramdisk. 86 // On device without a dedicated recovery partition, the module is only 87 // available after switching root into 88 // /first_stage_ramdisk. To expose the module before switching root, install 89 // the recovery variant instead. 90 Ramdisk_available *bool 91 92 // Make this module available when building for vendor ramdisk. 93 // On device without a dedicated recovery partition, the module is only 94 // available after switching root into 95 // /first_stage_ramdisk. To expose the module before switching root, install 96 // the recovery variant instead. 97 Vendor_ramdisk_available *bool 98 99 // Make this module available when building for debug ramdisk. 100 Debug_ramdisk_available *bool 101 102 // Make this module available when building for recovery. 103 Recovery_available *bool 104 105 // Whether this module is directly installable to one of the partitions. Default: true. 106 Installable *bool 107 108 // Install symlinks to the installed file. 109 Symlinks []string `android:"arch_variant"` 110} 111 112type prebuiltSubdirProperties struct { 113 // Optional subdirectory under which this file is installed into, cannot be specified with 114 // relative_install_path, prefer relative_install_path. 115 Sub_dir *string `android:"arch_variant"` 116 117 // Optional subdirectory under which this file is installed into, cannot be specified with 118 // sub_dir. 119 Relative_install_path *string `android:"arch_variant"` 120} 121 122type PrebuiltEtcModule interface { 123 android.Module 124 125 // Returns the base install directory, such as "etc", "usr/share". 126 BaseDir() string 127 128 // Returns the sub install directory relative to BaseDir(). 129 SubDir() string 130 131 // Returns an android.OutputPath to the intermeidate file, which is the renamed prebuilt source 132 // file. 133 OutputFile() android.OutputPath 134} 135 136type PrebuiltEtc struct { 137 android.ModuleBase 138 android.DefaultableModuleBase 139 android.BazelModuleBase 140 141 snapshot.VendorSnapshotModuleInterface 142 snapshot.RecoverySnapshotModuleInterface 143 144 properties prebuiltEtcProperties 145 subdirProperties prebuiltSubdirProperties 146 147 sourceFilePath android.Path 148 outputFilePath android.OutputPath 149 // The base install location, e.g. "etc" for prebuilt_etc, "usr/share" for prebuilt_usr_share. 150 installDirBase string 151 // The base install location when soc_specific property is set to true, e.g. "firmware" for 152 // prebuilt_firmware. 153 socInstallDirBase string 154 installDirPath android.InstallPath 155 additionalDependencies *android.Paths 156} 157 158type Defaults struct { 159 android.ModuleBase 160 android.DefaultsModuleBase 161} 162 163func (p *PrebuiltEtc) inRamdisk() bool { 164 return p.ModuleBase.InRamdisk() || p.ModuleBase.InstallInRamdisk() 165} 166 167func (p *PrebuiltEtc) onlyInRamdisk() bool { 168 return p.ModuleBase.InstallInRamdisk() 169} 170 171func (p *PrebuiltEtc) InstallInRamdisk() bool { 172 return p.inRamdisk() 173} 174 175func (p *PrebuiltEtc) inVendorRamdisk() bool { 176 return p.ModuleBase.InVendorRamdisk() || p.ModuleBase.InstallInVendorRamdisk() 177} 178 179func (p *PrebuiltEtc) onlyInVendorRamdisk() bool { 180 return p.ModuleBase.InstallInVendorRamdisk() 181} 182 183func (p *PrebuiltEtc) InstallInVendorRamdisk() bool { 184 return p.inVendorRamdisk() 185} 186 187func (p *PrebuiltEtc) inDebugRamdisk() bool { 188 return p.ModuleBase.InDebugRamdisk() || p.ModuleBase.InstallInDebugRamdisk() 189} 190 191func (p *PrebuiltEtc) onlyInDebugRamdisk() bool { 192 return p.ModuleBase.InstallInDebugRamdisk() 193} 194 195func (p *PrebuiltEtc) InstallInDebugRamdisk() bool { 196 return p.inDebugRamdisk() 197} 198 199func (p *PrebuiltEtc) InRecovery() bool { 200 return p.ModuleBase.InRecovery() || p.ModuleBase.InstallInRecovery() 201} 202 203func (p *PrebuiltEtc) onlyInRecovery() bool { 204 return p.ModuleBase.InstallInRecovery() 205} 206 207func (p *PrebuiltEtc) InstallInRecovery() bool { 208 return p.InRecovery() 209} 210 211var _ android.ImageInterface = (*PrebuiltEtc)(nil) 212 213func (p *PrebuiltEtc) ImageMutatorBegin(ctx android.BaseModuleContext) {} 214 215func (p *PrebuiltEtc) CoreVariantNeeded(ctx android.BaseModuleContext) bool { 216 return !p.ModuleBase.InstallInRecovery() && !p.ModuleBase.InstallInRamdisk() && 217 !p.ModuleBase.InstallInVendorRamdisk() && !p.ModuleBase.InstallInDebugRamdisk() 218} 219 220func (p *PrebuiltEtc) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool { 221 return proptools.Bool(p.properties.Ramdisk_available) || p.ModuleBase.InstallInRamdisk() 222} 223 224func (p *PrebuiltEtc) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool { 225 return proptools.Bool(p.properties.Vendor_ramdisk_available) || p.ModuleBase.InstallInVendorRamdisk() 226} 227 228func (p *PrebuiltEtc) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool { 229 return proptools.Bool(p.properties.Debug_ramdisk_available) || p.ModuleBase.InstallInDebugRamdisk() 230} 231 232func (p *PrebuiltEtc) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool { 233 return proptools.Bool(p.properties.Recovery_available) || p.ModuleBase.InstallInRecovery() 234} 235 236func (p *PrebuiltEtc) ExtraImageVariations(ctx android.BaseModuleContext) []string { 237 return nil 238} 239 240func (p *PrebuiltEtc) SetImageVariation(ctx android.BaseModuleContext, variation string, module android.Module) { 241} 242 243func (p *PrebuiltEtc) SourceFilePath(ctx android.ModuleContext) android.Path { 244 return android.PathForModuleSrc(ctx, proptools.String(p.properties.Src)) 245} 246 247func (p *PrebuiltEtc) InstallDirPath() android.InstallPath { 248 return p.installDirPath 249} 250 251// This allows other derivative modules (e.g. prebuilt_etc_xml) to perform 252// additional steps (like validating the src) before the file is installed. 253func (p *PrebuiltEtc) SetAdditionalDependencies(paths android.Paths) { 254 p.additionalDependencies = &paths 255} 256 257func (p *PrebuiltEtc) OutputFile() android.OutputPath { 258 return p.outputFilePath 259} 260 261var _ android.OutputFileProducer = (*PrebuiltEtc)(nil) 262 263func (p *PrebuiltEtc) OutputFiles(tag string) (android.Paths, error) { 264 switch tag { 265 case "": 266 return android.Paths{p.outputFilePath}, nil 267 default: 268 return nil, fmt.Errorf("unsupported module reference tag %q", tag) 269 } 270} 271 272func (p *PrebuiltEtc) SubDir() string { 273 if subDir := proptools.String(p.subdirProperties.Sub_dir); subDir != "" { 274 return subDir 275 } 276 return proptools.String(p.subdirProperties.Relative_install_path) 277} 278 279func (p *PrebuiltEtc) BaseDir() string { 280 return p.installDirBase 281} 282 283func (p *PrebuiltEtc) Installable() bool { 284 return p.properties.Installable == nil || proptools.Bool(p.properties.Installable) 285} 286 287func (p *PrebuiltEtc) InVendor() bool { 288 return p.ModuleBase.InstallInVendor() 289} 290 291func (p *PrebuiltEtc) ExcludeFromVendorSnapshot() bool { 292 return false 293} 294 295func (p *PrebuiltEtc) ExcludeFromRecoverySnapshot() bool { 296 return false 297} 298 299func (p *PrebuiltEtc) GenerateAndroidBuildActions(ctx android.ModuleContext) { 300 filename := proptools.String(p.properties.Filename) 301 filenameFromSrc := proptools.Bool(p.properties.Filename_from_src) 302 if p.properties.Src != nil { 303 p.sourceFilePath = android.PathForModuleSrc(ctx, proptools.String(p.properties.Src)) 304 305 // Determine the output file basename. 306 // If Filename is set, use the name specified by the property. 307 // If Filename_from_src is set, use the source file name. 308 // Otherwise use the module name. 309 if filename != "" { 310 if filenameFromSrc { 311 ctx.PropertyErrorf("filename_from_src", "filename is set. filename_from_src can't be true") 312 return 313 } 314 } else if filenameFromSrc { 315 filename = p.sourceFilePath.Base() 316 } else { 317 filename = ctx.ModuleName() 318 } 319 } else if ctx.Config().AllowMissingDependencies() { 320 // If no srcs was set and AllowMissingDependencies is enabled then 321 // mark the module as missing dependencies and set a fake source path 322 // and file name. 323 ctx.AddMissingDependencies([]string{"MISSING_PREBUILT_SRC_FILE"}) 324 p.sourceFilePath = android.PathForModuleSrc(ctx) 325 if filename == "" { 326 filename = ctx.ModuleName() 327 } 328 } else { 329 ctx.PropertyErrorf("src", "missing prebuilt source file") 330 return 331 } 332 p.outputFilePath = android.PathForModuleOut(ctx, filename).OutputPath 333 334 if strings.Contains(filename, "/") { 335 ctx.PropertyErrorf("filename", "filename cannot contain separator '/'") 336 return 337 } 338 339 // Check that `sub_dir` and `relative_install_path` are not set at the same time. 340 if p.subdirProperties.Sub_dir != nil && p.subdirProperties.Relative_install_path != nil { 341 ctx.PropertyErrorf("sub_dir", "relative_install_path is set. Cannot set sub_dir") 342 } 343 344 // If soc install dir was specified and SOC specific is set, set the installDirPath to the 345 // specified socInstallDirBase. 346 installBaseDir := p.installDirBase 347 if p.SocSpecific() && p.socInstallDirBase != "" { 348 installBaseDir = p.socInstallDirBase 349 } 350 p.installDirPath = android.PathForModuleInstall(ctx, installBaseDir, p.SubDir()) 351 352 // This ensures that outputFilePath has the correct name for others to 353 // use, as the source file may have a different name. 354 ctx.Build(pctx, android.BuildParams{ 355 Rule: android.Cp, 356 Output: p.outputFilePath, 357 Input: p.sourceFilePath, 358 }) 359 360 if !p.Installable() { 361 p.SkipInstall() 362 } 363 364 // Call InstallFile even when uninstallable to make the module included in the package 365 installPath := ctx.InstallFile(p.installDirPath, p.outputFilePath.Base(), p.outputFilePath) 366 for _, sl := range p.properties.Symlinks { 367 ctx.InstallSymlink(p.installDirPath, sl, installPath) 368 } 369} 370 371func (p *PrebuiltEtc) AndroidMkEntries() []android.AndroidMkEntries { 372 nameSuffix := "" 373 if p.inRamdisk() && !p.onlyInRamdisk() { 374 nameSuffix = ".ramdisk" 375 } 376 if p.inVendorRamdisk() && !p.onlyInVendorRamdisk() { 377 nameSuffix = ".vendor_ramdisk" 378 } 379 if p.inDebugRamdisk() && !p.onlyInDebugRamdisk() { 380 nameSuffix = ".debug_ramdisk" 381 } 382 if p.InRecovery() && !p.onlyInRecovery() { 383 nameSuffix = ".recovery" 384 } 385 return []android.AndroidMkEntries{android.AndroidMkEntries{ 386 Class: "ETC", 387 SubName: nameSuffix, 388 OutputFile: android.OptionalPathForPath(p.outputFilePath), 389 ExtraEntries: []android.AndroidMkExtraEntriesFunc{ 390 func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { 391 entries.SetString("LOCAL_MODULE_TAGS", "optional") 392 entries.SetString("LOCAL_MODULE_PATH", p.installDirPath.String()) 393 entries.SetString("LOCAL_INSTALLED_MODULE_STEM", p.outputFilePath.Base()) 394 if len(p.properties.Symlinks) > 0 { 395 entries.AddStrings("LOCAL_MODULE_SYMLINKS", p.properties.Symlinks...) 396 } 397 entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", !p.Installable()) 398 if p.additionalDependencies != nil { 399 entries.AddStrings("LOCAL_ADDITIONAL_DEPENDENCIES", p.additionalDependencies.Strings()...) 400 } 401 }, 402 }, 403 }} 404} 405 406func InitPrebuiltEtcModule(p *PrebuiltEtc, dirBase string) { 407 p.installDirBase = dirBase 408 p.AddProperties(&p.properties) 409 p.AddProperties(&p.subdirProperties) 410} 411 412func InitPrebuiltRootModule(p *PrebuiltEtc) { 413 p.installDirBase = "." 414 p.AddProperties(&p.properties) 415} 416 417// prebuilt_etc is for a prebuilt artifact that is installed in 418// <partition>/etc/<sub_dir> directory. 419func PrebuiltEtcFactory() android.Module { 420 module := &PrebuiltEtc{} 421 InitPrebuiltEtcModule(module, "etc") 422 // This module is device-only 423 android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst) 424 android.InitDefaultableModule(module) 425 android.InitBazelModule(module) 426 return module 427} 428 429func defaultsFactory() android.Module { 430 return DefaultsFactory() 431} 432 433func DefaultsFactory(props ...interface{}) android.Module { 434 module := &Defaults{} 435 436 module.AddProperties(props...) 437 module.AddProperties( 438 &prebuiltEtcProperties{}, 439 &prebuiltSubdirProperties{}, 440 ) 441 442 android.InitDefaultsModule(module) 443 444 return module 445} 446 447// prebuilt_etc_host is for a host prebuilt artifact that is installed in 448// $(HOST_OUT)/etc/<sub_dir> directory. 449func PrebuiltEtcHostFactory() android.Module { 450 module := &PrebuiltEtc{} 451 InitPrebuiltEtcModule(module, "etc") 452 // This module is host-only 453 android.InitAndroidArchModule(module, android.HostSupported, android.MultilibCommon) 454 android.InitDefaultableModule(module) 455 android.InitBazelModule(module) 456 return module 457} 458 459// prebuilt_etc_host is for a host prebuilt artifact that is installed in 460// <partition>/etc/<sub_dir> directory. 461func PrebuiltEtcCaCertsFactory() android.Module { 462 module := &PrebuiltEtc{} 463 InitPrebuiltEtcModule(module, "cacerts") 464 // This module is device-only 465 android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst) 466 android.InitBazelModule(module) 467 return module 468} 469 470// prebuilt_root is for a prebuilt artifact that is installed in 471// <partition>/ directory. Can't have any sub directories. 472func PrebuiltRootFactory() android.Module { 473 module := &PrebuiltEtc{} 474 InitPrebuiltRootModule(module) 475 // This module is device-only 476 android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst) 477 android.InitDefaultableModule(module) 478 return module 479} 480 481// prebuilt_root_host is for a host prebuilt artifact that is installed in $(HOST_OUT)/<sub_dir> 482// directory. 483func PrebuiltRootHostFactory() android.Module { 484 module := &PrebuiltEtc{} 485 InitPrebuiltEtcModule(module, ".") 486 // This module is host-only 487 android.InitAndroidArchModule(module, android.HostSupported, android.MultilibCommon) 488 android.InitDefaultableModule(module) 489 return module 490} 491 492// prebuilt_usr_share is for a prebuilt artifact that is installed in 493// <partition>/usr/share/<sub_dir> directory. 494func PrebuiltUserShareFactory() android.Module { 495 module := &PrebuiltEtc{} 496 InitPrebuiltEtcModule(module, "usr/share") 497 // This module is device-only 498 android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst) 499 android.InitDefaultableModule(module) 500 android.InitBazelModule(module) 501 return module 502} 503 504// prebuild_usr_share_host is for a host prebuilt artifact that is installed in 505// $(HOST_OUT)/usr/share/<sub_dir> directory. 506func PrebuiltUserShareHostFactory() android.Module { 507 module := &PrebuiltEtc{} 508 InitPrebuiltEtcModule(module, "usr/share") 509 // This module is host-only 510 android.InitAndroidArchModule(module, android.HostSupported, android.MultilibCommon) 511 android.InitDefaultableModule(module) 512 return module 513} 514 515// prebuilt_font installs a font in <partition>/fonts directory. 516func PrebuiltFontFactory() android.Module { 517 module := &PrebuiltEtc{} 518 InitPrebuiltEtcModule(module, "fonts") 519 // This module is device-only 520 android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst) 521 android.InitDefaultableModule(module) 522 return module 523} 524 525// prebuilt_firmware installs a firmware file to <partition>/etc/firmware directory for system 526// image. 527// If soc_specific property is set to true, the firmware file is installed to the 528// vendor <partition>/firmware directory for vendor image. 529func PrebuiltFirmwareFactory() android.Module { 530 module := &PrebuiltEtc{} 531 module.socInstallDirBase = "firmware" 532 InitPrebuiltEtcModule(module, "etc/firmware") 533 // This module is device-only 534 android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst) 535 android.InitDefaultableModule(module) 536 return module 537} 538 539// prebuilt_dsp installs a DSP related file to <partition>/etc/dsp directory for system image. 540// If soc_specific property is set to true, the DSP related file is installed to the 541// vendor <partition>/dsp directory for vendor image. 542func PrebuiltDSPFactory() android.Module { 543 module := &PrebuiltEtc{} 544 module.socInstallDirBase = "dsp" 545 InitPrebuiltEtcModule(module, "etc/dsp") 546 // This module is device-only 547 android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst) 548 android.InitDefaultableModule(module) 549 return module 550} 551 552// prebuilt_rfsa installs a firmware file that will be available through Qualcomm's RFSA 553// to the <partition>/lib/rfsa directory. 554func PrebuiltRFSAFactory() android.Module { 555 module := &PrebuiltEtc{} 556 // Ideally these would go in /vendor/dsp, but the /vendor/lib/rfsa paths are hardcoded in too 557 // many places outside of the application processor. They could be moved to /vendor/dsp once 558 // that is cleaned up. 559 InitPrebuiltEtcModule(module, "lib/rfsa") 560 // This module is device-only 561 android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst) 562 android.InitDefaultableModule(module) 563 return module 564} 565 566// Copy file into the snapshot 567func copyFile(ctx android.SingletonContext, path android.Path, out string, fake bool) android.OutputPath { 568 if fake { 569 // Create empty file instead for the fake snapshot 570 return snapshot.WriteStringToFileRule(ctx, "", out) 571 } else { 572 return snapshot.CopyFileRule(pctx, ctx, path, out) 573 } 574} 575 576// Check if the module is target of the snapshot 577func isSnapshotAware(ctx android.SingletonContext, m *PrebuiltEtc, image snapshot.SnapshotImage) bool { 578 if !m.Enabled() { 579 return false 580 } 581 582 // Skip if the module is not included in the image 583 if !image.InImage(m)() { 584 return false 585 } 586 587 // When android/prebuilt.go selects between source and prebuilt, it sets 588 // HideFromMake on the other one to avoid duplicate install rules in make. 589 if m.IsHideFromMake() { 590 return false 591 } 592 593 // There are some prebuilt_etc module with multiple definition of same name. 594 // Check if the target would be included from the build 595 if !m.ExportedToMake() { 596 return false 597 } 598 599 // Skip if the module is in the predefined path list to skip 600 if image.IsProprietaryPath(ctx.ModuleDir(m), ctx.DeviceConfig()) { 601 return false 602 } 603 604 // Skip if the module should be excluded 605 if image.ExcludeFromSnapshot(m) || image.ExcludeFromDirectedSnapshot(ctx.DeviceConfig(), m.BaseModuleName()) { 606 return false 607 } 608 609 // Skip from other exceptional cases 610 if m.Target().Os.Class != android.Device { 611 return false 612 } 613 if m.Target().NativeBridge == android.NativeBridgeEnabled { 614 return false 615 } 616 617 return true 618} 619 620func generatePrebuiltSnapshot(s snapshot.SnapshotSingleton, ctx android.SingletonContext, snapshotArchDir string) snapshot.SnapshotPaths { 621 /* 622 Snapshot zipped artifacts directory structure for etc modules: 623 {SNAPSHOT_ARCH}/ 624 arch-{TARGET_ARCH}-{TARGET_ARCH_VARIANT}/ 625 etc/ 626 (prebuilt etc files) 627 arch-{TARGET_2ND_ARCH}-{TARGET_2ND_ARCH_VARIANT}/ 628 etc/ 629 (prebuilt etc files) 630 NOTICE_FILES/ 631 (notice files) 632 */ 633 var snapshotOutputs android.Paths 634 var snapshotNotices android.Paths 635 installedNotices := make(map[string]bool) 636 637 ctx.VisitAllModules(func(module android.Module) { 638 m, ok := module.(*PrebuiltEtc) 639 if !ok { 640 return 641 } 642 643 if !isSnapshotAware(ctx, m, s.Image) { 644 return 645 } 646 647 targetArch := "arch-" + m.Target().Arch.ArchType.String() 648 649 snapshotLibOut := filepath.Join(snapshotArchDir, targetArch, "etc", m.BaseModuleName()) 650 snapshotOutputs = append(snapshotOutputs, copyFile(ctx, m.OutputFile(), snapshotLibOut, s.Fake)) 651 652 prop := snapshot.SnapshotJsonFlags{} 653 propOut := snapshotLibOut + ".json" 654 prop.InitBaseSnapshotProps(m) 655 prop.RelativeInstallPath = m.SubDir() 656 657 if m.properties.Filename != nil { 658 prop.Filename = *m.properties.Filename 659 } 660 661 j, err := json.Marshal(prop) 662 if err != nil { 663 ctx.Errorf("json marshal to %q failed: %#v", propOut, err) 664 return 665 } 666 snapshotOutputs = append(snapshotOutputs, snapshot.WriteStringToFileRule(ctx, string(j), propOut)) 667 668 for _, notice := range m.EffectiveLicenseFiles() { 669 if _, ok := installedNotices[notice.String()]; !ok { 670 installedNotices[notice.String()] = true 671 snapshotNotices = append(snapshotNotices, notice) 672 } 673 } 674 675 }) 676 677 return snapshot.SnapshotPaths{OutputFiles: snapshotOutputs, NoticeFiles: snapshotNotices} 678} 679 680// For Bazel / bp2build 681 682type bazelPrebuiltFileAttributes struct { 683 Src bazel.LabelAttribute 684 Filename bazel.LabelAttribute 685 Dir string 686 Installable bazel.BoolAttribute 687 Filename_from_src bazel.BoolAttribute 688} 689 690// Bp2buildHelper returns a bazelPrebuiltFileAttributes used for the conversion 691// of prebuilt_* modules. bazelPrebuiltFileAttributes has the common attributes 692// used by both prebuilt_etc_xml and other prebuilt_* moodules 693func (module *PrebuiltEtc) Bp2buildHelper(ctx android.TopDownMutatorContext) *bazelPrebuiltFileAttributes { 694 var src bazel.LabelAttribute 695 for axis, configToProps := range module.GetArchVariantProperties(ctx, &prebuiltEtcProperties{}) { 696 for config, p := range configToProps { 697 props, ok := p.(*prebuiltEtcProperties) 698 if !ok { 699 continue 700 } 701 if props.Src != nil { 702 label := android.BazelLabelForModuleSrcSingle(ctx, *props.Src) 703 src.SetSelectValue(axis, config, label) 704 } 705 } 706 707 for propName, productConfigProps := range android.ProductVariableProperties(ctx, ctx.Module()) { 708 for configProp, propVal := range productConfigProps { 709 if propName == "Src" { 710 props, ok := propVal.(*string) 711 if !ok { 712 ctx.PropertyErrorf(" Expected Property to have type string, but was %s\n", reflect.TypeOf(propVal).String()) 713 continue 714 } 715 if props != nil { 716 label := android.BazelLabelForModuleSrcSingle(ctx, *props) 717 src.SetSelectValue(configProp.ConfigurationAxis(), configProp.SelectKey(), label) 718 } 719 } 720 } 721 } 722 } 723 724 var filename string 725 var filenameFromSrc bool 726 moduleProps := module.properties 727 728 if moduleProps.Filename != nil && *moduleProps.Filename != "" { 729 filename = *moduleProps.Filename 730 } else if moduleProps.Filename_from_src != nil && *moduleProps.Filename_from_src { 731 if moduleProps.Src != nil { 732 filename = *moduleProps.Src 733 } 734 filenameFromSrc = true 735 } else { 736 filename = ctx.ModuleName() 737 } 738 739 var dir = module.installDirBase 740 if subDir := module.subdirProperties.Sub_dir; subDir != nil { 741 dir = dir + "/" + *subDir 742 } 743 744 var installable bazel.BoolAttribute 745 if install := module.properties.Installable; install != nil { 746 installable.Value = install 747 } 748 749 attrs := &bazelPrebuiltFileAttributes{ 750 Src: src, 751 Dir: dir, 752 Installable: installable, 753 } 754 755 if filename != "" { 756 attrs.Filename = bazel.LabelAttribute{Value: &bazel.Label{Label: filename}} 757 } else if filenameFromSrc { 758 attrs.Filename_from_src = bazel.BoolAttribute{Value: moduleProps.Filename_from_src} 759 } 760 761 return attrs 762 763} 764 765// ConvertWithBp2build performs bp2build conversion of PrebuiltEtc 766// prebuilt_* modules (except prebuilt_etc_xml) are PrebuiltEtc, 767// which we treat as *PrebuiltFile* 768func (module *PrebuiltEtc) ConvertWithBp2build(ctx android.TopDownMutatorContext) { 769 var dir = module.installDirBase 770 // prebuilt_file supports only `etc` or `usr/share` 771 if !(dir == "etc" || dir == "usr/share") { 772 return 773 } 774 775 attrs := module.Bp2buildHelper(ctx) 776 777 props := bazel.BazelTargetModuleProperties{ 778 Rule_class: "prebuilt_file", 779 Bzl_load_location: "//build/bazel/rules:prebuilt_file.bzl", 780 } 781 782 ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: module.Name()}, attrs) 783} 784