blob: ab90adecb863e213f30c874c3c32c2dbe925af42 [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
Colin Cross68f55102015-03-25 14:43:57 -070023type Config interface {
24 CpPreserveSymlinksFlags() string
25 SrcDir() string
26 Getenv(string) string
27 EnvDeps() map[string]string
28}
29
Colin Cross3f40fa42015-01-30 17:27:36 -080030var (
31 DeviceSharedLibrary = "shared_library"
32 DeviceStaticLibrary = "static_library"
33 DeviceExecutable = "executable"
34 HostSharedLibrary = "host_shared_library"
35 HostStaticLibrary = "host_static_library"
36 HostExecutable = "host_executable"
37)
38
Colin Crossf6566ed2015-03-24 11:13:38 -070039type androidBaseContext interface {
40 Arch() Arch
41 Host() bool
42 Device() bool
43 Debug() bool
44}
45
46type AndroidBaseContext interface {
47 blueprint.BaseModuleContext
48 androidBaseContext
49}
50
Colin Cross3f40fa42015-01-30 17:27:36 -080051type AndroidModuleContext interface {
52 blueprint.ModuleContext
Colin Crossf6566ed2015-03-24 11:13:38 -070053 androidBaseContext
Colin Cross3f40fa42015-01-30 17:27:36 -080054
Colin Cross3f40fa42015-01-30 17:27:36 -080055 InstallFile(installPath, srcPath string)
56 CheckbuildFile(srcPath string)
57}
58
59type AndroidModule interface {
60 blueprint.Module
61
62 GenerateAndroidBuildActions(AndroidModuleContext)
63
64 base() *AndroidModuleBase
65 Disabled() bool
66 HostOrDevice() HostOrDevice
67}
68
69type AndroidDynamicDepender interface {
70 AndroidDynamicDependencies(ctx AndroidDynamicDependerModuleContext) []string
71}
72
73type AndroidDynamicDependerModuleContext interface {
74 blueprint.DynamicDependerModuleContext
Colin Crossf6566ed2015-03-24 11:13:38 -070075 androidBaseContext
Colin Cross3f40fa42015-01-30 17:27:36 -080076}
77
78type commonProperties struct {
Colin Crossc77f9d12015-04-02 13:54:39 -070079 Name string
80 Deps []string
81 Tags []string
Colin Cross3f40fa42015-01-30 17:27:36 -080082
83 // disabled: don't emit any build rules for this module
84 Disabled bool `android:"arch_variant"`
85
86 // multilib: control whether this module compiles for 32-bit, 64-bit, or both. Possible values
87 // are "32" (compile for 32-bit only), "64" (compile for 64-bit only), "both" (compile for both
88 // architectures), or "first" (compile for 64-bit on a 64-bit platform, and 32-bit on a 32-bit
89 // platform
90 Compile_multilib string
91
92 // Set by ArchMutator
93 CompileArch Arch `blueprint:"mutated"`
94
95 // Set by InitAndroidModule
96 HostOrDeviceSupported HostOrDeviceSupported `blueprint:"mutated"`
97}
98
99type hostAndDeviceProperties struct {
100 Host_supported bool
101 Device_supported bool
102}
103
Colin Crossc472d572015-03-17 15:06:21 -0700104type Multilib string
105
106const (
107 MultilibBoth Multilib = "both"
108 MultilibFirst Multilib = "first"
109)
110
Colin Cross5049f022015-03-18 13:28:46 -0700111func InitAndroidModule(m AndroidModule,
Colin Cross3f40fa42015-01-30 17:27:36 -0800112 propertyStructs ...interface{}) (blueprint.Module, []interface{}) {
113
114 base := m.base()
115 base.module = m
Colin Cross28d76592015-03-26 16:14:04 -0700116 base.extendedProperties = make(map[string]struct{})
Colin Cross5049f022015-03-18 13:28:46 -0700117
118 propertyStructs = append(propertyStructs, &base.commonProperties)
119
120 return m, propertyStructs
121}
122
123func InitAndroidArchModule(m AndroidModule, hod HostOrDeviceSupported, defaultMultilib Multilib,
124 propertyStructs ...interface{}) (blueprint.Module, []interface{}) {
125
126 _, propertyStructs = InitAndroidModule(m, propertyStructs...)
127
128 base := m.base()
Colin Cross3f40fa42015-01-30 17:27:36 -0800129 base.commonProperties.HostOrDeviceSupported = hod
130
131 if hod == HostAndDeviceSupported {
132 // Default to module to device supported, host not supported, can override in module
133 // properties
134 base.hostAndDeviceProperties.Device_supported = true
135 propertyStructs = append(propertyStructs, &base.hostAndDeviceProperties)
136 }
137
138 return InitArchModule(m, defaultMultilib, propertyStructs...)
139}
140
141// A AndroidModuleBase object contains the properties that are common to all Android
142// modules. It should be included as an anonymous field in every module
143// struct definition. InitAndroidModule should then be called from the module's
144// factory function, and the return values from InitAndroidModule should be
145// returned from the factory function.
146//
147// The AndroidModuleBase type is responsible for implementing the
148// GenerateBuildActions method to support the blueprint.Module interface. This
149// method will then call the module's GenerateAndroidBuildActions method once
150// for each build variant that is to be built. GenerateAndroidBuildActions is
151// passed a AndroidModuleContext rather than the usual blueprint.ModuleContext.
152// AndroidModuleContext exposes extra functionality specific to the Android build
153// system including details about the particular build variant that is to be
154// generated.
155//
156// For example:
157//
158// import (
159// "android/soong/common"
Colin Cross70b40592015-03-23 12:57:34 -0700160// "github.com/google/blueprint"
Colin Cross3f40fa42015-01-30 17:27:36 -0800161// )
162//
163// type myModule struct {
164// common.AndroidModuleBase
165// properties struct {
166// MyProperty string
167// }
168// }
169//
170// func NewMyModule() (blueprint.Module, []interface{}) {
171// m := &myModule{}
172// return common.InitAndroidModule(m, &m.properties)
173// }
174//
175// func (m *myModule) GenerateAndroidBuildActions(ctx common.AndroidModuleContext) {
176// // Get the CPU architecture for the current build variant.
177// variantArch := ctx.Arch()
178//
179// // ...
180// }
181type AndroidModuleBase struct {
182 // Putting the curiously recurring thing pointing to the thing that contains
183 // the thing pattern to good use.
184 module AndroidModule
185
186 commonProperties commonProperties
187 hostAndDeviceProperties hostAndDeviceProperties
188 generalProperties []interface{}
189 archProperties []*archProperties
Colin Cross28d76592015-03-26 16:14:04 -0700190 extendedProperties map[string]struct{}
Colin Cross3f40fa42015-01-30 17:27:36 -0800191
192 noAddressSanitizer bool
193 installFiles []string
194 checkbuildFiles []string
195}
196
197func (a *AndroidModuleBase) base() *AndroidModuleBase {
198 return a
199}
200
201func (a *AndroidModuleBase) SetArch(arch Arch) {
202 a.commonProperties.CompileArch = arch
203}
204
205func (a *AndroidModuleBase) HostOrDevice() HostOrDevice {
206 return a.commonProperties.CompileArch.HostOrDevice
207}
208
209func (a *AndroidModuleBase) HostSupported() bool {
210 return a.commonProperties.HostOrDeviceSupported == HostSupported ||
211 a.commonProperties.HostOrDeviceSupported == HostAndDeviceSupported &&
212 a.hostAndDeviceProperties.Host_supported
213}
214
215func (a *AndroidModuleBase) DeviceSupported() bool {
216 return a.commonProperties.HostOrDeviceSupported == DeviceSupported ||
217 a.commonProperties.HostOrDeviceSupported == HostAndDeviceSupported &&
218 a.hostAndDeviceProperties.Device_supported
219}
220
221func (a *AndroidModuleBase) Disabled() bool {
222 return a.commonProperties.Disabled
223}
224
225func (a *AndroidModuleBase) computeInstallDeps(
226 ctx blueprint.ModuleContext) []string {
227
228 result := []string{}
229 ctx.VisitDepsDepthFirstIf(isFileInstaller,
230 func(m blueprint.Module) {
231 fileInstaller := m.(fileInstaller)
232 files := fileInstaller.filesToInstall()
233 result = append(result, files...)
234 })
235
236 return result
237}
238
239func (a *AndroidModuleBase) filesToInstall() []string {
240 return a.installFiles
241}
242
243func (p *AndroidModuleBase) NoAddressSanitizer() bool {
244 return p.noAddressSanitizer
245}
246
Colin Cross3f40fa42015-01-30 17:27:36 -0800247func (a *AndroidModuleBase) generateModuleTarget(ctx blueprint.ModuleContext) {
248 if a != ctx.FinalModule().(AndroidModule).base() {
249 return
250 }
251
252 allInstalledFiles := []string{}
Colin Cross9454bfa2015-03-17 13:24:18 -0700253 allCheckbuildFiles := []string{}
Colin Cross3f40fa42015-01-30 17:27:36 -0800254 ctx.VisitAllModuleVariants(func(module blueprint.Module) {
Colin Crossc9404352015-03-26 16:10:12 -0700255 a := module.(AndroidModule).base()
256 allInstalledFiles = append(allInstalledFiles, a.installFiles...)
257 allCheckbuildFiles = append(allCheckbuildFiles, a.checkbuildFiles...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800258 })
259
Colin Cross9454bfa2015-03-17 13:24:18 -0700260 deps := []string{}
261
Colin Cross3f40fa42015-01-30 17:27:36 -0800262 if len(allInstalledFiles) > 0 {
Colin Cross9454bfa2015-03-17 13:24:18 -0700263 name := ctx.ModuleName() + "-install"
Colin Cross3f40fa42015-01-30 17:27:36 -0800264 ctx.Build(pctx, blueprint.BuildParams{
Colin Cross9454bfa2015-03-17 13:24:18 -0700265 Rule: blueprint.Phony,
266 Outputs: []string{name},
267 Implicits: allInstalledFiles,
268 })
269 deps = append(deps, name)
270 }
271
272 if len(allCheckbuildFiles) > 0 {
273 name := ctx.ModuleName() + "-checkbuild"
274 ctx.Build(pctx, blueprint.BuildParams{
275 Rule: blueprint.Phony,
276 Outputs: []string{name},
277 Implicits: allCheckbuildFiles,
278 Optional: true,
279 })
280 deps = append(deps, name)
281 }
282
283 if len(deps) > 0 {
284 ctx.Build(pctx, blueprint.BuildParams{
285 Rule: blueprint.Phony,
286 Outputs: []string{ctx.ModuleName()},
287 Implicits: deps,
288 Optional: true,
Colin Cross3f40fa42015-01-30 17:27:36 -0800289 })
290 }
291}
292
293func (a *AndroidModuleBase) DynamicDependencies(ctx blueprint.DynamicDependerModuleContext) []string {
294 actx := &androidDynamicDependerContext{
295 DynamicDependerModuleContext: ctx,
Colin Crossf6566ed2015-03-24 11:13:38 -0700296 androidBaseContextImpl: androidBaseContextImpl{
297 arch: a.commonProperties.CompileArch,
298 },
Colin Cross3f40fa42015-01-30 17:27:36 -0800299 }
300
301 if dynamic, ok := a.module.(AndroidDynamicDepender); ok {
302 return dynamic.AndroidDynamicDependencies(actx)
303 }
304
305 return nil
306}
307
308func (a *AndroidModuleBase) GenerateBuildActions(ctx blueprint.ModuleContext) {
309 androidCtx := &androidModuleContext{
310 ModuleContext: ctx,
Colin Crossf6566ed2015-03-24 11:13:38 -0700311 androidBaseContextImpl: androidBaseContextImpl{
312 arch: a.commonProperties.CompileArch,
313 },
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 {
338 arch Arch
339 debug bool
340}
341
Colin Cross3f40fa42015-01-30 17:27:36 -0800342type androidModuleContext struct {
343 blueprint.ModuleContext
Colin Crossf6566ed2015-03-24 11:13:38 -0700344 androidBaseContextImpl
Colin Cross28d76592015-03-26 16:14:04 -0700345 installDeps []string
346 installFiles []string
347 checkbuildFiles []string
348 extendedProperties map[string]struct{}
Colin Cross3f40fa42015-01-30 17:27:36 -0800349}
350
351func (a *androidModuleContext) Build(pctx *blueprint.PackageContext, params blueprint.BuildParams) {
352 params.Optional = true
353 a.ModuleContext.Build(pctx, params)
354}
355
Colin Cross28d76592015-03-26 16:14:04 -0700356func (a *androidModuleContext) ContainsProperty(property string) bool {
357 if a.ModuleContext.ContainsProperty(property) {
358 return true
359 }
360 _, ok := a.extendedProperties[property]
361 return ok
362}
363
Colin Crossf6566ed2015-03-24 11:13:38 -0700364func (a *androidBaseContextImpl) Arch() Arch {
Colin Cross3f40fa42015-01-30 17:27:36 -0800365 return a.arch
366}
367
Colin Crossf6566ed2015-03-24 11:13:38 -0700368func (a *androidBaseContextImpl) Host() bool {
369 return a.arch.HostOrDevice.Host()
370}
371
372func (a *androidBaseContextImpl) Device() bool {
373 return a.arch.HostOrDevice.Device()
374}
375
376func (a *androidBaseContextImpl) Debug() bool {
377 return a.debug
378}
379
Colin Cross3f40fa42015-01-30 17:27:36 -0800380func (a *androidModuleContext) InstallFile(installPath, srcPath string) {
381 var fullInstallPath string
382 if a.arch.HostOrDevice.Device() {
383 // TODO: replace unset with a device name once we have device targeting
384 fullInstallPath = filepath.Join("out/target/product/unset/system", installPath,
385 filepath.Base(srcPath))
386 } else {
387 // TODO: replace unset with a host name
388 fullInstallPath = filepath.Join("out/host/unset/", installPath, filepath.Base(srcPath))
389 }
390
391 a.ModuleContext.Build(pctx, blueprint.BuildParams{
392 Rule: Cp,
393 Outputs: []string{fullInstallPath},
394 Inputs: []string{srcPath},
395 OrderOnly: a.installDeps,
396 })
397
398 a.installFiles = append(a.installFiles, fullInstallPath)
Colin Cross3f40fa42015-01-30 17:27:36 -0800399}
400
401func (a *androidModuleContext) CheckbuildFile(srcPath string) {
402 a.checkbuildFiles = append(a.checkbuildFiles, srcPath)
403}
404
405type androidDynamicDependerContext struct {
406 blueprint.DynamicDependerModuleContext
Colin Crossf6566ed2015-03-24 11:13:38 -0700407 androidBaseContextImpl
Colin Cross3f40fa42015-01-30 17:27:36 -0800408}
409
410type fileInstaller interface {
411 filesToInstall() []string
412}
413
414func isFileInstaller(m blueprint.Module) bool {
415 _, ok := m.(fileInstaller)
416 return ok
417}
418
419func isAndroidModule(m blueprint.Module) bool {
420 _, ok := m.(AndroidModule)
421 return ok
422}