blob: d420fe1f981b60ceac8ecf2692cf1335e036854d [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 {
79 Name string
80 Deps []string
81 ResourceDirs []string
82
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 Cross5049f022015-03-18 13:28:46 -0700116
117 propertyStructs = append(propertyStructs, &base.commonProperties)
118
119 return m, propertyStructs
120}
121
122func InitAndroidArchModule(m AndroidModule, hod HostOrDeviceSupported, defaultMultilib Multilib,
123 propertyStructs ...interface{}) (blueprint.Module, []interface{}) {
124
125 _, propertyStructs = InitAndroidModule(m, propertyStructs...)
126
127 base := m.base()
Colin Cross3f40fa42015-01-30 17:27:36 -0800128 base.commonProperties.HostOrDeviceSupported = hod
129
130 if hod == HostAndDeviceSupported {
131 // Default to module to device supported, host not supported, can override in module
132 // properties
133 base.hostAndDeviceProperties.Device_supported = true
134 propertyStructs = append(propertyStructs, &base.hostAndDeviceProperties)
135 }
136
137 return InitArchModule(m, defaultMultilib, propertyStructs...)
138}
139
140// A AndroidModuleBase object contains the properties that are common to all Android
141// modules. It should be included as an anonymous field in every module
142// struct definition. InitAndroidModule should then be called from the module's
143// factory function, and the return values from InitAndroidModule should be
144// returned from the factory function.
145//
146// The AndroidModuleBase type is responsible for implementing the
147// GenerateBuildActions method to support the blueprint.Module interface. This
148// method will then call the module's GenerateAndroidBuildActions method once
149// for each build variant that is to be built. GenerateAndroidBuildActions is
150// passed a AndroidModuleContext rather than the usual blueprint.ModuleContext.
151// AndroidModuleContext exposes extra functionality specific to the Android build
152// system including details about the particular build variant that is to be
153// generated.
154//
155// For example:
156//
157// import (
158// "android/soong/common"
Colin Cross70b40592015-03-23 12:57:34 -0700159// "github.com/google/blueprint"
Colin Cross3f40fa42015-01-30 17:27:36 -0800160// )
161//
162// type myModule struct {
163// common.AndroidModuleBase
164// properties struct {
165// MyProperty string
166// }
167// }
168//
169// func NewMyModule() (blueprint.Module, []interface{}) {
170// m := &myModule{}
171// return common.InitAndroidModule(m, &m.properties)
172// }
173//
174// func (m *myModule) GenerateAndroidBuildActions(ctx common.AndroidModuleContext) {
175// // Get the CPU architecture for the current build variant.
176// variantArch := ctx.Arch()
177//
178// // ...
179// }
180type AndroidModuleBase struct {
181 // Putting the curiously recurring thing pointing to the thing that contains
182 // the thing pattern to good use.
183 module AndroidModule
184
185 commonProperties commonProperties
186 hostAndDeviceProperties hostAndDeviceProperties
187 generalProperties []interface{}
188 archProperties []*archProperties
189
190 noAddressSanitizer bool
191 installFiles []string
192 checkbuildFiles []string
193}
194
195func (a *AndroidModuleBase) base() *AndroidModuleBase {
196 return a
197}
198
199func (a *AndroidModuleBase) SetArch(arch Arch) {
200 a.commonProperties.CompileArch = arch
201}
202
203func (a *AndroidModuleBase) HostOrDevice() HostOrDevice {
204 return a.commonProperties.CompileArch.HostOrDevice
205}
206
207func (a *AndroidModuleBase) HostSupported() bool {
208 return a.commonProperties.HostOrDeviceSupported == HostSupported ||
209 a.commonProperties.HostOrDeviceSupported == HostAndDeviceSupported &&
210 a.hostAndDeviceProperties.Host_supported
211}
212
213func (a *AndroidModuleBase) DeviceSupported() bool {
214 return a.commonProperties.HostOrDeviceSupported == DeviceSupported ||
215 a.commonProperties.HostOrDeviceSupported == HostAndDeviceSupported &&
216 a.hostAndDeviceProperties.Device_supported
217}
218
219func (a *AndroidModuleBase) Disabled() bool {
220 return a.commonProperties.Disabled
221}
222
223func (a *AndroidModuleBase) computeInstallDeps(
224 ctx blueprint.ModuleContext) []string {
225
226 result := []string{}
227 ctx.VisitDepsDepthFirstIf(isFileInstaller,
228 func(m blueprint.Module) {
229 fileInstaller := m.(fileInstaller)
230 files := fileInstaller.filesToInstall()
231 result = append(result, files...)
232 })
233
234 return result
235}
236
237func (a *AndroidModuleBase) filesToInstall() []string {
238 return a.installFiles
239}
240
241func (p *AndroidModuleBase) NoAddressSanitizer() bool {
242 return p.noAddressSanitizer
243}
244
245func (p *AndroidModuleBase) resourceDirs() []string {
246 return p.commonProperties.ResourceDirs
247}
248
249func (a *AndroidModuleBase) generateModuleTarget(ctx blueprint.ModuleContext) {
250 if a != ctx.FinalModule().(AndroidModule).base() {
251 return
252 }
253
254 allInstalledFiles := []string{}
Colin Cross9454bfa2015-03-17 13:24:18 -0700255 allCheckbuildFiles := []string{}
Colin Cross3f40fa42015-01-30 17:27:36 -0800256 ctx.VisitAllModuleVariants(func(module blueprint.Module) {
Colin Crossc9404352015-03-26 16:10:12 -0700257 a := module.(AndroidModule).base()
258 allInstalledFiles = append(allInstalledFiles, a.installFiles...)
259 allCheckbuildFiles = append(allCheckbuildFiles, a.checkbuildFiles...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800260 })
261
Colin Cross9454bfa2015-03-17 13:24:18 -0700262 deps := []string{}
263
Colin Cross3f40fa42015-01-30 17:27:36 -0800264 if len(allInstalledFiles) > 0 {
Colin Cross9454bfa2015-03-17 13:24:18 -0700265 name := ctx.ModuleName() + "-install"
Colin Cross3f40fa42015-01-30 17:27:36 -0800266 ctx.Build(pctx, blueprint.BuildParams{
Colin Cross9454bfa2015-03-17 13:24:18 -0700267 Rule: blueprint.Phony,
268 Outputs: []string{name},
269 Implicits: allInstalledFiles,
270 })
271 deps = append(deps, name)
272 }
273
274 if len(allCheckbuildFiles) > 0 {
275 name := ctx.ModuleName() + "-checkbuild"
276 ctx.Build(pctx, blueprint.BuildParams{
277 Rule: blueprint.Phony,
278 Outputs: []string{name},
279 Implicits: allCheckbuildFiles,
280 Optional: true,
281 })
282 deps = append(deps, name)
283 }
284
285 if len(deps) > 0 {
286 ctx.Build(pctx, blueprint.BuildParams{
287 Rule: blueprint.Phony,
288 Outputs: []string{ctx.ModuleName()},
289 Implicits: deps,
290 Optional: true,
Colin Cross3f40fa42015-01-30 17:27:36 -0800291 })
292 }
293}
294
295func (a *AndroidModuleBase) DynamicDependencies(ctx blueprint.DynamicDependerModuleContext) []string {
296 actx := &androidDynamicDependerContext{
297 DynamicDependerModuleContext: ctx,
Colin Crossf6566ed2015-03-24 11:13:38 -0700298 androidBaseContextImpl: androidBaseContextImpl{
299 arch: a.commonProperties.CompileArch,
300 },
Colin Cross3f40fa42015-01-30 17:27:36 -0800301 }
302
303 if dynamic, ok := a.module.(AndroidDynamicDepender); ok {
304 return dynamic.AndroidDynamicDependencies(actx)
305 }
306
307 return nil
308}
309
310func (a *AndroidModuleBase) GenerateBuildActions(ctx blueprint.ModuleContext) {
311 androidCtx := &androidModuleContext{
312 ModuleContext: ctx,
Colin Crossf6566ed2015-03-24 11:13:38 -0700313 androidBaseContextImpl: androidBaseContextImpl{
314 arch: a.commonProperties.CompileArch,
315 },
316 installDeps: a.computeInstallDeps(ctx),
317 installFiles: a.installFiles,
Colin Cross3f40fa42015-01-30 17:27:36 -0800318 }
319
320 if a.commonProperties.Disabled {
321 return
322 }
323
324 a.module.GenerateAndroidBuildActions(androidCtx)
325 if ctx.Failed() {
326 return
327 }
328
Colin Crossc9404352015-03-26 16:10:12 -0700329 a.installFiles = append(a.installFiles, androidCtx.installFiles...)
330 a.checkbuildFiles = append(a.checkbuildFiles, androidCtx.checkbuildFiles...)
331
Colin Cross3f40fa42015-01-30 17:27:36 -0800332 a.generateModuleTarget(ctx)
333 if ctx.Failed() {
334 return
335 }
336}
337
Colin Crossf6566ed2015-03-24 11:13:38 -0700338type androidBaseContextImpl struct {
339 arch Arch
340 debug bool
341}
342
Colin Cross3f40fa42015-01-30 17:27:36 -0800343type androidModuleContext struct {
344 blueprint.ModuleContext
Colin Crossf6566ed2015-03-24 11:13:38 -0700345 androidBaseContextImpl
Colin Cross3f40fa42015-01-30 17:27:36 -0800346 installDeps []string
347 installFiles []string
348 checkbuildFiles []string
349}
350
351func (a *androidModuleContext) Build(pctx *blueprint.PackageContext, params blueprint.BuildParams) {
352 params.Optional = true
353 a.ModuleContext.Build(pctx, params)
354}
355
Colin Crossf6566ed2015-03-24 11:13:38 -0700356func (a *androidBaseContextImpl) Arch() Arch {
Colin Cross3f40fa42015-01-30 17:27:36 -0800357 return a.arch
358}
359
Colin Crossf6566ed2015-03-24 11:13:38 -0700360func (a *androidBaseContextImpl) Host() bool {
361 return a.arch.HostOrDevice.Host()
362}
363
364func (a *androidBaseContextImpl) Device() bool {
365 return a.arch.HostOrDevice.Device()
366}
367
368func (a *androidBaseContextImpl) Debug() bool {
369 return a.debug
370}
371
Colin Cross3f40fa42015-01-30 17:27:36 -0800372func (a *androidModuleContext) InstallFile(installPath, srcPath string) {
373 var fullInstallPath string
374 if a.arch.HostOrDevice.Device() {
375 // TODO: replace unset with a device name once we have device targeting
376 fullInstallPath = filepath.Join("out/target/product/unset/system", installPath,
377 filepath.Base(srcPath))
378 } else {
379 // TODO: replace unset with a host name
380 fullInstallPath = filepath.Join("out/host/unset/", installPath, filepath.Base(srcPath))
381 }
382
383 a.ModuleContext.Build(pctx, blueprint.BuildParams{
384 Rule: Cp,
385 Outputs: []string{fullInstallPath},
386 Inputs: []string{srcPath},
387 OrderOnly: a.installDeps,
388 })
389
390 a.installFiles = append(a.installFiles, fullInstallPath)
Colin Cross3f40fa42015-01-30 17:27:36 -0800391}
392
393func (a *androidModuleContext) CheckbuildFile(srcPath string) {
394 a.checkbuildFiles = append(a.checkbuildFiles, srcPath)
395}
396
397type androidDynamicDependerContext struct {
398 blueprint.DynamicDependerModuleContext
Colin Crossf6566ed2015-03-24 11:13:38 -0700399 androidBaseContextImpl
Colin Cross3f40fa42015-01-30 17:27:36 -0800400}
401
402type fileInstaller interface {
403 filesToInstall() []string
404}
405
406func isFileInstaller(m blueprint.Module) bool {
407 _, ok := m.(fileInstaller)
408 return ok
409}
410
411func isAndroidModule(m blueprint.Module) bool {
412 _, ok := m.(AndroidModule)
413 return ok
414}