blob: a83438450cd7d3502ab58e840c3aed608579563f [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
Colin Cross35cec122015-04-02 14:37:16 -070028 DeviceOut() string
29 HostOut() string
Colin Cross68f55102015-03-25 14:43:57 -070030}
31
Colin Cross3f40fa42015-01-30 17:27:36 -080032var (
33 DeviceSharedLibrary = "shared_library"
34 DeviceStaticLibrary = "static_library"
35 DeviceExecutable = "executable"
36 HostSharedLibrary = "host_shared_library"
37 HostStaticLibrary = "host_static_library"
38 HostExecutable = "host_executable"
39)
40
Colin Crossf6566ed2015-03-24 11:13:38 -070041type androidBaseContext interface {
42 Arch() Arch
43 Host() bool
44 Device() bool
45 Debug() bool
46}
47
48type AndroidBaseContext interface {
49 blueprint.BaseModuleContext
50 androidBaseContext
51}
52
Colin Cross3f40fa42015-01-30 17:27:36 -080053type AndroidModuleContext interface {
54 blueprint.ModuleContext
Colin Crossf6566ed2015-03-24 11:13:38 -070055 androidBaseContext
Colin Cross3f40fa42015-01-30 17:27:36 -080056
Colin Cross35cec122015-04-02 14:37:16 -070057 InstallFile(installPath, srcPath string, deps ...string) string
58 InstallFileName(installPath, name, srcPath string, deps ...string) string
Colin Cross3f40fa42015-01-30 17:27:36 -080059 CheckbuildFile(srcPath string)
60}
61
62type AndroidModule interface {
63 blueprint.Module
64
65 GenerateAndroidBuildActions(AndroidModuleContext)
66
67 base() *AndroidModuleBase
68 Disabled() bool
69 HostOrDevice() HostOrDevice
70}
71
72type AndroidDynamicDepender interface {
73 AndroidDynamicDependencies(ctx AndroidDynamicDependerModuleContext) []string
74}
75
76type AndroidDynamicDependerModuleContext interface {
77 blueprint.DynamicDependerModuleContext
Colin Crossf6566ed2015-03-24 11:13:38 -070078 androidBaseContext
Colin Cross3f40fa42015-01-30 17:27:36 -080079}
80
81type commonProperties struct {
Colin Crossc77f9d12015-04-02 13:54:39 -070082 Name string
83 Deps []string
84 Tags []string
Colin Cross3f40fa42015-01-30 17:27:36 -080085
86 // disabled: don't emit any build rules for this module
87 Disabled bool `android:"arch_variant"`
88
89 // multilib: control whether this module compiles for 32-bit, 64-bit, or both. Possible values
90 // are "32" (compile for 32-bit only), "64" (compile for 64-bit only), "both" (compile for both
91 // architectures), or "first" (compile for 64-bit on a 64-bit platform, and 32-bit on a 32-bit
92 // platform
93 Compile_multilib string
94
95 // Set by ArchMutator
96 CompileArch Arch `blueprint:"mutated"`
97
98 // Set by InitAndroidModule
99 HostOrDeviceSupported HostOrDeviceSupported `blueprint:"mutated"`
100}
101
102type hostAndDeviceProperties struct {
103 Host_supported bool
104 Device_supported bool
105}
106
Colin Crossc472d572015-03-17 15:06:21 -0700107type Multilib string
108
109const (
110 MultilibBoth Multilib = "both"
111 MultilibFirst Multilib = "first"
112)
113
Colin Cross5049f022015-03-18 13:28:46 -0700114func InitAndroidModule(m AndroidModule,
Colin Cross3f40fa42015-01-30 17:27:36 -0800115 propertyStructs ...interface{}) (blueprint.Module, []interface{}) {
116
117 base := m.base()
118 base.module = m
Colin Cross28d76592015-03-26 16:14:04 -0700119 base.extendedProperties = make(map[string]struct{})
Colin Cross5049f022015-03-18 13:28:46 -0700120
121 propertyStructs = append(propertyStructs, &base.commonProperties)
122
123 return m, propertyStructs
124}
125
126func InitAndroidArchModule(m AndroidModule, hod HostOrDeviceSupported, defaultMultilib Multilib,
127 propertyStructs ...interface{}) (blueprint.Module, []interface{}) {
128
129 _, propertyStructs = InitAndroidModule(m, propertyStructs...)
130
131 base := m.base()
Colin Cross3f40fa42015-01-30 17:27:36 -0800132 base.commonProperties.HostOrDeviceSupported = hod
133
134 if hod == HostAndDeviceSupported {
135 // Default to module to device supported, host not supported, can override in module
136 // properties
137 base.hostAndDeviceProperties.Device_supported = true
138 propertyStructs = append(propertyStructs, &base.hostAndDeviceProperties)
139 }
140
141 return InitArchModule(m, defaultMultilib, propertyStructs...)
142}
143
144// A AndroidModuleBase object contains the properties that are common to all Android
145// modules. It should be included as an anonymous field in every module
146// struct definition. InitAndroidModule should then be called from the module's
147// factory function, and the return values from InitAndroidModule should be
148// returned from the factory function.
149//
150// The AndroidModuleBase type is responsible for implementing the
151// GenerateBuildActions method to support the blueprint.Module interface. This
152// method will then call the module's GenerateAndroidBuildActions method once
153// for each build variant that is to be built. GenerateAndroidBuildActions is
154// passed a AndroidModuleContext rather than the usual blueprint.ModuleContext.
155// AndroidModuleContext exposes extra functionality specific to the Android build
156// system including details about the particular build variant that is to be
157// generated.
158//
159// For example:
160//
161// import (
162// "android/soong/common"
Colin Cross70b40592015-03-23 12:57:34 -0700163// "github.com/google/blueprint"
Colin Cross3f40fa42015-01-30 17:27:36 -0800164// )
165//
166// type myModule struct {
167// common.AndroidModuleBase
168// properties struct {
169// MyProperty string
170// }
171// }
172//
173// func NewMyModule() (blueprint.Module, []interface{}) {
174// m := &myModule{}
175// return common.InitAndroidModule(m, &m.properties)
176// }
177//
178// func (m *myModule) GenerateAndroidBuildActions(ctx common.AndroidModuleContext) {
179// // Get the CPU architecture for the current build variant.
180// variantArch := ctx.Arch()
181//
182// // ...
183// }
184type AndroidModuleBase struct {
185 // Putting the curiously recurring thing pointing to the thing that contains
186 // the thing pattern to good use.
187 module AndroidModule
188
189 commonProperties commonProperties
190 hostAndDeviceProperties hostAndDeviceProperties
191 generalProperties []interface{}
192 archProperties []*archProperties
Colin Cross28d76592015-03-26 16:14:04 -0700193 extendedProperties map[string]struct{}
Colin Cross3f40fa42015-01-30 17:27:36 -0800194
195 noAddressSanitizer bool
196 installFiles []string
197 checkbuildFiles []string
198}
199
200func (a *AndroidModuleBase) base() *AndroidModuleBase {
201 return a
202}
203
204func (a *AndroidModuleBase) SetArch(arch Arch) {
205 a.commonProperties.CompileArch = arch
206}
207
208func (a *AndroidModuleBase) HostOrDevice() HostOrDevice {
209 return a.commonProperties.CompileArch.HostOrDevice
210}
211
212func (a *AndroidModuleBase) HostSupported() bool {
213 return a.commonProperties.HostOrDeviceSupported == HostSupported ||
214 a.commonProperties.HostOrDeviceSupported == HostAndDeviceSupported &&
215 a.hostAndDeviceProperties.Host_supported
216}
217
218func (a *AndroidModuleBase) DeviceSupported() bool {
219 return a.commonProperties.HostOrDeviceSupported == DeviceSupported ||
220 a.commonProperties.HostOrDeviceSupported == HostAndDeviceSupported &&
221 a.hostAndDeviceProperties.Device_supported
222}
223
224func (a *AndroidModuleBase) Disabled() bool {
225 return a.commonProperties.Disabled
226}
227
228func (a *AndroidModuleBase) computeInstallDeps(
229 ctx blueprint.ModuleContext) []string {
230
231 result := []string{}
232 ctx.VisitDepsDepthFirstIf(isFileInstaller,
233 func(m blueprint.Module) {
234 fileInstaller := m.(fileInstaller)
235 files := fileInstaller.filesToInstall()
236 result = append(result, files...)
237 })
238
239 return result
240}
241
242func (a *AndroidModuleBase) filesToInstall() []string {
243 return a.installFiles
244}
245
246func (p *AndroidModuleBase) NoAddressSanitizer() bool {
247 return p.noAddressSanitizer
248}
249
Colin Cross3f40fa42015-01-30 17:27:36 -0800250func (a *AndroidModuleBase) generateModuleTarget(ctx blueprint.ModuleContext) {
251 if a != ctx.FinalModule().(AndroidModule).base() {
252 return
253 }
254
255 allInstalledFiles := []string{}
Colin Cross9454bfa2015-03-17 13:24:18 -0700256 allCheckbuildFiles := []string{}
Colin Cross3f40fa42015-01-30 17:27:36 -0800257 ctx.VisitAllModuleVariants(func(module blueprint.Module) {
Colin Crossc9404352015-03-26 16:10:12 -0700258 a := module.(AndroidModule).base()
259 allInstalledFiles = append(allInstalledFiles, a.installFiles...)
260 allCheckbuildFiles = append(allCheckbuildFiles, a.checkbuildFiles...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800261 })
262
Colin Cross9454bfa2015-03-17 13:24:18 -0700263 deps := []string{}
264
Colin Cross3f40fa42015-01-30 17:27:36 -0800265 if len(allInstalledFiles) > 0 {
Colin Cross9454bfa2015-03-17 13:24:18 -0700266 name := ctx.ModuleName() + "-install"
Colin Cross3f40fa42015-01-30 17:27:36 -0800267 ctx.Build(pctx, blueprint.BuildParams{
Colin Cross9454bfa2015-03-17 13:24:18 -0700268 Rule: blueprint.Phony,
269 Outputs: []string{name},
270 Implicits: allInstalledFiles,
271 })
272 deps = append(deps, name)
273 }
274
275 if len(allCheckbuildFiles) > 0 {
276 name := ctx.ModuleName() + "-checkbuild"
277 ctx.Build(pctx, blueprint.BuildParams{
278 Rule: blueprint.Phony,
279 Outputs: []string{name},
280 Implicits: allCheckbuildFiles,
281 Optional: true,
282 })
283 deps = append(deps, name)
284 }
285
286 if len(deps) > 0 {
287 ctx.Build(pctx, blueprint.BuildParams{
288 Rule: blueprint.Phony,
289 Outputs: []string{ctx.ModuleName()},
290 Implicits: deps,
291 Optional: true,
Colin Cross3f40fa42015-01-30 17:27:36 -0800292 })
293 }
294}
295
296func (a *AndroidModuleBase) DynamicDependencies(ctx blueprint.DynamicDependerModuleContext) []string {
297 actx := &androidDynamicDependerContext{
298 DynamicDependerModuleContext: ctx,
Colin Crossf6566ed2015-03-24 11:13:38 -0700299 androidBaseContextImpl: androidBaseContextImpl{
300 arch: a.commonProperties.CompileArch,
301 },
Colin Cross3f40fa42015-01-30 17:27:36 -0800302 }
303
304 if dynamic, ok := a.module.(AndroidDynamicDepender); ok {
305 return dynamic.AndroidDynamicDependencies(actx)
306 }
307
308 return nil
309}
310
311func (a *AndroidModuleBase) GenerateBuildActions(ctx blueprint.ModuleContext) {
312 androidCtx := &androidModuleContext{
313 ModuleContext: ctx,
Colin Crossf6566ed2015-03-24 11:13:38 -0700314 androidBaseContextImpl: androidBaseContextImpl{
315 arch: a.commonProperties.CompileArch,
316 },
Colin Cross28d76592015-03-26 16:14:04 -0700317 installDeps: a.computeInstallDeps(ctx),
318 installFiles: a.installFiles,
319 extendedProperties: a.extendedProperties,
Colin Cross3f40fa42015-01-30 17:27:36 -0800320 }
321
322 if a.commonProperties.Disabled {
323 return
324 }
325
326 a.module.GenerateAndroidBuildActions(androidCtx)
327 if ctx.Failed() {
328 return
329 }
330
Colin Crossc9404352015-03-26 16:10:12 -0700331 a.installFiles = append(a.installFiles, androidCtx.installFiles...)
332 a.checkbuildFiles = append(a.checkbuildFiles, androidCtx.checkbuildFiles...)
333
Colin Cross3f40fa42015-01-30 17:27:36 -0800334 a.generateModuleTarget(ctx)
335 if ctx.Failed() {
336 return
337 }
338}
339
Colin Crossf6566ed2015-03-24 11:13:38 -0700340type androidBaseContextImpl struct {
341 arch Arch
342 debug bool
343}
344
Colin Cross3f40fa42015-01-30 17:27:36 -0800345type androidModuleContext struct {
346 blueprint.ModuleContext
Colin Crossf6566ed2015-03-24 11:13:38 -0700347 androidBaseContextImpl
Colin Cross28d76592015-03-26 16:14:04 -0700348 installDeps []string
349 installFiles []string
350 checkbuildFiles []string
351 extendedProperties map[string]struct{}
Colin Cross3f40fa42015-01-30 17:27:36 -0800352}
353
354func (a *androidModuleContext) Build(pctx *blueprint.PackageContext, params blueprint.BuildParams) {
355 params.Optional = true
356 a.ModuleContext.Build(pctx, params)
357}
358
Colin Cross28d76592015-03-26 16:14:04 -0700359func (a *androidModuleContext) ContainsProperty(property string) bool {
360 if a.ModuleContext.ContainsProperty(property) {
361 return true
362 }
363 _, ok := a.extendedProperties[property]
364 return ok
365}
366
Colin Crossf6566ed2015-03-24 11:13:38 -0700367func (a *androidBaseContextImpl) Arch() Arch {
Colin Cross3f40fa42015-01-30 17:27:36 -0800368 return a.arch
369}
370
Colin Crossf6566ed2015-03-24 11:13:38 -0700371func (a *androidBaseContextImpl) Host() bool {
372 return a.arch.HostOrDevice.Host()
373}
374
375func (a *androidBaseContextImpl) Device() bool {
376 return a.arch.HostOrDevice.Device()
377}
378
379func (a *androidBaseContextImpl) Debug() bool {
380 return a.debug
381}
382
Colin Cross35cec122015-04-02 14:37:16 -0700383func (a *androidModuleContext) InstallFileName(installPath, name, srcPath string,
384 deps ...string) string {
385
386 config := a.Config().(Config)
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}