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