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 "reflect" 20 21 "github.com/google/blueprint" 22 "github.com/google/blueprint/proptools" 23) 24 25// This file implements common functionality for handling modules that may exist as prebuilts, 26// source, or both. 27 28func RegisterPrebuiltMutators(ctx RegistrationContext) { 29 ctx.PreArchMutators(RegisterPrebuiltsPreArchMutators) 30 ctx.PostDepsMutators(RegisterPrebuiltsPostDepsMutators) 31} 32 33type prebuiltDependencyTag struct { 34 blueprint.BaseDependencyTag 35} 36 37var PrebuiltDepTag prebuiltDependencyTag 38 39// Mark this tag so dependencies that use it are excluded from visibility enforcement. 40func (t prebuiltDependencyTag) ExcludeFromVisibilityEnforcement() {} 41 42// Mark this tag so dependencies that use it are excluded from APEX contents. 43func (t prebuiltDependencyTag) ExcludeFromApexContents() {} 44 45var _ ExcludeFromVisibilityEnforcementTag = PrebuiltDepTag 46var _ ExcludeFromApexContentsTag = PrebuiltDepTag 47 48type PrebuiltProperties struct { 49 // When prefer is set to true the prebuilt will be used instead of any source module with 50 // a matching name. 51 Prefer *bool `android:"arch_variant"` 52 53 SourceExists bool `blueprint:"mutated"` 54 UsePrebuilt bool `blueprint:"mutated"` 55} 56 57type Prebuilt struct { 58 properties PrebuiltProperties 59 60 srcsSupplier PrebuiltSrcsSupplier 61 srcsPropertyName string 62} 63 64func (p *Prebuilt) Name(name string) string { 65 return "prebuilt_" + name 66} 67 68func (p *Prebuilt) ForcePrefer() { 69 p.properties.Prefer = proptools.BoolPtr(true) 70} 71 72func (p *Prebuilt) Prefer() bool { 73 return proptools.Bool(p.properties.Prefer) 74} 75 76// The below source-related functions and the srcs, src fields are based on an assumption that 77// prebuilt modules have a static source property at the moment. Currently there is only one 78// exception, android_app_import, which chooses a source file depending on the product's DPI 79// preference configs. We'll want to add native support for dynamic source cases if we end up having 80// more modules like this. 81func (p *Prebuilt) SingleSourcePath(ctx ModuleContext) Path { 82 if p.srcsSupplier != nil { 83 srcs := p.srcsSupplier() 84 85 if len(srcs) == 0 { 86 ctx.PropertyErrorf(p.srcsPropertyName, "missing prebuilt source file") 87 return nil 88 } 89 90 if len(srcs) > 1 { 91 ctx.PropertyErrorf(p.srcsPropertyName, "multiple prebuilt source files") 92 return nil 93 } 94 95 // Return the singleton source after expanding any filegroup in the 96 // sources. 97 src := srcs[0] 98 return PathForModuleSrc(ctx, src) 99 } else { 100 ctx.ModuleErrorf("prebuilt source was not set") 101 return nil 102 } 103} 104 105func (p *Prebuilt) UsePrebuilt() bool { 106 return p.properties.UsePrebuilt 107} 108 109// Called to provide the srcs value for the prebuilt module. 110// 111// Return the src value or nil if it is not available. 112type PrebuiltSrcsSupplier func() []string 113 114// Initialize the module as a prebuilt module that uses the provided supplier to access the 115// prebuilt sources of the module. 116// 117// The supplier will be called multiple times and must return the same values each time it 118// is called. If it returns an empty array (or nil) then the prebuilt module will not be used 119// as a replacement for a source module with the same name even if prefer = true. 120// 121// If the Prebuilt.SingleSourcePath() is called on the module then this must return an array 122// containing exactly one source file. 123// 124// The provided property name is used to provide helpful error messages in the event that 125// a problem arises, e.g. calling SingleSourcePath() when more than one source is provided. 126func InitPrebuiltModuleWithSrcSupplier(module PrebuiltInterface, srcsSupplier PrebuiltSrcsSupplier, srcsPropertyName string) { 127 p := module.Prebuilt() 128 module.AddProperties(&p.properties) 129 130 if srcsSupplier == nil { 131 panic(fmt.Errorf("srcsSupplier must not be nil")) 132 } 133 if srcsPropertyName == "" { 134 panic(fmt.Errorf("srcsPropertyName must not be empty")) 135 } 136 137 p.srcsSupplier = srcsSupplier 138 p.srcsPropertyName = srcsPropertyName 139} 140 141func InitPrebuiltModule(module PrebuiltInterface, srcs *[]string) { 142 if srcs == nil { 143 panic(fmt.Errorf("srcs must not be nil")) 144 } 145 146 srcsSupplier := func() []string { 147 return *srcs 148 } 149 150 InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, "srcs") 151} 152 153func InitSingleSourcePrebuiltModule(module PrebuiltInterface, srcProps interface{}, srcField string) { 154 srcPropsValue := reflect.ValueOf(srcProps).Elem() 155 srcStructField, _ := srcPropsValue.Type().FieldByName(srcField) 156 if !srcPropsValue.IsValid() || srcStructField.Name == "" { 157 panic(fmt.Errorf("invalid single source prebuilt %+v", module)) 158 } 159 160 if srcPropsValue.Kind() != reflect.Struct && srcPropsValue.Kind() != reflect.Interface { 161 panic(fmt.Errorf("invalid single source prebuilt %+v", srcProps)) 162 } 163 164 srcFieldIndex := srcStructField.Index 165 srcPropertyName := proptools.PropertyNameForField(srcField) 166 167 srcsSupplier := func() []string { 168 value := srcPropsValue.FieldByIndex(srcFieldIndex) 169 if value.Kind() == reflect.Ptr { 170 value = value.Elem() 171 } 172 if value.Kind() != reflect.String { 173 panic(fmt.Errorf("prebuilt src field %q should be a string or a pointer to one but was %d %q", srcPropertyName, value.Kind(), value)) 174 } 175 src := value.String() 176 if src == "" { 177 return nil 178 } 179 return []string{src} 180 } 181 182 InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, srcPropertyName) 183} 184 185type PrebuiltInterface interface { 186 Module 187 Prebuilt() *Prebuilt 188} 189 190func RegisterPrebuiltsPreArchMutators(ctx RegisterMutatorsContext) { 191 ctx.BottomUp("prebuilts", PrebuiltMutator).Parallel() 192} 193 194func RegisterPrebuiltsPostDepsMutators(ctx RegisterMutatorsContext) { 195 ctx.TopDown("prebuilt_select", PrebuiltSelectModuleMutator).Parallel() 196 ctx.BottomUp("prebuilt_postdeps", PrebuiltPostDepsMutator).Parallel() 197} 198 199// PrebuiltMutator ensures that there is always a module with an undecorated name, and marks 200// prebuilt modules that have both a prebuilt and a source module. 201func PrebuiltMutator(ctx BottomUpMutatorContext) { 202 if m, ok := ctx.Module().(PrebuiltInterface); ok && m.Prebuilt() != nil { 203 p := m.Prebuilt() 204 name := m.base().BaseModuleName() 205 if ctx.OtherModuleExists(name) { 206 ctx.AddReverseDependency(ctx.Module(), PrebuiltDepTag, name) 207 p.properties.SourceExists = true 208 } else { 209 ctx.Rename(name) 210 } 211 } 212} 213 214// PrebuiltSelectModuleMutator marks prebuilts that are used, either overriding source modules or 215// because the source module doesn't exist. It also disables installing overridden source modules. 216func PrebuiltSelectModuleMutator(ctx TopDownMutatorContext) { 217 if m, ok := ctx.Module().(PrebuiltInterface); ok && m.Prebuilt() != nil { 218 p := m.Prebuilt() 219 if p.srcsSupplier == nil { 220 panic(fmt.Errorf("prebuilt module did not have InitPrebuiltModule called on it")) 221 } 222 if !p.properties.SourceExists { 223 p.properties.UsePrebuilt = p.usePrebuilt(ctx, nil) 224 } 225 } else if s, ok := ctx.Module().(Module); ok { 226 ctx.VisitDirectDepsWithTag(PrebuiltDepTag, func(m Module) { 227 p := m.(PrebuiltInterface).Prebuilt() 228 if p.usePrebuilt(ctx, s) { 229 p.properties.UsePrebuilt = true 230 s.SkipInstall() 231 } 232 }) 233 } 234} 235 236// PrebuiltPostDepsMutator does two operations. It replace dependencies on the 237// source module with dependencies on the prebuilt when both modules exist and 238// the prebuilt should be used. When the prebuilt should not be used, disable 239// installing it. Secondly, it also adds a sourcegroup to any filegroups found 240// in the prebuilt's 'Srcs' property. 241func PrebuiltPostDepsMutator(ctx BottomUpMutatorContext) { 242 if m, ok := ctx.Module().(PrebuiltInterface); ok && m.Prebuilt() != nil { 243 p := m.Prebuilt() 244 name := m.base().BaseModuleName() 245 if p.properties.UsePrebuilt { 246 if p.properties.SourceExists { 247 ctx.ReplaceDependencies(name) 248 } 249 } else { 250 m.SkipInstall() 251 } 252 } 253} 254 255// usePrebuilt returns true if a prebuilt should be used instead of the source module. The prebuilt 256// will be used if it is marked "prefer" or if the source module is disabled. 257func (p *Prebuilt) usePrebuilt(ctx TopDownMutatorContext, source Module) bool { 258 if p.srcsSupplier != nil && len(p.srcsSupplier()) == 0 { 259 return false 260 } 261 262 // TODO: use p.Properties.Name and ctx.ModuleDir to override preference 263 if Bool(p.properties.Prefer) { 264 return true 265 } 266 267 return source == nil || !source.Enabled() 268} 269 270func (p *Prebuilt) SourceExists() bool { 271 return p.properties.SourceExists 272} 273