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 20 "github.com/google/blueprint" 21 "github.com/google/blueprint/proptools" 22) 23 24// This file implements common functionality for handling modules that may exist as prebuilts, 25// source, or both. 26 27type prebuiltDependencyTag struct { 28 blueprint.BaseDependencyTag 29} 30 31var prebuiltDepTag prebuiltDependencyTag 32 33type PrebuiltProperties struct { 34 // When prefer is set to true the prebuilt will be used instead of any source module with 35 // a matching name. 36 Prefer *bool `android:"arch_variant"` 37 38 SourceExists bool `blueprint:"mutated"` 39 UsePrebuilt bool `blueprint:"mutated"` 40} 41 42type Prebuilt struct { 43 properties PrebuiltProperties 44 module Module 45 srcs *[]string 46 src *string 47} 48 49func (p *Prebuilt) Name(name string) string { 50 return "prebuilt_" + name 51} 52 53func (p *Prebuilt) SingleSourcePath(ctx ModuleContext) Path { 54 if p.srcs != nil { 55 if len(*p.srcs) == 0 { 56 ctx.PropertyErrorf("srcs", "missing prebuilt source file") 57 return nil 58 } 59 60 if len(*p.srcs) > 1 { 61 ctx.PropertyErrorf("srcs", "multiple prebuilt source files") 62 return nil 63 } 64 65 // Return the singleton source after expanding any filegroup in the 66 // sources. 67 return PathForModuleSrc(ctx, (*p.srcs)[0]) 68 } else { 69 if proptools.String(p.src) == "" { 70 ctx.PropertyErrorf("src", "missing prebuilt source file") 71 return nil 72 } 73 return PathForModuleSrc(ctx, *p.src) 74 } 75} 76 77func (p *Prebuilt) UsePrebuilt() bool { 78 return p.properties.UsePrebuilt 79} 80 81func InitPrebuiltModule(module PrebuiltInterface, srcs *[]string) { 82 p := module.Prebuilt() 83 module.AddProperties(&p.properties) 84 p.srcs = srcs 85} 86 87func InitSingleSourcePrebuiltModule(module PrebuiltInterface, src *string) { 88 p := module.Prebuilt() 89 module.AddProperties(&p.properties) 90 p.src = src 91} 92 93type PrebuiltInterface interface { 94 Module 95 Prebuilt() *Prebuilt 96} 97 98func RegisterPrebuiltsPreArchMutators(ctx RegisterMutatorsContext) { 99 ctx.BottomUp("prebuilts", PrebuiltMutator).Parallel() 100} 101 102func RegisterPrebuiltsPostDepsMutators(ctx RegisterMutatorsContext) { 103 ctx.TopDown("prebuilt_select", PrebuiltSelectModuleMutator).Parallel() 104 ctx.BottomUp("prebuilt_postdeps", PrebuiltPostDepsMutator).Parallel() 105} 106 107// PrebuiltMutator ensures that there is always a module with an undecorated name, and marks 108// prebuilt modules that have both a prebuilt and a source module. 109func PrebuiltMutator(ctx BottomUpMutatorContext) { 110 if m, ok := ctx.Module().(PrebuiltInterface); ok && m.Prebuilt() != nil { 111 p := m.Prebuilt() 112 name := m.base().BaseModuleName() 113 if ctx.OtherModuleExists(name) { 114 ctx.AddReverseDependency(ctx.Module(), prebuiltDepTag, name) 115 p.properties.SourceExists = true 116 } else { 117 ctx.Rename(name) 118 } 119 } 120} 121 122// PrebuiltSelectModuleMutator marks prebuilts that are used, either overriding source modules or 123// because the source module doesn't exist. It also disables installing overridden source modules. 124func PrebuiltSelectModuleMutator(ctx TopDownMutatorContext) { 125 if m, ok := ctx.Module().(PrebuiltInterface); ok && m.Prebuilt() != nil { 126 p := m.Prebuilt() 127 if p.srcs == nil && p.src == nil { 128 panic(fmt.Errorf("prebuilt module did not have InitPrebuiltModule called on it")) 129 } 130 if !p.properties.SourceExists { 131 p.properties.UsePrebuilt = p.usePrebuilt(ctx, nil) 132 } 133 } else if s, ok := ctx.Module().(Module); ok { 134 ctx.VisitDirectDepsWithTag(prebuiltDepTag, func(m Module) { 135 p := m.(PrebuiltInterface).Prebuilt() 136 if p.usePrebuilt(ctx, s) { 137 p.properties.UsePrebuilt = true 138 s.SkipInstall() 139 } 140 }) 141 } 142} 143 144// PrebuiltPostDepsMutator does two operations. It replace dependencies on the 145// source module with dependencies on the prebuilt when both modules exist and 146// the prebuilt should be used. When the prebuilt should not be used, disable 147// installing it. Secondly, it also adds a sourcegroup to any filegroups found 148// in the prebuilt's 'Srcs' property. 149func PrebuiltPostDepsMutator(ctx BottomUpMutatorContext) { 150 if m, ok := ctx.Module().(PrebuiltInterface); ok && m.Prebuilt() != nil { 151 p := m.Prebuilt() 152 name := m.base().BaseModuleName() 153 if p.properties.UsePrebuilt { 154 if p.properties.SourceExists { 155 ctx.ReplaceDependencies(name) 156 } 157 } else { 158 m.SkipInstall() 159 } 160 } 161} 162 163// usePrebuilt returns true if a prebuilt should be used instead of the source module. The prebuilt 164// will be used if it is marked "prefer" or if the source module is disabled. 165func (p *Prebuilt) usePrebuilt(ctx TopDownMutatorContext, source Module) bool { 166 if p.srcs != nil && len(*p.srcs) == 0 { 167 return false 168 } 169 170 if p.src != nil && *p.src == "" { 171 return false 172 } 173 174 // TODO: use p.Properties.Name and ctx.ModuleDir to override preference 175 if Bool(p.properties.Prefer) { 176 return true 177 } 178 179 return source == nil || !source.Enabled() 180} 181 182func (p *Prebuilt) SourceExists() bool { 183 return p.properties.SourceExists 184} 185