aboutsummaryrefslogtreecommitdiffstats
path: root/android/prebuilt.go
blob: 5f9b4b09473617bc44a687d0a6db7b4615ad0a62 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// Copyright 2016 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package android

import "github.com/google/blueprint"

// This file implements common functionality for handling modules that may exist as prebuilts,
// source, or both.

var prebuiltDependencyTag blueprint.BaseDependencyTag

type Prebuilt struct {
	Properties struct {
		Srcs []string `android:"arch_variant"`
		// When prefer is set to true the prebuilt will be used instead of any source module with
		// a matching name.
		Prefer bool `android:"arch_variant"`

		SourceExists bool `blueprint:"mutated"`
		UsePrebuilt  bool `blueprint:"mutated"`
	}
	module Module
}

func (p *Prebuilt) Name(name string) string {
	return "prebuilt_" + name
}

func (p *Prebuilt) Path(ctx ModuleContext) Path {
	if len(p.Properties.Srcs) == 0 {
		ctx.PropertyErrorf("srcs", "missing prebuilt source file")
		return nil
	}

	if len(p.Properties.Srcs) > 1 {
		ctx.PropertyErrorf("srcs", "multiple prebuilt source files")
		return nil
	}

	return PathForModuleSrc(ctx, p.Properties.Srcs[0])
}

type PrebuiltInterface interface {
	Module
	Prebuilt() *Prebuilt
}

// prebuiltMutator ensures that there is always a module with an undecorated name, and marks
// prebuilt modules that have both a prebuilt and a source module.
func prebuiltMutator(ctx BottomUpMutatorContext) {
	if m, ok := ctx.Module().(PrebuiltInterface); ok && m.Prebuilt() != nil {
		p := m.Prebuilt()
		name := m.base().BaseModuleName()
		if ctx.OtherModuleExists(name) {
			ctx.AddReverseDependency(ctx.Module(), prebuiltDependencyTag, name)
			p.Properties.SourceExists = true
		} else {
			ctx.Rename(name)
		}
	}
}

// PrebuiltSelectModuleMutator marks prebuilts that are overriding source modules, and disables
// installing the source module.
func PrebuiltSelectModuleMutator(ctx TopDownMutatorContext) {
	if s, ok := ctx.Module().(Module); ok {
		ctx.VisitDirectDeps(func(m blueprint.Module) {
			if ctx.OtherModuleDependencyTag(m) == prebuiltDependencyTag {
				p := m.(PrebuiltInterface).Prebuilt()
				if p.usePrebuilt(ctx, s) {
					p.Properties.UsePrebuilt = true
					s.SkipInstall()
				}
			}
		})
	}
}

// PrebuiltReplaceMutator replaces dependencies on the source module with dependencies on the
// prebuilt when both modules exist and the prebuilt should be used.  When the prebuilt should not
// be used, disable installing it.
func PrebuiltReplaceMutator(ctx BottomUpMutatorContext) {
	if m, ok := ctx.Module().(PrebuiltInterface); ok && m.Prebuilt() != nil {
		p := m.Prebuilt()
		name := m.base().BaseModuleName()
		if p.Properties.UsePrebuilt {
			if p.Properties.SourceExists {
				ctx.ReplaceDependencies(name)
			}
		} else {
			m.SkipInstall()
		}
	}
}

// usePrebuilt returns true if a prebuilt should be used instead of the source module.  The prebuilt
// will be used if it is marked "prefer" or if the source module is disabled.
func (p *Prebuilt) usePrebuilt(ctx TopDownMutatorContext, source Module) bool {
	if len(p.Properties.Srcs) == 0 {
		return false
	}

	// TODO: use p.Properties.Name and ctx.ModuleDir to override preference
	if p.Properties.Prefer {
		return true
	}

	return !source.Enabled()
}