• 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	"io"
20	"strings"
21)
22
23// TODO(jungw): Now that it handles more than the ones in etc/, consider renaming this file.
24
25func init() {
26	RegisterModuleType("prebuilt_etc", PrebuiltEtcFactory)
27	RegisterModuleType("prebuilt_etc_host", PrebuiltEtcHostFactory)
28	RegisterModuleType("prebuilt_usr_share", PrebuiltUserShareFactory)
29	RegisterModuleType("prebuilt_usr_share_host", PrebuiltUserShareHostFactory)
30
31	PreDepsMutators(func(ctx RegisterMutatorsContext) {
32		ctx.BottomUp("prebuilt_etc", prebuiltEtcMutator).Parallel()
33	})
34}
35
36type prebuiltEtcProperties struct {
37	// Source file of this prebuilt.
38	Src *string `android:"path,arch_variant"`
39
40	// optional subdirectory under which this file is installed into
41	Sub_dir *string `android:"arch_variant"`
42
43	// optional name for the installed file. If unspecified, name of the module is used as the file name
44	Filename *string `android:"arch_variant"`
45
46	// when set to true, and filename property is not set, the name for the installed file
47	// is the same as the file name of the source file.
48	Filename_from_src *bool `android:"arch_variant"`
49
50	// Make this module available when building for recovery.
51	Recovery_available *bool
52
53	InRecovery bool `blueprint:"mutated"`
54
55	// Whether this module is directly installable to one of the partitions. Default: true.
56	Installable *bool
57}
58
59type PrebuiltEtc struct {
60	ModuleBase
61
62	properties prebuiltEtcProperties
63
64	sourceFilePath Path
65	outputFilePath OutputPath
66	// The base install location, e.g. "etc" for prebuilt_etc, "usr/share" for prebuilt_usr_share.
67	installDirBase         string
68	installDirPath         OutputPath
69	additionalDependencies *Paths
70}
71
72func (p *PrebuiltEtc) inRecovery() bool {
73	return p.properties.InRecovery || p.ModuleBase.InstallInRecovery()
74}
75
76func (p *PrebuiltEtc) onlyInRecovery() bool {
77	return p.ModuleBase.InstallInRecovery()
78}
79
80func (p *PrebuiltEtc) InstallInRecovery() bool {
81	return p.inRecovery()
82}
83
84func (p *PrebuiltEtc) DepsMutator(ctx BottomUpMutatorContext) {
85	if p.properties.Src == nil {
86		ctx.PropertyErrorf("src", "missing prebuilt source file")
87	}
88}
89
90func (p *PrebuiltEtc) SourceFilePath(ctx ModuleContext) Path {
91	return PathForModuleSrc(ctx, String(p.properties.Src))
92}
93
94// This allows other derivative modules (e.g. prebuilt_etc_xml) to perform
95// additional steps (like validating the src) before the file is installed.
96func (p *PrebuiltEtc) SetAdditionalDependencies(paths Paths) {
97	p.additionalDependencies = &paths
98}
99
100func (p *PrebuiltEtc) OutputFile() OutputPath {
101	return p.outputFilePath
102}
103
104func (p *PrebuiltEtc) SubDir() string {
105	return String(p.properties.Sub_dir)
106}
107
108func (p *PrebuiltEtc) Installable() bool {
109	return p.properties.Installable == nil || Bool(p.properties.Installable)
110}
111
112func (p *PrebuiltEtc) GenerateAndroidBuildActions(ctx ModuleContext) {
113	p.sourceFilePath = PathForModuleSrc(ctx, String(p.properties.Src))
114	filename := String(p.properties.Filename)
115	filename_from_src := Bool(p.properties.Filename_from_src)
116	if filename == "" {
117		if filename_from_src {
118			filename = p.sourceFilePath.Base()
119		} else {
120			filename = ctx.ModuleName()
121		}
122	} else if filename_from_src {
123		ctx.PropertyErrorf("filename_from_src", "filename is set. filename_from_src can't be true")
124		return
125	}
126	p.outputFilePath = PathForModuleOut(ctx, filename).OutputPath
127	p.installDirPath = PathForModuleInstall(ctx, p.installDirBase, String(p.properties.Sub_dir))
128
129	// This ensures that outputFilePath has the correct name for others to
130	// use, as the source file may have a different name.
131	ctx.Build(pctx, BuildParams{
132		Rule:   Cp,
133		Output: p.outputFilePath,
134		Input:  p.sourceFilePath,
135	})
136}
137
138func (p *PrebuiltEtc) AndroidMk() AndroidMkData {
139	return AndroidMkData{
140		Custom: func(w io.Writer, name, prefix, moduleDir string, data AndroidMkData) {
141			nameSuffix := ""
142			if p.inRecovery() && !p.onlyInRecovery() {
143				nameSuffix = ".recovery"
144			}
145			fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
146			fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
147			fmt.Fprintln(w, "LOCAL_MODULE :=", name+nameSuffix)
148			fmt.Fprintln(w, "LOCAL_MODULE_CLASS := ETC")
149			if p.commonProperties.Owner != nil {
150				fmt.Fprintln(w, "LOCAL_MODULE_OWNER :=", *p.commonProperties.Owner)
151			}
152			fmt.Fprintln(w, "LOCAL_MODULE_TAGS := optional")
153			if p.Host() {
154				fmt.Fprintln(w, "LOCAL_IS_HOST_MODULE := true")
155			}
156			fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", p.outputFilePath.String())
157			fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", "$(OUT_DIR)/"+p.installDirPath.RelPathString())
158			fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", p.outputFilePath.Base())
159			fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE :=", !p.Installable())
160			fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES :=", strings.Join(data.Required, " "))
161			fmt.Fprintln(w, "LOCAL_MODULE_TARGET_ARCH :=", p.Arch().ArchType.String())
162			if p.additionalDependencies != nil {
163				fmt.Fprint(w, "LOCAL_ADDITIONAL_DEPENDENCIES :=")
164				for _, path := range *p.additionalDependencies {
165					fmt.Fprint(w, " "+path.String())
166				}
167				fmt.Fprintln(w, "")
168			}
169			fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
170		},
171	}
172}
173
174func InitPrebuiltEtcModule(p *PrebuiltEtc) {
175	p.AddProperties(&p.properties)
176}
177
178// prebuilt_etc is for a prebuilt artifact that is installed in
179// <partition>/etc/<sub_dir> directory.
180func PrebuiltEtcFactory() Module {
181	module := &PrebuiltEtc{installDirBase: "etc"}
182	InitPrebuiltEtcModule(module)
183	// This module is device-only
184	InitAndroidArchModule(module, DeviceSupported, MultilibFirst)
185	return module
186}
187
188// prebuilt_etc_host is for a host prebuilt artifact that is installed in
189// $(HOST_OUT)/etc/<sub_dir> directory.
190func PrebuiltEtcHostFactory() Module {
191	module := &PrebuiltEtc{installDirBase: "etc"}
192	InitPrebuiltEtcModule(module)
193	// This module is host-only
194	InitAndroidArchModule(module, HostSupported, MultilibCommon)
195	return module
196}
197
198// prebuilt_usr_share is for a prebuilt artifact that is installed in
199// <partition>/usr/share/<sub_dir> directory.
200func PrebuiltUserShareFactory() Module {
201	module := &PrebuiltEtc{installDirBase: "usr/share"}
202	InitPrebuiltEtcModule(module)
203	// This module is device-only
204	InitAndroidArchModule(module, DeviceSupported, MultilibFirst)
205	return module
206}
207
208// prebuild_usr_share_host is for a host prebuilt artifact that is installed in
209// $(HOST_OUT)/usr/share/<sub_dir> directory.
210func PrebuiltUserShareHostFactory() Module {
211	module := &PrebuiltEtc{installDirBase: "usr/share"}
212	InitPrebuiltEtcModule(module)
213	// This module is host-only
214	InitAndroidArchModule(module, HostSupported, MultilibCommon)
215	return module
216}
217
218const (
219	// coreMode is the variant for modules to be installed to system.
220	coreMode = "core"
221
222	// recoveryMode means a module to be installed to recovery image.
223	recoveryMode = "recovery"
224)
225
226// prebuiltEtcMutator creates the needed variants to install the module to
227// system or recovery.
228func prebuiltEtcMutator(mctx BottomUpMutatorContext) {
229	m, ok := mctx.Module().(*PrebuiltEtc)
230	if !ok || m.Host() {
231		return
232	}
233
234	var coreVariantNeeded bool = true
235	var recoveryVariantNeeded bool = false
236	if Bool(m.properties.Recovery_available) {
237		recoveryVariantNeeded = true
238	}
239
240	if m.ModuleBase.InstallInRecovery() {
241		recoveryVariantNeeded = true
242		coreVariantNeeded = false
243	}
244
245	var variants []string
246	if coreVariantNeeded {
247		variants = append(variants, coreMode)
248	}
249	if recoveryVariantNeeded {
250		variants = append(variants, recoveryMode)
251	}
252	mod := mctx.CreateVariations(variants...)
253	for i, v := range variants {
254		if v == recoveryMode {
255			m := mod[i].(*PrebuiltEtc)
256			m.properties.InRecovery = true
257		}
258	}
259}
260