blob: d933788546fe5342fe152a7a434326289f0c6efc [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
35 Host() bool
36 Device() bool
Colin Cross0af4b842015-04-30 16:36:18 -070037 Darwin() bool
Colin Crossf6566ed2015-03-24 11:13:38 -070038 Debug() bool
Colin Cross1332b002015-04-07 17:11:30 -070039 AConfig() Config
Colin Crossf6566ed2015-03-24 11:13:38 -070040}
41
42type AndroidBaseContext interface {
43 blueprint.BaseModuleContext
44 androidBaseContext
45}
46
Colin Cross3f40fa42015-01-30 17:27:36 -080047type AndroidModuleContext interface {
48 blueprint.ModuleContext
Colin Crossf6566ed2015-03-24 11:13:38 -070049 androidBaseContext
Colin Cross3f40fa42015-01-30 17:27:36 -080050
Colin Cross35cec122015-04-02 14:37:16 -070051 InstallFile(installPath, srcPath string, deps ...string) string
52 InstallFileName(installPath, name, srcPath string, deps ...string) string
Colin Cross3f40fa42015-01-30 17:27:36 -080053 CheckbuildFile(srcPath string)
54}
55
56type AndroidModule interface {
57 blueprint.Module
58
59 GenerateAndroidBuildActions(AndroidModuleContext)
60
61 base() *AndroidModuleBase
62 Disabled() bool
63 HostOrDevice() HostOrDevice
64}
65
66type AndroidDynamicDepender interface {
67 AndroidDynamicDependencies(ctx AndroidDynamicDependerModuleContext) []string
68}
69
70type AndroidDynamicDependerModuleContext interface {
71 blueprint.DynamicDependerModuleContext
Colin Crossf6566ed2015-03-24 11:13:38 -070072 androidBaseContext
Colin Cross3f40fa42015-01-30 17:27:36 -080073}
74
75type commonProperties struct {
Colin Crossc77f9d12015-04-02 13:54:39 -070076 Name string
77 Deps []string
78 Tags []string
Colin Cross3f40fa42015-01-30 17:27:36 -080079
80 // disabled: don't emit any build rules for this module
81 Disabled bool `android:"arch_variant"`
82
83 // multilib: control whether this module compiles for 32-bit, 64-bit, or both. Possible values
84 // are "32" (compile for 32-bit only), "64" (compile for 64-bit only), "both" (compile for both
85 // architectures), or "first" (compile for 64-bit on a 64-bit platform, and 32-bit on a 32-bit
86 // platform
87 Compile_multilib string
88
89 // Set by ArchMutator
90 CompileArch Arch `blueprint:"mutated"`
91
92 // Set by InitAndroidModule
93 HostOrDeviceSupported HostOrDeviceSupported `blueprint:"mutated"`
94}
95
96type hostAndDeviceProperties struct {
97 Host_supported bool
98 Device_supported bool
99}
100
Colin Crossc472d572015-03-17 15:06:21 -0700101type Multilib string
102
103const (
Colin Cross2fe66872015-03-30 17:20:39 -0700104 MultilibBoth Multilib = "both"
105 MultilibFirst Multilib = "first"
106 MultilibCommon Multilib = "common"
Colin Crossc472d572015-03-17 15:06:21 -0700107)
108
Colin Cross5049f022015-03-18 13:28:46 -0700109func InitAndroidModule(m AndroidModule,
Colin Cross3f40fa42015-01-30 17:27:36 -0800110 propertyStructs ...interface{}) (blueprint.Module, []interface{}) {
111
112 base := m.base()
113 base.module = m
Colin Cross28d76592015-03-26 16:14:04 -0700114 base.extendedProperties = make(map[string]struct{})
Colin Cross5049f022015-03-18 13:28:46 -0700115
116 propertyStructs = append(propertyStructs, &base.commonProperties)
117
118 return m, propertyStructs
119}
120
121func InitAndroidArchModule(m AndroidModule, hod HostOrDeviceSupported, defaultMultilib Multilib,
122 propertyStructs ...interface{}) (blueprint.Module, []interface{}) {
123
124 _, propertyStructs = InitAndroidModule(m, propertyStructs...)
125
126 base := m.base()
Colin Cross3f40fa42015-01-30 17:27:36 -0800127 base.commonProperties.HostOrDeviceSupported = hod
128
129 if hod == HostAndDeviceSupported {
130 // Default to module to device supported, host not supported, can override in module
131 // properties
132 base.hostAndDeviceProperties.Device_supported = true
133 propertyStructs = append(propertyStructs, &base.hostAndDeviceProperties)
134 }
135
136 return InitArchModule(m, defaultMultilib, propertyStructs...)
137}
138
139// A AndroidModuleBase object contains the properties that are common to all Android
140// modules. It should be included as an anonymous field in every module
141// struct definition. InitAndroidModule should then be called from the module's
142// factory function, and the return values from InitAndroidModule should be
143// returned from the factory function.
144//
145// The AndroidModuleBase type is responsible for implementing the
146// GenerateBuildActions method to support the blueprint.Module interface. This
147// method will then call the module's GenerateAndroidBuildActions method once
148// for each build variant that is to be built. GenerateAndroidBuildActions is
149// passed a AndroidModuleContext rather than the usual blueprint.ModuleContext.
150// AndroidModuleContext exposes extra functionality specific to the Android build
151// system including details about the particular build variant that is to be
152// generated.
153//
154// For example:
155//
156// import (
157// "android/soong/common"
Colin Cross70b40592015-03-23 12:57:34 -0700158// "github.com/google/blueprint"
Colin Cross3f40fa42015-01-30 17:27:36 -0800159// )
160//
161// type myModule struct {
162// common.AndroidModuleBase
163// properties struct {
164// MyProperty string
165// }
166// }
167//
168// func NewMyModule() (blueprint.Module, []interface{}) {
169// m := &myModule{}
170// return common.InitAndroidModule(m, &m.properties)
171// }
172//
173// func (m *myModule) GenerateAndroidBuildActions(ctx common.AndroidModuleContext) {
174// // Get the CPU architecture for the current build variant.
175// variantArch := ctx.Arch()
176//
177// // ...
178// }
179type AndroidModuleBase struct {
180 // Putting the curiously recurring thing pointing to the thing that contains
181 // the thing pattern to good use.
182 module AndroidModule
183
184 commonProperties commonProperties
185 hostAndDeviceProperties hostAndDeviceProperties
186 generalProperties []interface{}
187 archProperties []*archProperties
Colin Cross28d76592015-03-26 16:14:04 -0700188 extendedProperties map[string]struct{}
Colin Cross3f40fa42015-01-30 17:27:36 -0800189
190 noAddressSanitizer bool
191 installFiles []string
192 checkbuildFiles []string
193}
194
195func (a *AndroidModuleBase) base() *AndroidModuleBase {
196 return a
197}
198
199func (a *AndroidModuleBase) SetArch(arch Arch) {
200 a.commonProperties.CompileArch = arch
201}
202
203func (a *AndroidModuleBase) HostOrDevice() HostOrDevice {
204 return a.commonProperties.CompileArch.HostOrDevice
205}
206
207func (a *AndroidModuleBase) HostSupported() bool {
208 return a.commonProperties.HostOrDeviceSupported == HostSupported ||
209 a.commonProperties.HostOrDeviceSupported == HostAndDeviceSupported &&
210 a.hostAndDeviceProperties.Host_supported
211}
212
213func (a *AndroidModuleBase) DeviceSupported() bool {
214 return a.commonProperties.HostOrDeviceSupported == DeviceSupported ||
215 a.commonProperties.HostOrDeviceSupported == HostAndDeviceSupported &&
216 a.hostAndDeviceProperties.Device_supported
217}
218
219func (a *AndroidModuleBase) Disabled() bool {
220 return a.commonProperties.Disabled
221}
222
223func (a *AndroidModuleBase) computeInstallDeps(
224 ctx blueprint.ModuleContext) []string {
225
226 result := []string{}
227 ctx.VisitDepsDepthFirstIf(isFileInstaller,
228 func(m blueprint.Module) {
229 fileInstaller := m.(fileInstaller)
230 files := fileInstaller.filesToInstall()
231 result = append(result, files...)
232 })
233
234 return result
235}
236
237func (a *AndroidModuleBase) filesToInstall() []string {
238 return a.installFiles
239}
240
241func (p *AndroidModuleBase) NoAddressSanitizer() bool {
242 return p.noAddressSanitizer
243}
244
Colin Cross3f40fa42015-01-30 17:27:36 -0800245func (a *AndroidModuleBase) generateModuleTarget(ctx blueprint.ModuleContext) {
246 if a != ctx.FinalModule().(AndroidModule).base() {
247 return
248 }
249
250 allInstalledFiles := []string{}
Colin Cross9454bfa2015-03-17 13:24:18 -0700251 allCheckbuildFiles := []string{}
Colin Cross3f40fa42015-01-30 17:27:36 -0800252 ctx.VisitAllModuleVariants(func(module blueprint.Module) {
Colin Crossc9404352015-03-26 16:10:12 -0700253 a := module.(AndroidModule).base()
254 allInstalledFiles = append(allInstalledFiles, a.installFiles...)
255 allCheckbuildFiles = append(allCheckbuildFiles, a.checkbuildFiles...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800256 })
257
Colin Cross9454bfa2015-03-17 13:24:18 -0700258 deps := []string{}
259
Colin Cross3f40fa42015-01-30 17:27:36 -0800260 if len(allInstalledFiles) > 0 {
Colin Cross9454bfa2015-03-17 13:24:18 -0700261 name := ctx.ModuleName() + "-install"
Colin Cross3f40fa42015-01-30 17:27:36 -0800262 ctx.Build(pctx, blueprint.BuildParams{
Colin Cross9454bfa2015-03-17 13:24:18 -0700263 Rule: blueprint.Phony,
264 Outputs: []string{name},
265 Implicits: allInstalledFiles,
266 })
267 deps = append(deps, name)
268 }
269
270 if len(allCheckbuildFiles) > 0 {
271 name := ctx.ModuleName() + "-checkbuild"
272 ctx.Build(pctx, blueprint.BuildParams{
273 Rule: blueprint.Phony,
274 Outputs: []string{name},
275 Implicits: allCheckbuildFiles,
276 Optional: true,
277 })
278 deps = append(deps, name)
279 }
280
281 if len(deps) > 0 {
282 ctx.Build(pctx, blueprint.BuildParams{
283 Rule: blueprint.Phony,
284 Outputs: []string{ctx.ModuleName()},
285 Implicits: deps,
286 Optional: true,
Colin Cross3f40fa42015-01-30 17:27:36 -0800287 })
288 }
289}
290
291func (a *AndroidModuleBase) DynamicDependencies(ctx blueprint.DynamicDependerModuleContext) []string {
292 actx := &androidDynamicDependerContext{
293 DynamicDependerModuleContext: ctx,
Colin Crossf6566ed2015-03-24 11:13:38 -0700294 androidBaseContextImpl: androidBaseContextImpl{
Colin Cross1332b002015-04-07 17:11:30 -0700295 arch: a.commonProperties.CompileArch,
296 config: ctx.Config().(Config),
Colin Crossf6566ed2015-03-24 11:13:38 -0700297 },
Colin Cross3f40fa42015-01-30 17:27:36 -0800298 }
299
300 if dynamic, ok := a.module.(AndroidDynamicDepender); ok {
301 return dynamic.AndroidDynamicDependencies(actx)
302 }
303
304 return nil
305}
306
307func (a *AndroidModuleBase) GenerateBuildActions(ctx blueprint.ModuleContext) {
308 androidCtx := &androidModuleContext{
309 ModuleContext: ctx,
Colin Crossf6566ed2015-03-24 11:13:38 -0700310 androidBaseContextImpl: androidBaseContextImpl{
Colin Cross1332b002015-04-07 17:11:30 -0700311 arch: a.commonProperties.CompileArch,
312 config: ctx.Config().(Config),
Colin Crossf6566ed2015-03-24 11:13:38 -0700313 },
Colin Cross28d76592015-03-26 16:14:04 -0700314 installDeps: a.computeInstallDeps(ctx),
315 installFiles: a.installFiles,
316 extendedProperties: a.extendedProperties,
Colin Cross3f40fa42015-01-30 17:27:36 -0800317 }
318
319 if a.commonProperties.Disabled {
320 return
321 }
322
323 a.module.GenerateAndroidBuildActions(androidCtx)
324 if ctx.Failed() {
325 return
326 }
327
Colin Crossc9404352015-03-26 16:10:12 -0700328 a.installFiles = append(a.installFiles, androidCtx.installFiles...)
329 a.checkbuildFiles = append(a.checkbuildFiles, androidCtx.checkbuildFiles...)
330
Colin Cross3f40fa42015-01-30 17:27:36 -0800331 a.generateModuleTarget(ctx)
332 if ctx.Failed() {
333 return
334 }
335}
336
Colin Crossf6566ed2015-03-24 11:13:38 -0700337type androidBaseContextImpl struct {
Colin Cross1332b002015-04-07 17:11:30 -0700338 arch Arch
339 debug bool
340 config Config
Colin Crossf6566ed2015-03-24 11:13:38 -0700341}
342
Colin Cross3f40fa42015-01-30 17:27:36 -0800343type androidModuleContext struct {
344 blueprint.ModuleContext
Colin Crossf6566ed2015-03-24 11:13:38 -0700345 androidBaseContextImpl
Colin Cross28d76592015-03-26 16:14:04 -0700346 installDeps []string
347 installFiles []string
348 checkbuildFiles []string
349 extendedProperties map[string]struct{}
Colin Cross3f40fa42015-01-30 17:27:36 -0800350}
351
352func (a *androidModuleContext) Build(pctx *blueprint.PackageContext, params blueprint.BuildParams) {
353 params.Optional = true
354 a.ModuleContext.Build(pctx, params)
355}
356
Colin Cross28d76592015-03-26 16:14:04 -0700357func (a *androidModuleContext) ContainsProperty(property string) bool {
358 if a.ModuleContext.ContainsProperty(property) {
359 return true
360 }
361 _, ok := a.extendedProperties[property]
362 return ok
363}
364
Colin Crossf6566ed2015-03-24 11:13:38 -0700365func (a *androidBaseContextImpl) Arch() Arch {
Colin Cross3f40fa42015-01-30 17:27:36 -0800366 return a.arch
367}
368
Colin Crossf6566ed2015-03-24 11:13:38 -0700369func (a *androidBaseContextImpl) Host() bool {
370 return a.arch.HostOrDevice.Host()
371}
372
373func (a *androidBaseContextImpl) Device() bool {
374 return a.arch.HostOrDevice.Device()
375}
376
Colin Cross0af4b842015-04-30 16:36:18 -0700377func (a *androidBaseContextImpl) Darwin() bool {
378 return a.arch.HostOrDevice.Host() && runtime.GOOS == "darwin"
379}
380
Colin Crossf6566ed2015-03-24 11:13:38 -0700381func (a *androidBaseContextImpl) Debug() bool {
382 return a.debug
383}
384
Colin Cross1332b002015-04-07 17:11:30 -0700385func (a *androidBaseContextImpl) AConfig() Config {
386 return a.config
387}
388
Colin Cross35cec122015-04-02 14:37:16 -0700389func (a *androidModuleContext) InstallFileName(installPath, name, srcPath string,
390 deps ...string) string {
391
Colin Cross1332b002015-04-07 17:11:30 -0700392 config := a.AConfig()
Colin Cross3f40fa42015-01-30 17:27:36 -0800393 var fullInstallPath string
394 if a.arch.HostOrDevice.Device() {
395 // TODO: replace unset with a device name once we have device targeting
Colin Cross35cec122015-04-02 14:37:16 -0700396 fullInstallPath = filepath.Join(config.DeviceOut(), "system",
397 installPath, name)
Colin Cross3f40fa42015-01-30 17:27:36 -0800398 } else {
Colin Cross35cec122015-04-02 14:37:16 -0700399 fullInstallPath = filepath.Join(config.HostOut(), installPath, name)
Colin Cross3f40fa42015-01-30 17:27:36 -0800400 }
401
Colin Cross35cec122015-04-02 14:37:16 -0700402 deps = append(deps, a.installDeps...)
403
Colin Cross3f40fa42015-01-30 17:27:36 -0800404 a.ModuleContext.Build(pctx, blueprint.BuildParams{
405 Rule: Cp,
406 Outputs: []string{fullInstallPath},
407 Inputs: []string{srcPath},
Colin Cross35cec122015-04-02 14:37:16 -0700408 OrderOnly: deps,
Colin Cross3f40fa42015-01-30 17:27:36 -0800409 })
410
411 a.installFiles = append(a.installFiles, fullInstallPath)
Colin Cross35cec122015-04-02 14:37:16 -0700412 return fullInstallPath
413}
414
415func (a *androidModuleContext) InstallFile(installPath, srcPath string, deps ...string) string {
416 return a.InstallFileName(installPath, filepath.Base(srcPath), srcPath, deps...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800417}
418
419func (a *androidModuleContext) CheckbuildFile(srcPath string) {
420 a.checkbuildFiles = append(a.checkbuildFiles, srcPath)
421}
422
423type androidDynamicDependerContext struct {
424 blueprint.DynamicDependerModuleContext
Colin Crossf6566ed2015-03-24 11:13:38 -0700425 androidBaseContextImpl
Colin Cross3f40fa42015-01-30 17:27:36 -0800426}
427
428type fileInstaller interface {
429 filesToInstall() []string
430}
431
432func isFileInstaller(m blueprint.Module) bool {
433 _, ok := m.(fileInstaller)
434 return ok
435}
436
437func isAndroidModule(m blueprint.Module) bool {
438 _, ok := m.(AndroidModule)
439 return ok
440}
Colin Crossfce53272015-04-08 11:21:40 -0700441
442func ExpandSources(ctx AndroidModuleContext, srcFiles []string) []string {
443 prefix := ModuleSrcDir(ctx)
444 for i, srcFile := range srcFiles {
445 if srcFile[0] == '-' {
446 srcFiles[i] = "-" + filepath.Join(prefix, srcFile[1:])
447 } else {
448 srcFiles[i] = filepath.Join(prefix, srcFile)
449 }
450 }
451
452 srcFiles = expandGlobs(ctx, srcFiles)
453 return srcFiles
454}