1// Copyright (C) 2020 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 cuttlefish 16 17import ( 18 "fmt" 19 "strings" 20 21 "github.com/google/blueprint" 22 "github.com/google/blueprint/proptools" 23 24 "android/soong/android" 25) 26 27func init() { 28 android.RegisterModuleType("cvd_host_package", cvdHostPackageFactory) 29 android.RegisterParallelSingletonType("cvd_host_package_singleton", cvdHostPackageSingletonFactory) 30} 31 32type cvdHostPackage struct { 33 android.ModuleBase 34 android.PackagingBase 35 tarballFile android.InstallPath 36 stampFile android.InstallPath 37} 38 39func cvdHostPackageFactory() android.Module { 40 module := &cvdHostPackage{} 41 android.InitPackageModule(module) 42 android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst) 43 module.IgnoreMissingDependencies = true 44 return module 45} 46 47type cvdHostPackageSingleton struct { 48 tarballPaths android.Paths 49} 50 51func cvdHostPackageSingletonFactory() android.Singleton { 52 return &cvdHostPackageSingleton{} 53} 54 55type dependencyTag struct { 56 blueprint.BaseDependencyTag 57 android.InstallAlwaysNeededDependencyTag // to force installation of both "deps" and manually added dependencies 58 android.PackagingItemAlwaysDepTag // to force packaging of both "deps" and manually added dependencies 59} 60 61var cvdHostPackageDependencyTag = dependencyTag{} 62 63func (c *cvdHostPackage) DepsMutator(ctx android.BottomUpMutatorContext) { 64 c.AddDeps(ctx, cvdHostPackageDependencyTag) 65 66 variations := []blueprint.Variation{ 67 {Mutator: "os", Variation: ctx.Target().Os.String()}, 68 {Mutator: "arch", Variation: android.Common.String()}, 69 } 70 for _, dep := range strings.Split( 71 ctx.Config().VendorConfig("cvd").String("grub_config"), " ") { 72 if ctx.OtherModuleExists(dep) { 73 ctx.AddVariationDependencies(variations, cvdHostPackageDependencyTag, dep) 74 } 75 } 76 for _, dep := range strings.Split( 77 ctx.Config().VendorConfig("cvd").String("launch_configs"), " ") { 78 if ctx.OtherModuleExists(dep) { 79 ctx.AddVariationDependencies(variations, cvdHostPackageDependencyTag, dep) 80 } 81 } 82 83 for _, dep := range strings.Split( 84 ctx.Config().VendorConfig("cvd").String("binary"), " ") { 85 if ctx.OtherModuleExists(dep) { 86 ctx.AddVariationDependencies(ctx.Target().Variations(), cvdHostPackageDependencyTag, dep) 87 } 88 } 89 90 // If cvd_custom_action_config is set, include custom action servers in the 91 // host package as specified by cvd_custom_action_servers. 92 customActionConfig := ctx.Config().VendorConfig("cvd").String("custom_action_config") 93 if customActionConfig != "" && ctx.OtherModuleExists(customActionConfig) { 94 ctx.AddVariationDependencies(variations, cvdHostPackageDependencyTag, 95 customActionConfig) 96 for _, dep := range strings.Split( 97 ctx.Config().VendorConfig("cvd").String("custom_action_servers"), " ") { 98 if ctx.OtherModuleExists(dep) { 99 ctx.AddVariationDependencies(nil, cvdHostPackageDependencyTag, dep) 100 } 101 } 102 } 103 104 // Include custom CSS file in host package if custom_style is set 105 custom_style := ctx.Config().VendorConfig("cvd").String("custom_style") 106 if custom_style == "" || !ctx.OtherModuleExists(custom_style) { 107 custom_style = "webrtc_custom_blank.css" 108 } 109 ctx.AddVariationDependencies(variations, cvdHostPackageDependencyTag, custom_style) 110} 111 112var pctx = android.NewPackageContext("android/soong/cuttlefish") 113 114func (c *cvdHostPackage) GenerateAndroidBuildActions(ctx android.ModuleContext) { 115 packageDir := android.PathForModuleInstall(ctx, c.BaseModuleName()) 116 117 stamp := android.PathForModuleOut(ctx, "package.stamp") 118 dirBuilder := android.NewRuleBuilder(pctx, ctx) 119 dirBuilder.Command().Text("rm").Flag("-rf").Text(packageDir.String()) 120 dirBuilder.Command().Text("mkdir").Flag("-p").Text(packageDir.String()) 121 c.CopySpecsToDir(ctx, dirBuilder, c.GatherPackagingSpecs(ctx), packageDir) 122 dirBuilder.Command().Text("touch").Output(stamp) 123 dirBuilder.Build("cvd_host_package", fmt.Sprintf("Packaging %s", c.BaseModuleName())) 124 ctx.InstallFile(android.PathForModuleInstall(ctx), c.BaseModuleName()+".stamp", stamp) 125 c.stampFile = android.PathForModuleInPartitionInstall(ctx, c.BaseModuleName()+".stamp") 126 127 tarball := android.PathForModuleOut(ctx, "package.tar.gz") 128 tarballBuilder := android.NewRuleBuilder(pctx, ctx) 129 tarballBuilder.Command().Text("tar Scfz"). 130 Output(tarball). 131 Flag("-C"). 132 Text(packageDir.String()). 133 Implicit(stamp). 134 Flag("--mtime='2020-01-01'"). // to have reproducible builds 135 Text(".") 136 tarballBuilder.Build("cvd_host_tarball", fmt.Sprintf("Creating tarball for %s", c.BaseModuleName())) 137 ctx.InstallFile(android.PathForModuleInstall(ctx), c.BaseModuleName()+".tar.gz", tarball) 138 c.tarballFile = android.PathForModuleInstall(ctx, c.BaseModuleName()+".tar.gz") 139} 140 141type cvdHostPackageMetadataProvider interface { 142 tarballMetadata() android.Path 143 stampMetadata() android.Path 144} 145 146func (p *cvdHostPackage) tarballMetadata() android.Path { 147 return p.tarballFile 148} 149 150func (p *cvdHostPackage) stampMetadata() android.Path { 151 return p.stampFile 152} 153 154// Create "hosttar" phony target with "cvd-host_package.tar.gz" path. 155// Add stamp files into "droidcore" dependency. 156func (p *cvdHostPackageSingleton) GenerateBuildActions(ctx android.SingletonContext) { 157 var cvdHostPackageTarball android.Paths 158 var cvdHostPackageStamp android.Paths 159 160 ctx.VisitAllModules(func(module android.Module) { 161 if !module.Enabled(ctx) { 162 return 163 } 164 if c, ok := module.(cvdHostPackageMetadataProvider); ok { 165 if !android.IsModulePreferred(module) { 166 return 167 } 168 cvdHostPackageTarball = append(cvdHostPackageTarball, c.tarballMetadata()) 169 cvdHostPackageStamp = append(cvdHostPackageStamp, c.stampMetadata()) 170 } 171 }) 172 173 if cvdHostPackageTarball == nil { 174 // nothing to do. 175 return 176 } 177 178 board_platform := proptools.String(ctx.Config().ProductVariables().BoardPlatform) 179 if (board_platform == "vsoc_arm") || (board_platform == "vsoc_arm64") || (board_platform == "vsoc_riscv64") || (board_platform == "vsoc_x86") || (board_platform == "vsoc_x86_64") { 180 p.tarballPaths = cvdHostPackageTarball 181 ctx.Phony("hosttar", cvdHostPackageTarball...) 182 ctx.Phony("droidcore", cvdHostPackageStamp...) 183 } 184} 185 186func (p *cvdHostPackageSingleton) MakeVars(ctx android.MakeVarsContext) { 187 if p.tarballPaths != nil { 188 for _, path := range p.tarballPaths { 189 // The riscv64 cuttlefish builds can be run on qemu on an x86_64 or arm64 host. Dist both sets of host packages. 190 if len(p.tarballPaths) > 1 && strings.Contains(path.String(), "linux-x86") { 191 ctx.DistForGoalWithFilename("dist_files", path, "cvd-host_package-x86_64.tar.gz") 192 } else { 193 ctx.DistForGoal("dist_files", path) 194 } 195 } 196 } 197} 198