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