blob: 77e02952b9b9a9bb86ec1e4d7395f67bac8b3359 [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"
Dan Willemsenbf9207a2015-06-17 15:17:12 -070020 "sort"
21 "strings"
Colin Crossf6566ed2015-03-24 11:13:38 -070022
Colin Cross8f101b42015-06-17 15:09:06 -070023 "android/soong/glob"
24
Colin Crossf6566ed2015-03-24 11:13:38 -070025 "github.com/google/blueprint"
Colin Cross3f40fa42015-01-30 17:27:36 -080026)
27
28var (
29 DeviceSharedLibrary = "shared_library"
30 DeviceStaticLibrary = "static_library"
31 DeviceExecutable = "executable"
32 HostSharedLibrary = "host_shared_library"
33 HostStaticLibrary = "host_static_library"
34 HostExecutable = "host_executable"
35)
36
Colin Crossf6566ed2015-03-24 11:13:38 -070037type androidBaseContext interface {
38 Arch() Arch
Colin Crossd3ba0392015-05-07 14:11:29 -070039 HostOrDevice() HostOrDevice
Colin Crossf6566ed2015-03-24 11:13:38 -070040 Host() bool
41 Device() bool
Colin Cross0af4b842015-04-30 16:36:18 -070042 Darwin() bool
Colin Crossf6566ed2015-03-24 11:13:38 -070043 Debug() bool
Colin Cross1332b002015-04-07 17:11:30 -070044 AConfig() Config
Colin Crossf6566ed2015-03-24 11:13:38 -070045}
46
47type AndroidBaseContext interface {
48 blueprint.BaseModuleContext
49 androidBaseContext
50}
51
Colin Cross3f40fa42015-01-30 17:27:36 -080052type AndroidModuleContext interface {
53 blueprint.ModuleContext
Colin Crossf6566ed2015-03-24 11:13:38 -070054 androidBaseContext
Colin Cross3f40fa42015-01-30 17:27:36 -080055
Colin Cross8f101b42015-06-17 15:09:06 -070056 ExpandSources(srcFiles []string) []string
57 Glob(globPattern string, excludes []string) []string
58
Colin Cross35cec122015-04-02 14:37:16 -070059 InstallFile(installPath, srcPath string, deps ...string) string
60 InstallFileName(installPath, name, srcPath string, deps ...string) string
Colin Cross3f40fa42015-01-30 17:27:36 -080061 CheckbuildFile(srcPath string)
62}
63
64type AndroidModule interface {
65 blueprint.Module
66
67 GenerateAndroidBuildActions(AndroidModuleContext)
68
69 base() *AndroidModuleBase
70 Disabled() bool
71 HostOrDevice() HostOrDevice
72}
73
74type AndroidDynamicDepender interface {
75 AndroidDynamicDependencies(ctx AndroidDynamicDependerModuleContext) []string
76}
77
78type AndroidDynamicDependerModuleContext interface {
79 blueprint.DynamicDependerModuleContext
Colin Crossf6566ed2015-03-24 11:13:38 -070080 androidBaseContext
Colin Cross3f40fa42015-01-30 17:27:36 -080081}
82
83type commonProperties struct {
Colin Crossc77f9d12015-04-02 13:54:39 -070084 Name string
85 Deps []string
86 Tags []string
Colin Cross3f40fa42015-01-30 17:27:36 -080087
Colin Cross7d5136f2015-05-11 13:39:40 -070088 // don't emit any build rules for this module
Colin Cross3f40fa42015-01-30 17:27:36 -080089 Disabled bool `android:"arch_variant"`
90
Colin Cross7d5136f2015-05-11 13:39:40 -070091 // control whether this module compiles for 32-bit, 64-bit, or both. Possible values
Colin Cross3f40fa42015-01-30 17:27:36 -080092 // are "32" (compile for 32-bit only), "64" (compile for 64-bit only), "both" (compile for both
93 // architectures), or "first" (compile for 64-bit on a 64-bit platform, and 32-bit on a 32-bit
94 // platform
95 Compile_multilib string
96
Colin Crossd3ba0392015-05-07 14:11:29 -070097 // Set by HostOrDeviceMutator
98 CompileHostOrDevice HostOrDevice `blueprint:"mutated"`
99
Colin Cross3f40fa42015-01-30 17:27:36 -0800100 // Set by ArchMutator
101 CompileArch Arch `blueprint:"mutated"`
102
103 // Set by InitAndroidModule
104 HostOrDeviceSupported HostOrDeviceSupported `blueprint:"mutated"`
105}
106
107type hostAndDeviceProperties struct {
108 Host_supported bool
109 Device_supported bool
110}
111
Colin Crossc472d572015-03-17 15:06:21 -0700112type Multilib string
113
114const (
Colin Cross2fe66872015-03-30 17:20:39 -0700115 MultilibBoth Multilib = "both"
116 MultilibFirst Multilib = "first"
117 MultilibCommon Multilib = "common"
Colin Crossc472d572015-03-17 15:06:21 -0700118)
119
Colin Cross5049f022015-03-18 13:28:46 -0700120func InitAndroidModule(m AndroidModule,
Colin Cross3f40fa42015-01-30 17:27:36 -0800121 propertyStructs ...interface{}) (blueprint.Module, []interface{}) {
122
123 base := m.base()
124 base.module = m
Colin Cross28d76592015-03-26 16:14:04 -0700125 base.extendedProperties = make(map[string]struct{})
Colin Cross5049f022015-03-18 13:28:46 -0700126
127 propertyStructs = append(propertyStructs, &base.commonProperties)
128
129 return m, propertyStructs
130}
131
132func InitAndroidArchModule(m AndroidModule, hod HostOrDeviceSupported, defaultMultilib Multilib,
133 propertyStructs ...interface{}) (blueprint.Module, []interface{}) {
134
135 _, propertyStructs = InitAndroidModule(m, propertyStructs...)
136
137 base := m.base()
Colin Cross3f40fa42015-01-30 17:27:36 -0800138 base.commonProperties.HostOrDeviceSupported = hod
139
140 if hod == HostAndDeviceSupported {
141 // Default to module to device supported, host not supported, can override in module
142 // properties
143 base.hostAndDeviceProperties.Device_supported = true
144 propertyStructs = append(propertyStructs, &base.hostAndDeviceProperties)
145 }
146
147 return InitArchModule(m, defaultMultilib, propertyStructs...)
148}
149
150// A AndroidModuleBase object contains the properties that are common to all Android
151// modules. It should be included as an anonymous field in every module
152// struct definition. InitAndroidModule should then be called from the module's
153// factory function, and the return values from InitAndroidModule should be
154// returned from the factory function.
155//
156// The AndroidModuleBase type is responsible for implementing the
157// GenerateBuildActions method to support the blueprint.Module interface. This
158// method will then call the module's GenerateAndroidBuildActions method once
159// for each build variant that is to be built. GenerateAndroidBuildActions is
160// passed a AndroidModuleContext rather than the usual blueprint.ModuleContext.
161// AndroidModuleContext exposes extra functionality specific to the Android build
162// system including details about the particular build variant that is to be
163// generated.
164//
165// For example:
166//
167// import (
168// "android/soong/common"
Colin Cross70b40592015-03-23 12:57:34 -0700169// "github.com/google/blueprint"
Colin Cross3f40fa42015-01-30 17:27:36 -0800170// )
171//
172// type myModule struct {
173// common.AndroidModuleBase
174// properties struct {
175// MyProperty string
176// }
177// }
178//
179// func NewMyModule() (blueprint.Module, []interface{}) {
180// m := &myModule{}
181// return common.InitAndroidModule(m, &m.properties)
182// }
183//
184// func (m *myModule) GenerateAndroidBuildActions(ctx common.AndroidModuleContext) {
185// // Get the CPU architecture for the current build variant.
186// variantArch := ctx.Arch()
187//
188// // ...
189// }
190type AndroidModuleBase struct {
191 // Putting the curiously recurring thing pointing to the thing that contains
192 // the thing pattern to good use.
193 module AndroidModule
194
195 commonProperties commonProperties
196 hostAndDeviceProperties hostAndDeviceProperties
197 generalProperties []interface{}
198 archProperties []*archProperties
Colin Cross28d76592015-03-26 16:14:04 -0700199 extendedProperties map[string]struct{}
Colin Cross3f40fa42015-01-30 17:27:36 -0800200
201 noAddressSanitizer bool
202 installFiles []string
203 checkbuildFiles []string
Colin Cross1f8c52b2015-06-16 16:38:17 -0700204
205 // Used by buildTargetSingleton to create checkbuild and per-directory build targets
206 // Only set on the final variant of each module
207 installTarget string
208 checkbuildTarget string
209 blueprintDir string
Colin Cross3f40fa42015-01-30 17:27:36 -0800210}
211
212func (a *AndroidModuleBase) base() *AndroidModuleBase {
213 return a
214}
215
Colin Crossd3ba0392015-05-07 14:11:29 -0700216func (a *AndroidModuleBase) SetHostOrDevice(hod HostOrDevice) {
217 a.commonProperties.CompileHostOrDevice = hod
218}
219
Colin Cross3f40fa42015-01-30 17:27:36 -0800220func (a *AndroidModuleBase) SetArch(arch Arch) {
221 a.commonProperties.CompileArch = arch
222}
223
224func (a *AndroidModuleBase) HostOrDevice() HostOrDevice {
Colin Crossd3ba0392015-05-07 14:11:29 -0700225 return a.commonProperties.CompileHostOrDevice
Colin Cross3f40fa42015-01-30 17:27:36 -0800226}
227
228func (a *AndroidModuleBase) HostSupported() bool {
229 return a.commonProperties.HostOrDeviceSupported == HostSupported ||
230 a.commonProperties.HostOrDeviceSupported == HostAndDeviceSupported &&
231 a.hostAndDeviceProperties.Host_supported
232}
233
234func (a *AndroidModuleBase) DeviceSupported() bool {
235 return a.commonProperties.HostOrDeviceSupported == DeviceSupported ||
236 a.commonProperties.HostOrDeviceSupported == HostAndDeviceSupported &&
237 a.hostAndDeviceProperties.Device_supported
238}
239
240func (a *AndroidModuleBase) Disabled() bool {
241 return a.commonProperties.Disabled
242}
243
244func (a *AndroidModuleBase) computeInstallDeps(
245 ctx blueprint.ModuleContext) []string {
246
247 result := []string{}
248 ctx.VisitDepsDepthFirstIf(isFileInstaller,
249 func(m blueprint.Module) {
250 fileInstaller := m.(fileInstaller)
251 files := fileInstaller.filesToInstall()
252 result = append(result, files...)
253 })
254
255 return result
256}
257
258func (a *AndroidModuleBase) filesToInstall() []string {
259 return a.installFiles
260}
261
262func (p *AndroidModuleBase) NoAddressSanitizer() bool {
263 return p.noAddressSanitizer
264}
265
Colin Cross3f40fa42015-01-30 17:27:36 -0800266func (a *AndroidModuleBase) generateModuleTarget(ctx blueprint.ModuleContext) {
267 if a != ctx.FinalModule().(AndroidModule).base() {
268 return
269 }
270
271 allInstalledFiles := []string{}
Colin Cross9454bfa2015-03-17 13:24:18 -0700272 allCheckbuildFiles := []string{}
Colin Cross3f40fa42015-01-30 17:27:36 -0800273 ctx.VisitAllModuleVariants(func(module blueprint.Module) {
Colin Crossc9404352015-03-26 16:10:12 -0700274 a := module.(AndroidModule).base()
275 allInstalledFiles = append(allInstalledFiles, a.installFiles...)
276 allCheckbuildFiles = append(allCheckbuildFiles, a.checkbuildFiles...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800277 })
278
Colin Cross9454bfa2015-03-17 13:24:18 -0700279 deps := []string{}
280
Colin Cross3f40fa42015-01-30 17:27:36 -0800281 if len(allInstalledFiles) > 0 {
Colin Cross9454bfa2015-03-17 13:24:18 -0700282 name := ctx.ModuleName() + "-install"
Colin Cross3f40fa42015-01-30 17:27:36 -0800283 ctx.Build(pctx, blueprint.BuildParams{
Colin Cross9454bfa2015-03-17 13:24:18 -0700284 Rule: blueprint.Phony,
285 Outputs: []string{name},
286 Implicits: allInstalledFiles,
287 })
288 deps = append(deps, name)
Colin Cross1f8c52b2015-06-16 16:38:17 -0700289 a.installTarget = name
Colin Cross9454bfa2015-03-17 13:24:18 -0700290 }
291
292 if len(allCheckbuildFiles) > 0 {
293 name := ctx.ModuleName() + "-checkbuild"
294 ctx.Build(pctx, blueprint.BuildParams{
295 Rule: blueprint.Phony,
296 Outputs: []string{name},
297 Implicits: allCheckbuildFiles,
298 Optional: true,
299 })
300 deps = append(deps, name)
Colin Cross1f8c52b2015-06-16 16:38:17 -0700301 a.checkbuildTarget = name
Colin Cross9454bfa2015-03-17 13:24:18 -0700302 }
303
304 if len(deps) > 0 {
305 ctx.Build(pctx, blueprint.BuildParams{
306 Rule: blueprint.Phony,
307 Outputs: []string{ctx.ModuleName()},
308 Implicits: deps,
309 Optional: true,
Colin Cross3f40fa42015-01-30 17:27:36 -0800310 })
Colin Cross1f8c52b2015-06-16 16:38:17 -0700311
312 a.blueprintDir = ctx.ModuleDir()
Colin Cross3f40fa42015-01-30 17:27:36 -0800313 }
314}
315
316func (a *AndroidModuleBase) DynamicDependencies(ctx blueprint.DynamicDependerModuleContext) []string {
317 actx := &androidDynamicDependerContext{
318 DynamicDependerModuleContext: 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 Cross3f40fa42015-01-30 17:27:36 -0800324 }
325
326 if dynamic, ok := a.module.(AndroidDynamicDepender); ok {
327 return dynamic.AndroidDynamicDependencies(actx)
328 }
329
330 return nil
331}
332
333func (a *AndroidModuleBase) GenerateBuildActions(ctx blueprint.ModuleContext) {
334 androidCtx := &androidModuleContext{
335 ModuleContext: ctx,
Colin Crossf6566ed2015-03-24 11:13:38 -0700336 androidBaseContextImpl: androidBaseContextImpl{
Colin Cross1332b002015-04-07 17:11:30 -0700337 arch: a.commonProperties.CompileArch,
Colin Crossd3ba0392015-05-07 14:11:29 -0700338 hod: a.commonProperties.CompileHostOrDevice,
Colin Cross1332b002015-04-07 17:11:30 -0700339 config: ctx.Config().(Config),
Colin Crossf6566ed2015-03-24 11:13:38 -0700340 },
Colin Cross28d76592015-03-26 16:14:04 -0700341 installDeps: a.computeInstallDeps(ctx),
342 installFiles: a.installFiles,
343 extendedProperties: a.extendedProperties,
Colin Cross3f40fa42015-01-30 17:27:36 -0800344 }
345
346 if a.commonProperties.Disabled {
347 return
348 }
349
350 a.module.GenerateAndroidBuildActions(androidCtx)
351 if ctx.Failed() {
352 return
353 }
354
Colin Crossc9404352015-03-26 16:10:12 -0700355 a.installFiles = append(a.installFiles, androidCtx.installFiles...)
356 a.checkbuildFiles = append(a.checkbuildFiles, androidCtx.checkbuildFiles...)
357
Colin Cross3f40fa42015-01-30 17:27:36 -0800358 a.generateModuleTarget(ctx)
359 if ctx.Failed() {
360 return
361 }
362}
363
Colin Crossf6566ed2015-03-24 11:13:38 -0700364type androidBaseContextImpl struct {
Colin Cross1332b002015-04-07 17:11:30 -0700365 arch Arch
Colin Crossd3ba0392015-05-07 14:11:29 -0700366 hod HostOrDevice
Colin Cross1332b002015-04-07 17:11:30 -0700367 debug bool
368 config Config
Colin Crossf6566ed2015-03-24 11:13:38 -0700369}
370
Colin Cross3f40fa42015-01-30 17:27:36 -0800371type androidModuleContext struct {
372 blueprint.ModuleContext
Colin Crossf6566ed2015-03-24 11:13:38 -0700373 androidBaseContextImpl
Colin Cross28d76592015-03-26 16:14:04 -0700374 installDeps []string
375 installFiles []string
376 checkbuildFiles []string
377 extendedProperties map[string]struct{}
Colin Cross3f40fa42015-01-30 17:27:36 -0800378}
379
380func (a *androidModuleContext) Build(pctx *blueprint.PackageContext, params blueprint.BuildParams) {
381 params.Optional = true
382 a.ModuleContext.Build(pctx, params)
383}
384
Colin Cross28d76592015-03-26 16:14:04 -0700385func (a *androidModuleContext) ContainsProperty(property string) bool {
386 if a.ModuleContext.ContainsProperty(property) {
387 return true
388 }
389 _, ok := a.extendedProperties[property]
390 return ok
391}
392
Colin Crossf6566ed2015-03-24 11:13:38 -0700393func (a *androidBaseContextImpl) Arch() Arch {
Colin Cross3f40fa42015-01-30 17:27:36 -0800394 return a.arch
395}
396
Colin Crossd3ba0392015-05-07 14:11:29 -0700397func (a *androidBaseContextImpl) HostOrDevice() HostOrDevice {
398 return a.hod
399}
400
Colin Crossf6566ed2015-03-24 11:13:38 -0700401func (a *androidBaseContextImpl) Host() bool {
Colin Crossd3ba0392015-05-07 14:11:29 -0700402 return a.hod.Host()
Colin Crossf6566ed2015-03-24 11:13:38 -0700403}
404
405func (a *androidBaseContextImpl) Device() bool {
Colin Crossd3ba0392015-05-07 14:11:29 -0700406 return a.hod.Device()
Colin Crossf6566ed2015-03-24 11:13:38 -0700407}
408
Colin Cross0af4b842015-04-30 16:36:18 -0700409func (a *androidBaseContextImpl) Darwin() bool {
Colin Crossd3ba0392015-05-07 14:11:29 -0700410 return a.hod.Host() && runtime.GOOS == "darwin"
Colin Cross0af4b842015-04-30 16:36:18 -0700411}
412
Colin Crossf6566ed2015-03-24 11:13:38 -0700413func (a *androidBaseContextImpl) Debug() bool {
414 return a.debug
415}
416
Colin Cross1332b002015-04-07 17:11:30 -0700417func (a *androidBaseContextImpl) AConfig() Config {
418 return a.config
419}
420
Colin Cross35cec122015-04-02 14:37:16 -0700421func (a *androidModuleContext) InstallFileName(installPath, name, srcPath string,
422 deps ...string) string {
423
Colin Cross1332b002015-04-07 17:11:30 -0700424 config := a.AConfig()
Colin Cross3f40fa42015-01-30 17:27:36 -0800425 var fullInstallPath string
Colin Crossd3ba0392015-05-07 14:11:29 -0700426 if a.hod.Device() {
Colin Cross3f40fa42015-01-30 17:27:36 -0800427 // TODO: replace unset with a device name once we have device targeting
Colin Cross35cec122015-04-02 14:37:16 -0700428 fullInstallPath = filepath.Join(config.DeviceOut(), "system",
429 installPath, name)
Colin Cross3f40fa42015-01-30 17:27:36 -0800430 } else {
Colin Cross35cec122015-04-02 14:37:16 -0700431 fullInstallPath = filepath.Join(config.HostOut(), installPath, name)
Colin Cross3f40fa42015-01-30 17:27:36 -0800432 }
433
Colin Cross35cec122015-04-02 14:37:16 -0700434 deps = append(deps, a.installDeps...)
435
Colin Cross3f40fa42015-01-30 17:27:36 -0800436 a.ModuleContext.Build(pctx, blueprint.BuildParams{
437 Rule: Cp,
438 Outputs: []string{fullInstallPath},
439 Inputs: []string{srcPath},
Colin Cross35cec122015-04-02 14:37:16 -0700440 OrderOnly: deps,
Colin Cross3f40fa42015-01-30 17:27:36 -0800441 })
442
443 a.installFiles = append(a.installFiles, fullInstallPath)
Colin Cross1f8c52b2015-06-16 16:38:17 -0700444 a.checkbuildFiles = append(a.checkbuildFiles, srcPath)
Colin Cross35cec122015-04-02 14:37:16 -0700445 return fullInstallPath
446}
447
448func (a *androidModuleContext) InstallFile(installPath, srcPath string, deps ...string) string {
449 return a.InstallFileName(installPath, filepath.Base(srcPath), srcPath, deps...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800450}
451
452func (a *androidModuleContext) CheckbuildFile(srcPath string) {
453 a.checkbuildFiles = append(a.checkbuildFiles, srcPath)
454}
455
456type androidDynamicDependerContext struct {
457 blueprint.DynamicDependerModuleContext
Colin Crossf6566ed2015-03-24 11:13:38 -0700458 androidBaseContextImpl
Colin Cross3f40fa42015-01-30 17:27:36 -0800459}
460
461type fileInstaller interface {
462 filesToInstall() []string
463}
464
465func isFileInstaller(m blueprint.Module) bool {
466 _, ok := m.(fileInstaller)
467 return ok
468}
469
470func isAndroidModule(m blueprint.Module) bool {
471 _, ok := m.(AndroidModule)
472 return ok
473}
Colin Crossfce53272015-04-08 11:21:40 -0700474
Colin Cross8f101b42015-06-17 15:09:06 -0700475func (ctx *androidModuleContext) ExpandSources(srcFiles []string) []string {
Colin Crossfce53272015-04-08 11:21:40 -0700476 prefix := ModuleSrcDir(ctx)
477 for i, srcFile := range srcFiles {
478 if srcFile[0] == '-' {
479 srcFiles[i] = "-" + filepath.Join(prefix, srcFile[1:])
480 } else {
481 srcFiles[i] = filepath.Join(prefix, srcFile)
482 }
483 }
484
Colin Cross8f101b42015-06-17 15:09:06 -0700485 if !hasGlob(srcFiles) {
486 return srcFiles
487 }
488
489 var excludes []string
490 for _, s := range srcFiles {
491 if s[0] == '-' {
492 excludes = append(excludes, s[1:])
493 }
494 }
495
496 globbedSrcFiles := make([]string, 0, len(srcFiles))
497 for _, s := range srcFiles {
498 if s[0] == '-' {
499 continue
500 } else if glob.IsGlob(s) {
501 globbedSrcFiles = append(globbedSrcFiles, ctx.Glob(s, excludes)...)
502 } else {
503 globbedSrcFiles = append(globbedSrcFiles, s)
504 }
505 }
506
507 return globbedSrcFiles
508}
509
510func (ctx *androidModuleContext) Glob(globPattern string, excludes []string) []string {
511 ret, err := Glob(ctx, ModuleOutDir(ctx), globPattern, excludes)
512 if err != nil {
513 ctx.ModuleErrorf("glob: %s", err.Error())
514 }
515 return ret
Colin Crossfce53272015-04-08 11:21:40 -0700516}
Colin Cross1f8c52b2015-06-16 16:38:17 -0700517
518func BuildTargetSingleton() blueprint.Singleton {
519 return &buildTargetSingleton{}
520}
521
522type buildTargetSingleton struct{}
523
524func (c *buildTargetSingleton) GenerateBuildActions(ctx blueprint.SingletonContext) {
525 checkbuildDeps := []string{}
526
527 dirModules := make(map[string][]string)
Dan Willemsenbf9207a2015-06-17 15:17:12 -0700528 hasBPFile := make(map[string]bool)
529 bpFiles := []string{}
Colin Cross1f8c52b2015-06-16 16:38:17 -0700530
531 ctx.VisitAllModules(func(module blueprint.Module) {
532 if a, ok := module.(AndroidModule); ok {
533 blueprintDir := a.base().blueprintDir
534 installTarget := a.base().installTarget
535 checkbuildTarget := a.base().checkbuildTarget
Dan Willemsenbf9207a2015-06-17 15:17:12 -0700536 bpFile := ctx.BlueprintFile(module)
Colin Cross1f8c52b2015-06-16 16:38:17 -0700537
538 if checkbuildTarget != "" {
539 checkbuildDeps = append(checkbuildDeps, checkbuildTarget)
540 dirModules[blueprintDir] = append(dirModules[blueprintDir], checkbuildTarget)
541 }
542
543 if installTarget != "" {
544 dirModules[blueprintDir] = append(dirModules[blueprintDir], installTarget)
545 }
Dan Willemsenbf9207a2015-06-17 15:17:12 -0700546
547 if !hasBPFile[bpFile] {
548 hasBPFile[bpFile] = true
549 bpFiles = append(bpFiles, bpFile)
550 }
Colin Cross1f8c52b2015-06-16 16:38:17 -0700551 }
552 })
553
554 // Create a top-level checkbuild target that depends on all modules
555 ctx.Build(pctx, blueprint.BuildParams{
556 Rule: blueprint.Phony,
557 Outputs: []string{"checkbuild"},
558 Implicits: checkbuildDeps,
559 // HACK: checkbuild should be an optional build, but force it enabled for now
560 //Optional: true,
561 })
562
563 // Create a mm/<directory> target that depends on all modules in a directory
564 dirs := sortedKeys(dirModules)
565 for _, dir := range dirs {
566 ctx.Build(pctx, blueprint.BuildParams{
567 Rule: blueprint.Phony,
568 Outputs: []string{filepath.Join("mm", dir)},
569 Implicits: dirModules[dir],
570 Optional: true,
571 })
572 }
Dan Willemsenbf9207a2015-06-17 15:17:12 -0700573
574 // Create Android.bp->mk translation rules
575 androidMks := []string{}
576 srcDir := ctx.Config().(Config).SrcDir()
577 intermediatesDir := filepath.Join(ctx.Config().(Config).IntermediatesDir(), "androidmk")
578 sort.Strings(bpFiles)
579 for _, origBp := range bpFiles {
580 bpFile := filepath.Join(srcDir, origBp)
581 mkFile := filepath.Join(srcDir, filepath.Dir(origBp), "Android.mk")
582
583 files, err := Glob(ctx, intermediatesDir, mkFile, nil)
584 if err != nil {
585 ctx.Errorf("glob: %s", err.Error())
586 continue
587 }
588
589 // Existing Android.mk file, use that instead
590 if len(files) > 0 {
Dan Willemsencdd1a992015-06-19 14:22:08 -0700591 for _, file := range files {
592 ctx.AddNinjaFileDeps(file)
593 }
Dan Willemsenbf9207a2015-06-17 15:17:12 -0700594 continue
595 }
596
597 transMk := filepath.Join("androidmk", "Android_"+strings.Replace(filepath.Dir(origBp), "/", "_", -1)+".mk")
598 ctx.Build(pctx, blueprint.BuildParams{
599 Rule: androidbp,
600 Outputs: []string{transMk},
601 Inputs: []string{bpFile},
602 Implicits: []string{androidbpCmd},
603 Optional: true,
604 })
605
606 androidMks = append(androidMks, transMk)
607 }
608
609 ctx.Build(pctx, blueprint.BuildParams{
610 Rule: blueprint.Phony,
611 Outputs: []string{"androidmk"},
612 Implicits: androidMks,
613 Optional: true,
614 })
Colin Cross1f8c52b2015-06-16 16:38:17 -0700615}