• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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