blob: e61d31317846eebcc6ac05dcbfc1f9cdd4b21730 [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
Colin Cross581c1892015-04-07 16:50:10 -070026 IntermediatesDir() string
Colin Cross68f55102015-03-25 14:43:57 -070027 Getenv(string) string
28 EnvDeps() map[string]string
Colin Cross35cec122015-04-02 14:37:16 -070029 DeviceOut() string
30 HostOut() string
Colin Cross68f55102015-03-25 14:43:57 -070031}
32
Colin Cross3f40fa42015-01-30 17:27:36 -080033var (
34 DeviceSharedLibrary = "shared_library"
35 DeviceStaticLibrary = "static_library"
36 DeviceExecutable = "executable"
37 HostSharedLibrary = "host_shared_library"
38 HostStaticLibrary = "host_static_library"
39 HostExecutable = "host_executable"
40)
41
Colin Crossf6566ed2015-03-24 11:13:38 -070042type androidBaseContext interface {
43 Arch() Arch
44 Host() bool
45 Device() bool
46 Debug() bool
47}
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
Colin Cross35cec122015-04-02 14:37:16 -070058 InstallFile(installPath, srcPath string, deps ...string) string
59 InstallFileName(installPath, name, srcPath string, deps ...string) string
Colin Cross3f40fa42015-01-30 17:27:36 -080060 CheckbuildFile(srcPath string)
61}
62
63type AndroidModule interface {
64 blueprint.Module
65
66 GenerateAndroidBuildActions(AndroidModuleContext)
67
68 base() *AndroidModuleBase
69 Disabled() bool
70 HostOrDevice() HostOrDevice
71}
72
73type AndroidDynamicDepender interface {
74 AndroidDynamicDependencies(ctx AndroidDynamicDependerModuleContext) []string
75}
76
77type AndroidDynamicDependerModuleContext interface {
78 blueprint.DynamicDependerModuleContext
Colin Crossf6566ed2015-03-24 11:13:38 -070079 androidBaseContext
Colin Cross3f40fa42015-01-30 17:27:36 -080080}
81
82type commonProperties struct {
Colin Crossc77f9d12015-04-02 13:54:39 -070083 Name string
84 Deps []string
85 Tags []string
Colin Cross3f40fa42015-01-30 17:27:36 -080086
87 // disabled: don't emit any build rules for this module
88 Disabled bool `android:"arch_variant"`
89
90 // multilib: control whether this module compiles for 32-bit, 64-bit, or both. Possible values
91 // are "32" (compile for 32-bit only), "64" (compile for 64-bit only), "both" (compile for both
92 // architectures), or "first" (compile for 64-bit on a 64-bit platform, and 32-bit on a 32-bit
93 // platform
94 Compile_multilib string
95
96 // Set by ArchMutator
97 CompileArch Arch `blueprint:"mutated"`
98
99 // Set by InitAndroidModule
100 HostOrDeviceSupported HostOrDeviceSupported `blueprint:"mutated"`
101}
102
103type hostAndDeviceProperties struct {
104 Host_supported bool
105 Device_supported bool
106}
107
Colin Crossc472d572015-03-17 15:06:21 -0700108type Multilib string
109
110const (
Colin Cross2fe66872015-03-30 17:20:39 -0700111 MultilibBoth Multilib = "both"
112 MultilibFirst Multilib = "first"
113 MultilibCommon Multilib = "common"
Colin Crossc472d572015-03-17 15:06:21 -0700114)
115
Colin Cross5049f022015-03-18 13:28:46 -0700116func InitAndroidModule(m AndroidModule,
Colin Cross3f40fa42015-01-30 17:27:36 -0800117 propertyStructs ...interface{}) (blueprint.Module, []interface{}) {
118
119 base := m.base()
120 base.module = m
Colin Cross28d76592015-03-26 16:14:04 -0700121 base.extendedProperties = make(map[string]struct{})
Colin Cross5049f022015-03-18 13:28:46 -0700122
123 propertyStructs = append(propertyStructs, &base.commonProperties)
124
125 return m, propertyStructs
126}
127
128func InitAndroidArchModule(m AndroidModule, hod HostOrDeviceSupported, defaultMultilib Multilib,
129 propertyStructs ...interface{}) (blueprint.Module, []interface{}) {
130
131 _, propertyStructs = InitAndroidModule(m, propertyStructs...)
132
133 base := m.base()
Colin Cross3f40fa42015-01-30 17:27:36 -0800134 base.commonProperties.HostOrDeviceSupported = hod
135
136 if hod == HostAndDeviceSupported {
137 // Default to module to device supported, host not supported, can override in module
138 // properties
139 base.hostAndDeviceProperties.Device_supported = true
140 propertyStructs = append(propertyStructs, &base.hostAndDeviceProperties)
141 }
142
143 return InitArchModule(m, defaultMultilib, propertyStructs...)
144}
145
146// A AndroidModuleBase object contains the properties that are common to all Android
147// modules. It should be included as an anonymous field in every module
148// struct definition. InitAndroidModule should then be called from the module's
149// factory function, and the return values from InitAndroidModule should be
150// returned from the factory function.
151//
152// The AndroidModuleBase type is responsible for implementing the
153// GenerateBuildActions method to support the blueprint.Module interface. This
154// method will then call the module's GenerateAndroidBuildActions method once
155// for each build variant that is to be built. GenerateAndroidBuildActions is
156// passed a AndroidModuleContext rather than the usual blueprint.ModuleContext.
157// AndroidModuleContext exposes extra functionality specific to the Android build
158// system including details about the particular build variant that is to be
159// generated.
160//
161// For example:
162//
163// import (
164// "android/soong/common"
Colin Cross70b40592015-03-23 12:57:34 -0700165// "github.com/google/blueprint"
Colin Cross3f40fa42015-01-30 17:27:36 -0800166// )
167//
168// type myModule struct {
169// common.AndroidModuleBase
170// properties struct {
171// MyProperty string
172// }
173// }
174//
175// func NewMyModule() (blueprint.Module, []interface{}) {
176// m := &myModule{}
177// return common.InitAndroidModule(m, &m.properties)
178// }
179//
180// func (m *myModule) GenerateAndroidBuildActions(ctx common.AndroidModuleContext) {
181// // Get the CPU architecture for the current build variant.
182// variantArch := ctx.Arch()
183//
184// // ...
185// }
186type AndroidModuleBase struct {
187 // Putting the curiously recurring thing pointing to the thing that contains
188 // the thing pattern to good use.
189 module AndroidModule
190
191 commonProperties commonProperties
192 hostAndDeviceProperties hostAndDeviceProperties
193 generalProperties []interface{}
194 archProperties []*archProperties
Colin Cross28d76592015-03-26 16:14:04 -0700195 extendedProperties map[string]struct{}
Colin Cross3f40fa42015-01-30 17:27:36 -0800196
197 noAddressSanitizer bool
198 installFiles []string
199 checkbuildFiles []string
200}
201
202func (a *AndroidModuleBase) base() *AndroidModuleBase {
203 return a
204}
205
206func (a *AndroidModuleBase) SetArch(arch Arch) {
207 a.commonProperties.CompileArch = arch
208}
209
210func (a *AndroidModuleBase) HostOrDevice() HostOrDevice {
211 return a.commonProperties.CompileArch.HostOrDevice
212}
213
214func (a *AndroidModuleBase) HostSupported() bool {
215 return a.commonProperties.HostOrDeviceSupported == HostSupported ||
216 a.commonProperties.HostOrDeviceSupported == HostAndDeviceSupported &&
217 a.hostAndDeviceProperties.Host_supported
218}
219
220func (a *AndroidModuleBase) DeviceSupported() bool {
221 return a.commonProperties.HostOrDeviceSupported == DeviceSupported ||
222 a.commonProperties.HostOrDeviceSupported == HostAndDeviceSupported &&
223 a.hostAndDeviceProperties.Device_supported
224}
225
226func (a *AndroidModuleBase) Disabled() bool {
227 return a.commonProperties.Disabled
228}
229
230func (a *AndroidModuleBase) computeInstallDeps(
231 ctx blueprint.ModuleContext) []string {
232
233 result := []string{}
234 ctx.VisitDepsDepthFirstIf(isFileInstaller,
235 func(m blueprint.Module) {
236 fileInstaller := m.(fileInstaller)
237 files := fileInstaller.filesToInstall()
238 result = append(result, files...)
239 })
240
241 return result
242}
243
244func (a *AndroidModuleBase) filesToInstall() []string {
245 return a.installFiles
246}
247
248func (p *AndroidModuleBase) NoAddressSanitizer() bool {
249 return p.noAddressSanitizer
250}
251
Colin Cross3f40fa42015-01-30 17:27:36 -0800252func (a *AndroidModuleBase) generateModuleTarget(ctx blueprint.ModuleContext) {
253 if a != ctx.FinalModule().(AndroidModule).base() {
254 return
255 }
256
257 allInstalledFiles := []string{}
Colin Cross9454bfa2015-03-17 13:24:18 -0700258 allCheckbuildFiles := []string{}
Colin Cross3f40fa42015-01-30 17:27:36 -0800259 ctx.VisitAllModuleVariants(func(module blueprint.Module) {
Colin Crossc9404352015-03-26 16:10:12 -0700260 a := module.(AndroidModule).base()
261 allInstalledFiles = append(allInstalledFiles, a.installFiles...)
262 allCheckbuildFiles = append(allCheckbuildFiles, a.checkbuildFiles...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800263 })
264
Colin Cross9454bfa2015-03-17 13:24:18 -0700265 deps := []string{}
266
Colin Cross3f40fa42015-01-30 17:27:36 -0800267 if len(allInstalledFiles) > 0 {
Colin Cross9454bfa2015-03-17 13:24:18 -0700268 name := ctx.ModuleName() + "-install"
Colin Cross3f40fa42015-01-30 17:27:36 -0800269 ctx.Build(pctx, blueprint.BuildParams{
Colin Cross9454bfa2015-03-17 13:24:18 -0700270 Rule: blueprint.Phony,
271 Outputs: []string{name},
272 Implicits: allInstalledFiles,
273 })
274 deps = append(deps, name)
275 }
276
277 if len(allCheckbuildFiles) > 0 {
278 name := ctx.ModuleName() + "-checkbuild"
279 ctx.Build(pctx, blueprint.BuildParams{
280 Rule: blueprint.Phony,
281 Outputs: []string{name},
282 Implicits: allCheckbuildFiles,
283 Optional: true,
284 })
285 deps = append(deps, name)
286 }
287
288 if len(deps) > 0 {
289 ctx.Build(pctx, blueprint.BuildParams{
290 Rule: blueprint.Phony,
291 Outputs: []string{ctx.ModuleName()},
292 Implicits: deps,
293 Optional: true,
Colin Cross3f40fa42015-01-30 17:27:36 -0800294 })
295 }
296}
297
298func (a *AndroidModuleBase) DynamicDependencies(ctx blueprint.DynamicDependerModuleContext) []string {
299 actx := &androidDynamicDependerContext{
300 DynamicDependerModuleContext: ctx,
Colin Crossf6566ed2015-03-24 11:13:38 -0700301 androidBaseContextImpl: androidBaseContextImpl{
302 arch: a.commonProperties.CompileArch,
303 },
Colin Cross3f40fa42015-01-30 17:27:36 -0800304 }
305
306 if dynamic, ok := a.module.(AndroidDynamicDepender); ok {
307 return dynamic.AndroidDynamicDependencies(actx)
308 }
309
310 return nil
311}
312
313func (a *AndroidModuleBase) GenerateBuildActions(ctx blueprint.ModuleContext) {
314 androidCtx := &androidModuleContext{
315 ModuleContext: ctx,
Colin Crossf6566ed2015-03-24 11:13:38 -0700316 androidBaseContextImpl: androidBaseContextImpl{
317 arch: a.commonProperties.CompileArch,
318 },
Colin Cross28d76592015-03-26 16:14:04 -0700319 installDeps: a.computeInstallDeps(ctx),
320 installFiles: a.installFiles,
321 extendedProperties: a.extendedProperties,
Colin Cross3f40fa42015-01-30 17:27:36 -0800322 }
323
324 if a.commonProperties.Disabled {
325 return
326 }
327
328 a.module.GenerateAndroidBuildActions(androidCtx)
329 if ctx.Failed() {
330 return
331 }
332
Colin Crossc9404352015-03-26 16:10:12 -0700333 a.installFiles = append(a.installFiles, androidCtx.installFiles...)
334 a.checkbuildFiles = append(a.checkbuildFiles, androidCtx.checkbuildFiles...)
335
Colin Cross3f40fa42015-01-30 17:27:36 -0800336 a.generateModuleTarget(ctx)
337 if ctx.Failed() {
338 return
339 }
340}
341
Colin Crossf6566ed2015-03-24 11:13:38 -0700342type androidBaseContextImpl struct {
343 arch Arch
344 debug bool
345}
346
Colin Cross3f40fa42015-01-30 17:27:36 -0800347type androidModuleContext struct {
348 blueprint.ModuleContext
Colin Crossf6566ed2015-03-24 11:13:38 -0700349 androidBaseContextImpl
Colin Cross28d76592015-03-26 16:14:04 -0700350 installDeps []string
351 installFiles []string
352 checkbuildFiles []string
353 extendedProperties map[string]struct{}
Colin Cross3f40fa42015-01-30 17:27:36 -0800354}
355
356func (a *androidModuleContext) Build(pctx *blueprint.PackageContext, params blueprint.BuildParams) {
357 params.Optional = true
358 a.ModuleContext.Build(pctx, params)
359}
360
Colin Cross28d76592015-03-26 16:14:04 -0700361func (a *androidModuleContext) ContainsProperty(property string) bool {
362 if a.ModuleContext.ContainsProperty(property) {
363 return true
364 }
365 _, ok := a.extendedProperties[property]
366 return ok
367}
368
Colin Crossf6566ed2015-03-24 11:13:38 -0700369func (a *androidBaseContextImpl) Arch() Arch {
Colin Cross3f40fa42015-01-30 17:27:36 -0800370 return a.arch
371}
372
Colin Crossf6566ed2015-03-24 11:13:38 -0700373func (a *androidBaseContextImpl) Host() bool {
374 return a.arch.HostOrDevice.Host()
375}
376
377func (a *androidBaseContextImpl) Device() bool {
378 return a.arch.HostOrDevice.Device()
379}
380
381func (a *androidBaseContextImpl) Debug() bool {
382 return a.debug
383}
384
Colin Cross35cec122015-04-02 14:37:16 -0700385func (a *androidModuleContext) InstallFileName(installPath, name, srcPath string,
386 deps ...string) string {
387
388 config := a.Config().(Config)
Colin Cross3f40fa42015-01-30 17:27:36 -0800389 var fullInstallPath string
390 if a.arch.HostOrDevice.Device() {
391 // TODO: replace unset with a device name once we have device targeting
Colin Cross35cec122015-04-02 14:37:16 -0700392 fullInstallPath = filepath.Join(config.DeviceOut(), "system",
393 installPath, name)
Colin Cross3f40fa42015-01-30 17:27:36 -0800394 } else {
Colin Cross35cec122015-04-02 14:37:16 -0700395 fullInstallPath = filepath.Join(config.HostOut(), installPath, name)
Colin Cross3f40fa42015-01-30 17:27:36 -0800396 }
397
Colin Cross35cec122015-04-02 14:37:16 -0700398 deps = append(deps, a.installDeps...)
399
Colin Cross3f40fa42015-01-30 17:27:36 -0800400 a.ModuleContext.Build(pctx, blueprint.BuildParams{
401 Rule: Cp,
402 Outputs: []string{fullInstallPath},
403 Inputs: []string{srcPath},
Colin Cross35cec122015-04-02 14:37:16 -0700404 OrderOnly: deps,
Colin Cross3f40fa42015-01-30 17:27:36 -0800405 })
406
407 a.installFiles = append(a.installFiles, fullInstallPath)
Colin Cross35cec122015-04-02 14:37:16 -0700408 return fullInstallPath
409}
410
411func (a *androidModuleContext) InstallFile(installPath, srcPath string, deps ...string) string {
412 return a.InstallFileName(installPath, filepath.Base(srcPath), srcPath, deps...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800413}
414
415func (a *androidModuleContext) CheckbuildFile(srcPath string) {
416 a.checkbuildFiles = append(a.checkbuildFiles, srcPath)
417}
418
419type androidDynamicDependerContext struct {
420 blueprint.DynamicDependerModuleContext
Colin Crossf6566ed2015-03-24 11:13:38 -0700421 androidBaseContextImpl
Colin Cross3f40fa42015-01-30 17:27:36 -0800422}
423
424type fileInstaller interface {
425 filesToInstall() []string
426}
427
428func isFileInstaller(m blueprint.Module) bool {
429 _, ok := m.(fileInstaller)
430 return ok
431}
432
433func isAndroidModule(m blueprint.Module) bool {
434 _, ok := m.(AndroidModule)
435 return ok
436}