blob: cb38513cdd5db5d5ffaf736de3ff01327d46ff3d [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 Cross463a90e2015-06-17 14:20:06 -070018 "android/soong"
Colin Cross3f40fa42015-01-30 17:27:36 -080019 "path/filepath"
Colin Cross0af4b842015-04-30 16:36:18 -070020 "runtime"
Dan Willemsenbf9207a2015-06-17 15:17:12 -070021 "sort"
22 "strings"
Colin Crossf6566ed2015-03-24 11:13:38 -070023
Colin Cross8f101b42015-06-17 15:09:06 -070024 "android/soong/glob"
25
Colin Crossf6566ed2015-03-24 11:13:38 -070026 "github.com/google/blueprint"
Dan Willemsen53aa1f62015-11-09 14:05:27 -080027 "github.com/google/blueprint/proptools"
Colin Cross3f40fa42015-01-30 17:27:36 -080028)
29
30var (
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
Colin Crossd3ba0392015-05-07 14:11:29 -070041 HostOrDevice() HostOrDevice
Colin Crossf6566ed2015-03-24 11:13:38 -070042 Host() bool
43 Device() bool
Colin Cross0af4b842015-04-30 16:36:18 -070044 Darwin() bool
Colin Crossf6566ed2015-03-24 11:13:38 -070045 Debug() bool
Colin Cross1332b002015-04-07 17:11:30 -070046 AConfig() Config
Colin Crossf6566ed2015-03-24 11:13:38 -070047}
48
49type AndroidBaseContext interface {
50 blueprint.BaseModuleContext
51 androidBaseContext
52}
53
Colin Cross3f40fa42015-01-30 17:27:36 -080054type AndroidModuleContext interface {
55 blueprint.ModuleContext
Colin Crossf6566ed2015-03-24 11:13:38 -070056 androidBaseContext
Colin Cross3f40fa42015-01-30 17:27:36 -080057
Dan Willemsen2ef08f42015-06-30 18:15:24 -070058 ExpandSources(srcFiles, excludes []string) []string
Colin Crossa819f082015-07-14 18:26:10 -070059 Glob(outDir, globPattern string, excludes []string) []string
Colin Cross8f101b42015-06-17 15:09:06 -070060
Colin Cross35cec122015-04-02 14:37:16 -070061 InstallFile(installPath, srcPath string, deps ...string) string
62 InstallFileName(installPath, name, srcPath string, deps ...string) string
Colin Cross3f40fa42015-01-30 17:27:36 -080063 CheckbuildFile(srcPath string)
64}
65
66type AndroidModule interface {
67 blueprint.Module
68
69 GenerateAndroidBuildActions(AndroidModuleContext)
70
71 base() *AndroidModuleBase
72 Disabled() bool
73 HostOrDevice() HostOrDevice
74}
75
Colin Cross3f40fa42015-01-30 17:27:36 -080076type 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
Colin Cross7d5136f2015-05-11 13:39:40 -070081 // don't emit any build rules for this module
Dan Willemsen53aa1f62015-11-09 14:05:27 -080082 Disabled *bool `android:"arch_variant"`
Colin Cross3f40fa42015-01-30 17:27:36 -080083
Colin Cross7d5136f2015-05-11 13:39:40 -070084 // control whether this module compiles for 32-bit, 64-bit, or both. Possible values
Colin Cross3f40fa42015-01-30 17:27:36 -080085 // 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 Cross5049f022015-03-18 13:28:46 -0700118
Colin Cross7f64b6d2015-07-09 13:57:48 -0700119 propertyStructs = append(propertyStructs, &base.commonProperties, &base.variableProperties)
Colin Cross5049f022015-03-18 13:28:46 -0700120
121 return m, propertyStructs
122}
123
124func InitAndroidArchModule(m AndroidModule, hod HostOrDeviceSupported, defaultMultilib Multilib,
125 propertyStructs ...interface{}) (blueprint.Module, []interface{}) {
126
127 _, propertyStructs = InitAndroidModule(m, propertyStructs...)
128
129 base := m.base()
Colin Cross3f40fa42015-01-30 17:27:36 -0800130 base.commonProperties.HostOrDeviceSupported = hod
Colin Crosscfad1192015-11-02 16:43:11 -0800131 base.commonProperties.Compile_multilib = string(defaultMultilib)
Colin Cross3f40fa42015-01-30 17:27:36 -0800132
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
Colin Crosscfad1192015-11-02 16:43:11 -0800140 return InitArchModule(m, propertyStructs...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800141}
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
Colin Cross7f64b6d2015-07-09 13:57:48 -0700189 variableProperties variableProperties
Colin Cross3f40fa42015-01-30 17:27:36 -0800190 hostAndDeviceProperties hostAndDeviceProperties
191 generalProperties []interface{}
192 archProperties []*archProperties
193
194 noAddressSanitizer bool
195 installFiles []string
196 checkbuildFiles []string
Colin Cross1f8c52b2015-06-16 16:38:17 -0700197
198 // Used by buildTargetSingleton to create checkbuild and per-directory build targets
199 // Only set on the final variant of each module
200 installTarget string
201 checkbuildTarget string
202 blueprintDir string
Colin Cross3f40fa42015-01-30 17:27:36 -0800203}
204
205func (a *AndroidModuleBase) base() *AndroidModuleBase {
206 return a
207}
208
Colin Crossd3ba0392015-05-07 14:11:29 -0700209func (a *AndroidModuleBase) SetHostOrDevice(hod HostOrDevice) {
210 a.commonProperties.CompileHostOrDevice = hod
211}
212
Colin Cross3f40fa42015-01-30 17:27:36 -0800213func (a *AndroidModuleBase) SetArch(arch Arch) {
214 a.commonProperties.CompileArch = arch
215}
216
217func (a *AndroidModuleBase) HostOrDevice() HostOrDevice {
Colin Crossd3ba0392015-05-07 14:11:29 -0700218 return a.commonProperties.CompileHostOrDevice
Colin Cross3f40fa42015-01-30 17:27:36 -0800219}
220
221func (a *AndroidModuleBase) HostSupported() bool {
222 return a.commonProperties.HostOrDeviceSupported == HostSupported ||
223 a.commonProperties.HostOrDeviceSupported == HostAndDeviceSupported &&
224 a.hostAndDeviceProperties.Host_supported
225}
226
227func (a *AndroidModuleBase) DeviceSupported() bool {
228 return a.commonProperties.HostOrDeviceSupported == DeviceSupported ||
229 a.commonProperties.HostOrDeviceSupported == HostAndDeviceSupported &&
230 a.hostAndDeviceProperties.Device_supported
231}
232
233func (a *AndroidModuleBase) Disabled() bool {
Dan Willemsen53aa1f62015-11-09 14:05:27 -0800234 return proptools.Bool(a.commonProperties.Disabled)
Colin Cross3f40fa42015-01-30 17:27:36 -0800235}
236
237func (a *AndroidModuleBase) computeInstallDeps(
238 ctx blueprint.ModuleContext) []string {
239
240 result := []string{}
241 ctx.VisitDepsDepthFirstIf(isFileInstaller,
242 func(m blueprint.Module) {
243 fileInstaller := m.(fileInstaller)
244 files := fileInstaller.filesToInstall()
245 result = append(result, files...)
246 })
247
248 return result
249}
250
251func (a *AndroidModuleBase) filesToInstall() []string {
252 return a.installFiles
253}
254
255func (p *AndroidModuleBase) NoAddressSanitizer() bool {
256 return p.noAddressSanitizer
257}
258
Colin Cross3f40fa42015-01-30 17:27:36 -0800259func (a *AndroidModuleBase) generateModuleTarget(ctx blueprint.ModuleContext) {
260 if a != ctx.FinalModule().(AndroidModule).base() {
261 return
262 }
263
264 allInstalledFiles := []string{}
Colin Cross9454bfa2015-03-17 13:24:18 -0700265 allCheckbuildFiles := []string{}
Colin Cross3f40fa42015-01-30 17:27:36 -0800266 ctx.VisitAllModuleVariants(func(module blueprint.Module) {
Colin Crossc9404352015-03-26 16:10:12 -0700267 a := module.(AndroidModule).base()
268 allInstalledFiles = append(allInstalledFiles, a.installFiles...)
269 allCheckbuildFiles = append(allCheckbuildFiles, a.checkbuildFiles...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800270 })
271
Colin Cross9454bfa2015-03-17 13:24:18 -0700272 deps := []string{}
273
Colin Cross3f40fa42015-01-30 17:27:36 -0800274 if len(allInstalledFiles) > 0 {
Colin Cross9454bfa2015-03-17 13:24:18 -0700275 name := ctx.ModuleName() + "-install"
Colin Cross3f40fa42015-01-30 17:27:36 -0800276 ctx.Build(pctx, blueprint.BuildParams{
Colin Cross9454bfa2015-03-17 13:24:18 -0700277 Rule: blueprint.Phony,
278 Outputs: []string{name},
279 Implicits: allInstalledFiles,
280 })
281 deps = append(deps, name)
Colin Cross1f8c52b2015-06-16 16:38:17 -0700282 a.installTarget = name
Colin Cross9454bfa2015-03-17 13:24:18 -0700283 }
284
285 if len(allCheckbuildFiles) > 0 {
286 name := ctx.ModuleName() + "-checkbuild"
287 ctx.Build(pctx, blueprint.BuildParams{
288 Rule: blueprint.Phony,
289 Outputs: []string{name},
290 Implicits: allCheckbuildFiles,
291 Optional: true,
292 })
293 deps = append(deps, name)
Colin Cross1f8c52b2015-06-16 16:38:17 -0700294 a.checkbuildTarget = name
Colin Cross9454bfa2015-03-17 13:24:18 -0700295 }
296
297 if len(deps) > 0 {
298 ctx.Build(pctx, blueprint.BuildParams{
299 Rule: blueprint.Phony,
300 Outputs: []string{ctx.ModuleName()},
301 Implicits: deps,
302 Optional: true,
Colin Cross3f40fa42015-01-30 17:27:36 -0800303 })
Colin Cross1f8c52b2015-06-16 16:38:17 -0700304
305 a.blueprintDir = ctx.ModuleDir()
Colin Cross3f40fa42015-01-30 17:27:36 -0800306 }
307}
308
Colin Cross6362e272015-10-29 15:25:03 -0700309func (a *AndroidModuleBase) androidBaseContextFactory(ctx blueprint.BaseModuleContext) androidBaseContextImpl {
310 return androidBaseContextImpl{
311 arch: a.commonProperties.CompileArch,
312 hod: a.commonProperties.CompileHostOrDevice,
313 config: ctx.Config().(Config),
Colin Cross3f40fa42015-01-30 17:27:36 -0800314 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800315}
316
317func (a *AndroidModuleBase) GenerateBuildActions(ctx blueprint.ModuleContext) {
318 androidCtx := &androidModuleContext{
Colin Cross6362e272015-10-29 15:25:03 -0700319 ModuleContext: ctx,
320 androidBaseContextImpl: a.androidBaseContextFactory(ctx),
321 installDeps: a.computeInstallDeps(ctx),
322 installFiles: a.installFiles,
Colin Cross3f40fa42015-01-30 17:27:36 -0800323 }
324
Dan Willemsen53aa1f62015-11-09 14:05:27 -0800325 if proptools.Bool(a.commonProperties.Disabled) {
Colin Cross3f40fa42015-01-30 17:27:36 -0800326 return
327 }
328
329 a.module.GenerateAndroidBuildActions(androidCtx)
330 if ctx.Failed() {
331 return
332 }
333
Colin Crossc9404352015-03-26 16:10:12 -0700334 a.installFiles = append(a.installFiles, androidCtx.installFiles...)
335 a.checkbuildFiles = append(a.checkbuildFiles, androidCtx.checkbuildFiles...)
336
Colin Cross3f40fa42015-01-30 17:27:36 -0800337 a.generateModuleTarget(ctx)
338 if ctx.Failed() {
339 return
340 }
341}
342
Colin Crossf6566ed2015-03-24 11:13:38 -0700343type androidBaseContextImpl struct {
Colin Cross1332b002015-04-07 17:11:30 -0700344 arch Arch
Colin Crossd3ba0392015-05-07 14:11:29 -0700345 hod HostOrDevice
Colin Cross1332b002015-04-07 17:11:30 -0700346 debug bool
347 config Config
Colin Crossf6566ed2015-03-24 11:13:38 -0700348}
349
Colin Cross3f40fa42015-01-30 17:27:36 -0800350type androidModuleContext struct {
351 blueprint.ModuleContext
Colin Crossf6566ed2015-03-24 11:13:38 -0700352 androidBaseContextImpl
Colin Cross06a931b2015-10-28 17:23:31 -0700353 installDeps []string
354 installFiles []string
355 checkbuildFiles []string
Colin Cross3f40fa42015-01-30 17:27:36 -0800356}
357
358func (a *androidModuleContext) Build(pctx *blueprint.PackageContext, params blueprint.BuildParams) {
359 params.Optional = true
360 a.ModuleContext.Build(pctx, params)
361}
362
Colin Crossf6566ed2015-03-24 11:13:38 -0700363func (a *androidBaseContextImpl) Arch() Arch {
Colin Cross3f40fa42015-01-30 17:27:36 -0800364 return a.arch
365}
366
Colin Crossd3ba0392015-05-07 14:11:29 -0700367func (a *androidBaseContextImpl) HostOrDevice() HostOrDevice {
368 return a.hod
369}
370
Colin Crossf6566ed2015-03-24 11:13:38 -0700371func (a *androidBaseContextImpl) Host() bool {
Colin Crossd3ba0392015-05-07 14:11:29 -0700372 return a.hod.Host()
Colin Crossf6566ed2015-03-24 11:13:38 -0700373}
374
375func (a *androidBaseContextImpl) Device() bool {
Colin Crossd3ba0392015-05-07 14:11:29 -0700376 return a.hod.Device()
Colin Crossf6566ed2015-03-24 11:13:38 -0700377}
378
Colin Cross0af4b842015-04-30 16:36:18 -0700379func (a *androidBaseContextImpl) Darwin() bool {
Colin Crossd3ba0392015-05-07 14:11:29 -0700380 return a.hod.Host() && runtime.GOOS == "darwin"
Colin Cross0af4b842015-04-30 16:36:18 -0700381}
382
Colin Crossf6566ed2015-03-24 11:13:38 -0700383func (a *androidBaseContextImpl) Debug() bool {
384 return a.debug
385}
386
Colin Cross1332b002015-04-07 17:11:30 -0700387func (a *androidBaseContextImpl) AConfig() Config {
388 return a.config
389}
390
Colin Cross35cec122015-04-02 14:37:16 -0700391func (a *androidModuleContext) InstallFileName(installPath, name, srcPath string,
392 deps ...string) string {
393
Colin Cross1332b002015-04-07 17:11:30 -0700394 config := a.AConfig()
Colin Cross3f40fa42015-01-30 17:27:36 -0800395 var fullInstallPath string
Colin Crossd3ba0392015-05-07 14:11:29 -0700396 if a.hod.Device() {
Colin Cross3f40fa42015-01-30 17:27:36 -0800397 // TODO: replace unset with a device name once we have device targeting
Colin Cross35cec122015-04-02 14:37:16 -0700398 fullInstallPath = filepath.Join(config.DeviceOut(), "system",
399 installPath, name)
Colin Cross3f40fa42015-01-30 17:27:36 -0800400 } else {
Colin Cross35cec122015-04-02 14:37:16 -0700401 fullInstallPath = filepath.Join(config.HostOut(), installPath, name)
Colin Cross3f40fa42015-01-30 17:27:36 -0800402 }
403
Colin Cross35cec122015-04-02 14:37:16 -0700404 deps = append(deps, a.installDeps...)
405
Colin Cross3f40fa42015-01-30 17:27:36 -0800406 a.ModuleContext.Build(pctx, blueprint.BuildParams{
407 Rule: Cp,
408 Outputs: []string{fullInstallPath},
409 Inputs: []string{srcPath},
Colin Cross35cec122015-04-02 14:37:16 -0700410 OrderOnly: deps,
Colin Cross3f40fa42015-01-30 17:27:36 -0800411 })
412
413 a.installFiles = append(a.installFiles, fullInstallPath)
Colin Cross1f8c52b2015-06-16 16:38:17 -0700414 a.checkbuildFiles = append(a.checkbuildFiles, srcPath)
Colin Cross35cec122015-04-02 14:37:16 -0700415 return fullInstallPath
416}
417
418func (a *androidModuleContext) InstallFile(installPath, srcPath string, deps ...string) string {
419 return a.InstallFileName(installPath, filepath.Base(srcPath), srcPath, deps...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800420}
421
422func (a *androidModuleContext) CheckbuildFile(srcPath string) {
423 a.checkbuildFiles = append(a.checkbuildFiles, srcPath)
424}
425
Colin Cross3f40fa42015-01-30 17:27:36 -0800426type fileInstaller interface {
427 filesToInstall() []string
428}
429
430func isFileInstaller(m blueprint.Module) bool {
431 _, ok := m.(fileInstaller)
432 return ok
433}
434
435func isAndroidModule(m blueprint.Module) bool {
436 _, ok := m.(AndroidModule)
437 return ok
438}
Colin Crossfce53272015-04-08 11:21:40 -0700439
Dan Willemsen2ef08f42015-06-30 18:15:24 -0700440func findStringInSlice(str string, slice []string) int {
441 for i, s := range slice {
442 if s == str {
443 return i
Colin Crossfce53272015-04-08 11:21:40 -0700444 }
445 }
Dan Willemsen2ef08f42015-06-30 18:15:24 -0700446 return -1
447}
448
449func (ctx *androidModuleContext) ExpandSources(srcFiles, excludes []string) []string {
450 prefix := ModuleSrcDir(ctx)
451 for i, e := range excludes {
452 j := findStringInSlice(e, srcFiles)
453 if j != -1 {
454 srcFiles = append(srcFiles[:j], srcFiles[j+1:]...)
455 }
456
457 excludes[i] = filepath.Join(prefix, e)
458 }
459
460 for i, srcFile := range srcFiles {
461 srcFiles[i] = filepath.Join(prefix, srcFile)
462 }
Colin Crossfce53272015-04-08 11:21:40 -0700463
Colin Cross8f101b42015-06-17 15:09:06 -0700464 if !hasGlob(srcFiles) {
465 return srcFiles
466 }
467
Colin Cross8f101b42015-06-17 15:09:06 -0700468 globbedSrcFiles := make([]string, 0, len(srcFiles))
469 for _, s := range srcFiles {
Dan Willemsen2ef08f42015-06-30 18:15:24 -0700470 if glob.IsGlob(s) {
Colin Crossa819f082015-07-14 18:26:10 -0700471 globbedSrcFiles = append(globbedSrcFiles, ctx.Glob("src_glob", s, excludes)...)
Colin Cross8f101b42015-06-17 15:09:06 -0700472 } else {
473 globbedSrcFiles = append(globbedSrcFiles, s)
474 }
475 }
476
477 return globbedSrcFiles
478}
479
Colin Crossa819f082015-07-14 18:26:10 -0700480func (ctx *androidModuleContext) Glob(outDir, globPattern string, excludes []string) []string {
481 ret, err := Glob(ctx, filepath.Join(ModuleOutDir(ctx), outDir), globPattern, excludes)
Colin Cross8f101b42015-06-17 15:09:06 -0700482 if err != nil {
483 ctx.ModuleErrorf("glob: %s", err.Error())
484 }
485 return ret
Colin Crossfce53272015-04-08 11:21:40 -0700486}
Colin Cross1f8c52b2015-06-16 16:38:17 -0700487
Colin Cross463a90e2015-06-17 14:20:06 -0700488func init() {
489 soong.RegisterSingletonType("buildtarget", BuildTargetSingleton)
490}
491
Colin Cross1f8c52b2015-06-16 16:38:17 -0700492func BuildTargetSingleton() blueprint.Singleton {
493 return &buildTargetSingleton{}
494}
495
496type buildTargetSingleton struct{}
497
498func (c *buildTargetSingleton) GenerateBuildActions(ctx blueprint.SingletonContext) {
499 checkbuildDeps := []string{}
500
501 dirModules := make(map[string][]string)
Dan Willemsenbf9207a2015-06-17 15:17:12 -0700502 hasBPFile := make(map[string]bool)
503 bpFiles := []string{}
Colin Cross1f8c52b2015-06-16 16:38:17 -0700504
505 ctx.VisitAllModules(func(module blueprint.Module) {
506 if a, ok := module.(AndroidModule); ok {
507 blueprintDir := a.base().blueprintDir
508 installTarget := a.base().installTarget
509 checkbuildTarget := a.base().checkbuildTarget
Dan Willemsenbf9207a2015-06-17 15:17:12 -0700510 bpFile := ctx.BlueprintFile(module)
Colin Cross1f8c52b2015-06-16 16:38:17 -0700511
512 if checkbuildTarget != "" {
513 checkbuildDeps = append(checkbuildDeps, checkbuildTarget)
514 dirModules[blueprintDir] = append(dirModules[blueprintDir], checkbuildTarget)
515 }
516
517 if installTarget != "" {
518 dirModules[blueprintDir] = append(dirModules[blueprintDir], installTarget)
519 }
Dan Willemsenbf9207a2015-06-17 15:17:12 -0700520
521 if !hasBPFile[bpFile] {
522 hasBPFile[bpFile] = true
523 bpFiles = append(bpFiles, bpFile)
524 }
Colin Cross1f8c52b2015-06-16 16:38:17 -0700525 }
526 })
527
528 // Create a top-level checkbuild target that depends on all modules
529 ctx.Build(pctx, blueprint.BuildParams{
530 Rule: blueprint.Phony,
531 Outputs: []string{"checkbuild"},
532 Implicits: checkbuildDeps,
533 // HACK: checkbuild should be an optional build, but force it enabled for now
534 //Optional: true,
535 })
536
537 // Create a mm/<directory> target that depends on all modules in a directory
538 dirs := sortedKeys(dirModules)
539 for _, dir := range dirs {
540 ctx.Build(pctx, blueprint.BuildParams{
541 Rule: blueprint.Phony,
542 Outputs: []string{filepath.Join("mm", dir)},
543 Implicits: dirModules[dir],
544 Optional: true,
545 })
546 }
Dan Willemsenbf9207a2015-06-17 15:17:12 -0700547
548 // Create Android.bp->mk translation rules
549 androidMks := []string{}
550 srcDir := ctx.Config().(Config).SrcDir()
551 intermediatesDir := filepath.Join(ctx.Config().(Config).IntermediatesDir(), "androidmk")
552 sort.Strings(bpFiles)
553 for _, origBp := range bpFiles {
554 bpFile := filepath.Join(srcDir, origBp)
555 mkFile := filepath.Join(srcDir, filepath.Dir(origBp), "Android.mk")
556
557 files, err := Glob(ctx, intermediatesDir, mkFile, nil)
558 if err != nil {
559 ctx.Errorf("glob: %s", err.Error())
560 continue
561 }
562
563 // Existing Android.mk file, use that instead
564 if len(files) > 0 {
Dan Willemsencdd1a992015-06-19 14:22:08 -0700565 for _, file := range files {
566 ctx.AddNinjaFileDeps(file)
567 }
Dan Willemsenbf9207a2015-06-17 15:17:12 -0700568 continue
569 }
570
571 transMk := filepath.Join("androidmk", "Android_"+strings.Replace(filepath.Dir(origBp), "/", "_", -1)+".mk")
572 ctx.Build(pctx, blueprint.BuildParams{
573 Rule: androidbp,
574 Outputs: []string{transMk},
575 Inputs: []string{bpFile},
576 Implicits: []string{androidbpCmd},
577 Optional: true,
578 })
579
580 androidMks = append(androidMks, transMk)
581 }
582
583 ctx.Build(pctx, blueprint.BuildParams{
584 Rule: blueprint.Phony,
585 Outputs: []string{"androidmk"},
586 Implicits: androidMks,
587 Optional: true,
588 })
Colin Cross1f8c52b2015-06-16 16:38:17 -0700589}