host_fake_snapshot.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. // Copyright 2021 The Android Open Source Project
  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. package snapshot
  15. import (
  16. "encoding/json"
  17. "path/filepath"
  18. "android/soong/android"
  19. )
  20. // The host_snapshot module creates a snapshot of host tools to be used
  21. // in a minimal source tree. In order to create the host_snapshot the
  22. // user must explicitly list the modules to be included. The
  23. // host-fake-snapshot, defined in this file, is a utility to help determine
  24. // which host modules are being used in the minimal source tree.
  25. //
  26. // The host-fake-snapshot is designed to run in a full source tree and
  27. // will result in a snapshot that contains an empty file for each host
  28. // tool found in the tree. The fake snapshot is only used to determine
  29. // the host modules that the minimal source tree depends on, hence the
  30. // snapshot uses an empty file for each module and saves on having to
  31. // actually build any tool to generate the snapshot. The fake snapshot
  32. // is compatible with an actual host_snapshot and is installed into a
  33. // minimal source tree via the development/vendor_snapshot/update.py
  34. // script.
  35. //
  36. // After generating the fake snapshot and installing into the minimal
  37. // source tree, the dependent modules are determined via the
  38. // development/vendor_snapshot/update.py script (see script for more
  39. // information). These modules are then used to define the actual
  40. // host_snapshot to be used. This is a similar process to the other
  41. // snapshots (vendor, recovery,...)
  42. //
  43. // Example
  44. //
  45. // Full source tree:
  46. // 1/ Generate fake host snapshot
  47. //
  48. // Minimal source tree:
  49. // 2/ Install the fake host snapshot
  50. // 3/ List the host modules used from the snapshot
  51. // 4/ Remove fake host snapshot
  52. //
  53. // Full source tree:
  54. // 4/ Create host_snapshot with modules identified in step 3
  55. //
  56. // Minimal source tree:
  57. // 5/ Install host snapshot
  58. // 6/ Build
  59. //
  60. // The host-fake-snapshot is a singleton module, that will be built
  61. // if HOST_FAKE_SNAPSHOT_ENABLE=true.
  62. func init() {
  63. registerHostSnapshotComponents(android.InitRegistrationContext)
  64. }
  65. // Add prebuilt information to snapshot data
  66. type hostSnapshotFakeJsonFlags struct {
  67. SnapshotJsonFlags
  68. Prebuilt bool `json:",omitempty"`
  69. }
  70. func registerHostSnapshotComponents(ctx android.RegistrationContext) {
  71. ctx.RegisterParallelSingletonType("host-fake-snapshot", HostToolsFakeAndroidSingleton)
  72. }
  73. type hostFakeSingleton struct {
  74. snapshotDir string
  75. zipFile android.OptionalPath
  76. }
  77. func (c *hostFakeSingleton) init() {
  78. c.snapshotDir = "host-fake-snapshot"
  79. }
  80. func HostToolsFakeAndroidSingleton() android.Singleton {
  81. singleton := &hostFakeSingleton{}
  82. singleton.init()
  83. return singleton
  84. }
  85. func (c *hostFakeSingleton) GenerateBuildActions(ctx android.SingletonContext) {
  86. if !ctx.DeviceConfig().HostFakeSnapshotEnabled() {
  87. return
  88. }
  89. // Find all host binary modules add 'fake' versions to snapshot
  90. var outputs android.Paths
  91. seen := make(map[string]bool)
  92. var jsonData []hostSnapshotFakeJsonFlags
  93. prebuilts := make(map[string]bool)
  94. ctx.VisitAllModules(func(module android.Module) {
  95. if module.Target().Os != ctx.Config().BuildOSTarget.Os {
  96. return
  97. }
  98. if module.Target().Arch.ArchType != ctx.Config().BuildOSTarget.Arch.ArchType {
  99. return
  100. }
  101. if android.IsModulePrebuilt(module) {
  102. // Add non-prebuilt module name to map of prebuilts
  103. prebuilts[android.RemoveOptionalPrebuiltPrefix(module.Name())] = true
  104. return
  105. }
  106. if !module.Enabled() || module.IsHideFromMake() {
  107. return
  108. }
  109. apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
  110. if !apexInfo.IsForPlatform() {
  111. return
  112. }
  113. path := hostToolPath(module)
  114. if path.Valid() && path.String() != "" {
  115. outFile := filepath.Join(c.snapshotDir, path.String())
  116. if !seen[outFile] {
  117. seen[outFile] = true
  118. outputs = append(outputs, WriteStringToFileRule(ctx, "", outFile))
  119. jsonData = append(jsonData, hostSnapshotFakeJsonFlags{*hostJsonDesc(module), false})
  120. }
  121. }
  122. })
  123. // Update any module prebuilt information
  124. for idx, _ := range jsonData {
  125. if _, ok := prebuilts[jsonData[idx].ModuleName]; ok {
  126. // Prebuilt exists for this module
  127. jsonData[idx].Prebuilt = true
  128. }
  129. }
  130. marsh, err := json.Marshal(jsonData)
  131. if err != nil {
  132. ctx.Errorf("host fake snapshot json marshal failure: %#v", err)
  133. return
  134. }
  135. outputs = append(outputs, WriteStringToFileRule(ctx, string(marsh), filepath.Join(c.snapshotDir, "host_snapshot.json")))
  136. c.zipFile = zipSnapshot(ctx, c.snapshotDir, c.snapshotDir, outputs)
  137. }
  138. func (c *hostFakeSingleton) MakeVars(ctx android.MakeVarsContext) {
  139. if !c.zipFile.Valid() {
  140. return
  141. }
  142. ctx.Phony(
  143. "host-fake-snapshot",
  144. c.zipFile.Path())
  145. ctx.DistForGoal(
  146. "host-fake-snapshot",
  147. c.zipFile.Path())
  148. }