blob: bafb583f2a6d137cfbc58cd155dc54249a0bf422 [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 (
Colin Cross3f40fa42015-01-30 17:27:36 -080018 "path/filepath"
Colin Crossf6566ed2015-03-24 11:13:38 -070019
20 "github.com/google/blueprint"
Colin Cross3f40fa42015-01-30 17:27:36 -080021)
22
23var (
24 DeviceSharedLibrary = "shared_library"
25 DeviceStaticLibrary = "static_library"
26 DeviceExecutable = "executable"
27 HostSharedLibrary = "host_shared_library"
28 HostStaticLibrary = "host_static_library"
29 HostExecutable = "host_executable"
30)
31
Colin Crossf6566ed2015-03-24 11:13:38 -070032type androidBaseContext interface {
33 Arch() Arch
34 Host() bool
35 Device() bool
36 Debug() bool
Colin Cross1332b002015-04-07 17:11:30 -070037 AConfig() Config
Colin Crossf6566ed2015-03-24 11:13:38 -070038}
39
40type AndroidBaseContext interface {
41 blueprint.BaseModuleContext
42 androidBaseContext
43}
44
Colin Cross3f40fa42015-01-30 17:27:36 -080045type AndroidModuleContext interface {
46 blueprint.ModuleContext
Colin Crossf6566ed2015-03-24 11:13:38 -070047 androidBaseContext
Colin Cross3f40fa42015-01-30 17:27:36 -080048
Colin Cross35cec122015-04-02 14:37:16 -070049 InstallFile(installPath, srcPath string, deps ...string) string
50 InstallFileName(installPath, name, srcPath string, deps ...string) string
Colin Cross3f40fa42015-01-30 17:27:36 -080051 CheckbuildFile(srcPath string)
52}
53
54type AndroidModule interface {
55 blueprint.Module
56
57 GenerateAndroidBuildActions(AndroidModuleContext)
58
59 base() *AndroidModuleBase
60 Disabled() bool
61 HostOrDevice() HostOrDevice
62}
63
64type AndroidDynamicDepender interface {
65 AndroidDynamicDependencies(ctx AndroidDynamicDependerModuleContext) []string
66}
67
68type AndroidDynamicDependerModuleContext interface {
69 blueprint.DynamicDependerModuleContext
Colin Crossf6566ed2015-03-24 11:13:38 -070070 androidBaseContext
Colin Cross3f40fa42015-01-30 17:27:36 -080071}
72
73type commonProperties struct {
Colin Crossc77f9d12015-04-02 13:54:39 -070074 Name string
75 Deps []string
76 Tags []string
Colin Cross3f40fa42015-01-30 17:27:36 -080077
78 // disabled: don't emit any build rules for this module
79 Disabled bool `android:"arch_variant"`
80
81 // multilib: control whether this module compiles for 32-bit, 64-bit, or both. Possible values
82 // are "32" (compile for 32-bit only), "64" (compile for 64-bit only), "both" (compile for both
83 // architectures), or "first" (compile for 64-bit on a 64-bit platform, and 32-bit on a 32-bit
84 // platform
85 Compile_multilib string
86
87 // Set by ArchMutator
88 CompileArch Arch `blueprint:"mutated"`
89
90 // Set by InitAndroidModule
91 HostOrDeviceSupported HostOrDeviceSupported `blueprint:"mutated"`
92}
93
94type hostAndDeviceProperties struct {
95 Host_supported bool
96 Device_supported bool
97}
98
Colin Crossc472d572015-03-17 15:06:21 -070099type Multilib string
100
101const (
Colin Cross2fe66872015-03-30 17:20:39 -0700102 MultilibBoth Multilib = "both"
103 MultilibFirst Multilib = "first"
104 MultilibCommon Multilib = "common"
Colin Crossc472d572015-03-17 15:06:21 -0700105)
106
Colin Cross5049f022015-03-18 13:28:46 -0700107func InitAndroidModule(m AndroidModule,
Colin Cross3f40fa42015-01-30 17:27:36 -0800108 propertyStructs ...interface{}) (blueprint.Module, []interface{}) {
109
110 base := m.base()
111 base.module = m
Colin Cross28d76592015-03-26 16:14:04 -0700112 base.extendedProperties = make(map[string]struct{})
Colin Cross5049f022015-03-18 13:28:46 -0700113
114 propertyStructs = append(propertyStructs, &base.commonProperties)
115
116 return m, propertyStructs
117}
118
119func InitAndroidArchModule(m AndroidModule, hod HostOrDeviceSupported, defaultMultilib Multilib,
120 propertyStructs ...interface{}) (blueprint.Module, []interface{}) {
121
122 _, propertyStructs = InitAndroidModule(m, propertyStructs...)
123
124 base := m.base()
Colin Cross3f40fa42015-01-30 17:27:36 -0800125 base.commonProperties.HostOrDeviceSupported = hod
126
127 if hod == HostAndDeviceSupported {
128 // Default to module to device supported, host not supported, can override in module
129 // properties
130 base.hostAndDeviceProperties.Device_supported = true
131 propertyStructs = append(propertyStructs, &base.hostAndDeviceProperties)
132 }
133
134 return InitArchModule(m, defaultMultilib, propertyStructs...)
135}
136
137// A AndroidModuleBase object contains the properties that are common to all Android
138// modules. It should be included as an anonymous field in every module
139// struct definition. InitAndroidModule should then be called from the module's
140// factory function, and the return values from InitAndroidModule should be
141// returned from the factory function.
142//
143// The AndroidModuleBase type is responsible for implementing the
144// GenerateBuildActions method to support the blueprint.Module interface. This
145// method will then call the module's GenerateAndroidBuildActions method once
146// for each build variant that is to be built. GenerateAndroidBuildActions is
147// passed a AndroidModuleContext rather than the usual blueprint.ModuleContext.
148// AndroidModuleContext exposes extra functionality specific to the Android build
149// system including details about the particular build variant that is to be
150// generated.
151//
152// For example:
153//
154// import (
155// "android/soong/common"
Colin Cross70b40592015-03-23 12:57:34 -0700156// "github.com/google/blueprint"
Colin Cross3f40fa42015-01-30 17:27:36 -0800157// )
158//
159// type myModule struct {
160// common.AndroidModuleBase
161// properties struct {
162// MyProperty string
163// }
164// }
165//
166// func NewMyModule() (blueprint.Module, []interface{}) {
167// m := &myModule{}
168// return common.InitAndroidModule(m, &m.properties)
169// }
170//
171// func (m *myModule) GenerateAndroidBuildActions(ctx common.AndroidModuleContext) {
172// // Get the CPU architecture for the current build variant.
173// variantArch := ctx.Arch()
174//
175// // ...
176// }
177type AndroidModuleBase struct {
178 // Putting the curiously recurring thing pointing to the thing that contains
179 // the thing pattern to good use.
180 module AndroidModule
181
182 commonProperties commonProperties
183 hostAndDeviceProperties hostAndDeviceProperties
184 generalProperties []interface{}
185 archProperties []*archProperties
Colin Cross28d76592015-03-26 16:14:04 -0700186 extendedProperties map[string]struct{}
Colin Cross3f40fa42015-01-30 17:27:36 -0800187
188 noAddressSanitizer bool
189 installFiles []string
190 checkbuildFiles []string
191}
192
193func (a *AndroidModuleBase) base() *AndroidModuleBase {
194 return a
195}
196
197func (a *AndroidModuleBase) SetArch(arch Arch) {
198 a.commonProperties.CompileArch = arch
199}
200
201func (a *AndroidModuleBase) HostOrDevice() HostOrDevice {
202 return a.commonProperties.CompileArch.HostOrDevice
203}
204
205func (a *AndroidModuleBase) HostSupported() bool {
206 return a.commonProperties.HostOrDeviceSupported == HostSupported ||
207 a.commonProperties.HostOrDeviceSupported == HostAndDeviceSupported &&
208 a.hostAndDeviceProperties.Host_supported
209}
210
211func (a *AndroidModuleBase) DeviceSupported() bool {
212 return a.commonProperties.HostOrDeviceSupported == DeviceSupported ||
213 a.commonProperties.HostOrDeviceSupported == HostAndDeviceSupported &&
214 a.hostAndDeviceProperties.Device_supported
215}
216
217func (a *AndroidModuleBase) Disabled() bool {
218 return a.commonProperties.Disabled
219}
220
221func (a *AndroidModuleBase) computeInstallDeps(
222 ctx blueprint.ModuleContext) []string {
223
224 result := []string{}
225 ctx.VisitDepsDepthFirstIf(isFileInstaller,
226 func(m blueprint.Module) {
227 fileInstaller := m.(fileInstaller)
228 files := fileInstaller.filesToInstall()
229 result = append(result, files...)
230 })
231
232 return result
233}
234
235func (a *AndroidModuleBase) filesToInstall() []string {
236 return a.installFiles
237}
238
239func (p *AndroidModuleBase) NoAddressSanitizer() bool {
240 return p.noAddressSanitizer
241}
242
Colin Cross3f40fa42015-01-30 17:27:36 -0800243func (a *AndroidModuleBase) generateModuleTarget(ctx blueprint.ModuleContext) {
244 if a != ctx.FinalModule().(AndroidModule).base() {
245 return
246 }
247
248 allInstalledFiles := []string{}
Colin Cross9454bfa2015-03-17 13:24:18 -0700249 allCheckbuildFiles := []string{}
Colin Cross3f40fa42015-01-30 17:27:36 -0800250 ctx.VisitAllModuleVariants(func(module blueprint.Module) {
Colin Crossc9404352015-03-26 16:10:12 -0700251 a := module.(AndroidModule).base()
252 allInstalledFiles = append(allInstalledFiles, a.installFiles...)
253 allCheckbuildFiles = append(allCheckbuildFiles, a.checkbuildFiles...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800254 })
255
Colin Cross9454bfa2015-03-17 13:24:18 -0700256 deps := []string{}
257
Colin Cross3f40fa42015-01-30 17:27:36 -0800258 if len(allInstalledFiles) > 0 {
Colin Cross9454bfa2015-03-17 13:24:18 -0700259 name := ctx.ModuleName() + "-install"
Colin Cross3f40fa42015-01-30 17:27:36 -0800260 ctx.Build(pctx, blueprint.BuildParams{
Colin Cross9454bfa2015-03-17 13:24:18 -0700261 Rule: blueprint.Phony,
262 Outputs: []string{name},
263 Implicits: allInstalledFiles,
264 })
265 deps = append(deps, name)
266 }
267
268 if len(allCheckbuildFiles) > 0 {
269 name := ctx.ModuleName() + "-checkbuild"
270 ctx.Build(pctx, blueprint.BuildParams{
271 Rule: blueprint.Phony,
272 Outputs: []string{name},
273 Implicits: allCheckbuildFiles,
274 Optional: true,
275 })
276 deps = append(deps, name)
277 }
278
279 if len(deps) > 0 {
280 ctx.Build(pctx, blueprint.BuildParams{
281 Rule: blueprint.Phony,
282 Outputs: []string{ctx.ModuleName()},
283 Implicits: deps,
284 Optional: true,
Colin Cross3f40fa42015-01-30 17:27:36 -0800285 })
286 }
287}
288
289func (a *AndroidModuleBase) DynamicDependencies(ctx blueprint.DynamicDependerModuleContext) []string {
290 actx := &androidDynamicDependerContext{
291 DynamicDependerModuleContext: ctx,
Colin Crossf6566ed2015-03-24 11:13:38 -0700292 androidBaseContextImpl: androidBaseContextImpl{
Colin Cross1332b002015-04-07 17:11:30 -0700293 arch: a.commonProperties.CompileArch,
294 config: ctx.Config().(Config),
Colin Crossf6566ed2015-03-24 11:13:38 -0700295 },
Colin Cross3f40fa42015-01-30 17:27:36 -0800296 }
297
298 if dynamic, ok := a.module.(AndroidDynamicDepender); ok {
299 return dynamic.AndroidDynamicDependencies(actx)
300 }
301
302 return nil
303}
304
305func (a *AndroidModuleBase) GenerateBuildActions(ctx blueprint.ModuleContext) {
306 androidCtx := &androidModuleContext{
307 ModuleContext: ctx,
Colin Crossf6566ed2015-03-24 11:13:38 -0700308 androidBaseContextImpl: androidBaseContextImpl{
Colin Cross1332b002015-04-07 17:11:30 -0700309 arch: a.commonProperties.CompileArch,
310 config: ctx.Config().(Config),
Colin Crossf6566ed2015-03-24 11:13:38 -0700311 },
Colin Cross28d76592015-03-26 16:14:04 -0700312 installDeps: a.computeInstallDeps(ctx),
313 installFiles: a.installFiles,
314 extendedProperties: a.extendedProperties,
Colin Cross3f40fa42015-01-30 17:27:36 -0800315 }
316
317 if a.commonProperties.Disabled {
318 return
319 }
320
321 a.module.GenerateAndroidBuildActions(androidCtx)
322 if ctx.Failed() {
323 return
324 }
325
Colin Crossc9404352015-03-26 16:10:12 -0700326 a.installFiles = append(a.installFiles, androidCtx.installFiles...)
327 a.checkbuildFiles = append(a.checkbuildFiles, androidCtx.checkbuildFiles...)
328
Colin Cross3f40fa42015-01-30 17:27:36 -0800329 a.generateModuleTarget(ctx)
330 if ctx.Failed() {
331 return
332 }
333}
334
Colin Crossf6566ed2015-03-24 11:13:38 -0700335type androidBaseContextImpl struct {
Colin Cross1332b002015-04-07 17:11:30 -0700336 arch Arch
337 debug bool
338 config Config
Colin Crossf6566ed2015-03-24 11:13:38 -0700339}
340
Colin Cross3f40fa42015-01-30 17:27:36 -0800341type androidModuleContext struct {
342 blueprint.ModuleContext
Colin Crossf6566ed2015-03-24 11:13:38 -0700343 androidBaseContextImpl
Colin Cross28d76592015-03-26 16:14:04 -0700344 installDeps []string
345 installFiles []string
346 checkbuildFiles []string
347 extendedProperties map[string]struct{}
Colin Cross3f40fa42015-01-30 17:27:36 -0800348}
349
350func (a *androidModuleContext) Build(pctx *blueprint.PackageContext, params blueprint.BuildParams) {
351 params.Optional = true
352 a.ModuleContext.Build(pctx, params)
353}
354
Colin Cross28d76592015-03-26 16:14:04 -0700355func (a *androidModuleContext) ContainsProperty(property string) bool {
356 if a.ModuleContext.ContainsProperty(property) {
357 return true
358 }
359 _, ok := a.extendedProperties[property]
360 return ok
361}
362
Colin Crossf6566ed2015-03-24 11:13:38 -0700363func (a *androidBaseContextImpl) Arch() Arch {
Colin Cross3f40fa42015-01-30 17:27:36 -0800364 return a.arch
365}
366
Colin Crossf6566ed2015-03-24 11:13:38 -0700367func (a *androidBaseContextImpl) Host() bool {
368 return a.arch.HostOrDevice.Host()
369}
370
371func (a *androidBaseContextImpl) Device() bool {
372 return a.arch.HostOrDevice.Device()
373}
374
375func (a *androidBaseContextImpl) Debug() bool {
376 return a.debug
377}
378
Colin Cross1332b002015-04-07 17:11:30 -0700379func (a *androidBaseContextImpl) AConfig() Config {
380 return a.config
381}
382
Colin Cross35cec122015-04-02 14:37:16 -0700383func (a *androidModuleContext) InstallFileName(installPath, name, srcPath string,
384 deps ...string) string {
385
Colin Cross1332b002015-04-07 17:11:30 -0700386 config := a.AConfig()
Colin Cross3f40fa42015-01-30 17:27:36 -0800387 var fullInstallPath string
388 if a.arch.HostOrDevice.Device() {
389 // TODO: replace unset with a device name once we have device targeting
Colin Cross35cec122015-04-02 14:37:16 -0700390 fullInstallPath = filepath.Join(config.DeviceOut(), "system",
391 installPath, name)
Colin Cross3f40fa42015-01-30 17:27:36 -0800392 } else {
Colin Cross35cec122015-04-02 14:37:16 -0700393 fullInstallPath = filepath.Join(config.HostOut(), installPath, name)
Colin Cross3f40fa42015-01-30 17:27:36 -0800394 }
395
Colin Cross35cec122015-04-02 14:37:16 -0700396 deps = append(deps, a.installDeps...)
397
Colin Cross3f40fa42015-01-30 17:27:36 -0800398 a.ModuleContext.Build(pctx, blueprint.BuildParams{
399 Rule: Cp,
400 Outputs: []string{fullInstallPath},
401 Inputs: []string{srcPath},
Colin Cross35cec122015-04-02 14:37:16 -0700402 OrderOnly: deps,
Colin Cross3f40fa42015-01-30 17:27:36 -0800403 })
404
405 a.installFiles = append(a.installFiles, fullInstallPath)
Colin Cross35cec122015-04-02 14:37:16 -0700406 return fullInstallPath
407}
408
409func (a *androidModuleContext) InstallFile(installPath, srcPath string, deps ...string) string {
410 return a.InstallFileName(installPath, filepath.Base(srcPath), srcPath, deps...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800411}
412
413func (a *androidModuleContext) CheckbuildFile(srcPath string) {
414 a.checkbuildFiles = append(a.checkbuildFiles, srcPath)
415}
416
417type androidDynamicDependerContext struct {
418 blueprint.DynamicDependerModuleContext
Colin Crossf6566ed2015-03-24 11:13:38 -0700419 androidBaseContextImpl
Colin Cross3f40fa42015-01-30 17:27:36 -0800420}
421
422type fileInstaller interface {
423 filesToInstall() []string
424}
425
426func isFileInstaller(m blueprint.Module) bool {
427 _, ok := m.(fileInstaller)
428 return ok
429}
430
431func isAndroidModule(m blueprint.Module) bool {
432 _, ok := m.(AndroidModule)
433 return ok
434}
Colin Crossfce53272015-04-08 11:21:40 -0700435
436func ExpandSources(ctx AndroidModuleContext, srcFiles []string) []string {
437 prefix := ModuleSrcDir(ctx)
438 for i, srcFile := range srcFiles {
439 if srcFile[0] == '-' {
440 srcFiles[i] = "-" + filepath.Join(prefix, srcFile[1:])
441 } else {
442 srcFiles[i] = filepath.Join(prefix, srcFile)
443 }
444 }
445
446 srcFiles = expandGlobs(ctx, srcFiles)
447 return srcFiles
448}