blob: ef7c63aeed1d467fc54096a0e8815e4c936781fb [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 Cross0af4b842015-04-30 16:36:18 -070019 "runtime"
Colin Crossf6566ed2015-03-24 11:13:38 -070020
21 "github.com/google/blueprint"
Colin Cross3f40fa42015-01-30 17:27:36 -080022)
23
24var (
25 DeviceSharedLibrary = "shared_library"
26 DeviceStaticLibrary = "static_library"
27 DeviceExecutable = "executable"
28 HostSharedLibrary = "host_shared_library"
29 HostStaticLibrary = "host_static_library"
30 HostExecutable = "host_executable"
31)
32
Colin Crossf6566ed2015-03-24 11:13:38 -070033type androidBaseContext interface {
34 Arch() Arch
Colin Crossd3ba0392015-05-07 14:11:29 -070035 HostOrDevice() HostOrDevice
Colin Crossf6566ed2015-03-24 11:13:38 -070036 Host() bool
37 Device() bool
Colin Cross0af4b842015-04-30 16:36:18 -070038 Darwin() bool
Colin Crossf6566ed2015-03-24 11:13:38 -070039 Debug() bool
Colin Cross1332b002015-04-07 17:11:30 -070040 AConfig() Config
Colin Crossf6566ed2015-03-24 11:13:38 -070041}
42
43type AndroidBaseContext interface {
44 blueprint.BaseModuleContext
45 androidBaseContext
46}
47
Colin Cross3f40fa42015-01-30 17:27:36 -080048type AndroidModuleContext interface {
49 blueprint.ModuleContext
Colin Crossf6566ed2015-03-24 11:13:38 -070050 androidBaseContext
Colin Cross3f40fa42015-01-30 17:27:36 -080051
Colin Cross35cec122015-04-02 14:37:16 -070052 InstallFile(installPath, srcPath string, deps ...string) string
53 InstallFileName(installPath, name, srcPath string, deps ...string) string
Colin Cross3f40fa42015-01-30 17:27:36 -080054 CheckbuildFile(srcPath string)
55}
56
57type AndroidModule interface {
58 blueprint.Module
59
60 GenerateAndroidBuildActions(AndroidModuleContext)
61
62 base() *AndroidModuleBase
63 Disabled() bool
64 HostOrDevice() HostOrDevice
65}
66
67type AndroidDynamicDepender interface {
68 AndroidDynamicDependencies(ctx AndroidDynamicDependerModuleContext) []string
69}
70
71type AndroidDynamicDependerModuleContext interface {
72 blueprint.DynamicDependerModuleContext
Colin Crossf6566ed2015-03-24 11:13:38 -070073 androidBaseContext
Colin Cross3f40fa42015-01-30 17:27:36 -080074}
75
76type commonProperties struct {
Colin Crossc77f9d12015-04-02 13:54:39 -070077 Name string
78 Deps []string
79 Tags []string
Colin Cross3f40fa42015-01-30 17:27:36 -080080
81 // disabled: don't emit any build rules for this module
82 Disabled bool `android:"arch_variant"`
83
84 // multilib: control whether this module compiles for 32-bit, 64-bit, or both. Possible values
85 // are "32" (compile for 32-bit only), "64" (compile for 64-bit only), "both" (compile for both
86 // architectures), or "first" (compile for 64-bit on a 64-bit platform, and 32-bit on a 32-bit
87 // platform
88 Compile_multilib string
89
Colin Crossd3ba0392015-05-07 14:11:29 -070090 // Set by HostOrDeviceMutator
91 CompileHostOrDevice HostOrDevice `blueprint:"mutated"`
92
Colin Cross3f40fa42015-01-30 17:27:36 -080093 // Set by ArchMutator
94 CompileArch Arch `blueprint:"mutated"`
95
96 // Set by InitAndroidModule
97 HostOrDeviceSupported HostOrDeviceSupported `blueprint:"mutated"`
98}
99
100type hostAndDeviceProperties struct {
101 Host_supported bool
102 Device_supported bool
103}
104
Colin Crossc472d572015-03-17 15:06:21 -0700105type Multilib string
106
107const (
Colin Cross2fe66872015-03-30 17:20:39 -0700108 MultilibBoth Multilib = "both"
109 MultilibFirst Multilib = "first"
110 MultilibCommon Multilib = "common"
Colin Crossc472d572015-03-17 15:06:21 -0700111)
112
Colin Cross5049f022015-03-18 13:28:46 -0700113func InitAndroidModule(m AndroidModule,
Colin Cross3f40fa42015-01-30 17:27:36 -0800114 propertyStructs ...interface{}) (blueprint.Module, []interface{}) {
115
116 base := m.base()
117 base.module = m
Colin Cross28d76592015-03-26 16:14:04 -0700118 base.extendedProperties = make(map[string]struct{})
Colin Cross5049f022015-03-18 13:28:46 -0700119
120 propertyStructs = append(propertyStructs, &base.commonProperties)
121
122 return m, propertyStructs
123}
124
125func InitAndroidArchModule(m AndroidModule, hod HostOrDeviceSupported, defaultMultilib Multilib,
126 propertyStructs ...interface{}) (blueprint.Module, []interface{}) {
127
128 _, propertyStructs = InitAndroidModule(m, propertyStructs...)
129
130 base := m.base()
Colin Cross3f40fa42015-01-30 17:27:36 -0800131 base.commonProperties.HostOrDeviceSupported = hod
132
133 if hod == HostAndDeviceSupported {
134 // Default to module to device supported, host not supported, can override in module
135 // properties
136 base.hostAndDeviceProperties.Device_supported = true
137 propertyStructs = append(propertyStructs, &base.hostAndDeviceProperties)
138 }
139
140 return InitArchModule(m, defaultMultilib, propertyStructs...)
141}
142
143// A AndroidModuleBase object contains the properties that are common to all Android
144// modules. It should be included as an anonymous field in every module
145// struct definition. InitAndroidModule should then be called from the module's
146// factory function, and the return values from InitAndroidModule should be
147// returned from the factory function.
148//
149// The AndroidModuleBase type is responsible for implementing the
150// GenerateBuildActions method to support the blueprint.Module interface. This
151// method will then call the module's GenerateAndroidBuildActions method once
152// for each build variant that is to be built. GenerateAndroidBuildActions is
153// passed a AndroidModuleContext rather than the usual blueprint.ModuleContext.
154// AndroidModuleContext exposes extra functionality specific to the Android build
155// system including details about the particular build variant that is to be
156// generated.
157//
158// For example:
159//
160// import (
161// "android/soong/common"
Colin Cross70b40592015-03-23 12:57:34 -0700162// "github.com/google/blueprint"
Colin Cross3f40fa42015-01-30 17:27:36 -0800163// )
164//
165// type myModule struct {
166// common.AndroidModuleBase
167// properties struct {
168// MyProperty string
169// }
170// }
171//
172// func NewMyModule() (blueprint.Module, []interface{}) {
173// m := &myModule{}
174// return common.InitAndroidModule(m, &m.properties)
175// }
176//
177// func (m *myModule) GenerateAndroidBuildActions(ctx common.AndroidModuleContext) {
178// // Get the CPU architecture for the current build variant.
179// variantArch := ctx.Arch()
180//
181// // ...
182// }
183type AndroidModuleBase struct {
184 // Putting the curiously recurring thing pointing to the thing that contains
185 // the thing pattern to good use.
186 module AndroidModule
187
188 commonProperties commonProperties
189 hostAndDeviceProperties hostAndDeviceProperties
190 generalProperties []interface{}
191 archProperties []*archProperties
Colin Cross28d76592015-03-26 16:14:04 -0700192 extendedProperties map[string]struct{}
Colin Cross3f40fa42015-01-30 17:27:36 -0800193
194 noAddressSanitizer bool
195 installFiles []string
196 checkbuildFiles []string
197}
198
199func (a *AndroidModuleBase) base() *AndroidModuleBase {
200 return a
201}
202
Colin Crossd3ba0392015-05-07 14:11:29 -0700203func (a *AndroidModuleBase) SetHostOrDevice(hod HostOrDevice) {
204 a.commonProperties.CompileHostOrDevice = hod
205}
206
Colin Cross3f40fa42015-01-30 17:27:36 -0800207func (a *AndroidModuleBase) SetArch(arch Arch) {
208 a.commonProperties.CompileArch = arch
209}
210
211func (a *AndroidModuleBase) HostOrDevice() HostOrDevice {
Colin Crossd3ba0392015-05-07 14:11:29 -0700212 return a.commonProperties.CompileHostOrDevice
Colin Cross3f40fa42015-01-30 17:27:36 -0800213}
214
215func (a *AndroidModuleBase) HostSupported() bool {
216 return a.commonProperties.HostOrDeviceSupported == HostSupported ||
217 a.commonProperties.HostOrDeviceSupported == HostAndDeviceSupported &&
218 a.hostAndDeviceProperties.Host_supported
219}
220
221func (a *AndroidModuleBase) DeviceSupported() bool {
222 return a.commonProperties.HostOrDeviceSupported == DeviceSupported ||
223 a.commonProperties.HostOrDeviceSupported == HostAndDeviceSupported &&
224 a.hostAndDeviceProperties.Device_supported
225}
226
227func (a *AndroidModuleBase) Disabled() bool {
228 return a.commonProperties.Disabled
229}
230
231func (a *AndroidModuleBase) computeInstallDeps(
232 ctx blueprint.ModuleContext) []string {
233
234 result := []string{}
235 ctx.VisitDepsDepthFirstIf(isFileInstaller,
236 func(m blueprint.Module) {
237 fileInstaller := m.(fileInstaller)
238 files := fileInstaller.filesToInstall()
239 result = append(result, files...)
240 })
241
242 return result
243}
244
245func (a *AndroidModuleBase) filesToInstall() []string {
246 return a.installFiles
247}
248
249func (p *AndroidModuleBase) NoAddressSanitizer() bool {
250 return p.noAddressSanitizer
251}
252
Colin Cross3f40fa42015-01-30 17:27:36 -0800253func (a *AndroidModuleBase) generateModuleTarget(ctx blueprint.ModuleContext) {
254 if a != ctx.FinalModule().(AndroidModule).base() {
255 return
256 }
257
258 allInstalledFiles := []string{}
Colin Cross9454bfa2015-03-17 13:24:18 -0700259 allCheckbuildFiles := []string{}
Colin Cross3f40fa42015-01-30 17:27:36 -0800260 ctx.VisitAllModuleVariants(func(module blueprint.Module) {
Colin Crossc9404352015-03-26 16:10:12 -0700261 a := module.(AndroidModule).base()
262 allInstalledFiles = append(allInstalledFiles, a.installFiles...)
263 allCheckbuildFiles = append(allCheckbuildFiles, a.checkbuildFiles...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800264 })
265
Colin Cross9454bfa2015-03-17 13:24:18 -0700266 deps := []string{}
267
Colin Cross3f40fa42015-01-30 17:27:36 -0800268 if len(allInstalledFiles) > 0 {
Colin Cross9454bfa2015-03-17 13:24:18 -0700269 name := ctx.ModuleName() + "-install"
Colin Cross3f40fa42015-01-30 17:27:36 -0800270 ctx.Build(pctx, blueprint.BuildParams{
Colin Cross9454bfa2015-03-17 13:24:18 -0700271 Rule: blueprint.Phony,
272 Outputs: []string{name},
273 Implicits: allInstalledFiles,
274 })
275 deps = append(deps, name)
276 }
277
278 if len(allCheckbuildFiles) > 0 {
279 name := ctx.ModuleName() + "-checkbuild"
280 ctx.Build(pctx, blueprint.BuildParams{
281 Rule: blueprint.Phony,
282 Outputs: []string{name},
283 Implicits: allCheckbuildFiles,
284 Optional: true,
285 })
286 deps = append(deps, name)
287 }
288
289 if len(deps) > 0 {
290 ctx.Build(pctx, blueprint.BuildParams{
291 Rule: blueprint.Phony,
292 Outputs: []string{ctx.ModuleName()},
293 Implicits: deps,
294 Optional: true,
Colin Cross3f40fa42015-01-30 17:27:36 -0800295 })
296 }
297}
298
299func (a *AndroidModuleBase) DynamicDependencies(ctx blueprint.DynamicDependerModuleContext) []string {
300 actx := &androidDynamicDependerContext{
301 DynamicDependerModuleContext: ctx,
Colin Crossf6566ed2015-03-24 11:13:38 -0700302 androidBaseContextImpl: androidBaseContextImpl{
Colin Cross1332b002015-04-07 17:11:30 -0700303 arch: a.commonProperties.CompileArch,
Colin Crossd3ba0392015-05-07 14:11:29 -0700304 hod: a.commonProperties.CompileHostOrDevice,
Colin Cross1332b002015-04-07 17:11:30 -0700305 config: ctx.Config().(Config),
Colin Crossf6566ed2015-03-24 11:13:38 -0700306 },
Colin Cross3f40fa42015-01-30 17:27:36 -0800307 }
308
309 if dynamic, ok := a.module.(AndroidDynamicDepender); ok {
310 return dynamic.AndroidDynamicDependencies(actx)
311 }
312
313 return nil
314}
315
316func (a *AndroidModuleBase) GenerateBuildActions(ctx blueprint.ModuleContext) {
317 androidCtx := &androidModuleContext{
318 ModuleContext: ctx,
Colin Crossf6566ed2015-03-24 11:13:38 -0700319 androidBaseContextImpl: androidBaseContextImpl{
Colin Cross1332b002015-04-07 17:11:30 -0700320 arch: a.commonProperties.CompileArch,
Colin Crossd3ba0392015-05-07 14:11:29 -0700321 hod: a.commonProperties.CompileHostOrDevice,
Colin Cross1332b002015-04-07 17:11:30 -0700322 config: ctx.Config().(Config),
Colin Crossf6566ed2015-03-24 11:13:38 -0700323 },
Colin Cross28d76592015-03-26 16:14:04 -0700324 installDeps: a.computeInstallDeps(ctx),
325 installFiles: a.installFiles,
326 extendedProperties: a.extendedProperties,
Colin Cross3f40fa42015-01-30 17:27:36 -0800327 }
328
329 if a.commonProperties.Disabled {
330 return
331 }
332
333 a.module.GenerateAndroidBuildActions(androidCtx)
334 if ctx.Failed() {
335 return
336 }
337
Colin Crossc9404352015-03-26 16:10:12 -0700338 a.installFiles = append(a.installFiles, androidCtx.installFiles...)
339 a.checkbuildFiles = append(a.checkbuildFiles, androidCtx.checkbuildFiles...)
340
Colin Cross3f40fa42015-01-30 17:27:36 -0800341 a.generateModuleTarget(ctx)
342 if ctx.Failed() {
343 return
344 }
345}
346
Colin Crossf6566ed2015-03-24 11:13:38 -0700347type androidBaseContextImpl struct {
Colin Cross1332b002015-04-07 17:11:30 -0700348 arch Arch
Colin Crossd3ba0392015-05-07 14:11:29 -0700349 hod HostOrDevice
Colin Cross1332b002015-04-07 17:11:30 -0700350 debug bool
351 config Config
Colin Crossf6566ed2015-03-24 11:13:38 -0700352}
353
Colin Cross3f40fa42015-01-30 17:27:36 -0800354type androidModuleContext struct {
355 blueprint.ModuleContext
Colin Crossf6566ed2015-03-24 11:13:38 -0700356 androidBaseContextImpl
Colin Cross28d76592015-03-26 16:14:04 -0700357 installDeps []string
358 installFiles []string
359 checkbuildFiles []string
360 extendedProperties map[string]struct{}
Colin Cross3f40fa42015-01-30 17:27:36 -0800361}
362
363func (a *androidModuleContext) Build(pctx *blueprint.PackageContext, params blueprint.BuildParams) {
364 params.Optional = true
365 a.ModuleContext.Build(pctx, params)
366}
367
Colin Cross28d76592015-03-26 16:14:04 -0700368func (a *androidModuleContext) ContainsProperty(property string) bool {
369 if a.ModuleContext.ContainsProperty(property) {
370 return true
371 }
372 _, ok := a.extendedProperties[property]
373 return ok
374}
375
Colin Crossf6566ed2015-03-24 11:13:38 -0700376func (a *androidBaseContextImpl) Arch() Arch {
Colin Cross3f40fa42015-01-30 17:27:36 -0800377 return a.arch
378}
379
Colin Crossd3ba0392015-05-07 14:11:29 -0700380func (a *androidBaseContextImpl) HostOrDevice() HostOrDevice {
381 return a.hod
382}
383
Colin Crossf6566ed2015-03-24 11:13:38 -0700384func (a *androidBaseContextImpl) Host() bool {
Colin Crossd3ba0392015-05-07 14:11:29 -0700385 return a.hod.Host()
Colin Crossf6566ed2015-03-24 11:13:38 -0700386}
387
388func (a *androidBaseContextImpl) Device() bool {
Colin Crossd3ba0392015-05-07 14:11:29 -0700389 return a.hod.Device()
Colin Crossf6566ed2015-03-24 11:13:38 -0700390}
391
Colin Cross0af4b842015-04-30 16:36:18 -0700392func (a *androidBaseContextImpl) Darwin() bool {
Colin Crossd3ba0392015-05-07 14:11:29 -0700393 return a.hod.Host() && runtime.GOOS == "darwin"
Colin Cross0af4b842015-04-30 16:36:18 -0700394}
395
Colin Crossf6566ed2015-03-24 11:13:38 -0700396func (a *androidBaseContextImpl) Debug() bool {
397 return a.debug
398}
399
Colin Cross1332b002015-04-07 17:11:30 -0700400func (a *androidBaseContextImpl) AConfig() Config {
401 return a.config
402}
403
Colin Cross35cec122015-04-02 14:37:16 -0700404func (a *androidModuleContext) InstallFileName(installPath, name, srcPath string,
405 deps ...string) string {
406
Colin Cross1332b002015-04-07 17:11:30 -0700407 config := a.AConfig()
Colin Cross3f40fa42015-01-30 17:27:36 -0800408 var fullInstallPath string
Colin Crossd3ba0392015-05-07 14:11:29 -0700409 if a.hod.Device() {
Colin Cross3f40fa42015-01-30 17:27:36 -0800410 // TODO: replace unset with a device name once we have device targeting
Colin Cross35cec122015-04-02 14:37:16 -0700411 fullInstallPath = filepath.Join(config.DeviceOut(), "system",
412 installPath, name)
Colin Cross3f40fa42015-01-30 17:27:36 -0800413 } else {
Colin Cross35cec122015-04-02 14:37:16 -0700414 fullInstallPath = filepath.Join(config.HostOut(), installPath, name)
Colin Cross3f40fa42015-01-30 17:27:36 -0800415 }
416
Colin Cross35cec122015-04-02 14:37:16 -0700417 deps = append(deps, a.installDeps...)
418
Colin Cross3f40fa42015-01-30 17:27:36 -0800419 a.ModuleContext.Build(pctx, blueprint.BuildParams{
420 Rule: Cp,
421 Outputs: []string{fullInstallPath},
422 Inputs: []string{srcPath},
Colin Cross35cec122015-04-02 14:37:16 -0700423 OrderOnly: deps,
Colin Cross3f40fa42015-01-30 17:27:36 -0800424 })
425
426 a.installFiles = append(a.installFiles, fullInstallPath)
Colin Cross35cec122015-04-02 14:37:16 -0700427 return fullInstallPath
428}
429
430func (a *androidModuleContext) InstallFile(installPath, srcPath string, deps ...string) string {
431 return a.InstallFileName(installPath, filepath.Base(srcPath), srcPath, deps...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800432}
433
434func (a *androidModuleContext) CheckbuildFile(srcPath string) {
435 a.checkbuildFiles = append(a.checkbuildFiles, srcPath)
436}
437
438type androidDynamicDependerContext struct {
439 blueprint.DynamicDependerModuleContext
Colin Crossf6566ed2015-03-24 11:13:38 -0700440 androidBaseContextImpl
Colin Cross3f40fa42015-01-30 17:27:36 -0800441}
442
443type fileInstaller interface {
444 filesToInstall() []string
445}
446
447func isFileInstaller(m blueprint.Module) bool {
448 _, ok := m.(fileInstaller)
449 return ok
450}
451
452func isAndroidModule(m blueprint.Module) bool {
453 _, ok := m.(AndroidModule)
454 return ok
455}
Colin Crossfce53272015-04-08 11:21:40 -0700456
457func ExpandSources(ctx AndroidModuleContext, srcFiles []string) []string {
458 prefix := ModuleSrcDir(ctx)
459 for i, srcFile := range srcFiles {
460 if srcFile[0] == '-' {
461 srcFiles[i] = "-" + filepath.Join(prefix, srcFile[1:])
462 } else {
463 srcFiles[i] = filepath.Join(prefix, srcFile)
464 }
465 }
466
467 srcFiles = expandGlobs(ctx, srcFiles)
468 return srcFiles
469}