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 android 16 17import ( 18 "fmt" 19 "io" 20 "strings" 21) 22 23// TODO(jungw): Now that it handles more than the ones in etc/, consider renaming this file. 24 25func init() { 26 RegisterModuleType("prebuilt_etc", PrebuiltEtcFactory) 27 RegisterModuleType("prebuilt_etc_host", PrebuiltEtcHostFactory) 28 RegisterModuleType("prebuilt_usr_share", PrebuiltUserShareFactory) 29 RegisterModuleType("prebuilt_usr_share_host", PrebuiltUserShareHostFactory) 30 31 PreDepsMutators(func(ctx RegisterMutatorsContext) { 32 ctx.BottomUp("prebuilt_etc", prebuiltEtcMutator).Parallel() 33 }) 34} 35 36type prebuiltEtcProperties struct { 37 // Source file of this prebuilt. 38 Src *string `android:"path,arch_variant"` 39 40 // optional subdirectory under which this file is installed into 41 Sub_dir *string `android:"arch_variant"` 42 43 // optional name for the installed file. If unspecified, name of the module is used as the file name 44 Filename *string `android:"arch_variant"` 45 46 // when set to true, and filename property is not set, the name for the installed file 47 // is the same as the file name of the source file. 48 Filename_from_src *bool `android:"arch_variant"` 49 50 // Make this module available when building for recovery. 51 Recovery_available *bool 52 53 InRecovery bool `blueprint:"mutated"` 54 55 // Whether this module is directly installable to one of the partitions. Default: true. 56 Installable *bool 57} 58 59type PrebuiltEtc struct { 60 ModuleBase 61 62 properties prebuiltEtcProperties 63 64 sourceFilePath Path 65 outputFilePath OutputPath 66 // The base install location, e.g. "etc" for prebuilt_etc, "usr/share" for prebuilt_usr_share. 67 installDirBase string 68 installDirPath OutputPath 69 additionalDependencies *Paths 70} 71 72func (p *PrebuiltEtc) inRecovery() bool { 73 return p.properties.InRecovery || p.ModuleBase.InstallInRecovery() 74} 75 76func (p *PrebuiltEtc) onlyInRecovery() bool { 77 return p.ModuleBase.InstallInRecovery() 78} 79 80func (p *PrebuiltEtc) InstallInRecovery() bool { 81 return p.inRecovery() 82} 83 84func (p *PrebuiltEtc) DepsMutator(ctx BottomUpMutatorContext) { 85 if p.properties.Src == nil { 86 ctx.PropertyErrorf("src", "missing prebuilt source file") 87 } 88} 89 90func (p *PrebuiltEtc) SourceFilePath(ctx ModuleContext) Path { 91 return PathForModuleSrc(ctx, String(p.properties.Src)) 92} 93 94// This allows other derivative modules (e.g. prebuilt_etc_xml) to perform 95// additional steps (like validating the src) before the file is installed. 96func (p *PrebuiltEtc) SetAdditionalDependencies(paths Paths) { 97 p.additionalDependencies = &paths 98} 99 100func (p *PrebuiltEtc) OutputFile() OutputPath { 101 return p.outputFilePath 102} 103 104func (p *PrebuiltEtc) SubDir() string { 105 return String(p.properties.Sub_dir) 106} 107 108func (p *PrebuiltEtc) Installable() bool { 109 return p.properties.Installable == nil || Bool(p.properties.Installable) 110} 111 112func (p *PrebuiltEtc) GenerateAndroidBuildActions(ctx ModuleContext) { 113 p.sourceFilePath = PathForModuleSrc(ctx, String(p.properties.Src)) 114 filename := String(p.properties.Filename) 115 filename_from_src := Bool(p.properties.Filename_from_src) 116 if filename == "" { 117 if filename_from_src { 118 filename = p.sourceFilePath.Base() 119 } else { 120 filename = ctx.ModuleName() 121 } 122 } else if filename_from_src { 123 ctx.PropertyErrorf("filename_from_src", "filename is set. filename_from_src can't be true") 124 return 125 } 126 p.outputFilePath = PathForModuleOut(ctx, filename).OutputPath 127 p.installDirPath = PathForModuleInstall(ctx, p.installDirBase, String(p.properties.Sub_dir)) 128 129 // This ensures that outputFilePath has the correct name for others to 130 // use, as the source file may have a different name. 131 ctx.Build(pctx, BuildParams{ 132 Rule: Cp, 133 Output: p.outputFilePath, 134 Input: p.sourceFilePath, 135 }) 136} 137 138func (p *PrebuiltEtc) AndroidMk() AndroidMkData { 139 return AndroidMkData{ 140 Custom: func(w io.Writer, name, prefix, moduleDir string, data AndroidMkData) { 141 nameSuffix := "" 142 if p.inRecovery() && !p.onlyInRecovery() { 143 nameSuffix = ".recovery" 144 } 145 fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)") 146 fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir) 147 fmt.Fprintln(w, "LOCAL_MODULE :=", name+nameSuffix) 148 fmt.Fprintln(w, "LOCAL_MODULE_CLASS := ETC") 149 if p.commonProperties.Owner != nil { 150 fmt.Fprintln(w, "LOCAL_MODULE_OWNER :=", *p.commonProperties.Owner) 151 } 152 fmt.Fprintln(w, "LOCAL_MODULE_TAGS := optional") 153 if p.Host() { 154 fmt.Fprintln(w, "LOCAL_IS_HOST_MODULE := true") 155 } 156 fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", p.outputFilePath.String()) 157 fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", "$(OUT_DIR)/"+p.installDirPath.RelPathString()) 158 fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", p.outputFilePath.Base()) 159 fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE :=", !p.Installable()) 160 fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES :=", strings.Join(data.Required, " ")) 161 fmt.Fprintln(w, "LOCAL_MODULE_TARGET_ARCH :=", p.Arch().ArchType.String()) 162 if p.additionalDependencies != nil { 163 fmt.Fprint(w, "LOCAL_ADDITIONAL_DEPENDENCIES :=") 164 for _, path := range *p.additionalDependencies { 165 fmt.Fprint(w, " "+path.String()) 166 } 167 fmt.Fprintln(w, "") 168 } 169 fmt.Fprintln(w, "include $(BUILD_PREBUILT)") 170 }, 171 } 172} 173 174func InitPrebuiltEtcModule(p *PrebuiltEtc) { 175 p.AddProperties(&p.properties) 176} 177 178// prebuilt_etc is for a prebuilt artifact that is installed in 179// <partition>/etc/<sub_dir> directory. 180func PrebuiltEtcFactory() Module { 181 module := &PrebuiltEtc{installDirBase: "etc"} 182 InitPrebuiltEtcModule(module) 183 // This module is device-only 184 InitAndroidArchModule(module, DeviceSupported, MultilibFirst) 185 return module 186} 187 188// prebuilt_etc_host is for a host prebuilt artifact that is installed in 189// $(HOST_OUT)/etc/<sub_dir> directory. 190func PrebuiltEtcHostFactory() Module { 191 module := &PrebuiltEtc{installDirBase: "etc"} 192 InitPrebuiltEtcModule(module) 193 // This module is host-only 194 InitAndroidArchModule(module, HostSupported, MultilibCommon) 195 return module 196} 197 198// prebuilt_usr_share is for a prebuilt artifact that is installed in 199// <partition>/usr/share/<sub_dir> directory. 200func PrebuiltUserShareFactory() Module { 201 module := &PrebuiltEtc{installDirBase: "usr/share"} 202 InitPrebuiltEtcModule(module) 203 // This module is device-only 204 InitAndroidArchModule(module, DeviceSupported, MultilibFirst) 205 return module 206} 207 208// prebuild_usr_share_host is for a host prebuilt artifact that is installed in 209// $(HOST_OUT)/usr/share/<sub_dir> directory. 210func PrebuiltUserShareHostFactory() Module { 211 module := &PrebuiltEtc{installDirBase: "usr/share"} 212 InitPrebuiltEtcModule(module) 213 // This module is host-only 214 InitAndroidArchModule(module, HostSupported, MultilibCommon) 215 return module 216} 217 218const ( 219 // coreMode is the variant for modules to be installed to system. 220 coreMode = "core" 221 222 // recoveryMode means a module to be installed to recovery image. 223 recoveryMode = "recovery" 224) 225 226// prebuiltEtcMutator creates the needed variants to install the module to 227// system or recovery. 228func prebuiltEtcMutator(mctx BottomUpMutatorContext) { 229 m, ok := mctx.Module().(*PrebuiltEtc) 230 if !ok || m.Host() { 231 return 232 } 233 234 var coreVariantNeeded bool = true 235 var recoveryVariantNeeded bool = false 236 if Bool(m.properties.Recovery_available) { 237 recoveryVariantNeeded = true 238 } 239 240 if m.ModuleBase.InstallInRecovery() { 241 recoveryVariantNeeded = true 242 coreVariantNeeded = false 243 } 244 245 var variants []string 246 if coreVariantNeeded { 247 variants = append(variants, coreMode) 248 } 249 if recoveryVariantNeeded { 250 variants = append(variants, recoveryMode) 251 } 252 mod := mctx.CreateVariations(variants...) 253 for i, v := range variants { 254 if v == recoveryMode { 255 m := mod[i].(*PrebuiltEtc) 256 m.properties.InRecovery = true 257 } 258 } 259} 260