1*333d2b36SAndroid Build Coastguard Worker// Copyright 2016 Google Inc. All rights reserved. 2*333d2b36SAndroid Build Coastguard Worker// 3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); 4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License. 5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at 6*333d2b36SAndroid Build Coastguard Worker// 7*333d2b36SAndroid Build Coastguard Worker// http://www.apache.org/licenses/LICENSE-2.0 8*333d2b36SAndroid Build Coastguard Worker// 9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, 11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and 13*333d2b36SAndroid Build Coastguard Worker// limitations under the License. 14*333d2b36SAndroid Build Coastguard Worker 15*333d2b36SAndroid Build Coastguard Workerpackage android 16*333d2b36SAndroid Build Coastguard Worker 17*333d2b36SAndroid Build Coastguard Workerimport ( 18*333d2b36SAndroid Build Coastguard Worker "fmt" 19*333d2b36SAndroid Build Coastguard Worker "reflect" 20*333d2b36SAndroid Build Coastguard Worker "strings" 21*333d2b36SAndroid Build Coastguard Worker 22*333d2b36SAndroid Build Coastguard Worker "github.com/google/blueprint" 23*333d2b36SAndroid Build Coastguard Worker "github.com/google/blueprint/proptools" 24*333d2b36SAndroid Build Coastguard Worker) 25*333d2b36SAndroid Build Coastguard Worker 26*333d2b36SAndroid Build Coastguard Worker// This file implements common functionality for handling modules that may exist as prebuilts, 27*333d2b36SAndroid Build Coastguard Worker// source, or both. 28*333d2b36SAndroid Build Coastguard Worker 29*333d2b36SAndroid Build Coastguard Workerfunc RegisterPrebuiltMutators(ctx RegistrationContext) { 30*333d2b36SAndroid Build Coastguard Worker ctx.PreArchMutators(RegisterPrebuiltsPreArchMutators) 31*333d2b36SAndroid Build Coastguard Worker ctx.PostDepsMutators(RegisterPrebuiltsPostDepsMutators) 32*333d2b36SAndroid Build Coastguard Worker} 33*333d2b36SAndroid Build Coastguard Worker 34*333d2b36SAndroid Build Coastguard Worker// Marks a dependency tag as possibly preventing a reference to a source from being 35*333d2b36SAndroid Build Coastguard Worker// replaced with the prebuilt. 36*333d2b36SAndroid Build Coastguard Workertype ReplaceSourceWithPrebuilt interface { 37*333d2b36SAndroid Build Coastguard Worker blueprint.DependencyTag 38*333d2b36SAndroid Build Coastguard Worker 39*333d2b36SAndroid Build Coastguard Worker // Return true if the dependency defined by this tag should be replaced with the 40*333d2b36SAndroid Build Coastguard Worker // prebuilt. 41*333d2b36SAndroid Build Coastguard Worker ReplaceSourceWithPrebuilt() bool 42*333d2b36SAndroid Build Coastguard Worker} 43*333d2b36SAndroid Build Coastguard Worker 44*333d2b36SAndroid Build Coastguard Workertype prebuiltDependencyTag struct { 45*333d2b36SAndroid Build Coastguard Worker blueprint.BaseDependencyTag 46*333d2b36SAndroid Build Coastguard Worker} 47*333d2b36SAndroid Build Coastguard Worker 48*333d2b36SAndroid Build Coastguard Workervar PrebuiltDepTag prebuiltDependencyTag 49*333d2b36SAndroid Build Coastguard Worker 50*333d2b36SAndroid Build Coastguard Worker// Mark this tag so dependencies that use it are excluded from visibility enforcement. 51*333d2b36SAndroid Build Coastguard Workerfunc (t prebuiltDependencyTag) ExcludeFromVisibilityEnforcement() {} 52*333d2b36SAndroid Build Coastguard Worker 53*333d2b36SAndroid Build Coastguard Worker// Mark this tag so dependencies that use it are excluded from APEX contents. 54*333d2b36SAndroid Build Coastguard Workerfunc (t prebuiltDependencyTag) ExcludeFromApexContents() {} 55*333d2b36SAndroid Build Coastguard Worker 56*333d2b36SAndroid Build Coastguard Workervar _ ExcludeFromVisibilityEnforcementTag = PrebuiltDepTag 57*333d2b36SAndroid Build Coastguard Workervar _ ExcludeFromApexContentsTag = PrebuiltDepTag 58*333d2b36SAndroid Build Coastguard Worker 59*333d2b36SAndroid Build Coastguard Worker// UserSuppliedPrebuiltProperties contains the prebuilt properties that can be specified in an 60*333d2b36SAndroid Build Coastguard Worker// Android.bp file. 61*333d2b36SAndroid Build Coastguard Workertype UserSuppliedPrebuiltProperties struct { 62*333d2b36SAndroid Build Coastguard Worker // When prefer is set to true the prebuilt will be used instead of any source module with 63*333d2b36SAndroid Build Coastguard Worker // a matching name. 64*333d2b36SAndroid Build Coastguard Worker Prefer proptools.Configurable[bool] `android:"arch_variant,replace_instead_of_append"` 65*333d2b36SAndroid Build Coastguard Worker 66*333d2b36SAndroid Build Coastguard Worker // When specified this names a Soong config variable that controls the prefer property. 67*333d2b36SAndroid Build Coastguard Worker // 68*333d2b36SAndroid Build Coastguard Worker // If the value of the named Soong config variable is true then prefer is set to false and vice 69*333d2b36SAndroid Build Coastguard Worker // versa. If the Soong config variable is not set then it defaults to false, so prefer defaults 70*333d2b36SAndroid Build Coastguard Worker // to true. 71*333d2b36SAndroid Build Coastguard Worker // 72*333d2b36SAndroid Build Coastguard Worker // If specified then the prefer property is ignored in favor of the value of the Soong config 73*333d2b36SAndroid Build Coastguard Worker // variable. 74*333d2b36SAndroid Build Coastguard Worker // 75*333d2b36SAndroid Build Coastguard Worker // DEPRECATED: This property is being deprecated b/308188211. 76*333d2b36SAndroid Build Coastguard Worker // Use RELEASE_APEX_CONTRIBUTIONS build flags to select prebuilts of mainline modules. 77*333d2b36SAndroid Build Coastguard Worker Use_source_config_var *ConfigVarProperties 78*333d2b36SAndroid Build Coastguard Worker} 79*333d2b36SAndroid Build Coastguard Worker 80*333d2b36SAndroid Build Coastguard Worker// CopyUserSuppliedPropertiesFromPrebuilt copies the user supplied prebuilt properties from the 81*333d2b36SAndroid Build Coastguard Worker// prebuilt properties. 82*333d2b36SAndroid Build Coastguard Workerfunc (u *UserSuppliedPrebuiltProperties) CopyUserSuppliedPropertiesFromPrebuilt(p *Prebuilt) { 83*333d2b36SAndroid Build Coastguard Worker *u = p.properties.UserSuppliedPrebuiltProperties 84*333d2b36SAndroid Build Coastguard Worker} 85*333d2b36SAndroid Build Coastguard Worker 86*333d2b36SAndroid Build Coastguard Workertype PrebuiltProperties struct { 87*333d2b36SAndroid Build Coastguard Worker UserSuppliedPrebuiltProperties 88*333d2b36SAndroid Build Coastguard Worker 89*333d2b36SAndroid Build Coastguard Worker SourceExists bool `blueprint:"mutated"` 90*333d2b36SAndroid Build Coastguard Worker UsePrebuilt bool `blueprint:"mutated"` 91*333d2b36SAndroid Build Coastguard Worker 92*333d2b36SAndroid Build Coastguard Worker // Set if the module has been renamed to remove the "prebuilt_" prefix. 93*333d2b36SAndroid Build Coastguard Worker PrebuiltRenamedToSource bool `blueprint:"mutated"` 94*333d2b36SAndroid Build Coastguard Worker} 95*333d2b36SAndroid Build Coastguard Worker 96*333d2b36SAndroid Build Coastguard Worker// Properties that can be used to select a Soong config variable. 97*333d2b36SAndroid Build Coastguard Workertype ConfigVarProperties struct { 98*333d2b36SAndroid Build Coastguard Worker // Allow instances of this struct to be used as a property value in a BpPropertySet. 99*333d2b36SAndroid Build Coastguard Worker BpPrintableBase 100*333d2b36SAndroid Build Coastguard Worker 101*333d2b36SAndroid Build Coastguard Worker // The name of the configuration namespace. 102*333d2b36SAndroid Build Coastguard Worker // 103*333d2b36SAndroid Build Coastguard Worker // As passed to add_soong_config_namespace in Make. 104*333d2b36SAndroid Build Coastguard Worker Config_namespace *string 105*333d2b36SAndroid Build Coastguard Worker 106*333d2b36SAndroid Build Coastguard Worker // The name of the configuration variable. 107*333d2b36SAndroid Build Coastguard Worker // 108*333d2b36SAndroid Build Coastguard Worker // As passed to add_soong_config_var_value in Make. 109*333d2b36SAndroid Build Coastguard Worker Var_name *string 110*333d2b36SAndroid Build Coastguard Worker} 111*333d2b36SAndroid Build Coastguard Worker 112*333d2b36SAndroid Build Coastguard Workertype Prebuilt struct { 113*333d2b36SAndroid Build Coastguard Worker properties PrebuiltProperties 114*333d2b36SAndroid Build Coastguard Worker 115*333d2b36SAndroid Build Coastguard Worker // nil if the prebuilt has no srcs property at all. See InitPrebuiltModuleWithoutSrcs. 116*333d2b36SAndroid Build Coastguard Worker srcsSupplier PrebuiltSrcsSupplier 117*333d2b36SAndroid Build Coastguard Worker 118*333d2b36SAndroid Build Coastguard Worker // "-" if the prebuilt has no srcs property at all. See InitPrebuiltModuleWithoutSrcs. 119*333d2b36SAndroid Build Coastguard Worker srcsPropertyName string 120*333d2b36SAndroid Build Coastguard Worker} 121*333d2b36SAndroid Build Coastguard Worker 122*333d2b36SAndroid Build Coastguard Worker// RemoveOptionalPrebuiltPrefix returns the result of removing the "prebuilt_" prefix from the 123*333d2b36SAndroid Build Coastguard Worker// supplied name if it has one, or returns the name unmodified if it does not. 124*333d2b36SAndroid Build Coastguard Workerfunc RemoveOptionalPrebuiltPrefix(name string) string { 125*333d2b36SAndroid Build Coastguard Worker return strings.TrimPrefix(name, "prebuilt_") 126*333d2b36SAndroid Build Coastguard Worker} 127*333d2b36SAndroid Build Coastguard Worker 128*333d2b36SAndroid Build Coastguard Worker// RemoveOptionalPrebuiltPrefixFromBazelLabel removes the "prebuilt_" prefix from the *target name* of a Bazel label. 129*333d2b36SAndroid Build Coastguard Worker// This differs from RemoveOptionalPrebuiltPrefix in that it does not remove it from the start of the string, but 130*333d2b36SAndroid Build Coastguard Worker// instead removes it from the target name itself. 131*333d2b36SAndroid Build Coastguard Workerfunc RemoveOptionalPrebuiltPrefixFromBazelLabel(label string) string { 132*333d2b36SAndroid Build Coastguard Worker splitLabel := strings.Split(label, ":") 133*333d2b36SAndroid Build Coastguard Worker bazelModuleNameNoPrebuilt := RemoveOptionalPrebuiltPrefix(splitLabel[1]) 134*333d2b36SAndroid Build Coastguard Worker return strings.Join([]string{ 135*333d2b36SAndroid Build Coastguard Worker splitLabel[0], 136*333d2b36SAndroid Build Coastguard Worker bazelModuleNameNoPrebuilt, 137*333d2b36SAndroid Build Coastguard Worker }, ":") 138*333d2b36SAndroid Build Coastguard Worker} 139*333d2b36SAndroid Build Coastguard Worker 140*333d2b36SAndroid Build Coastguard Workerfunc (p *Prebuilt) Name(name string) string { 141*333d2b36SAndroid Build Coastguard Worker return PrebuiltNameFromSource(name) 142*333d2b36SAndroid Build Coastguard Worker} 143*333d2b36SAndroid Build Coastguard Worker 144*333d2b36SAndroid Build Coastguard Worker// PrebuiltNameFromSource returns the result of prepending the "prebuilt_" prefix to the supplied 145*333d2b36SAndroid Build Coastguard Worker// name. 146*333d2b36SAndroid Build Coastguard Workerfunc PrebuiltNameFromSource(name string) string { 147*333d2b36SAndroid Build Coastguard Worker return "prebuilt_" + name 148*333d2b36SAndroid Build Coastguard Worker} 149*333d2b36SAndroid Build Coastguard Worker 150*333d2b36SAndroid Build Coastguard Workerfunc (p *Prebuilt) ForcePrefer() { 151*333d2b36SAndroid Build Coastguard Worker p.properties.Prefer = NewSimpleConfigurable(true) 152*333d2b36SAndroid Build Coastguard Worker} 153*333d2b36SAndroid Build Coastguard Worker 154*333d2b36SAndroid Build Coastguard Worker// SingleSourcePathFromSupplier invokes the supplied supplier for the current module in the 155*333d2b36SAndroid Build Coastguard Worker// supplied context to retrieve a list of file paths, ensures that the returned list of file paths 156*333d2b36SAndroid Build Coastguard Worker// contains a single value and then assumes that is a module relative file path and converts it to 157*333d2b36SAndroid Build Coastguard Worker// a Path accordingly. 158*333d2b36SAndroid Build Coastguard Worker// 159*333d2b36SAndroid Build Coastguard Worker// Any issues, such as nil supplier or not exactly one file path will be reported as errors on the 160*333d2b36SAndroid Build Coastguard Worker// supplied context and this will return nil. 161*333d2b36SAndroid Build Coastguard Workerfunc SingleSourcePathFromSupplier(ctx ModuleContext, srcsSupplier PrebuiltSrcsSupplier, srcsPropertyName string) Path { 162*333d2b36SAndroid Build Coastguard Worker if srcsSupplier != nil { 163*333d2b36SAndroid Build Coastguard Worker srcs := srcsSupplier(ctx, ctx.Module()) 164*333d2b36SAndroid Build Coastguard Worker 165*333d2b36SAndroid Build Coastguard Worker if len(srcs) == 0 { 166*333d2b36SAndroid Build Coastguard Worker ctx.PropertyErrorf(srcsPropertyName, "missing prebuilt source file") 167*333d2b36SAndroid Build Coastguard Worker return nil 168*333d2b36SAndroid Build Coastguard Worker } 169*333d2b36SAndroid Build Coastguard Worker 170*333d2b36SAndroid Build Coastguard Worker if len(srcs) > 1 { 171*333d2b36SAndroid Build Coastguard Worker ctx.PropertyErrorf(srcsPropertyName, "multiple prebuilt source files") 172*333d2b36SAndroid Build Coastguard Worker return nil 173*333d2b36SAndroid Build Coastguard Worker } 174*333d2b36SAndroid Build Coastguard Worker 175*333d2b36SAndroid Build Coastguard Worker // Return the singleton source after expanding any filegroup in the 176*333d2b36SAndroid Build Coastguard Worker // sources. 177*333d2b36SAndroid Build Coastguard Worker src := srcs[0] 178*333d2b36SAndroid Build Coastguard Worker return PathForModuleSrc(ctx, src) 179*333d2b36SAndroid Build Coastguard Worker } else { 180*333d2b36SAndroid Build Coastguard Worker ctx.ModuleErrorf("prebuilt source was not set") 181*333d2b36SAndroid Build Coastguard Worker return nil 182*333d2b36SAndroid Build Coastguard Worker } 183*333d2b36SAndroid Build Coastguard Worker} 184*333d2b36SAndroid Build Coastguard Worker 185*333d2b36SAndroid Build Coastguard Worker// The below source-related functions and the srcs, src fields are based on an assumption that 186*333d2b36SAndroid Build Coastguard Worker// prebuilt modules have a static source property at the moment. Currently there is only one 187*333d2b36SAndroid Build Coastguard Worker// exception, android_app_import, which chooses a source file depending on the product's DPI 188*333d2b36SAndroid Build Coastguard Worker// preference configs. We'll want to add native support for dynamic source cases if we end up having 189*333d2b36SAndroid Build Coastguard Worker// more modules like this. 190*333d2b36SAndroid Build Coastguard Workerfunc (p *Prebuilt) SingleSourcePath(ctx ModuleContext) Path { 191*333d2b36SAndroid Build Coastguard Worker return SingleSourcePathFromSupplier(ctx, p.srcsSupplier, p.srcsPropertyName) 192*333d2b36SAndroid Build Coastguard Worker} 193*333d2b36SAndroid Build Coastguard Worker 194*333d2b36SAndroid Build Coastguard Workerfunc (p *Prebuilt) UsePrebuilt() bool { 195*333d2b36SAndroid Build Coastguard Worker return p.properties.UsePrebuilt 196*333d2b36SAndroid Build Coastguard Worker} 197*333d2b36SAndroid Build Coastguard Worker 198*333d2b36SAndroid Build Coastguard Worker// Called to provide the srcs value for the prebuilt module. 199*333d2b36SAndroid Build Coastguard Worker// 200*333d2b36SAndroid Build Coastguard Worker// This can be called with a context for any module not just the prebuilt one itself. It can also be 201*333d2b36SAndroid Build Coastguard Worker// called concurrently. 202*333d2b36SAndroid Build Coastguard Worker// 203*333d2b36SAndroid Build Coastguard Worker// Return the src value or nil if it is not available. 204*333d2b36SAndroid Build Coastguard Workertype PrebuiltSrcsSupplier func(ctx BaseModuleContext, prebuilt Module) []string 205*333d2b36SAndroid Build Coastguard Worker 206*333d2b36SAndroid Build Coastguard Workerfunc initPrebuiltModuleCommon(module PrebuiltInterface) *Prebuilt { 207*333d2b36SAndroid Build Coastguard Worker p := module.Prebuilt() 208*333d2b36SAndroid Build Coastguard Worker module.AddProperties(&p.properties) 209*333d2b36SAndroid Build Coastguard Worker return p 210*333d2b36SAndroid Build Coastguard Worker} 211*333d2b36SAndroid Build Coastguard Worker 212*333d2b36SAndroid Build Coastguard Worker// Initialize the module as a prebuilt module that has no dedicated property that lists its 213*333d2b36SAndroid Build Coastguard Worker// sources. SingleSourcePathFromSupplier should not be called for this module. 214*333d2b36SAndroid Build Coastguard Worker// 215*333d2b36SAndroid Build Coastguard Worker// This is the case e.g. for header modules, which provides the headers in source form 216*333d2b36SAndroid Build Coastguard Worker// regardless whether they are prebuilt or not. 217*333d2b36SAndroid Build Coastguard Workerfunc InitPrebuiltModuleWithoutSrcs(module PrebuiltInterface) { 218*333d2b36SAndroid Build Coastguard Worker p := initPrebuiltModuleCommon(module) 219*333d2b36SAndroid Build Coastguard Worker p.srcsPropertyName = "-" 220*333d2b36SAndroid Build Coastguard Worker} 221*333d2b36SAndroid Build Coastguard Worker 222*333d2b36SAndroid Build Coastguard Worker// Initialize the module as a prebuilt module that uses the provided supplier to access the 223*333d2b36SAndroid Build Coastguard Worker// prebuilt sources of the module. 224*333d2b36SAndroid Build Coastguard Worker// 225*333d2b36SAndroid Build Coastguard Worker// The supplier will be called multiple times and must return the same values each time it 226*333d2b36SAndroid Build Coastguard Worker// is called. If it returns an empty array (or nil) then the prebuilt module will not be used 227*333d2b36SAndroid Build Coastguard Worker// as a replacement for a source module with the same name even if prefer = true. 228*333d2b36SAndroid Build Coastguard Worker// 229*333d2b36SAndroid Build Coastguard Worker// If the Prebuilt.SingleSourcePath() is called on the module then this must return an array 230*333d2b36SAndroid Build Coastguard Worker// containing exactly one source file. 231*333d2b36SAndroid Build Coastguard Worker// 232*333d2b36SAndroid Build Coastguard Worker// The provided property name is used to provide helpful error messages in the event that 233*333d2b36SAndroid Build Coastguard Worker// a problem arises, e.g. calling SingleSourcePath() when more than one source is provided. 234*333d2b36SAndroid Build Coastguard Workerfunc InitPrebuiltModuleWithSrcSupplier(module PrebuiltInterface, srcsSupplier PrebuiltSrcsSupplier, srcsPropertyName string) { 235*333d2b36SAndroid Build Coastguard Worker if srcsSupplier == nil { 236*333d2b36SAndroid Build Coastguard Worker panic(fmt.Errorf("srcsSupplier must not be nil")) 237*333d2b36SAndroid Build Coastguard Worker } 238*333d2b36SAndroid Build Coastguard Worker if srcsPropertyName == "" { 239*333d2b36SAndroid Build Coastguard Worker panic(fmt.Errorf("srcsPropertyName must not be empty")) 240*333d2b36SAndroid Build Coastguard Worker } 241*333d2b36SAndroid Build Coastguard Worker 242*333d2b36SAndroid Build Coastguard Worker p := initPrebuiltModuleCommon(module) 243*333d2b36SAndroid Build Coastguard Worker p.srcsSupplier = srcsSupplier 244*333d2b36SAndroid Build Coastguard Worker p.srcsPropertyName = srcsPropertyName 245*333d2b36SAndroid Build Coastguard Worker} 246*333d2b36SAndroid Build Coastguard Worker 247*333d2b36SAndroid Build Coastguard Worker// InitPrebuiltModule is the same as InitPrebuiltModuleWithSrcSupplier, but uses the 248*333d2b36SAndroid Build Coastguard Worker// provided list of strings property as the source provider. 249*333d2b36SAndroid Build Coastguard Workerfunc InitPrebuiltModule(module PrebuiltInterface, srcs *[]string) { 250*333d2b36SAndroid Build Coastguard Worker if srcs == nil { 251*333d2b36SAndroid Build Coastguard Worker panic(fmt.Errorf("srcs must not be nil")) 252*333d2b36SAndroid Build Coastguard Worker } 253*333d2b36SAndroid Build Coastguard Worker 254*333d2b36SAndroid Build Coastguard Worker srcsSupplier := func(ctx BaseModuleContext, _ Module) []string { 255*333d2b36SAndroid Build Coastguard Worker return *srcs 256*333d2b36SAndroid Build Coastguard Worker } 257*333d2b36SAndroid Build Coastguard Worker 258*333d2b36SAndroid Build Coastguard Worker InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, "srcs") 259*333d2b36SAndroid Build Coastguard Worker} 260*333d2b36SAndroid Build Coastguard Worker 261*333d2b36SAndroid Build Coastguard Worker// InitConfigurablePrebuiltModule is the same as InitPrebuiltModule, but uses a 262*333d2b36SAndroid Build Coastguard Worker// Configurable list of strings property instead of a regular list of strings. 263*333d2b36SAndroid Build Coastguard Workerfunc InitConfigurablePrebuiltModule(module PrebuiltInterface, srcs *proptools.Configurable[[]string]) { 264*333d2b36SAndroid Build Coastguard Worker if srcs == nil { 265*333d2b36SAndroid Build Coastguard Worker panic(fmt.Errorf("srcs must not be nil")) 266*333d2b36SAndroid Build Coastguard Worker } 267*333d2b36SAndroid Build Coastguard Worker 268*333d2b36SAndroid Build Coastguard Worker srcsSupplier := func(ctx BaseModuleContext, _ Module) []string { 269*333d2b36SAndroid Build Coastguard Worker return srcs.GetOrDefault(ctx, nil) 270*333d2b36SAndroid Build Coastguard Worker } 271*333d2b36SAndroid Build Coastguard Worker 272*333d2b36SAndroid Build Coastguard Worker InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, "srcs") 273*333d2b36SAndroid Build Coastguard Worker} 274*333d2b36SAndroid Build Coastguard Worker 275*333d2b36SAndroid Build Coastguard Worker// InitConfigurablePrebuiltModuleString is the same as InitPrebuiltModule, but uses a 276*333d2b36SAndroid Build Coastguard Worker// Configurable string property instead of a regular list of strings. It only produces a single 277*333d2b36SAndroid Build Coastguard Worker// source file. 278*333d2b36SAndroid Build Coastguard Workerfunc InitConfigurablePrebuiltModuleString(module PrebuiltInterface, srcs *proptools.Configurable[string], propertyName string) { 279*333d2b36SAndroid Build Coastguard Worker if srcs == nil { 280*333d2b36SAndroid Build Coastguard Worker panic(fmt.Errorf("%s must not be nil", propertyName)) 281*333d2b36SAndroid Build Coastguard Worker } 282*333d2b36SAndroid Build Coastguard Worker 283*333d2b36SAndroid Build Coastguard Worker srcsSupplier := func(ctx BaseModuleContext, _ Module) []string { 284*333d2b36SAndroid Build Coastguard Worker src := srcs.GetOrDefault(ctx, "") 285*333d2b36SAndroid Build Coastguard Worker if src == "" { 286*333d2b36SAndroid Build Coastguard Worker return nil 287*333d2b36SAndroid Build Coastguard Worker } 288*333d2b36SAndroid Build Coastguard Worker return []string{src} 289*333d2b36SAndroid Build Coastguard Worker } 290*333d2b36SAndroid Build Coastguard Worker 291*333d2b36SAndroid Build Coastguard Worker InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, propertyName) 292*333d2b36SAndroid Build Coastguard Worker} 293*333d2b36SAndroid Build Coastguard Worker 294*333d2b36SAndroid Build Coastguard Workerfunc InitSingleSourcePrebuiltModule(module PrebuiltInterface, srcProps interface{}, srcField string) { 295*333d2b36SAndroid Build Coastguard Worker srcPropsValue := reflect.ValueOf(srcProps).Elem() 296*333d2b36SAndroid Build Coastguard Worker srcStructField, _ := srcPropsValue.Type().FieldByName(srcField) 297*333d2b36SAndroid Build Coastguard Worker if !srcPropsValue.IsValid() || srcStructField.Name == "" { 298*333d2b36SAndroid Build Coastguard Worker panic(fmt.Errorf("invalid single source prebuilt %+v", module)) 299*333d2b36SAndroid Build Coastguard Worker } 300*333d2b36SAndroid Build Coastguard Worker 301*333d2b36SAndroid Build Coastguard Worker if srcPropsValue.Kind() != reflect.Struct && srcPropsValue.Kind() != reflect.Interface { 302*333d2b36SAndroid Build Coastguard Worker panic(fmt.Errorf("invalid single source prebuilt %+v", srcProps)) 303*333d2b36SAndroid Build Coastguard Worker } 304*333d2b36SAndroid Build Coastguard Worker 305*333d2b36SAndroid Build Coastguard Worker srcFieldIndex := srcStructField.Index 306*333d2b36SAndroid Build Coastguard Worker srcPropertyName := proptools.PropertyNameForField(srcField) 307*333d2b36SAndroid Build Coastguard Worker 308*333d2b36SAndroid Build Coastguard Worker srcsSupplier := func(ctx BaseModuleContext, _ Module) []string { 309*333d2b36SAndroid Build Coastguard Worker if !module.Enabled(ctx) { 310*333d2b36SAndroid Build Coastguard Worker return nil 311*333d2b36SAndroid Build Coastguard Worker } 312*333d2b36SAndroid Build Coastguard Worker value := srcPropsValue.FieldByIndex(srcFieldIndex) 313*333d2b36SAndroid Build Coastguard Worker if value.Kind() == reflect.Ptr { 314*333d2b36SAndroid Build Coastguard Worker if value.IsNil() { 315*333d2b36SAndroid Build Coastguard Worker return nil 316*333d2b36SAndroid Build Coastguard Worker } 317*333d2b36SAndroid Build Coastguard Worker value = value.Elem() 318*333d2b36SAndroid Build Coastguard Worker } 319*333d2b36SAndroid Build Coastguard Worker if value.Kind() != reflect.String { 320*333d2b36SAndroid Build Coastguard Worker panic(fmt.Errorf("prebuilt src field %q in %T in module %s should be a string or a pointer to one but was %v", srcField, srcProps, module, value)) 321*333d2b36SAndroid Build Coastguard Worker } 322*333d2b36SAndroid Build Coastguard Worker src := value.String() 323*333d2b36SAndroid Build Coastguard Worker if src == "" { 324*333d2b36SAndroid Build Coastguard Worker return nil 325*333d2b36SAndroid Build Coastguard Worker } 326*333d2b36SAndroid Build Coastguard Worker return []string{src} 327*333d2b36SAndroid Build Coastguard Worker } 328*333d2b36SAndroid Build Coastguard Worker 329*333d2b36SAndroid Build Coastguard Worker InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, srcPropertyName) 330*333d2b36SAndroid Build Coastguard Worker} 331*333d2b36SAndroid Build Coastguard Worker 332*333d2b36SAndroid Build Coastguard Workertype PrebuiltInterface interface { 333*333d2b36SAndroid Build Coastguard Worker Module 334*333d2b36SAndroid Build Coastguard Worker Prebuilt() *Prebuilt 335*333d2b36SAndroid Build Coastguard Worker} 336*333d2b36SAndroid Build Coastguard Worker 337*333d2b36SAndroid Build Coastguard Worker// IsModulePreferred returns true if the given module is preferred. 338*333d2b36SAndroid Build Coastguard Worker// 339*333d2b36SAndroid Build Coastguard Worker// A source module is preferred if there is no corresponding prebuilt module or the prebuilt module 340*333d2b36SAndroid Build Coastguard Worker// does not have "prefer: true". 341*333d2b36SAndroid Build Coastguard Worker// 342*333d2b36SAndroid Build Coastguard Worker// A prebuilt module is preferred if there is no corresponding source module or the prebuilt module 343*333d2b36SAndroid Build Coastguard Worker// has "prefer: true". 344*333d2b36SAndroid Build Coastguard Workerfunc IsModulePreferred(module Module) bool { 345*333d2b36SAndroid Build Coastguard Worker if module.IsReplacedByPrebuilt() { 346*333d2b36SAndroid Build Coastguard Worker // A source module that has been replaced by a prebuilt counterpart. 347*333d2b36SAndroid Build Coastguard Worker return false 348*333d2b36SAndroid Build Coastguard Worker } 349*333d2b36SAndroid Build Coastguard Worker if p := GetEmbeddedPrebuilt(module); p != nil { 350*333d2b36SAndroid Build Coastguard Worker return p.UsePrebuilt() 351*333d2b36SAndroid Build Coastguard Worker } 352*333d2b36SAndroid Build Coastguard Worker return true 353*333d2b36SAndroid Build Coastguard Worker} 354*333d2b36SAndroid Build Coastguard Worker 355*333d2b36SAndroid Build Coastguard Worker// IsModulePrebuilt returns true if the module implements PrebuiltInterface and 356*333d2b36SAndroid Build Coastguard Worker// has been initialized as a prebuilt and so returns a non-nil value from the 357*333d2b36SAndroid Build Coastguard Worker// PrebuiltInterface.Prebuilt() method. 358*333d2b36SAndroid Build Coastguard Workerfunc IsModulePrebuilt(module Module) bool { 359*333d2b36SAndroid Build Coastguard Worker return GetEmbeddedPrebuilt(module) != nil 360*333d2b36SAndroid Build Coastguard Worker} 361*333d2b36SAndroid Build Coastguard Worker 362*333d2b36SAndroid Build Coastguard Worker// GetEmbeddedPrebuilt returns a pointer to the embedded Prebuilt structure or 363*333d2b36SAndroid Build Coastguard Worker// nil if the module does not implement PrebuiltInterface or has not been 364*333d2b36SAndroid Build Coastguard Worker// initialized as a prebuilt module. 365*333d2b36SAndroid Build Coastguard Workerfunc GetEmbeddedPrebuilt(module Module) *Prebuilt { 366*333d2b36SAndroid Build Coastguard Worker if p, ok := module.(PrebuiltInterface); ok { 367*333d2b36SAndroid Build Coastguard Worker return p.Prebuilt() 368*333d2b36SAndroid Build Coastguard Worker } 369*333d2b36SAndroid Build Coastguard Worker 370*333d2b36SAndroid Build Coastguard Worker return nil 371*333d2b36SAndroid Build Coastguard Worker} 372*333d2b36SAndroid Build Coastguard Worker 373*333d2b36SAndroid Build Coastguard Worker// PrebuiltGetPreferred returns the module that is preferred for the given 374*333d2b36SAndroid Build Coastguard Worker// module. That is either the module itself or the prebuilt counterpart that has 375*333d2b36SAndroid Build Coastguard Worker// taken its place. The given module must be a direct dependency of the current 376*333d2b36SAndroid Build Coastguard Worker// context module, and it must be the source module if both source and prebuilt 377*333d2b36SAndroid Build Coastguard Worker// exist. 378*333d2b36SAndroid Build Coastguard Worker// 379*333d2b36SAndroid Build Coastguard Worker// This function is for use on dependencies after PrebuiltPostDepsMutator has 380*333d2b36SAndroid Build Coastguard Worker// run - any dependency that is registered before that will already reference 381*333d2b36SAndroid Build Coastguard Worker// the right module. This function is only safe to call after all TransitionMutators 382*333d2b36SAndroid Build Coastguard Worker// have run, e.g. in GenerateAndroidBuildActions. 383*333d2b36SAndroid Build Coastguard Workerfunc PrebuiltGetPreferred(ctx BaseModuleContext, module Module) Module { 384*333d2b36SAndroid Build Coastguard Worker if !OtherModuleProviderOrDefault(ctx, module, CommonModuleInfoKey).ReplacedByPrebuilt { 385*333d2b36SAndroid Build Coastguard Worker return module 386*333d2b36SAndroid Build Coastguard Worker } 387*333d2b36SAndroid Build Coastguard Worker if _, ok := OtherModuleProvider(ctx, module, PrebuiltModuleProviderKey); ok { 388*333d2b36SAndroid Build Coastguard Worker // If we're given a prebuilt then assume there's no source module around. 389*333d2b36SAndroid Build Coastguard Worker return module 390*333d2b36SAndroid Build Coastguard Worker } 391*333d2b36SAndroid Build Coastguard Worker 392*333d2b36SAndroid Build Coastguard Worker sourceModDepFound := false 393*333d2b36SAndroid Build Coastguard Worker var prebuiltMod Module 394*333d2b36SAndroid Build Coastguard Worker 395*333d2b36SAndroid Build Coastguard Worker ctx.WalkDepsProxy(func(child, parent ModuleProxy) bool { 396*333d2b36SAndroid Build Coastguard Worker if prebuiltMod != nil { 397*333d2b36SAndroid Build Coastguard Worker return false 398*333d2b36SAndroid Build Coastguard Worker } 399*333d2b36SAndroid Build Coastguard Worker if ctx.EqualModules(parent, ctx.Module()) { 400*333d2b36SAndroid Build Coastguard Worker // First level: Only recurse if the module is found as a direct dependency. 401*333d2b36SAndroid Build Coastguard Worker sourceModDepFound = child == module 402*333d2b36SAndroid Build Coastguard Worker return sourceModDepFound 403*333d2b36SAndroid Build Coastguard Worker } 404*333d2b36SAndroid Build Coastguard Worker // Second level: Follow PrebuiltDepTag to the prebuilt. 405*333d2b36SAndroid Build Coastguard Worker if t := ctx.OtherModuleDependencyTag(child); t == PrebuiltDepTag { 406*333d2b36SAndroid Build Coastguard Worker prebuiltMod = child 407*333d2b36SAndroid Build Coastguard Worker } 408*333d2b36SAndroid Build Coastguard Worker return false 409*333d2b36SAndroid Build Coastguard Worker }) 410*333d2b36SAndroid Build Coastguard Worker 411*333d2b36SAndroid Build Coastguard Worker if prebuiltMod == nil { 412*333d2b36SAndroid Build Coastguard Worker if !sourceModDepFound { 413*333d2b36SAndroid Build Coastguard Worker panic(fmt.Errorf("Failed to find source module as a direct dependency: %s", module)) 414*333d2b36SAndroid Build Coastguard Worker } else { 415*333d2b36SAndroid Build Coastguard Worker panic(fmt.Errorf("Failed to find prebuilt for source module: %s", module)) 416*333d2b36SAndroid Build Coastguard Worker } 417*333d2b36SAndroid Build Coastguard Worker } 418*333d2b36SAndroid Build Coastguard Worker return prebuiltMod 419*333d2b36SAndroid Build Coastguard Worker} 420*333d2b36SAndroid Build Coastguard Worker 421*333d2b36SAndroid Build Coastguard Workerfunc RegisterPrebuiltsPreArchMutators(ctx RegisterMutatorsContext) { 422*333d2b36SAndroid Build Coastguard Worker ctx.BottomUp("prebuilt_rename", PrebuiltRenameMutator).UsesRename() 423*333d2b36SAndroid Build Coastguard Worker} 424*333d2b36SAndroid Build Coastguard Worker 425*333d2b36SAndroid Build Coastguard Workerfunc RegisterPrebuiltsPostDepsMutators(ctx RegisterMutatorsContext) { 426*333d2b36SAndroid Build Coastguard Worker ctx.BottomUp("prebuilt_source", PrebuiltSourceDepsMutator).UsesReverseDependencies() 427*333d2b36SAndroid Build Coastguard Worker ctx.BottomUp("prebuilt_select", PrebuiltSelectModuleMutator) 428*333d2b36SAndroid Build Coastguard Worker ctx.BottomUp("prebuilt_postdeps", PrebuiltPostDepsMutator).UsesReplaceDependencies() 429*333d2b36SAndroid Build Coastguard Worker} 430*333d2b36SAndroid Build Coastguard Worker 431*333d2b36SAndroid Build Coastguard Worker// Returns the name of the source module corresponding to a prebuilt module 432*333d2b36SAndroid Build Coastguard Worker// For source modules, it returns its own name 433*333d2b36SAndroid Build Coastguard Workertype baseModuleName interface { 434*333d2b36SAndroid Build Coastguard Worker BaseModuleName() string 435*333d2b36SAndroid Build Coastguard Worker} 436*333d2b36SAndroid Build Coastguard Worker 437*333d2b36SAndroid Build Coastguard Worker// PrebuiltRenameMutator ensures that there always is a module with an 438*333d2b36SAndroid Build Coastguard Worker// undecorated name. 439*333d2b36SAndroid Build Coastguard Workerfunc PrebuiltRenameMutator(ctx BottomUpMutatorContext) { 440*333d2b36SAndroid Build Coastguard Worker m := ctx.Module() 441*333d2b36SAndroid Build Coastguard Worker if p := GetEmbeddedPrebuilt(m); p != nil { 442*333d2b36SAndroid Build Coastguard Worker bmn, _ := m.(baseModuleName) 443*333d2b36SAndroid Build Coastguard Worker name := bmn.BaseModuleName() 444*333d2b36SAndroid Build Coastguard Worker if !ctx.OtherModuleExists(name) { 445*333d2b36SAndroid Build Coastguard Worker ctx.Rename(name) 446*333d2b36SAndroid Build Coastguard Worker p.properties.PrebuiltRenamedToSource = true 447*333d2b36SAndroid Build Coastguard Worker } 448*333d2b36SAndroid Build Coastguard Worker } 449*333d2b36SAndroid Build Coastguard Worker} 450*333d2b36SAndroid Build Coastguard Worker 451*333d2b36SAndroid Build Coastguard Worker// PrebuiltSourceDepsMutator adds dependencies to the prebuilt module from the 452*333d2b36SAndroid Build Coastguard Worker// corresponding source module, if one exists for the same variant. 453*333d2b36SAndroid Build Coastguard Worker// Add a dependency from the prebuilt to `all_apex_contributions` 454*333d2b36SAndroid Build Coastguard Worker// The metadata will be used for source vs prebuilts selection 455*333d2b36SAndroid Build Coastguard Workerfunc PrebuiltSourceDepsMutator(ctx BottomUpMutatorContext) { 456*333d2b36SAndroid Build Coastguard Worker m := ctx.Module() 457*333d2b36SAndroid Build Coastguard Worker if p := GetEmbeddedPrebuilt(m); p != nil { 458*333d2b36SAndroid Build Coastguard Worker // Add a dependency from the prebuilt to the `all_apex_contributions` 459*333d2b36SAndroid Build Coastguard Worker // metadata module 460*333d2b36SAndroid Build Coastguard Worker // TODO: When all branches contain this singleton module, make this strict 461*333d2b36SAndroid Build Coastguard Worker // TODO: Add this dependency only for mainline prebuilts and not every prebuilt module 462*333d2b36SAndroid Build Coastguard Worker if ctx.OtherModuleExists("all_apex_contributions") { 463*333d2b36SAndroid Build Coastguard Worker ctx.AddDependency(m, AcDepTag, "all_apex_contributions") 464*333d2b36SAndroid Build Coastguard Worker } 465*333d2b36SAndroid Build Coastguard Worker if m.Enabled(ctx) && !p.properties.PrebuiltRenamedToSource { 466*333d2b36SAndroid Build Coastguard Worker // If this module is a prebuilt, is enabled and has not been renamed to source then add a 467*333d2b36SAndroid Build Coastguard Worker // dependency onto the source if it is present. 468*333d2b36SAndroid Build Coastguard Worker bmn, _ := m.(baseModuleName) 469*333d2b36SAndroid Build Coastguard Worker name := bmn.BaseModuleName() 470*333d2b36SAndroid Build Coastguard Worker if ctx.OtherModuleReverseDependencyVariantExists(name) { 471*333d2b36SAndroid Build Coastguard Worker ctx.AddReverseDependency(ctx.Module(), PrebuiltDepTag, name) 472*333d2b36SAndroid Build Coastguard Worker p.properties.SourceExists = true 473*333d2b36SAndroid Build Coastguard Worker } 474*333d2b36SAndroid Build Coastguard Worker } 475*333d2b36SAndroid Build Coastguard Worker } 476*333d2b36SAndroid Build Coastguard Worker} 477*333d2b36SAndroid Build Coastguard Worker 478*333d2b36SAndroid Build Coastguard Worker// checkInvariantsForSourceAndPrebuilt checks if invariants are kept when replacing 479*333d2b36SAndroid Build Coastguard Worker// source with prebuilt. Note that the current module for the context is the source module. 480*333d2b36SAndroid Build Coastguard Workerfunc checkInvariantsForSourceAndPrebuilt(ctx BaseModuleContext, s, p Module) { 481*333d2b36SAndroid Build Coastguard Worker if _, ok := s.(OverrideModule); ok { 482*333d2b36SAndroid Build Coastguard Worker // skip the check when the source module is `override_X` because it's only a placeholder 483*333d2b36SAndroid Build Coastguard Worker // for the actual source module. The check will be invoked for the actual module. 484*333d2b36SAndroid Build Coastguard Worker return 485*333d2b36SAndroid Build Coastguard Worker } 486*333d2b36SAndroid Build Coastguard Worker if sourcePartition, prebuiltPartition := s.PartitionTag(ctx.DeviceConfig()), p.PartitionTag(ctx.DeviceConfig()); sourcePartition != prebuiltPartition { 487*333d2b36SAndroid Build Coastguard Worker ctx.OtherModuleErrorf(p, "partition is different: %s(%s) != %s(%s)", 488*333d2b36SAndroid Build Coastguard Worker sourcePartition, ctx.ModuleName(), prebuiltPartition, ctx.OtherModuleName(p)) 489*333d2b36SAndroid Build Coastguard Worker } 490*333d2b36SAndroid Build Coastguard Worker} 491*333d2b36SAndroid Build Coastguard Worker 492*333d2b36SAndroid Build Coastguard Worker// PrebuiltSelectModuleMutator marks prebuilts that are used, either overriding source modules or 493*333d2b36SAndroid Build Coastguard Worker// because the source module doesn't exist. It also disables installing overridden source modules. 494*333d2b36SAndroid Build Coastguard Worker// 495*333d2b36SAndroid Build Coastguard Worker// If the visited module is the metadata module `all_apex_contributions`, it sets a 496*333d2b36SAndroid Build Coastguard Worker// provider containing metadata about whether source or prebuilt of mainline modules should be used. 497*333d2b36SAndroid Build Coastguard Worker// This logic was added here to prevent the overhead of creating a new mutator. 498*333d2b36SAndroid Build Coastguard Workerfunc PrebuiltSelectModuleMutator(ctx BottomUpMutatorContext) { 499*333d2b36SAndroid Build Coastguard Worker m := ctx.Module() 500*333d2b36SAndroid Build Coastguard Worker if p := GetEmbeddedPrebuilt(m); p != nil { 501*333d2b36SAndroid Build Coastguard Worker if p.srcsSupplier == nil && p.srcsPropertyName == "" { 502*333d2b36SAndroid Build Coastguard Worker panic(fmt.Errorf("prebuilt module did not have InitPrebuiltModule called on it")) 503*333d2b36SAndroid Build Coastguard Worker } 504*333d2b36SAndroid Build Coastguard Worker if !p.properties.SourceExists { 505*333d2b36SAndroid Build Coastguard Worker p.properties.UsePrebuilt = p.usePrebuilt(ctx, nil, m) 506*333d2b36SAndroid Build Coastguard Worker } 507*333d2b36SAndroid Build Coastguard Worker // Propagate the provider received from `all_apex_contributions` 508*333d2b36SAndroid Build Coastguard Worker // to the source module 509*333d2b36SAndroid Build Coastguard Worker ctx.VisitDirectDepsWithTag(AcDepTag, func(am Module) { 510*333d2b36SAndroid Build Coastguard Worker psi, _ := OtherModuleProvider(ctx, am, PrebuiltSelectionInfoProvider) 511*333d2b36SAndroid Build Coastguard Worker SetProvider(ctx, PrebuiltSelectionInfoProvider, psi) 512*333d2b36SAndroid Build Coastguard Worker }) 513*333d2b36SAndroid Build Coastguard Worker 514*333d2b36SAndroid Build Coastguard Worker } else if s, ok := ctx.Module().(Module); ok { 515*333d2b36SAndroid Build Coastguard Worker // Use `all_apex_contributions` for source vs prebuilt selection. 516*333d2b36SAndroid Build Coastguard Worker psi := PrebuiltSelectionInfoMap{} 517*333d2b36SAndroid Build Coastguard Worker ctx.VisitDirectDepsWithTag(PrebuiltDepTag, func(am Module) { 518*333d2b36SAndroid Build Coastguard Worker // The value of psi gets overwritten with the provider from the last visited prebuilt. 519*333d2b36SAndroid Build Coastguard Worker // But all prebuilts have the same value of the provider, so this should be idempontent. 520*333d2b36SAndroid Build Coastguard Worker psi, _ = OtherModuleProvider(ctx, am, PrebuiltSelectionInfoProvider) 521*333d2b36SAndroid Build Coastguard Worker }) 522*333d2b36SAndroid Build Coastguard Worker ctx.VisitDirectDepsWithTag(PrebuiltDepTag, func(prebuiltModule Module) { 523*333d2b36SAndroid Build Coastguard Worker p := GetEmbeddedPrebuilt(prebuiltModule) 524*333d2b36SAndroid Build Coastguard Worker if p.usePrebuilt(ctx, s, prebuiltModule) { 525*333d2b36SAndroid Build Coastguard Worker checkInvariantsForSourceAndPrebuilt(ctx, s, prebuiltModule) 526*333d2b36SAndroid Build Coastguard Worker 527*333d2b36SAndroid Build Coastguard Worker p.properties.UsePrebuilt = true 528*333d2b36SAndroid Build Coastguard Worker s.ReplacedByPrebuilt() 529*333d2b36SAndroid Build Coastguard Worker } 530*333d2b36SAndroid Build Coastguard Worker }) 531*333d2b36SAndroid Build Coastguard Worker 532*333d2b36SAndroid Build Coastguard Worker // If any module in this mainline module family has been flagged using apex_contributions, disable every other module in that family 533*333d2b36SAndroid Build Coastguard Worker // Add source 534*333d2b36SAndroid Build Coastguard Worker allModules := []Module{s} 535*333d2b36SAndroid Build Coastguard Worker // Add each prebuilt 536*333d2b36SAndroid Build Coastguard Worker ctx.VisitDirectDepsWithTag(PrebuiltDepTag, func(prebuiltModule Module) { 537*333d2b36SAndroid Build Coastguard Worker allModules = append(allModules, prebuiltModule) 538*333d2b36SAndroid Build Coastguard Worker }) 539*333d2b36SAndroid Build Coastguard Worker hideUnflaggedModules(ctx, psi, allModules) 540*333d2b36SAndroid Build Coastguard Worker 541*333d2b36SAndroid Build Coastguard Worker } 542*333d2b36SAndroid Build Coastguard Worker 543*333d2b36SAndroid Build Coastguard Worker // If this is `all_apex_contributions`, set a provider containing 544*333d2b36SAndroid Build Coastguard Worker // metadata about source vs prebuilts selection 545*333d2b36SAndroid Build Coastguard Worker if am, ok := m.(*allApexContributions); ok { 546*333d2b36SAndroid Build Coastguard Worker am.SetPrebuiltSelectionInfoProvider(ctx) 547*333d2b36SAndroid Build Coastguard Worker } 548*333d2b36SAndroid Build Coastguard Worker} 549*333d2b36SAndroid Build Coastguard Worker 550*333d2b36SAndroid Build Coastguard Worker// If any module in this mainline module family has been flagged using apex_contributions, disable every other module in that family 551*333d2b36SAndroid Build Coastguard Workerfunc hideUnflaggedModules(ctx BottomUpMutatorContext, psi PrebuiltSelectionInfoMap, allModulesInFamily []Module) { 552*333d2b36SAndroid Build Coastguard Worker var selectedModuleInFamily Module 553*333d2b36SAndroid Build Coastguard Worker // query all_apex_contributions to see if any module in this family has been selected 554*333d2b36SAndroid Build Coastguard Worker for _, moduleInFamily := range allModulesInFamily { 555*333d2b36SAndroid Build Coastguard Worker // validate that are no duplicates 556*333d2b36SAndroid Build Coastguard Worker if isSelected(psi, moduleInFamily) { 557*333d2b36SAndroid Build Coastguard Worker if selectedModuleInFamily == nil { 558*333d2b36SAndroid Build Coastguard Worker // Store this so we can validate that there are no duplicates 559*333d2b36SAndroid Build Coastguard Worker selectedModuleInFamily = moduleInFamily 560*333d2b36SAndroid Build Coastguard Worker } else { 561*333d2b36SAndroid Build Coastguard Worker // There are duplicate modules from the same mainline module family 562*333d2b36SAndroid Build Coastguard Worker ctx.ModuleErrorf("Found duplicate variations of the same module in apex_contributions: %s and %s. Please remove one of these.\n", selectedModuleInFamily.Name(), moduleInFamily.Name()) 563*333d2b36SAndroid Build Coastguard Worker } 564*333d2b36SAndroid Build Coastguard Worker } 565*333d2b36SAndroid Build Coastguard Worker } 566*333d2b36SAndroid Build Coastguard Worker 567*333d2b36SAndroid Build Coastguard Worker // If a module has been selected, hide all other modules 568*333d2b36SAndroid Build Coastguard Worker if selectedModuleInFamily != nil { 569*333d2b36SAndroid Build Coastguard Worker for _, moduleInFamily := range allModulesInFamily { 570*333d2b36SAndroid Build Coastguard Worker if moduleInFamily.Name() != selectedModuleInFamily.Name() { 571*333d2b36SAndroid Build Coastguard Worker moduleInFamily.HideFromMake() 572*333d2b36SAndroid Build Coastguard Worker moduleInFamily.SkipInstall() 573*333d2b36SAndroid Build Coastguard Worker // If this is a prebuilt module, unset properties.UsePrebuilt 574*333d2b36SAndroid Build Coastguard Worker // properties.UsePrebuilt might evaluate to true via soong config var fallback mechanism 575*333d2b36SAndroid Build Coastguard Worker // Set it to false explicitly so that the following mutator does not replace rdeps to this unselected prebuilt 576*333d2b36SAndroid Build Coastguard Worker if p := GetEmbeddedPrebuilt(moduleInFamily); p != nil { 577*333d2b36SAndroid Build Coastguard Worker p.properties.UsePrebuilt = false 578*333d2b36SAndroid Build Coastguard Worker } 579*333d2b36SAndroid Build Coastguard Worker } 580*333d2b36SAndroid Build Coastguard Worker } 581*333d2b36SAndroid Build Coastguard Worker } 582*333d2b36SAndroid Build Coastguard Worker // Do a validation pass to make sure that multiple prebuilts of a specific module are not selected. 583*333d2b36SAndroid Build Coastguard Worker // This might happen if the prebuilts share the same soong config var namespace. 584*333d2b36SAndroid Build Coastguard Worker // This should be an error, unless one of the prebuilts has been explicitly declared in apex_contributions 585*333d2b36SAndroid Build Coastguard Worker var selectedPrebuilt Module 586*333d2b36SAndroid Build Coastguard Worker for _, moduleInFamily := range allModulesInFamily { 587*333d2b36SAndroid Build Coastguard Worker // Skip if this module is in a different namespace 588*333d2b36SAndroid Build Coastguard Worker if !moduleInFamily.ExportedToMake() { 589*333d2b36SAndroid Build Coastguard Worker continue 590*333d2b36SAndroid Build Coastguard Worker } 591*333d2b36SAndroid Build Coastguard Worker // Skip for the top-level java_sdk_library_(_import). This has some special cases that need to be addressed first. 592*333d2b36SAndroid Build Coastguard Worker // This does not run into non-determinism because PrebuiltPostDepsMutator also has the special case 593*333d2b36SAndroid Build Coastguard Worker if sdkLibrary, ok := moduleInFamily.(interface{ SdkLibraryName() *string }); ok && sdkLibrary.SdkLibraryName() != nil { 594*333d2b36SAndroid Build Coastguard Worker continue 595*333d2b36SAndroid Build Coastguard Worker } 596*333d2b36SAndroid Build Coastguard Worker if p := GetEmbeddedPrebuilt(moduleInFamily); p != nil && p.properties.UsePrebuilt { 597*333d2b36SAndroid Build Coastguard Worker if selectedPrebuilt == nil { 598*333d2b36SAndroid Build Coastguard Worker selectedPrebuilt = moduleInFamily 599*333d2b36SAndroid Build Coastguard Worker } else { 600*333d2b36SAndroid Build Coastguard Worker ctx.ModuleErrorf("Multiple prebuilt modules %v and %v have been marked as preferred for this source module. "+ 601*333d2b36SAndroid Build Coastguard Worker "Please add the appropriate prebuilt module to apex_contributions for this release config.", selectedPrebuilt.Name(), moduleInFamily.Name()) 602*333d2b36SAndroid Build Coastguard Worker } 603*333d2b36SAndroid Build Coastguard Worker } 604*333d2b36SAndroid Build Coastguard Worker } 605*333d2b36SAndroid Build Coastguard Worker} 606*333d2b36SAndroid Build Coastguard Worker 607*333d2b36SAndroid Build Coastguard Worker// PrebuiltPostDepsMutator replaces dependencies on the source module with dependencies on the 608*333d2b36SAndroid Build Coastguard Worker// prebuilt when both modules exist and the prebuilt should be used. When the prebuilt should not 609*333d2b36SAndroid Build Coastguard Worker// be used, disable installing it. 610*333d2b36SAndroid Build Coastguard Workerfunc PrebuiltPostDepsMutator(ctx BottomUpMutatorContext) { 611*333d2b36SAndroid Build Coastguard Worker m := ctx.Module() 612*333d2b36SAndroid Build Coastguard Worker if p := GetEmbeddedPrebuilt(m); p != nil { 613*333d2b36SAndroid Build Coastguard Worker bmn, _ := m.(baseModuleName) 614*333d2b36SAndroid Build Coastguard Worker name := bmn.BaseModuleName() 615*333d2b36SAndroid Build Coastguard Worker psi := PrebuiltSelectionInfoMap{} 616*333d2b36SAndroid Build Coastguard Worker ctx.VisitDirectDepsWithTag(AcDepTag, func(am Module) { 617*333d2b36SAndroid Build Coastguard Worker psi, _ = OtherModuleProvider(ctx, am, PrebuiltSelectionInfoProvider) 618*333d2b36SAndroid Build Coastguard Worker }) 619*333d2b36SAndroid Build Coastguard Worker 620*333d2b36SAndroid Build Coastguard Worker if p.properties.UsePrebuilt { 621*333d2b36SAndroid Build Coastguard Worker if p.properties.SourceExists { 622*333d2b36SAndroid Build Coastguard Worker ctx.ReplaceDependenciesIf(name, func(from blueprint.Module, tag blueprint.DependencyTag, to blueprint.Module) bool { 623*333d2b36SAndroid Build Coastguard Worker if sdkLibrary, ok := m.(interface{ SdkLibraryName() *string }); ok && sdkLibrary.SdkLibraryName() != nil { 624*333d2b36SAndroid Build Coastguard Worker // Do not replace deps to the top-level prebuilt java_sdk_library hook. 625*333d2b36SAndroid Build Coastguard Worker // This hook has been special-cased in #isSelected to be _always_ active, even in next builds 626*333d2b36SAndroid Build Coastguard Worker // for dexpreopt and hiddenapi processing. 627*333d2b36SAndroid Build Coastguard Worker // If we do not special-case this here, rdeps referring to a java_sdk_library in next builds via libs 628*333d2b36SAndroid Build Coastguard Worker // will get prebuilt stubs 629*333d2b36SAndroid Build Coastguard Worker // TODO (b/308187268): Remove this after the apexes have been added to apex_contributions 630*333d2b36SAndroid Build Coastguard Worker if psi.IsSelected(name) { 631*333d2b36SAndroid Build Coastguard Worker return false 632*333d2b36SAndroid Build Coastguard Worker } 633*333d2b36SAndroid Build Coastguard Worker } 634*333d2b36SAndroid Build Coastguard Worker 635*333d2b36SAndroid Build Coastguard Worker if t, ok := tag.(ReplaceSourceWithPrebuilt); ok { 636*333d2b36SAndroid Build Coastguard Worker return t.ReplaceSourceWithPrebuilt() 637*333d2b36SAndroid Build Coastguard Worker } 638*333d2b36SAndroid Build Coastguard Worker return true 639*333d2b36SAndroid Build Coastguard Worker }) 640*333d2b36SAndroid Build Coastguard Worker } 641*333d2b36SAndroid Build Coastguard Worker } else { 642*333d2b36SAndroid Build Coastguard Worker m.HideFromMake() 643*333d2b36SAndroid Build Coastguard Worker m.SkipInstall() 644*333d2b36SAndroid Build Coastguard Worker } 645*333d2b36SAndroid Build Coastguard Worker } 646*333d2b36SAndroid Build Coastguard Worker} 647*333d2b36SAndroid Build Coastguard Worker 648*333d2b36SAndroid Build Coastguard Worker// A wrapper around PrebuiltSelectionInfoMap.IsSelected with special handling for java_sdk_library 649*333d2b36SAndroid Build Coastguard Worker// java_sdk_library is a macro that creates 650*333d2b36SAndroid Build Coastguard Worker// 1. top-level impl library 651*333d2b36SAndroid Build Coastguard Worker// 2. stub libraries (suffixed with .stubs...) 652*333d2b36SAndroid Build Coastguard Worker// 653*333d2b36SAndroid Build Coastguard Worker// java_sdk_library_import is a macro that creates 654*333d2b36SAndroid Build Coastguard Worker// 1. top-level "impl" library 655*333d2b36SAndroid Build Coastguard Worker// 2. stub libraries (suffixed with .stubs...) 656*333d2b36SAndroid Build Coastguard Worker// 657*333d2b36SAndroid Build Coastguard Worker// the impl of java_sdk_library_import is a "hook" for hiddenapi and dexpreopt processing. It does not have an impl jar, but acts as a shim 658*333d2b36SAndroid Build Coastguard Worker// to provide the jar deapxed from the prebuilt apex 659*333d2b36SAndroid Build Coastguard Worker// 660*333d2b36SAndroid Build Coastguard Worker// isSelected uses `all_apex_contributions` to supersede source vs prebuilts selection of the stub libraries. It does not supersede the 661*333d2b36SAndroid Build Coastguard Worker// selection of the top-level "impl" library so that this hook can work 662*333d2b36SAndroid Build Coastguard Worker// 663*333d2b36SAndroid Build Coastguard Worker// TODO (b/308174306) - Fix this when we need to support multiple prebuilts in main 664*333d2b36SAndroid Build Coastguard Workerfunc isSelected(psi PrebuiltSelectionInfoMap, m Module) bool { 665*333d2b36SAndroid Build Coastguard Worker if sdkLibrary, ok := m.(interface{ SdkLibraryName() *string }); ok && sdkLibrary.SdkLibraryName() != nil { 666*333d2b36SAndroid Build Coastguard Worker sln := proptools.String(sdkLibrary.SdkLibraryName()) 667*333d2b36SAndroid Build Coastguard Worker 668*333d2b36SAndroid Build Coastguard Worker // This is the top-level library 669*333d2b36SAndroid Build Coastguard Worker // Do not supersede the existing prebuilts vs source selection mechanisms 670*333d2b36SAndroid Build Coastguard Worker // TODO (b/308187268): Remove this after the apexes have been added to apex_contributions 671*333d2b36SAndroid Build Coastguard Worker if bmn, ok := m.(baseModuleName); ok && sln == bmn.BaseModuleName() { 672*333d2b36SAndroid Build Coastguard Worker return false 673*333d2b36SAndroid Build Coastguard Worker } 674*333d2b36SAndroid Build Coastguard Worker 675*333d2b36SAndroid Build Coastguard Worker // Stub library created by java_sdk_library_import 676*333d2b36SAndroid Build Coastguard Worker // java_sdk_library creates several child modules (java_import + prebuilt_stubs_sources) dynamically. 677*333d2b36SAndroid Build Coastguard Worker // This code block ensures that these child modules are selected if the top-level java_sdk_library_import is listed 678*333d2b36SAndroid Build Coastguard Worker // in the selected apex_contributions. 679*333d2b36SAndroid Build Coastguard Worker if javaImport, ok := m.(createdByJavaSdkLibraryName); ok && javaImport.CreatedByJavaSdkLibraryName() != nil { 680*333d2b36SAndroid Build Coastguard Worker return psi.IsSelected(PrebuiltNameFromSource(proptools.String(javaImport.CreatedByJavaSdkLibraryName()))) 681*333d2b36SAndroid Build Coastguard Worker } 682*333d2b36SAndroid Build Coastguard Worker 683*333d2b36SAndroid Build Coastguard Worker // Stub library created by java_sdk_library 684*333d2b36SAndroid Build Coastguard Worker return psi.IsSelected(sln) 685*333d2b36SAndroid Build Coastguard Worker } 686*333d2b36SAndroid Build Coastguard Worker return psi.IsSelected(m.Name()) 687*333d2b36SAndroid Build Coastguard Worker} 688*333d2b36SAndroid Build Coastguard Worker 689*333d2b36SAndroid Build Coastguard Worker// implemented by child modules of java_sdk_library_import 690*333d2b36SAndroid Build Coastguard Workertype createdByJavaSdkLibraryName interface { 691*333d2b36SAndroid Build Coastguard Worker CreatedByJavaSdkLibraryName() *string 692*333d2b36SAndroid Build Coastguard Worker} 693*333d2b36SAndroid Build Coastguard Worker 694*333d2b36SAndroid Build Coastguard Worker// Returns true if the prebuilt variant is disabled 695*333d2b36SAndroid Build Coastguard Worker// e.g. for a cc_prebuilt_library_shared, this will return 696*333d2b36SAndroid Build Coastguard Worker// - true for the static variant of the module 697*333d2b36SAndroid Build Coastguard Worker// - false for the shared variant of the module 698*333d2b36SAndroid Build Coastguard Worker// 699*333d2b36SAndroid Build Coastguard Worker// Even though this is a cc_prebuilt_library_shared, we create both the variants today 700*333d2b36SAndroid Build Coastguard Worker// https://source.corp.google.com/h/googleplex-android/platform/build/soong/+/e08e32b45a18a77bc3c3e751f730539b1b374f1b:cc/library.go;l=2113-2116;drc=2c4a9779cd1921d0397a12b3d3521f4c9b30d747;bpv=1;bpt=0 701*333d2b36SAndroid Build Coastguard Workerfunc (p *Prebuilt) variantIsDisabled(ctx BaseModuleContext, prebuilt Module) bool { 702*333d2b36SAndroid Build Coastguard Worker return p.srcsSupplier != nil && len(p.srcsSupplier(ctx, prebuilt)) == 0 703*333d2b36SAndroid Build Coastguard Worker} 704*333d2b36SAndroid Build Coastguard Worker 705*333d2b36SAndroid Build Coastguard Workertype apexVariationName interface { 706*333d2b36SAndroid Build Coastguard Worker ApexVariationName() string 707*333d2b36SAndroid Build Coastguard Worker} 708*333d2b36SAndroid Build Coastguard Worker 709*333d2b36SAndroid Build Coastguard Worker// usePrebuilt returns true if a prebuilt should be used instead of the source module. The prebuilt 710*333d2b36SAndroid Build Coastguard Worker// will be used if it is marked "prefer" or if the source module is disabled. 711*333d2b36SAndroid Build Coastguard Workerfunc (p *Prebuilt) usePrebuilt(ctx BaseModuleContext, source Module, prebuilt Module) bool { 712*333d2b36SAndroid Build Coastguard Worker isMainlinePrebuilt := func(prebuilt Module) bool { 713*333d2b36SAndroid Build Coastguard Worker apex, ok := prebuilt.(apexVariationName) 714*333d2b36SAndroid Build Coastguard Worker if !ok { 715*333d2b36SAndroid Build Coastguard Worker return false 716*333d2b36SAndroid Build Coastguard Worker } 717*333d2b36SAndroid Build Coastguard Worker // Prebuilts of aosp apexes in prebuilts/runtime 718*333d2b36SAndroid Build Coastguard Worker // Used in minimal art branches 719*333d2b36SAndroid Build Coastguard Worker if prebuilt.base().BaseModuleName() == apex.ApexVariationName() { 720*333d2b36SAndroid Build Coastguard Worker return false 721*333d2b36SAndroid Build Coastguard Worker } 722*333d2b36SAndroid Build Coastguard Worker return InList(apex.ApexVariationName(), ctx.Config().AllMainlineApexNames()) 723*333d2b36SAndroid Build Coastguard Worker } 724*333d2b36SAndroid Build Coastguard Worker 725*333d2b36SAndroid Build Coastguard Worker // Use `all_apex_contributions` for source vs prebuilt selection. 726*333d2b36SAndroid Build Coastguard Worker psi := PrebuiltSelectionInfoMap{} 727*333d2b36SAndroid Build Coastguard Worker var psiDepTag blueprint.DependencyTag 728*333d2b36SAndroid Build Coastguard Worker if p := GetEmbeddedPrebuilt(ctx.Module()); p != nil { 729*333d2b36SAndroid Build Coastguard Worker // This is a prebuilt module, visit all_apex_contributions to get the info 730*333d2b36SAndroid Build Coastguard Worker psiDepTag = AcDepTag 731*333d2b36SAndroid Build Coastguard Worker } else { 732*333d2b36SAndroid Build Coastguard Worker // This is a source module, visit any of its prebuilts to get the info 733*333d2b36SAndroid Build Coastguard Worker psiDepTag = PrebuiltDepTag 734*333d2b36SAndroid Build Coastguard Worker } 735*333d2b36SAndroid Build Coastguard Worker ctx.VisitDirectDepsWithTag(psiDepTag, func(am Module) { 736*333d2b36SAndroid Build Coastguard Worker psi, _ = OtherModuleProvider(ctx, am, PrebuiltSelectionInfoProvider) 737*333d2b36SAndroid Build Coastguard Worker }) 738*333d2b36SAndroid Build Coastguard Worker 739*333d2b36SAndroid Build Coastguard Worker // If the source module is explicitly listed in the metadata module, use that 740*333d2b36SAndroid Build Coastguard Worker if source != nil && isSelected(psi, source) { 741*333d2b36SAndroid Build Coastguard Worker return false 742*333d2b36SAndroid Build Coastguard Worker } 743*333d2b36SAndroid Build Coastguard Worker // If the prebuilt module is explicitly listed in the metadata module, use that 744*333d2b36SAndroid Build Coastguard Worker if isSelected(psi, prebuilt) && !p.variantIsDisabled(ctx, prebuilt) { 745*333d2b36SAndroid Build Coastguard Worker return true 746*333d2b36SAndroid Build Coastguard Worker } 747*333d2b36SAndroid Build Coastguard Worker 748*333d2b36SAndroid Build Coastguard Worker // If this is a mainline prebuilt, but has not been flagged, hide it. 749*333d2b36SAndroid Build Coastguard Worker if isMainlinePrebuilt(prebuilt) { 750*333d2b36SAndroid Build Coastguard Worker return false 751*333d2b36SAndroid Build Coastguard Worker } 752*333d2b36SAndroid Build Coastguard Worker 753*333d2b36SAndroid Build Coastguard Worker // If the baseModuleName could not be found in the metadata module, 754*333d2b36SAndroid Build Coastguard Worker // fall back to the existing source vs prebuilt selection. 755*333d2b36SAndroid Build Coastguard Worker // TODO: Drop the fallback mechanisms 756*333d2b36SAndroid Build Coastguard Worker 757*333d2b36SAndroid Build Coastguard Worker if p.variantIsDisabled(ctx, prebuilt) { 758*333d2b36SAndroid Build Coastguard Worker return false 759*333d2b36SAndroid Build Coastguard Worker } 760*333d2b36SAndroid Build Coastguard Worker 761*333d2b36SAndroid Build Coastguard Worker // Skip prebuilt modules under unexported namespaces so that we won't 762*333d2b36SAndroid Build Coastguard Worker // end up shadowing non-prebuilt module when prebuilt module under same 763*333d2b36SAndroid Build Coastguard Worker // name happens to have a `Prefer` property set to true. 764*333d2b36SAndroid Build Coastguard Worker if ctx.Config().KatiEnabled() && !prebuilt.ExportedToMake() { 765*333d2b36SAndroid Build Coastguard Worker return false 766*333d2b36SAndroid Build Coastguard Worker } 767*333d2b36SAndroid Build Coastguard Worker 768*333d2b36SAndroid Build Coastguard Worker // If source is not available or is disabled then always use the prebuilt. 769*333d2b36SAndroid Build Coastguard Worker if source == nil || !source.Enabled(ctx) { 770*333d2b36SAndroid Build Coastguard Worker return true 771*333d2b36SAndroid Build Coastguard Worker } 772*333d2b36SAndroid Build Coastguard Worker 773*333d2b36SAndroid Build Coastguard Worker // TODO: use p.Properties.Name and ctx.ModuleDir to override preference 774*333d2b36SAndroid Build Coastguard Worker return p.properties.Prefer.GetOrDefault(ctx, false) 775*333d2b36SAndroid Build Coastguard Worker} 776*333d2b36SAndroid Build Coastguard Worker 777*333d2b36SAndroid Build Coastguard Workerfunc (p *Prebuilt) SourceExists() bool { 778*333d2b36SAndroid Build Coastguard Worker return p.properties.SourceExists 779*333d2b36SAndroid Build Coastguard Worker} 780