blob: 6b2dfb465ded7e72821b6636187f786583e8e861 [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 Cross70b40592015-03-23 12:57:34 -070018 "github.com/google/blueprint"
Colin Cross3f40fa42015-01-30 17:27:36 -080019 "path/filepath"
20)
21
22var (
23 DeviceSharedLibrary = "shared_library"
24 DeviceStaticLibrary = "static_library"
25 DeviceExecutable = "executable"
26 HostSharedLibrary = "host_shared_library"
27 HostStaticLibrary = "host_static_library"
28 HostExecutable = "host_executable"
29)
30
31type AndroidModuleContext interface {
32 blueprint.ModuleContext
33
34 Arch() Arch
35 InstallFile(installPath, srcPath string)
36 CheckbuildFile(srcPath string)
37}
38
39type AndroidModule interface {
40 blueprint.Module
41
42 GenerateAndroidBuildActions(AndroidModuleContext)
43
44 base() *AndroidModuleBase
45 Disabled() bool
46 HostOrDevice() HostOrDevice
47}
48
49type AndroidDynamicDepender interface {
50 AndroidDynamicDependencies(ctx AndroidDynamicDependerModuleContext) []string
51}
52
53type AndroidDynamicDependerModuleContext interface {
54 blueprint.DynamicDependerModuleContext
55}
56
57type commonProperties struct {
58 Name string
59 Deps []string
60 ResourceDirs []string
61
62 // disabled: don't emit any build rules for this module
63 Disabled bool `android:"arch_variant"`
64
65 // multilib: control whether this module compiles for 32-bit, 64-bit, or both. Possible values
66 // are "32" (compile for 32-bit only), "64" (compile for 64-bit only), "both" (compile for both
67 // architectures), or "first" (compile for 64-bit on a 64-bit platform, and 32-bit on a 32-bit
68 // platform
69 Compile_multilib string
70
71 // Set by ArchMutator
72 CompileArch Arch `blueprint:"mutated"`
73
74 // Set by InitAndroidModule
75 HostOrDeviceSupported HostOrDeviceSupported `blueprint:"mutated"`
76}
77
78type hostAndDeviceProperties struct {
79 Host_supported bool
80 Device_supported bool
81}
82
Colin Crossc472d572015-03-17 15:06:21 -070083type Multilib string
84
85const (
86 MultilibBoth Multilib = "both"
87 MultilibFirst Multilib = "first"
88)
89
Colin Cross5049f022015-03-18 13:28:46 -070090func InitAndroidModule(m AndroidModule,
Colin Cross3f40fa42015-01-30 17:27:36 -080091 propertyStructs ...interface{}) (blueprint.Module, []interface{}) {
92
93 base := m.base()
94 base.module = m
Colin Cross5049f022015-03-18 13:28:46 -070095
96 propertyStructs = append(propertyStructs, &base.commonProperties)
97
98 return m, propertyStructs
99}
100
101func InitAndroidArchModule(m AndroidModule, hod HostOrDeviceSupported, defaultMultilib Multilib,
102 propertyStructs ...interface{}) (blueprint.Module, []interface{}) {
103
104 _, propertyStructs = InitAndroidModule(m, propertyStructs...)
105
106 base := m.base()
Colin Cross3f40fa42015-01-30 17:27:36 -0800107 base.commonProperties.HostOrDeviceSupported = hod
108
109 if hod == HostAndDeviceSupported {
110 // Default to module to device supported, host not supported, can override in module
111 // properties
112 base.hostAndDeviceProperties.Device_supported = true
113 propertyStructs = append(propertyStructs, &base.hostAndDeviceProperties)
114 }
115
116 return InitArchModule(m, defaultMultilib, propertyStructs...)
117}
118
119// A AndroidModuleBase object contains the properties that are common to all Android
120// modules. It should be included as an anonymous field in every module
121// struct definition. InitAndroidModule should then be called from the module's
122// factory function, and the return values from InitAndroidModule should be
123// returned from the factory function.
124//
125// The AndroidModuleBase type is responsible for implementing the
126// GenerateBuildActions method to support the blueprint.Module interface. This
127// method will then call the module's GenerateAndroidBuildActions method once
128// for each build variant that is to be built. GenerateAndroidBuildActions is
129// passed a AndroidModuleContext rather than the usual blueprint.ModuleContext.
130// AndroidModuleContext exposes extra functionality specific to the Android build
131// system including details about the particular build variant that is to be
132// generated.
133//
134// For example:
135//
136// import (
137// "android/soong/common"
Colin Cross70b40592015-03-23 12:57:34 -0700138// "github.com/google/blueprint"
Colin Cross3f40fa42015-01-30 17:27:36 -0800139// )
140//
141// type myModule struct {
142// common.AndroidModuleBase
143// properties struct {
144// MyProperty string
145// }
146// }
147//
148// func NewMyModule() (blueprint.Module, []interface{}) {
149// m := &myModule{}
150// return common.InitAndroidModule(m, &m.properties)
151// }
152//
153// func (m *myModule) GenerateAndroidBuildActions(ctx common.AndroidModuleContext) {
154// // Get the CPU architecture for the current build variant.
155// variantArch := ctx.Arch()
156//
157// // ...
158// }
159type AndroidModuleBase struct {
160 // Putting the curiously recurring thing pointing to the thing that contains
161 // the thing pattern to good use.
162 module AndroidModule
163
164 commonProperties commonProperties
165 hostAndDeviceProperties hostAndDeviceProperties
166 generalProperties []interface{}
167 archProperties []*archProperties
168
169 noAddressSanitizer bool
170 installFiles []string
171 checkbuildFiles []string
172}
173
174func (a *AndroidModuleBase) base() *AndroidModuleBase {
175 return a
176}
177
178func (a *AndroidModuleBase) SetArch(arch Arch) {
179 a.commonProperties.CompileArch = arch
180}
181
182func (a *AndroidModuleBase) HostOrDevice() HostOrDevice {
183 return a.commonProperties.CompileArch.HostOrDevice
184}
185
186func (a *AndroidModuleBase) HostSupported() bool {
187 return a.commonProperties.HostOrDeviceSupported == HostSupported ||
188 a.commonProperties.HostOrDeviceSupported == HostAndDeviceSupported &&
189 a.hostAndDeviceProperties.Host_supported
190}
191
192func (a *AndroidModuleBase) DeviceSupported() bool {
193 return a.commonProperties.HostOrDeviceSupported == DeviceSupported ||
194 a.commonProperties.HostOrDeviceSupported == HostAndDeviceSupported &&
195 a.hostAndDeviceProperties.Device_supported
196}
197
198func (a *AndroidModuleBase) Disabled() bool {
199 return a.commonProperties.Disabled
200}
201
202func (a *AndroidModuleBase) computeInstallDeps(
203 ctx blueprint.ModuleContext) []string {
204
205 result := []string{}
206 ctx.VisitDepsDepthFirstIf(isFileInstaller,
207 func(m blueprint.Module) {
208 fileInstaller := m.(fileInstaller)
209 files := fileInstaller.filesToInstall()
210 result = append(result, files...)
211 })
212
213 return result
214}
215
216func (a *AndroidModuleBase) filesToInstall() []string {
217 return a.installFiles
218}
219
220func (p *AndroidModuleBase) NoAddressSanitizer() bool {
221 return p.noAddressSanitizer
222}
223
224func (p *AndroidModuleBase) resourceDirs() []string {
225 return p.commonProperties.ResourceDirs
226}
227
228func (a *AndroidModuleBase) generateModuleTarget(ctx blueprint.ModuleContext) {
229 if a != ctx.FinalModule().(AndroidModule).base() {
230 return
231 }
232
233 allInstalledFiles := []string{}
Colin Cross9454bfa2015-03-17 13:24:18 -0700234 allCheckbuildFiles := []string{}
Colin Cross3f40fa42015-01-30 17:27:36 -0800235 ctx.VisitAllModuleVariants(func(module blueprint.Module) {
236 if androidModule, ok := module.(AndroidModule); ok {
237 files := androidModule.base().installFiles
238 allInstalledFiles = append(allInstalledFiles, files...)
Colin Cross9454bfa2015-03-17 13:24:18 -0700239 files = androidModule.base().checkbuildFiles
240 allCheckbuildFiles = append(allCheckbuildFiles, files...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800241 }
242 })
243
Colin Cross9454bfa2015-03-17 13:24:18 -0700244 deps := []string{}
245
Colin Cross3f40fa42015-01-30 17:27:36 -0800246 if len(allInstalledFiles) > 0 {
Colin Cross9454bfa2015-03-17 13:24:18 -0700247 name := ctx.ModuleName() + "-install"
Colin Cross3f40fa42015-01-30 17:27:36 -0800248 ctx.Build(pctx, blueprint.BuildParams{
Colin Cross9454bfa2015-03-17 13:24:18 -0700249 Rule: blueprint.Phony,
250 Outputs: []string{name},
251 Implicits: allInstalledFiles,
252 })
253 deps = append(deps, name)
254 }
255
256 if len(allCheckbuildFiles) > 0 {
257 name := ctx.ModuleName() + "-checkbuild"
258 ctx.Build(pctx, blueprint.BuildParams{
259 Rule: blueprint.Phony,
260 Outputs: []string{name},
261 Implicits: allCheckbuildFiles,
262 Optional: true,
263 })
264 deps = append(deps, name)
265 }
266
267 if len(deps) > 0 {
268 ctx.Build(pctx, blueprint.BuildParams{
269 Rule: blueprint.Phony,
270 Outputs: []string{ctx.ModuleName()},
271 Implicits: deps,
272 Optional: true,
Colin Cross3f40fa42015-01-30 17:27:36 -0800273 })
274 }
275}
276
277func (a *AndroidModuleBase) DynamicDependencies(ctx blueprint.DynamicDependerModuleContext) []string {
278 actx := &androidDynamicDependerContext{
279 DynamicDependerModuleContext: ctx,
280 module: a,
281 }
282
283 if dynamic, ok := a.module.(AndroidDynamicDepender); ok {
284 return dynamic.AndroidDynamicDependencies(actx)
285 }
286
287 return nil
288}
289
290func (a *AndroidModuleBase) GenerateBuildActions(ctx blueprint.ModuleContext) {
291 androidCtx := &androidModuleContext{
292 ModuleContext: ctx,
293 installDeps: a.computeInstallDeps(ctx),
294 installFiles: a.installFiles,
295 arch: a.commonProperties.CompileArch,
296 }
297
298 if a.commonProperties.Disabled {
299 return
300 }
301
302 a.module.GenerateAndroidBuildActions(androidCtx)
303 if ctx.Failed() {
304 return
305 }
306
307 a.generateModuleTarget(ctx)
308 if ctx.Failed() {
309 return
310 }
Colin Cross9454bfa2015-03-17 13:24:18 -0700311
312 a.installFiles = append(a.installFiles, androidCtx.installFiles...)
313 a.checkbuildFiles = append(a.checkbuildFiles, androidCtx.checkbuildFiles...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800314}
315
316type androidModuleContext struct {
317 blueprint.ModuleContext
318 arch Arch
319 installDeps []string
320 installFiles []string
321 checkbuildFiles []string
322}
323
324func (a *androidModuleContext) Build(pctx *blueprint.PackageContext, params blueprint.BuildParams) {
325 params.Optional = true
326 a.ModuleContext.Build(pctx, params)
327}
328
329func (a *androidModuleContext) Arch() Arch {
330 return a.arch
331}
332
333func (a *androidModuleContext) InstallFile(installPath, srcPath string) {
334 var fullInstallPath string
335 if a.arch.HostOrDevice.Device() {
336 // TODO: replace unset with a device name once we have device targeting
337 fullInstallPath = filepath.Join("out/target/product/unset/system", installPath,
338 filepath.Base(srcPath))
339 } else {
340 // TODO: replace unset with a host name
341 fullInstallPath = filepath.Join("out/host/unset/", installPath, filepath.Base(srcPath))
342 }
343
344 a.ModuleContext.Build(pctx, blueprint.BuildParams{
345 Rule: Cp,
346 Outputs: []string{fullInstallPath},
347 Inputs: []string{srcPath},
348 OrderOnly: a.installDeps,
349 })
350
351 a.installFiles = append(a.installFiles, fullInstallPath)
Colin Cross3f40fa42015-01-30 17:27:36 -0800352}
353
354func (a *androidModuleContext) CheckbuildFile(srcPath string) {
355 a.checkbuildFiles = append(a.checkbuildFiles, srcPath)
356}
357
358type androidDynamicDependerContext struct {
359 blueprint.DynamicDependerModuleContext
360 module *AndroidModuleBase
361}
362
363type fileInstaller interface {
364 filesToInstall() []string
365}
366
367func isFileInstaller(m blueprint.Module) bool {
368 _, ok := m.(fileInstaller)
369 return ok
370}
371
372func isAndroidModule(m blueprint.Module) bool {
373 _, ok := m.(AndroidModule)
374 return ok
375}