blob: 0cbe4b07c7191d163811670816d249bb968f5463 [file] [log] [blame]
Colin Cross3f40fa42015-01-30 17:27:36 -08001// Copyright 2015 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 common
16
17import (
18 "blueprint"
19 "path/filepath"
20)
21
22var (
23 DeviceSharedLibrary = "shared_library"
24 DeviceStaticLibrary = "static_library"
25 DeviceExecutable = "executable"
26 HostSharedLibrary = "host_shared_library"
27 HostStaticLibrary = "host_static_library"
28 HostExecutable = "host_executable"
29)
30
31type AndroidModuleContext interface {
32 blueprint.ModuleContext
33
34 Arch() Arch
35 InstallFile(installPath, srcPath string)
36 CheckbuildFile(srcPath string)
37}
38
39type AndroidModule interface {
40 blueprint.Module
41
42 GenerateAndroidBuildActions(AndroidModuleContext)
43
44 base() *AndroidModuleBase
45 Disabled() bool
46 HostOrDevice() HostOrDevice
47}
48
49type AndroidDynamicDepender interface {
50 AndroidDynamicDependencies(ctx AndroidDynamicDependerModuleContext) []string
51}
52
53type AndroidDynamicDependerModuleContext interface {
54 blueprint.DynamicDependerModuleContext
55}
56
57type commonProperties struct {
58 Name string
59 Deps []string
60 ResourceDirs []string
61
62 // disabled: don't emit any build rules for this module
63 Disabled bool `android:"arch_variant"`
64
65 // multilib: control whether this module compiles for 32-bit, 64-bit, or both. Possible values
66 // are "32" (compile for 32-bit only), "64" (compile for 64-bit only), "both" (compile for both
67 // architectures), or "first" (compile for 64-bit on a 64-bit platform, and 32-bit on a 32-bit
68 // platform
69 Compile_multilib string
70
71 // Set by ArchMutator
72 CompileArch Arch `blueprint:"mutated"`
73
74 // Set by InitAndroidModule
75 HostOrDeviceSupported HostOrDeviceSupported `blueprint:"mutated"`
76}
77
78type hostAndDeviceProperties struct {
79 Host_supported bool
80 Device_supported bool
81}
82
83func InitAndroidModule(m AndroidModule, hod HostOrDeviceSupported, defaultMultilib string,
84 propertyStructs ...interface{}) (blueprint.Module, []interface{}) {
85
86 base := m.base()
87 base.module = m
88 base.commonProperties.HostOrDeviceSupported = hod
89
90 if hod == HostAndDeviceSupported {
91 // Default to module to device supported, host not supported, can override in module
92 // properties
93 base.hostAndDeviceProperties.Device_supported = true
94 propertyStructs = append(propertyStructs, &base.hostAndDeviceProperties)
95 }
96
97 return InitArchModule(m, defaultMultilib, propertyStructs...)
98}
99
100// A AndroidModuleBase object contains the properties that are common to all Android
101// modules. It should be included as an anonymous field in every module
102// struct definition. InitAndroidModule should then be called from the module's
103// factory function, and the return values from InitAndroidModule should be
104// returned from the factory function.
105//
106// The AndroidModuleBase type is responsible for implementing the
107// GenerateBuildActions method to support the blueprint.Module interface. This
108// method will then call the module's GenerateAndroidBuildActions method once
109// for each build variant that is to be built. GenerateAndroidBuildActions is
110// passed a AndroidModuleContext rather than the usual blueprint.ModuleContext.
111// AndroidModuleContext exposes extra functionality specific to the Android build
112// system including details about the particular build variant that is to be
113// generated.
114//
115// For example:
116//
117// import (
118// "android/soong/common"
119// "blueprint"
120// )
121//
122// type myModule struct {
123// common.AndroidModuleBase
124// properties struct {
125// MyProperty string
126// }
127// }
128//
129// func NewMyModule() (blueprint.Module, []interface{}) {
130// m := &myModule{}
131// return common.InitAndroidModule(m, &m.properties)
132// }
133//
134// func (m *myModule) GenerateAndroidBuildActions(ctx common.AndroidModuleContext) {
135// // Get the CPU architecture for the current build variant.
136// variantArch := ctx.Arch()
137//
138// // ...
139// }
140type AndroidModuleBase struct {
141 // Putting the curiously recurring thing pointing to the thing that contains
142 // the thing pattern to good use.
143 module AndroidModule
144
145 commonProperties commonProperties
146 hostAndDeviceProperties hostAndDeviceProperties
147 generalProperties []interface{}
148 archProperties []*archProperties
149
150 noAddressSanitizer bool
151 installFiles []string
152 checkbuildFiles []string
153}
154
155func (a *AndroidModuleBase) base() *AndroidModuleBase {
156 return a
157}
158
159func (a *AndroidModuleBase) SetArch(arch Arch) {
160 a.commonProperties.CompileArch = arch
161}
162
163func (a *AndroidModuleBase) HostOrDevice() HostOrDevice {
164 return a.commonProperties.CompileArch.HostOrDevice
165}
166
167func (a *AndroidModuleBase) HostSupported() bool {
168 return a.commonProperties.HostOrDeviceSupported == HostSupported ||
169 a.commonProperties.HostOrDeviceSupported == HostAndDeviceSupported &&
170 a.hostAndDeviceProperties.Host_supported
171}
172
173func (a *AndroidModuleBase) DeviceSupported() bool {
174 return a.commonProperties.HostOrDeviceSupported == DeviceSupported ||
175 a.commonProperties.HostOrDeviceSupported == HostAndDeviceSupported &&
176 a.hostAndDeviceProperties.Device_supported
177}
178
179func (a *AndroidModuleBase) Disabled() bool {
180 return a.commonProperties.Disabled
181}
182
183func (a *AndroidModuleBase) computeInstallDeps(
184 ctx blueprint.ModuleContext) []string {
185
186 result := []string{}
187 ctx.VisitDepsDepthFirstIf(isFileInstaller,
188 func(m blueprint.Module) {
189 fileInstaller := m.(fileInstaller)
190 files := fileInstaller.filesToInstall()
191 result = append(result, files...)
192 })
193
194 return result
195}
196
197func (a *AndroidModuleBase) filesToInstall() []string {
198 return a.installFiles
199}
200
201func (p *AndroidModuleBase) NoAddressSanitizer() bool {
202 return p.noAddressSanitizer
203}
204
205func (p *AndroidModuleBase) resourceDirs() []string {
206 return p.commonProperties.ResourceDirs
207}
208
209func (a *AndroidModuleBase) generateModuleTarget(ctx blueprint.ModuleContext) {
210 if a != ctx.FinalModule().(AndroidModule).base() {
211 return
212 }
213
214 allInstalledFiles := []string{}
215 ctx.VisitAllModuleVariants(func(module blueprint.Module) {
216 if androidModule, ok := module.(AndroidModule); ok {
217 files := androidModule.base().installFiles
218 allInstalledFiles = append(allInstalledFiles, files...)
219 }
220 })
221
222 if len(allInstalledFiles) > 0 {
223 ctx.Build(pctx, blueprint.BuildParams{
224 Rule: blueprint.Phony,
225 Outputs: []string{ctx.ModuleName()},
226 Inputs: allInstalledFiles,
227 })
228 }
229}
230
231func (a *AndroidModuleBase) DynamicDependencies(ctx blueprint.DynamicDependerModuleContext) []string {
232 actx := &androidDynamicDependerContext{
233 DynamicDependerModuleContext: ctx,
234 module: a,
235 }
236
237 if dynamic, ok := a.module.(AndroidDynamicDepender); ok {
238 return dynamic.AndroidDynamicDependencies(actx)
239 }
240
241 return nil
242}
243
244func (a *AndroidModuleBase) GenerateBuildActions(ctx blueprint.ModuleContext) {
245 androidCtx := &androidModuleContext{
246 ModuleContext: ctx,
247 installDeps: a.computeInstallDeps(ctx),
248 installFiles: a.installFiles,
249 arch: a.commonProperties.CompileArch,
250 }
251
252 if a.commonProperties.Disabled {
253 return
254 }
255
256 a.module.GenerateAndroidBuildActions(androidCtx)
257 if ctx.Failed() {
258 return
259 }
260
261 a.generateModuleTarget(ctx)
262 if ctx.Failed() {
263 return
264 }
265}
266
267type androidModuleContext struct {
268 blueprint.ModuleContext
269 arch Arch
270 installDeps []string
271 installFiles []string
272 checkbuildFiles []string
273}
274
275func (a *androidModuleContext) Build(pctx *blueprint.PackageContext, params blueprint.BuildParams) {
276 params.Optional = true
277 a.ModuleContext.Build(pctx, params)
278}
279
280func (a *androidModuleContext) Arch() Arch {
281 return a.arch
282}
283
284func (a *androidModuleContext) InstallFile(installPath, srcPath string) {
285 var fullInstallPath string
286 if a.arch.HostOrDevice.Device() {
287 // TODO: replace unset with a device name once we have device targeting
288 fullInstallPath = filepath.Join("out/target/product/unset/system", installPath,
289 filepath.Base(srcPath))
290 } else {
291 // TODO: replace unset with a host name
292 fullInstallPath = filepath.Join("out/host/unset/", installPath, filepath.Base(srcPath))
293 }
294
295 a.ModuleContext.Build(pctx, blueprint.BuildParams{
296 Rule: Cp,
297 Outputs: []string{fullInstallPath},
298 Inputs: []string{srcPath},
299 OrderOnly: a.installDeps,
300 })
301
302 a.installFiles = append(a.installFiles, fullInstallPath)
303 a.checkbuildFiles = append(a.checkbuildFiles, srcPath)
304}
305
306func (a *androidModuleContext) CheckbuildFile(srcPath string) {
307 a.checkbuildFiles = append(a.checkbuildFiles, srcPath)
308}
309
310type androidDynamicDependerContext struct {
311 blueprint.DynamicDependerModuleContext
312 module *AndroidModuleBase
313}
314
315type fileInstaller interface {
316 filesToInstall() []string
317}
318
319func isFileInstaller(m blueprint.Module) bool {
320 _, ok := m.(fileInstaller)
321 return ok
322}
323
324func isAndroidModule(m blueprint.Module) bool {
325 _, ok := m.(AndroidModule)
326 return ok
327}