blob: 551824d6c4d14034ddfdea966f2085492edddf43 [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
Colin Cross635c3b02016-05-18 15:37:25 -070015package android
Colin Cross3f40fa42015-01-30 17:27:36 -080016
17import (
Colin Cross6ff51382015-12-17 16:39:19 -080018 "fmt"
Alex Lightfb4353d2019-01-17 13:57:45 -080019 "path"
Colin Cross3f40fa42015-01-30 17:27:36 -080020 "path/filepath"
Colin Cross0875c522017-11-28 17:34:01 -080021 "sort"
Colin Cross6ff51382015-12-17 16:39:19 -080022 "strings"
Colin Crossaabf6792017-11-29 00:27:14 -080023 "text/scanner"
Colin Crossf6566ed2015-03-24 11:13:38 -070024
25 "github.com/google/blueprint"
Colin Cross7f19f372016-11-01 11:10:25 -070026 "github.com/google/blueprint/pathtools"
Colin Crossfe4bc362018-09-12 10:02:13 -070027 "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 Crossae887032017-10-23 17:16:14 -070039type BuildParams struct {
Dan Willemsen9f3c5742016-11-03 14:28:31 -070040 Rule blueprint.Rule
Colin Cross33bfb0a2016-11-21 17:23:08 -080041 Deps blueprint.Deps
42 Depfile WritablePath
Colin Cross67a5c132017-05-09 13:45:28 -070043 Description string
Dan Willemsen9f3c5742016-11-03 14:28:31 -070044 Output WritablePath
45 Outputs WritablePaths
46 ImplicitOutput WritablePath
47 ImplicitOutputs WritablePaths
48 Input Path
49 Inputs Paths
50 Implicit Path
51 Implicits Paths
52 OrderOnly Paths
53 Default bool
54 Args map[string]string
Dan Willemsen34cc69e2015-09-23 15:26:20 -070055}
56
Colin Crossae887032017-10-23 17:16:14 -070057type ModuleBuildParams BuildParams
58
Colin Crossf6566ed2015-03-24 11:13:38 -070059type androidBaseContext interface {
Colin Crossa1ad8d12016-06-01 17:09:44 -070060 Target() Target
Colin Cross8b74d172016-09-13 09:59:14 -070061 TargetPrimary() bool
Colin Crossee0bc3b2018-10-02 22:01:37 -070062 MultiTargets() []Target
Colin Crossf6566ed2015-03-24 11:13:38 -070063 Arch() Arch
Colin Crossa1ad8d12016-06-01 17:09:44 -070064 Os() OsType
Colin Crossf6566ed2015-03-24 11:13:38 -070065 Host() bool
66 Device() bool
Colin Cross0af4b842015-04-30 16:36:18 -070067 Darwin() bool
Doug Horn21b94272019-01-16 12:06:11 -080068 Fuchsia() bool
Colin Cross3edeee12017-04-04 12:59:48 -070069 Windows() bool
Colin Crossf6566ed2015-03-24 11:13:38 -070070 Debug() bool
Colin Cross1e7d3702016-08-24 15:25:47 -070071 PrimaryArch() bool
Jiyong Park2db76922017-11-08 16:03:48 +090072 Platform() bool
73 DeviceSpecific() bool
74 SocSpecific() bool
75 ProductSpecific() bool
Dario Frenifd05a742018-05-29 13:28:54 +010076 ProductServicesSpecific() bool
Colin Cross1332b002015-04-07 17:11:30 -070077 AConfig() Config
Colin Cross9272ade2016-08-17 15:24:12 -070078 DeviceConfig() DeviceConfig
Colin Crossf6566ed2015-03-24 11:13:38 -070079}
80
Colin Cross635c3b02016-05-18 15:37:25 -070081type BaseContext interface {
Colin Crossaabf6792017-11-29 00:27:14 -080082 BaseModuleContext
Colin Crossf6566ed2015-03-24 11:13:38 -070083 androidBaseContext
84}
85
Colin Crossaabf6792017-11-29 00:27:14 -080086// BaseModuleContext is the same as blueprint.BaseModuleContext except that Config() returns
87// a Config instead of an interface{}.
88type BaseModuleContext interface {
89 ModuleName() string
90 ModuleDir() string
91 Config() Config
92
93 ContainsProperty(name string) bool
94 Errorf(pos scanner.Position, fmt string, args ...interface{})
95 ModuleErrorf(fmt string, args ...interface{})
96 PropertyErrorf(property, fmt string, args ...interface{})
97 Failed() bool
98
99 // GlobWithDeps returns a list of files that match the specified pattern but do not match any
100 // of the patterns in excludes. It also adds efficient dependencies to rerun the primary
101 // builder whenever a file matching the pattern as added or removed, without rerunning if a
102 // file that does not match the pattern is added to a searched directory.
103 GlobWithDeps(pattern string, excludes []string) ([]string, error)
104
105 Fs() pathtools.FileSystem
106 AddNinjaFileDeps(deps ...string)
107}
108
Colin Cross635c3b02016-05-18 15:37:25 -0700109type ModuleContext interface {
Colin Crossf6566ed2015-03-24 11:13:38 -0700110 androidBaseContext
Colin Crossaabf6792017-11-29 00:27:14 -0800111 BaseModuleContext
Colin Cross3f40fa42015-01-30 17:27:36 -0800112
Colin Crossae887032017-10-23 17:16:14 -0700113 // Deprecated: use ModuleContext.Build instead.
Colin Cross0875c522017-11-28 17:34:01 -0800114 ModuleBuild(pctx PackageContext, params ModuleBuildParams)
Colin Cross8f101b42015-06-17 15:09:06 -0700115
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700116 ExpandSources(srcFiles, excludes []string) Paths
Colin Cross366938f2017-12-11 16:29:02 -0800117 ExpandSource(srcFile, prop string) Path
Colin Cross2383f3b2018-02-06 14:40:13 -0800118 ExpandOptionalSource(srcFile *string, prop string) OptionalPath
Colin Crossfaeb7aa2017-02-01 14:12:44 -0800119 ExpandSourcesSubDir(srcFiles, excludes []string, subDir string) Paths
Colin Cross7f19f372016-11-01 11:10:25 -0700120 Glob(globPattern string, excludes []string) Paths
Nan Zhang581fd212018-01-10 16:06:12 -0800121 GlobFiles(globPattern string, excludes []string) Paths
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700122
Colin Cross5c517922017-08-31 12:29:17 -0700123 InstallExecutable(installPath OutputPath, name string, srcPath Path, deps ...Path) OutputPath
124 InstallFile(installPath OutputPath, name string, srcPath Path, deps ...Path) OutputPath
Colin Cross3854a602016-01-11 12:49:11 -0800125 InstallSymlink(installPath OutputPath, name string, srcPath OutputPath) OutputPath
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700126 CheckbuildFile(srcPath Path)
Dan Willemsen6553f5e2016-03-10 18:14:25 -0800127
128 AddMissingDependencies(deps []string)
Colin Cross8d8f8e22016-08-03 11:57:50 -0700129
Colin Cross8d8f8e22016-08-03 11:57:50 -0700130 InstallInData() bool
Vishwath Mohan1dd88392017-03-29 22:00:18 -0700131 InstallInSanitizerDir() bool
Jiyong Parkf9332f12018-02-01 00:54:12 +0900132 InstallInRecovery() bool
Nan Zhang6d34b302017-02-04 17:47:46 -0800133
134 RequiredModuleNames() []string
Colin Cross3f68a132017-10-23 17:10:29 -0700135
136 // android.ModuleContext methods
137 // These are duplicated instead of embedded so that can eventually be wrapped to take an
138 // android.Module instead of a blueprint.Module
139 OtherModuleName(m blueprint.Module) string
140 OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{})
141 OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag
142
143 GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module
144 GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag)
145
146 ModuleSubDir() string
147
Colin Cross35143d02017-11-16 00:11:20 -0800148 VisitDirectDepsBlueprint(visit func(blueprint.Module))
Colin Crossd11fcda2017-10-23 17:59:01 -0700149 VisitDirectDeps(visit func(Module))
Colin Crossee6143c2017-12-30 17:54:27 -0800150 VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module))
Colin Crossd11fcda2017-10-23 17:59:01 -0700151 VisitDirectDepsIf(pred func(Module) bool, visit func(Module))
Colin Cross6b753602018-06-21 13:03:07 -0700152 // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
Colin Crossd11fcda2017-10-23 17:59:01 -0700153 VisitDepsDepthFirst(visit func(Module))
Colin Cross6b753602018-06-21 13:03:07 -0700154 // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
Colin Crossd11fcda2017-10-23 17:59:01 -0700155 VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module))
156 WalkDeps(visit func(Module, Module) bool)
Colin Cross3f68a132017-10-23 17:10:29 -0700157
Colin Cross0875c522017-11-28 17:34:01 -0800158 Variable(pctx PackageContext, name, value string)
159 Rule(pctx PackageContext, name string, params blueprint.RuleParams, argNames ...string) blueprint.Rule
Colin Crossae887032017-10-23 17:16:14 -0700160 // Similar to blueprint.ModuleContext.Build, but takes Paths instead of []string,
161 // and performs more verification.
Colin Cross0875c522017-11-28 17:34:01 -0800162 Build(pctx PackageContext, params BuildParams)
Colin Cross3f68a132017-10-23 17:10:29 -0700163
Colin Cross0875c522017-11-28 17:34:01 -0800164 PrimaryModule() Module
165 FinalModule() Module
166 VisitAllModuleVariants(visit func(Module))
Colin Cross3f68a132017-10-23 17:10:29 -0700167
168 GetMissingDependencies() []string
Jeff Gaston088e29e2017-11-29 16:47:17 -0800169 Namespace() blueprint.Namespace
Colin Cross3f40fa42015-01-30 17:27:36 -0800170}
171
Colin Cross635c3b02016-05-18 15:37:25 -0700172type Module interface {
Colin Cross3f40fa42015-01-30 17:27:36 -0800173 blueprint.Module
174
Jeff Gastonaf3cc2d2017-09-27 17:01:44 -0700175 // GenerateAndroidBuildActions is analogous to Blueprints' GenerateBuildActions,
176 // but GenerateAndroidBuildActions also has access to Android-specific information.
177 // For more information, see Module.GenerateBuildActions within Blueprint's module_ctx.go
Colin Cross635c3b02016-05-18 15:37:25 -0700178 GenerateAndroidBuildActions(ModuleContext)
Jeff Gastonaf3cc2d2017-09-27 17:01:44 -0700179
Colin Cross1e676be2016-10-12 14:38:15 -0700180 DepsMutator(BottomUpMutatorContext)
Colin Cross3f40fa42015-01-30 17:27:36 -0800181
Colin Cross635c3b02016-05-18 15:37:25 -0700182 base() *ModuleBase
Dan Willemsen0effe062015-11-30 16:06:01 -0800183 Enabled() bool
Colin Crossa1ad8d12016-06-01 17:09:44 -0700184 Target() Target
Dan Willemsen782a2d12015-12-21 14:55:28 -0800185 InstallInData() bool
Vishwath Mohan1dd88392017-03-29 22:00:18 -0700186 InstallInSanitizerDir() bool
Jiyong Parkf9332f12018-02-01 00:54:12 +0900187 InstallInRecovery() bool
Colin Crossa2f296f2016-11-29 15:16:18 -0800188 SkipInstall()
Jiyong Park374510b2018-03-19 18:23:01 +0900189 ExportedToMake() bool
Colin Cross36242852017-06-23 15:06:31 -0700190
191 AddProperties(props ...interface{})
192 GetProperties() []interface{}
Colin Crosscec81712017-07-13 14:43:27 -0700193
Colin Crossae887032017-10-23 17:16:14 -0700194 BuildParamsForTests() []BuildParams
Jaewoong Jung38e4fb22018-12-12 09:01:34 -0800195 VariablesForTests() map[string]string
Colin Cross3f40fa42015-01-30 17:27:36 -0800196}
197
Colin Crossfc754582016-05-17 16:34:16 -0700198type nameProperties struct {
199 // The name of the module. Must be unique across all modules.
Nan Zhang0007d812017-11-07 10:57:05 -0800200 Name *string
Colin Crossfc754582016-05-17 16:34:16 -0700201}
202
203type commonProperties struct {
Dan Willemsen0effe062015-11-30 16:06:01 -0800204 // emit build rules for this module
205 Enabled *bool `android:"arch_variant"`
Colin Cross3f40fa42015-01-30 17:27:36 -0800206
Colin Cross7d5136f2015-05-11 13:39:40 -0700207 // control whether this module compiles for 32-bit, 64-bit, or both. Possible values
Colin Cross3f40fa42015-01-30 17:27:36 -0800208 // are "32" (compile for 32-bit only), "64" (compile for 64-bit only), "both" (compile for both
209 // architectures), or "first" (compile for 64-bit on a 64-bit platform, and 32-bit on a 32-bit
210 // platform
Colin Cross7d716ba2017-11-01 10:38:29 -0700211 Compile_multilib *string `android:"arch_variant"`
Colin Cross69617d32016-09-06 10:39:07 -0700212
213 Target struct {
214 Host struct {
Colin Cross7d716ba2017-11-01 10:38:29 -0700215 Compile_multilib *string
Colin Cross69617d32016-09-06 10:39:07 -0700216 }
217 Android struct {
Colin Cross7d716ba2017-11-01 10:38:29 -0700218 Compile_multilib *string
Colin Cross69617d32016-09-06 10:39:07 -0700219 }
220 }
221
Colin Crossee0bc3b2018-10-02 22:01:37 -0700222 UseTargetVariants bool `blueprint:"mutated"`
223 Default_multilib string `blueprint:"mutated"`
Colin Cross3f40fa42015-01-30 17:27:36 -0800224
Dan Willemsen782a2d12015-12-21 14:55:28 -0800225 // whether this is a proprietary vendor module, and should be installed into /vendor
Colin Cross7d716ba2017-11-01 10:38:29 -0700226 Proprietary *bool
Dan Willemsen782a2d12015-12-21 14:55:28 -0800227
Colin Cross55708f32017-03-20 13:23:34 -0700228 // vendor who owns this module
Dan Willemsenefac4a82017-07-18 19:42:09 -0700229 Owner *string
Colin Cross55708f32017-03-20 13:23:34 -0700230
Jiyong Park2db76922017-11-08 16:03:48 +0900231 // whether this module is specific to an SoC (System-On-a-Chip). When set to true,
232 // it is installed into /vendor (or /system/vendor if vendor partition does not exist).
233 // Use `soc_specific` instead for better meaning.
Colin Cross7d716ba2017-11-01 10:38:29 -0700234 Vendor *bool
Dan Willemsenaa118f92017-04-06 12:49:58 -0700235
Jiyong Park2db76922017-11-08 16:03:48 +0900236 // whether this module is specific to an SoC (System-On-a-Chip). When set to true,
237 // it is installed into /vendor (or /system/vendor if vendor partition does not exist).
238 Soc_specific *bool
239
240 // whether this module is specific to a device, not only for SoC, but also for off-chip
241 // peripherals. When set to true, it is installed into /odm (or /vendor/odm if odm partition
242 // does not exist, or /system/vendor/odm if both odm and vendor partitions do not exist).
243 // This implies `soc_specific:true`.
244 Device_specific *bool
245
246 // whether this module is specific to a software configuration of a product (e.g. country,
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900247 // network operator, etc). When set to true, it is installed into /product (or
248 // /system/product if product partition does not exist).
Jiyong Park2db76922017-11-08 16:03:48 +0900249 Product_specific *bool
250
Dario Frenifd05a742018-05-29 13:28:54 +0100251 // whether this module provides services owned by the OS provider to the core platform. When set
Dario Freni95cf7672018-08-17 00:57:57 +0100252 // to true, it is installed into /product_services (or /system/product_services if
253 // product_services partition does not exist).
254 Product_services_specific *bool
Dario Frenifd05a742018-05-29 13:28:54 +0100255
Jiyong Parkf9332f12018-02-01 00:54:12 +0900256 // Whether this module is installed to recovery partition
257 Recovery *bool
258
Dan Willemsen2277bcb2016-07-25 20:27:39 -0700259 // init.rc files to be installed if this module is installed
260 Init_rc []string
261
Steven Moreland57a23d22018-04-04 15:42:19 -0700262 // VINTF manifest fragments to be installed if this module is installed
263 Vintf_fragments []string
264
Chris Wolfe998306e2016-08-15 14:47:23 -0400265 // names of other modules to install if this module is installed
Colin Crossc602b7d2017-05-05 13:36:36 -0700266 Required []string `android:"arch_variant"`
Chris Wolfe998306e2016-08-15 14:47:23 -0400267
Colin Cross5aac3622017-08-31 15:07:09 -0700268 // relative path to a file to include in the list of notices for the device
269 Notice *string
270
Dan Willemsen569edc52018-11-19 09:33:29 -0800271 Dist struct {
272 // copy the output of this module to the $DIST_DIR when `dist` is specified on the
273 // command line and any of these targets are also on the command line, or otherwise
274 // built
275 Targets []string `android:"arch_variant"`
276
277 // The name of the output artifact. This defaults to the basename of the output of
278 // the module.
279 Dest *string `android:"arch_variant"`
280
281 // The directory within the dist directory to store the artifact. Defaults to the
282 // top level directory ("").
283 Dir *string `android:"arch_variant"`
284
285 // A suffix to add to the artifact file name (before any extension).
286 Suffix *string `android:"arch_variant"`
287 } `android:"arch_variant"`
288
Colin Crossa1ad8d12016-06-01 17:09:44 -0700289 // Set by TargetMutator
Colin Crossee0bc3b2018-10-02 22:01:37 -0700290 CompileTarget Target `blueprint:"mutated"`
291 CompileMultiTargets []Target `blueprint:"mutated"`
292 CompilePrimary bool `blueprint:"mutated"`
Colin Cross3f40fa42015-01-30 17:27:36 -0800293
294 // Set by InitAndroidModule
295 HostOrDeviceSupported HostOrDeviceSupported `blueprint:"mutated"`
Dan Willemsen0b24c742016-10-04 15:13:37 -0700296 ArchSpecific bool `blueprint:"mutated"`
Colin Crossce75d2c2016-10-06 16:12:58 -0700297
298 SkipInstall bool `blueprint:"mutated"`
Jeff Gaston088e29e2017-11-29 16:47:17 -0800299
300 NamespaceExportedToMake bool `blueprint:"mutated"`
Colin Cross3f40fa42015-01-30 17:27:36 -0800301}
302
303type hostAndDeviceProperties struct {
Colin Cross4e81d702018-11-09 10:36:55 -0800304 // If set to true, build a variant of the module for the host. Defaults to false.
305 Host_supported *bool
306
307 // If set to true, build a variant of the module for the device. Defaults to true.
Colin Crossa4190c12016-07-12 13:11:25 -0700308 Device_supported *bool
Colin Cross3f40fa42015-01-30 17:27:36 -0800309}
310
Colin Crossc472d572015-03-17 15:06:21 -0700311type Multilib string
312
313const (
Colin Cross6b4a32d2017-12-05 13:42:45 -0800314 MultilibBoth Multilib = "both"
315 MultilibFirst Multilib = "first"
316 MultilibCommon Multilib = "common"
317 MultilibCommonFirst Multilib = "common_first"
318 MultilibDefault Multilib = ""
Colin Crossc472d572015-03-17 15:06:21 -0700319)
320
Colin Crossa1ad8d12016-06-01 17:09:44 -0700321type HostOrDeviceSupported int
322
323const (
324 _ HostOrDeviceSupported = iota
Dan Albert0981b5c2018-08-02 13:46:35 -0700325
326 // Host and HostCross are built by default. Device is not supported.
Colin Crossa1ad8d12016-06-01 17:09:44 -0700327 HostSupported
Dan Albert0981b5c2018-08-02 13:46:35 -0700328
329 // Host is built by default. HostCross and Device are not supported.
Dan Albertc6345fb2016-10-20 01:36:11 -0700330 HostSupportedNoCross
Dan Albert0981b5c2018-08-02 13:46:35 -0700331
332 // Device is built by default. Host and HostCross are not supported.
Colin Crossa1ad8d12016-06-01 17:09:44 -0700333 DeviceSupported
Dan Albert0981b5c2018-08-02 13:46:35 -0700334
335 // Device is built by default. Host and HostCross are supported.
Colin Crossa1ad8d12016-06-01 17:09:44 -0700336 HostAndDeviceSupported
Dan Albert0981b5c2018-08-02 13:46:35 -0700337
338 // Host, HostCross, and Device are built by default.
Colin Crossa1ad8d12016-06-01 17:09:44 -0700339 HostAndDeviceDefault
Dan Albert0981b5c2018-08-02 13:46:35 -0700340
341 // Nothing is supported. This is not exposed to the user, but used to mark a
342 // host only module as unsupported when the module type is not supported on
343 // the host OS. E.g. benchmarks are supported on Linux but not Darwin.
Dan Willemsen0b24c742016-10-04 15:13:37 -0700344 NeitherHostNorDeviceSupported
Colin Crossa1ad8d12016-06-01 17:09:44 -0700345)
346
Jiyong Park2db76922017-11-08 16:03:48 +0900347type moduleKind int
348
349const (
350 platformModule moduleKind = iota
351 deviceSpecificModule
352 socSpecificModule
353 productSpecificModule
Dario Frenifd05a742018-05-29 13:28:54 +0100354 productServicesSpecificModule
Jiyong Park2db76922017-11-08 16:03:48 +0900355)
356
357func (k moduleKind) String() string {
358 switch k {
359 case platformModule:
360 return "platform"
361 case deviceSpecificModule:
362 return "device-specific"
363 case socSpecificModule:
364 return "soc-specific"
365 case productSpecificModule:
366 return "product-specific"
Dario Frenifd05a742018-05-29 13:28:54 +0100367 case productServicesSpecificModule:
368 return "productservices-specific"
Jiyong Park2db76922017-11-08 16:03:48 +0900369 default:
370 panic(fmt.Errorf("unknown module kind %d", k))
371 }
372}
373
Colin Cross36242852017-06-23 15:06:31 -0700374func InitAndroidModule(m Module) {
Colin Cross3f40fa42015-01-30 17:27:36 -0800375 base := m.base()
376 base.module = m
Colin Cross5049f022015-03-18 13:28:46 -0700377
Colin Cross36242852017-06-23 15:06:31 -0700378 m.AddProperties(
Colin Crossfc754582016-05-17 16:34:16 -0700379 &base.nameProperties,
380 &base.commonProperties,
381 &base.variableProperties)
Pirama Arumuga Nainar955dc492018-04-17 14:58:42 -0700382 base.customizableProperties = m.GetProperties()
Colin Cross5049f022015-03-18 13:28:46 -0700383}
384
Colin Cross36242852017-06-23 15:06:31 -0700385func InitAndroidArchModule(m Module, hod HostOrDeviceSupported, defaultMultilib Multilib) {
386 InitAndroidModule(m)
Colin Cross5049f022015-03-18 13:28:46 -0700387
388 base := m.base()
Colin Cross3f40fa42015-01-30 17:27:36 -0800389 base.commonProperties.HostOrDeviceSupported = hod
Colin Cross69617d32016-09-06 10:39:07 -0700390 base.commonProperties.Default_multilib = string(defaultMultilib)
Dan Willemsen0b24c742016-10-04 15:13:37 -0700391 base.commonProperties.ArchSpecific = true
Colin Crossee0bc3b2018-10-02 22:01:37 -0700392 base.commonProperties.UseTargetVariants = true
Colin Cross3f40fa42015-01-30 17:27:36 -0800393
Dan Willemsen218f6562015-07-08 18:13:11 -0700394 switch hod {
Nan Zhang1a0f09b2017-07-05 10:35:11 -0700395 case HostAndDeviceSupported, HostAndDeviceDefault:
Colin Cross36242852017-06-23 15:06:31 -0700396 m.AddProperties(&base.hostAndDeviceProperties)
Colin Cross3f40fa42015-01-30 17:27:36 -0800397 }
398
Colin Cross36242852017-06-23 15:06:31 -0700399 InitArchModule(m)
Colin Cross3f40fa42015-01-30 17:27:36 -0800400}
401
Colin Crossee0bc3b2018-10-02 22:01:37 -0700402func InitAndroidMultiTargetsArchModule(m Module, hod HostOrDeviceSupported, defaultMultilib Multilib) {
403 InitAndroidArchModule(m, hod, defaultMultilib)
404 m.base().commonProperties.UseTargetVariants = false
405}
406
Nan Zhangb9eeb1d2017-02-02 10:46:07 -0800407// A ModuleBase object contains the properties that are common to all Android
Colin Cross3f40fa42015-01-30 17:27:36 -0800408// modules. It should be included as an anonymous field in every module
409// struct definition. InitAndroidModule should then be called from the module's
410// factory function, and the return values from InitAndroidModule should be
411// returned from the factory function.
412//
Nan Zhangb9eeb1d2017-02-02 10:46:07 -0800413// The ModuleBase type is responsible for implementing the GenerateBuildActions
414// method to support the blueprint.Module interface. This method will then call
415// the module's GenerateAndroidBuildActions method once for each build variant
416// that is to be built. GenerateAndroidBuildActions is passed a
417// AndroidModuleContext rather than the usual blueprint.ModuleContext.
Colin Cross3f40fa42015-01-30 17:27:36 -0800418// AndroidModuleContext exposes extra functionality specific to the Android build
419// system including details about the particular build variant that is to be
420// generated.
421//
422// For example:
423//
424// import (
Nan Zhangb9eeb1d2017-02-02 10:46:07 -0800425// "android/soong/android"
Colin Cross3f40fa42015-01-30 17:27:36 -0800426// )
427//
428// type myModule struct {
Nan Zhangb9eeb1d2017-02-02 10:46:07 -0800429// android.ModuleBase
Colin Cross3f40fa42015-01-30 17:27:36 -0800430// properties struct {
431// MyProperty string
432// }
433// }
434//
Colin Cross36242852017-06-23 15:06:31 -0700435// func NewMyModule() android.Module) {
Colin Cross3f40fa42015-01-30 17:27:36 -0800436// m := &myModule{}
Colin Cross36242852017-06-23 15:06:31 -0700437// m.AddProperties(&m.properties)
438// android.InitAndroidModule(m)
439// return m
Colin Cross3f40fa42015-01-30 17:27:36 -0800440// }
441//
Nan Zhangb9eeb1d2017-02-02 10:46:07 -0800442// func (m *myModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Colin Cross3f40fa42015-01-30 17:27:36 -0800443// // Get the CPU architecture for the current build variant.
444// variantArch := ctx.Arch()
445//
446// // ...
447// }
Colin Cross635c3b02016-05-18 15:37:25 -0700448type ModuleBase struct {
Colin Cross3f40fa42015-01-30 17:27:36 -0800449 // Putting the curiously recurring thing pointing to the thing that contains
450 // the thing pattern to good use.
Colin Cross36242852017-06-23 15:06:31 -0700451 // TODO: remove this
Colin Cross635c3b02016-05-18 15:37:25 -0700452 module Module
Colin Cross3f40fa42015-01-30 17:27:36 -0800453
Colin Crossfc754582016-05-17 16:34:16 -0700454 nameProperties nameProperties
Colin Cross3f40fa42015-01-30 17:27:36 -0800455 commonProperties commonProperties
Colin Cross7f64b6d2015-07-09 13:57:48 -0700456 variableProperties variableProperties
Colin Cross3f40fa42015-01-30 17:27:36 -0800457 hostAndDeviceProperties hostAndDeviceProperties
458 generalProperties []interface{}
Colin Crossc17727d2018-10-24 12:42:09 -0700459 archProperties [][]interface{}
Colin Crossa120ec12016-08-19 16:07:38 -0700460 customizableProperties []interface{}
Colin Cross3f40fa42015-01-30 17:27:36 -0800461
462 noAddressSanitizer bool
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700463 installFiles Paths
464 checkbuildFiles Paths
Jaewoong Jung62707f72018-11-16 13:26:43 -0800465 noticeFile Path
Colin Cross1f8c52b2015-06-16 16:38:17 -0700466
467 // Used by buildTargetSingleton to create checkbuild and per-directory build targets
468 // Only set on the final variant of each module
Colin Cross0875c522017-11-28 17:34:01 -0800469 installTarget WritablePath
470 checkbuildTarget WritablePath
Colin Cross1f8c52b2015-06-16 16:38:17 -0700471 blueprintDir string
Colin Crossa120ec12016-08-19 16:07:38 -0700472
Colin Cross178a5092016-09-13 13:42:32 -0700473 hooks hooks
Colin Cross36242852017-06-23 15:06:31 -0700474
475 registerProps []interface{}
Colin Crosscec81712017-07-13 14:43:27 -0700476
477 // For tests
Colin Crossae887032017-10-23 17:16:14 -0700478 buildParams []BuildParams
Jaewoong Jung38e4fb22018-12-12 09:01:34 -0800479 variables map[string]string
Colin Crossa9d8bee2018-10-02 13:59:46 -0700480
481 prefer32 func(ctx BaseModuleContext, base *ModuleBase, class OsClass) bool
Colin Cross36242852017-06-23 15:06:31 -0700482}
483
484func (a *ModuleBase) AddProperties(props ...interface{}) {
485 a.registerProps = append(a.registerProps, props...)
486}
487
488func (a *ModuleBase) GetProperties() []interface{} {
489 return a.registerProps
Colin Cross3f40fa42015-01-30 17:27:36 -0800490}
491
Colin Crossae887032017-10-23 17:16:14 -0700492func (a *ModuleBase) BuildParamsForTests() []BuildParams {
Colin Crosscec81712017-07-13 14:43:27 -0700493 return a.buildParams
494}
495
Jaewoong Jung38e4fb22018-12-12 09:01:34 -0800496func (a *ModuleBase) VariablesForTests() map[string]string {
497 return a.variables
498}
499
Colin Crossa9d8bee2018-10-02 13:59:46 -0700500func (a *ModuleBase) Prefer32(prefer32 func(ctx BaseModuleContext, base *ModuleBase, class OsClass) bool) {
501 a.prefer32 = prefer32
502}
503
Colin Crossce75d2c2016-10-06 16:12:58 -0700504// Name returns the name of the module. It may be overridden by individual module types, for
505// example prebuilts will prepend prebuilt_ to the name.
Colin Crossfc754582016-05-17 16:34:16 -0700506func (a *ModuleBase) Name() string {
Nan Zhang0007d812017-11-07 10:57:05 -0800507 return String(a.nameProperties.Name)
Colin Crossfc754582016-05-17 16:34:16 -0700508}
509
Colin Crossce75d2c2016-10-06 16:12:58 -0700510// BaseModuleName returns the name of the module as specified in the blueprints file.
511func (a *ModuleBase) BaseModuleName() string {
Nan Zhang0007d812017-11-07 10:57:05 -0800512 return String(a.nameProperties.Name)
Colin Crossce75d2c2016-10-06 16:12:58 -0700513}
514
Colin Cross635c3b02016-05-18 15:37:25 -0700515func (a *ModuleBase) base() *ModuleBase {
Colin Cross3f40fa42015-01-30 17:27:36 -0800516 return a
517}
518
Colin Crossee0bc3b2018-10-02 22:01:37 -0700519func (a *ModuleBase) SetTarget(target Target, multiTargets []Target, primary bool) {
Colin Crossa1ad8d12016-06-01 17:09:44 -0700520 a.commonProperties.CompileTarget = target
Colin Crossee0bc3b2018-10-02 22:01:37 -0700521 a.commonProperties.CompileMultiTargets = multiTargets
Colin Cross8b74d172016-09-13 09:59:14 -0700522 a.commonProperties.CompilePrimary = primary
Colin Crossd3ba0392015-05-07 14:11:29 -0700523}
524
Colin Crossa1ad8d12016-06-01 17:09:44 -0700525func (a *ModuleBase) Target() Target {
526 return a.commonProperties.CompileTarget
Dan Willemsen490fd492015-11-24 17:53:15 -0800527}
528
Colin Cross8b74d172016-09-13 09:59:14 -0700529func (a *ModuleBase) TargetPrimary() bool {
530 return a.commonProperties.CompilePrimary
531}
532
Colin Crossee0bc3b2018-10-02 22:01:37 -0700533func (a *ModuleBase) MultiTargets() []Target {
534 return a.commonProperties.CompileMultiTargets
535}
536
Colin Crossa1ad8d12016-06-01 17:09:44 -0700537func (a *ModuleBase) Os() OsType {
538 return a.Target().Os
Dan Willemsen490fd492015-11-24 17:53:15 -0800539}
540
Colin Cross635c3b02016-05-18 15:37:25 -0700541func (a *ModuleBase) Host() bool {
Colin Crossa1ad8d12016-06-01 17:09:44 -0700542 return a.Os().Class == Host || a.Os().Class == HostCross
Dan Willemsen97750522016-02-09 17:43:51 -0800543}
544
Colin Cross635c3b02016-05-18 15:37:25 -0700545func (a *ModuleBase) Arch() Arch {
Colin Crossa1ad8d12016-06-01 17:09:44 -0700546 return a.Target().Arch
Dan Willemsen97750522016-02-09 17:43:51 -0800547}
548
Dan Willemsen0b24c742016-10-04 15:13:37 -0700549func (a *ModuleBase) ArchSpecific() bool {
550 return a.commonProperties.ArchSpecific
551}
552
Colin Crossa1ad8d12016-06-01 17:09:44 -0700553func (a *ModuleBase) OsClassSupported() []OsClass {
554 switch a.commonProperties.HostOrDeviceSupported {
555 case HostSupported:
Colin Crossa1ad8d12016-06-01 17:09:44 -0700556 return []OsClass{Host, HostCross}
Dan Albertc6345fb2016-10-20 01:36:11 -0700557 case HostSupportedNoCross:
558 return []OsClass{Host}
Colin Crossa1ad8d12016-06-01 17:09:44 -0700559 case DeviceSupported:
560 return []OsClass{Device}
Dan Albert0981b5c2018-08-02 13:46:35 -0700561 case HostAndDeviceSupported, HostAndDeviceDefault:
Colin Crossa1ad8d12016-06-01 17:09:44 -0700562 var supported []OsClass
Dan Albert0981b5c2018-08-02 13:46:35 -0700563 if Bool(a.hostAndDeviceProperties.Host_supported) ||
564 (a.commonProperties.HostOrDeviceSupported == HostAndDeviceDefault &&
565 a.hostAndDeviceProperties.Host_supported == nil) {
Colin Crossa1ad8d12016-06-01 17:09:44 -0700566 supported = append(supported, Host, HostCross)
567 }
Nan Zhang1a0f09b2017-07-05 10:35:11 -0700568 if a.hostAndDeviceProperties.Device_supported == nil ||
569 *a.hostAndDeviceProperties.Device_supported {
Colin Crossa1ad8d12016-06-01 17:09:44 -0700570 supported = append(supported, Device)
571 }
572 return supported
573 default:
574 return nil
575 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800576}
577
Colin Cross635c3b02016-05-18 15:37:25 -0700578func (a *ModuleBase) DeviceSupported() bool {
Colin Cross3f40fa42015-01-30 17:27:36 -0800579 return a.commonProperties.HostOrDeviceSupported == DeviceSupported ||
580 a.commonProperties.HostOrDeviceSupported == HostAndDeviceSupported &&
Nan Zhang1a0f09b2017-07-05 10:35:11 -0700581 (a.hostAndDeviceProperties.Device_supported == nil ||
582 *a.hostAndDeviceProperties.Device_supported)
Colin Cross3f40fa42015-01-30 17:27:36 -0800583}
584
Jiyong Parkc678ad32018-04-10 13:07:10 +0900585func (a *ModuleBase) Platform() bool {
Dario Frenifd05a742018-05-29 13:28:54 +0100586 return !a.DeviceSpecific() && !a.SocSpecific() && !a.ProductSpecific() && !a.ProductServicesSpecific()
Jiyong Parkc678ad32018-04-10 13:07:10 +0900587}
588
589func (a *ModuleBase) DeviceSpecific() bool {
590 return Bool(a.commonProperties.Device_specific)
591}
592
593func (a *ModuleBase) SocSpecific() bool {
594 return Bool(a.commonProperties.Vendor) || Bool(a.commonProperties.Proprietary) || Bool(a.commonProperties.Soc_specific)
595}
596
597func (a *ModuleBase) ProductSpecific() bool {
598 return Bool(a.commonProperties.Product_specific)
599}
600
Dario Frenifd05a742018-05-29 13:28:54 +0100601func (a *ModuleBase) ProductServicesSpecific() bool {
Dario Freni95cf7672018-08-17 00:57:57 +0100602 return Bool(a.commonProperties.Product_services_specific)
Dario Frenifd05a742018-05-29 13:28:54 +0100603}
604
Colin Cross635c3b02016-05-18 15:37:25 -0700605func (a *ModuleBase) Enabled() bool {
Dan Willemsen0effe062015-11-30 16:06:01 -0800606 if a.commonProperties.Enabled == nil {
Dan Willemsen0a37a2a2016-11-13 10:16:05 -0800607 return !a.Os().DefaultDisabled
Dan Willemsen490fd492015-11-24 17:53:15 -0800608 }
Dan Willemsen0effe062015-11-30 16:06:01 -0800609 return *a.commonProperties.Enabled
Colin Cross3f40fa42015-01-30 17:27:36 -0800610}
611
Colin Crossce75d2c2016-10-06 16:12:58 -0700612func (a *ModuleBase) SkipInstall() {
613 a.commonProperties.SkipInstall = true
614}
615
Jiyong Park374510b2018-03-19 18:23:01 +0900616func (a *ModuleBase) ExportedToMake() bool {
617 return a.commonProperties.NamespaceExportedToMake
618}
619
Colin Cross635c3b02016-05-18 15:37:25 -0700620func (a *ModuleBase) computeInstallDeps(
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700621 ctx blueprint.ModuleContext) Paths {
Colin Cross3f40fa42015-01-30 17:27:36 -0800622
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700623 result := Paths{}
Colin Cross6b753602018-06-21 13:03:07 -0700624 // TODO(ccross): we need to use WalkDeps and have some way to know which dependencies require installation
Colin Cross3f40fa42015-01-30 17:27:36 -0800625 ctx.VisitDepsDepthFirstIf(isFileInstaller,
626 func(m blueprint.Module) {
627 fileInstaller := m.(fileInstaller)
628 files := fileInstaller.filesToInstall()
629 result = append(result, files...)
630 })
631
632 return result
633}
634
Colin Cross635c3b02016-05-18 15:37:25 -0700635func (a *ModuleBase) filesToInstall() Paths {
Colin Cross3f40fa42015-01-30 17:27:36 -0800636 return a.installFiles
637}
638
Colin Cross635c3b02016-05-18 15:37:25 -0700639func (p *ModuleBase) NoAddressSanitizer() bool {
Colin Cross3f40fa42015-01-30 17:27:36 -0800640 return p.noAddressSanitizer
641}
642
Colin Cross635c3b02016-05-18 15:37:25 -0700643func (p *ModuleBase) InstallInData() bool {
Dan Willemsen782a2d12015-12-21 14:55:28 -0800644 return false
645}
646
Vishwath Mohan1dd88392017-03-29 22:00:18 -0700647func (p *ModuleBase) InstallInSanitizerDir() bool {
648 return false
649}
650
Jiyong Parkf9332f12018-02-01 00:54:12 +0900651func (p *ModuleBase) InstallInRecovery() bool {
652 return Bool(p.commonProperties.Recovery)
653}
654
Sundong Ahn4fd04bb2018-08-31 18:01:37 +0900655func (a *ModuleBase) Owner() string {
656 return String(a.commonProperties.Owner)
657}
658
Colin Cross0875c522017-11-28 17:34:01 -0800659func (a *ModuleBase) generateModuleTarget(ctx ModuleContext) {
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700660 allInstalledFiles := Paths{}
661 allCheckbuildFiles := Paths{}
Colin Cross0875c522017-11-28 17:34:01 -0800662 ctx.VisitAllModuleVariants(func(module Module) {
663 a := module.base()
Colin Crossc9404352015-03-26 16:10:12 -0700664 allInstalledFiles = append(allInstalledFiles, a.installFiles...)
665 allCheckbuildFiles = append(allCheckbuildFiles, a.checkbuildFiles...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800666 })
667
Colin Cross0875c522017-11-28 17:34:01 -0800668 var deps Paths
Colin Cross9454bfa2015-03-17 13:24:18 -0700669
Jeff Gaston088e29e2017-11-29 16:47:17 -0800670 namespacePrefix := ctx.Namespace().(*Namespace).id
671 if namespacePrefix != "" {
672 namespacePrefix = namespacePrefix + "-"
673 }
674
Colin Cross3f40fa42015-01-30 17:27:36 -0800675 if len(allInstalledFiles) > 0 {
Jeff Gaston088e29e2017-11-29 16:47:17 -0800676 name := PathForPhony(ctx, namespacePrefix+ctx.ModuleName()+"-install")
Colin Cross0875c522017-11-28 17:34:01 -0800677 ctx.Build(pctx, BuildParams{
Colin Cross9454bfa2015-03-17 13:24:18 -0700678 Rule: blueprint.Phony,
Colin Cross0875c522017-11-28 17:34:01 -0800679 Output: name,
680 Implicits: allInstalledFiles,
Colin Crossaabf6792017-11-29 00:27:14 -0800681 Default: !ctx.Config().EmbeddedInMake(),
Colin Cross9454bfa2015-03-17 13:24:18 -0700682 })
683 deps = append(deps, name)
Colin Cross1f8c52b2015-06-16 16:38:17 -0700684 a.installTarget = name
Colin Cross9454bfa2015-03-17 13:24:18 -0700685 }
686
687 if len(allCheckbuildFiles) > 0 {
Jeff Gaston088e29e2017-11-29 16:47:17 -0800688 name := PathForPhony(ctx, namespacePrefix+ctx.ModuleName()+"-checkbuild")
Colin Cross0875c522017-11-28 17:34:01 -0800689 ctx.Build(pctx, BuildParams{
Colin Cross9454bfa2015-03-17 13:24:18 -0700690 Rule: blueprint.Phony,
Colin Cross0875c522017-11-28 17:34:01 -0800691 Output: name,
692 Implicits: allCheckbuildFiles,
Colin Cross9454bfa2015-03-17 13:24:18 -0700693 })
694 deps = append(deps, name)
Colin Cross1f8c52b2015-06-16 16:38:17 -0700695 a.checkbuildTarget = name
Colin Cross9454bfa2015-03-17 13:24:18 -0700696 }
697
698 if len(deps) > 0 {
Dan Willemsen5ba07e82015-12-11 13:51:06 -0800699 suffix := ""
Colin Crossaabf6792017-11-29 00:27:14 -0800700 if ctx.Config().EmbeddedInMake() {
Dan Willemsen5ba07e82015-12-11 13:51:06 -0800701 suffix = "-soong"
702 }
703
Jeff Gaston088e29e2017-11-29 16:47:17 -0800704 name := PathForPhony(ctx, namespacePrefix+ctx.ModuleName()+suffix)
Colin Cross0875c522017-11-28 17:34:01 -0800705 ctx.Build(pctx, BuildParams{
Colin Cross9454bfa2015-03-17 13:24:18 -0700706 Rule: blueprint.Phony,
Jeff Gaston088e29e2017-11-29 16:47:17 -0800707 Outputs: []WritablePath{name},
Colin Cross9454bfa2015-03-17 13:24:18 -0700708 Implicits: deps,
Colin Cross3f40fa42015-01-30 17:27:36 -0800709 })
Colin Cross1f8c52b2015-06-16 16:38:17 -0700710
711 a.blueprintDir = ctx.ModuleDir()
Colin Cross3f40fa42015-01-30 17:27:36 -0800712 }
713}
714
Jiyong Park2db76922017-11-08 16:03:48 +0900715func determineModuleKind(a *ModuleBase, ctx blueprint.BaseModuleContext) moduleKind {
716 var socSpecific = Bool(a.commonProperties.Vendor) || Bool(a.commonProperties.Proprietary) || Bool(a.commonProperties.Soc_specific)
717 var deviceSpecific = Bool(a.commonProperties.Device_specific)
718 var productSpecific = Bool(a.commonProperties.Product_specific)
Dario Freni95cf7672018-08-17 00:57:57 +0100719 var productServicesSpecific = Bool(a.commonProperties.Product_services_specific)
Jiyong Park2db76922017-11-08 16:03:48 +0900720
Dario Frenifd05a742018-05-29 13:28:54 +0100721 msg := "conflicting value set here"
722 if socSpecific && deviceSpecific {
723 ctx.PropertyErrorf("device_specific", "a module cannot be specific to SoC and device at the same time.")
Jiyong Park2db76922017-11-08 16:03:48 +0900724 if Bool(a.commonProperties.Vendor) {
725 ctx.PropertyErrorf("vendor", msg)
726 }
727 if Bool(a.commonProperties.Proprietary) {
728 ctx.PropertyErrorf("proprietary", msg)
729 }
730 if Bool(a.commonProperties.Soc_specific) {
731 ctx.PropertyErrorf("soc_specific", msg)
732 }
733 }
734
Dario Frenifd05a742018-05-29 13:28:54 +0100735 if productSpecific && productServicesSpecific {
736 ctx.PropertyErrorf("product_specific", "a module cannot be specific to product and product_services at the same time.")
737 ctx.PropertyErrorf("product_services_specific", msg)
738 }
739
740 if (socSpecific || deviceSpecific) && (productSpecific || productServicesSpecific) {
741 if productSpecific {
742 ctx.PropertyErrorf("product_specific", "a module cannot be specific to SoC or device and product at the same time.")
743 } else {
744 ctx.PropertyErrorf("product_services_specific", "a module cannot be specific to SoC or device and product_services at the same time.")
745 }
746 if deviceSpecific {
747 ctx.PropertyErrorf("device_specific", msg)
748 } else {
749 if Bool(a.commonProperties.Vendor) {
750 ctx.PropertyErrorf("vendor", msg)
751 }
752 if Bool(a.commonProperties.Proprietary) {
753 ctx.PropertyErrorf("proprietary", msg)
754 }
755 if Bool(a.commonProperties.Soc_specific) {
756 ctx.PropertyErrorf("soc_specific", msg)
757 }
758 }
759 }
760
Jiyong Park2db76922017-11-08 16:03:48 +0900761 if productSpecific {
762 return productSpecificModule
Dario Frenifd05a742018-05-29 13:28:54 +0100763 } else if productServicesSpecific {
764 return productServicesSpecificModule
Jiyong Park2db76922017-11-08 16:03:48 +0900765 } else if deviceSpecific {
766 return deviceSpecificModule
767 } else if socSpecific {
768 return socSpecificModule
769 } else {
770 return platformModule
771 }
772}
773
Colin Cross635c3b02016-05-18 15:37:25 -0700774func (a *ModuleBase) androidBaseContextFactory(ctx blueprint.BaseModuleContext) androidBaseContextImpl {
Colin Cross6362e272015-10-29 15:25:03 -0700775 return androidBaseContextImpl{
Colin Cross8b74d172016-09-13 09:59:14 -0700776 target: a.commonProperties.CompileTarget,
777 targetPrimary: a.commonProperties.CompilePrimary,
Colin Crossee0bc3b2018-10-02 22:01:37 -0700778 multiTargets: a.commonProperties.CompileMultiTargets,
Jiyong Park2db76922017-11-08 16:03:48 +0900779 kind: determineModuleKind(a, ctx),
Colin Cross8b74d172016-09-13 09:59:14 -0700780 config: ctx.Config().(Config),
Colin Cross3f40fa42015-01-30 17:27:36 -0800781 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800782}
783
Colin Cross0875c522017-11-28 17:34:01 -0800784func (a *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) {
785 ctx := &androidModuleContext{
Colin Cross8d8f8e22016-08-03 11:57:50 -0700786 module: a.module,
Colin Cross0875c522017-11-28 17:34:01 -0800787 ModuleContext: blueprintCtx,
788 androidBaseContextImpl: a.androidBaseContextFactory(blueprintCtx),
789 installDeps: a.computeInstallDeps(blueprintCtx),
Colin Cross6362e272015-10-29 15:25:03 -0700790 installFiles: a.installFiles,
Colin Cross0875c522017-11-28 17:34:01 -0800791 missingDeps: blueprintCtx.GetMissingDependencies(),
Jaewoong Jung38e4fb22018-12-12 09:01:34 -0800792 variables: make(map[string]string),
Colin Cross3f40fa42015-01-30 17:27:36 -0800793 }
794
Colin Cross67a5c132017-05-09 13:45:28 -0700795 desc := "//" + ctx.ModuleDir() + ":" + ctx.ModuleName() + " "
796 var suffix []string
Colin Cross0875c522017-11-28 17:34:01 -0800797 if ctx.Os().Class != Device && ctx.Os().Class != Generic {
798 suffix = append(suffix, ctx.Os().String())
Colin Cross67a5c132017-05-09 13:45:28 -0700799 }
Colin Cross0875c522017-11-28 17:34:01 -0800800 if !ctx.PrimaryArch() {
801 suffix = append(suffix, ctx.Arch().ArchType.String())
Colin Cross67a5c132017-05-09 13:45:28 -0700802 }
803
804 ctx.Variable(pctx, "moduleDesc", desc)
805
806 s := ""
807 if len(suffix) > 0 {
808 s = " [" + strings.Join(suffix, " ") + "]"
809 }
810 ctx.Variable(pctx, "moduleDescSuffix", s)
811
Dan Willemsen569edc52018-11-19 09:33:29 -0800812 // Some common property checks for properties that will be used later in androidmk.go
813 if a.commonProperties.Dist.Dest != nil {
814 _, err := validateSafePath(*a.commonProperties.Dist.Dest)
815 if err != nil {
816 ctx.PropertyErrorf("dist.dest", "%s", err.Error())
817 }
818 }
819 if a.commonProperties.Dist.Dir != nil {
820 _, err := validateSafePath(*a.commonProperties.Dist.Dir)
821 if err != nil {
822 ctx.PropertyErrorf("dist.dir", "%s", err.Error())
823 }
824 }
825 if a.commonProperties.Dist.Suffix != nil {
826 if strings.Contains(*a.commonProperties.Dist.Suffix, "/") {
827 ctx.PropertyErrorf("dist.suffix", "Suffix may not contain a '/' character.")
828 }
829 }
830
Colin Cross9b1d13d2016-09-19 15:18:11 -0700831 if a.Enabled() {
Colin Cross0875c522017-11-28 17:34:01 -0800832 a.module.GenerateAndroidBuildActions(ctx)
Colin Cross9b1d13d2016-09-19 15:18:11 -0700833 if ctx.Failed() {
834 return
835 }
836
Colin Cross0875c522017-11-28 17:34:01 -0800837 a.installFiles = append(a.installFiles, ctx.installFiles...)
838 a.checkbuildFiles = append(a.checkbuildFiles, ctx.checkbuildFiles...)
Jaewoong Jung62707f72018-11-16 13:26:43 -0800839
840 if a.commonProperties.Notice != nil {
841 // For filegroup-based notice file references.
842 a.noticeFile = ctx.ExpandSource(*a.commonProperties.Notice, "notice")
843 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800844 }
845
Colin Cross9b1d13d2016-09-19 15:18:11 -0700846 if a == ctx.FinalModule().(Module).base() {
847 a.generateModuleTarget(ctx)
848 if ctx.Failed() {
849 return
850 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800851 }
Colin Crosscec81712017-07-13 14:43:27 -0700852
Colin Cross0875c522017-11-28 17:34:01 -0800853 a.buildParams = ctx.buildParams
Jaewoong Jung38e4fb22018-12-12 09:01:34 -0800854 a.variables = ctx.variables
Colin Cross3f40fa42015-01-30 17:27:36 -0800855}
856
Colin Crossf6566ed2015-03-24 11:13:38 -0700857type androidBaseContextImpl struct {
Colin Cross8b74d172016-09-13 09:59:14 -0700858 target Target
Colin Crossee0bc3b2018-10-02 22:01:37 -0700859 multiTargets []Target
Colin Cross8b74d172016-09-13 09:59:14 -0700860 targetPrimary bool
861 debug bool
Jiyong Park2db76922017-11-08 16:03:48 +0900862 kind moduleKind
Colin Cross8b74d172016-09-13 09:59:14 -0700863 config Config
Colin Crossf6566ed2015-03-24 11:13:38 -0700864}
865
Colin Cross3f40fa42015-01-30 17:27:36 -0800866type androidModuleContext struct {
867 blueprint.ModuleContext
Colin Crossf6566ed2015-03-24 11:13:38 -0700868 androidBaseContextImpl
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700869 installDeps Paths
870 installFiles Paths
871 checkbuildFiles Paths
Colin Cross6ff51382015-12-17 16:39:19 -0800872 missingDeps []string
Colin Cross8d8f8e22016-08-03 11:57:50 -0700873 module Module
Colin Crosscec81712017-07-13 14:43:27 -0700874
875 // For tests
Colin Crossae887032017-10-23 17:16:14 -0700876 buildParams []BuildParams
Jaewoong Jung38e4fb22018-12-12 09:01:34 -0800877 variables map[string]string
Colin Cross6ff51382015-12-17 16:39:19 -0800878}
879
Colin Cross67a5c132017-05-09 13:45:28 -0700880func (a *androidModuleContext) ninjaError(desc string, outputs []string, err error) {
Colin Cross0875c522017-11-28 17:34:01 -0800881 a.ModuleContext.Build(pctx.PackageContext, blueprint.BuildParams{
Colin Cross67a5c132017-05-09 13:45:28 -0700882 Rule: ErrorRule,
883 Description: desc,
884 Outputs: outputs,
885 Optional: true,
Colin Cross6ff51382015-12-17 16:39:19 -0800886 Args: map[string]string{
887 "error": err.Error(),
888 },
889 })
890 return
Colin Cross3f40fa42015-01-30 17:27:36 -0800891}
892
Colin Crossaabf6792017-11-29 00:27:14 -0800893func (a *androidModuleContext) Config() Config {
894 return a.ModuleContext.Config().(Config)
895}
896
Colin Cross0875c522017-11-28 17:34:01 -0800897func (a *androidModuleContext) ModuleBuild(pctx PackageContext, params ModuleBuildParams) {
Colin Crossae887032017-10-23 17:16:14 -0700898 a.Build(pctx, BuildParams(params))
Colin Cross3f40fa42015-01-30 17:27:36 -0800899}
900
Colin Cross0875c522017-11-28 17:34:01 -0800901func convertBuildParams(params BuildParams) blueprint.BuildParams {
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700902 bparams := blueprint.BuildParams{
Dan Willemsen9f3c5742016-11-03 14:28:31 -0700903 Rule: params.Rule,
Colin Cross0875c522017-11-28 17:34:01 -0800904 Description: params.Description,
Colin Cross33bfb0a2016-11-21 17:23:08 -0800905 Deps: params.Deps,
Dan Willemsen9f3c5742016-11-03 14:28:31 -0700906 Outputs: params.Outputs.Strings(),
907 ImplicitOutputs: params.ImplicitOutputs.Strings(),
908 Inputs: params.Inputs.Strings(),
909 Implicits: params.Implicits.Strings(),
910 OrderOnly: params.OrderOnly.Strings(),
911 Args: params.Args,
912 Optional: !params.Default,
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700913 }
914
Colin Cross33bfb0a2016-11-21 17:23:08 -0800915 if params.Depfile != nil {
916 bparams.Depfile = params.Depfile.String()
917 }
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700918 if params.Output != nil {
919 bparams.Outputs = append(bparams.Outputs, params.Output.String())
920 }
Dan Willemsen9f3c5742016-11-03 14:28:31 -0700921 if params.ImplicitOutput != nil {
922 bparams.ImplicitOutputs = append(bparams.ImplicitOutputs, params.ImplicitOutput.String())
923 }
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700924 if params.Input != nil {
925 bparams.Inputs = append(bparams.Inputs, params.Input.String())
926 }
927 if params.Implicit != nil {
928 bparams.Implicits = append(bparams.Implicits, params.Implicit.String())
929 }
930
Colin Crossfe4bc362018-09-12 10:02:13 -0700931 bparams.Outputs = proptools.NinjaEscape(bparams.Outputs)
932 bparams.ImplicitOutputs = proptools.NinjaEscape(bparams.ImplicitOutputs)
933 bparams.Inputs = proptools.NinjaEscape(bparams.Inputs)
934 bparams.Implicits = proptools.NinjaEscape(bparams.Implicits)
935 bparams.OrderOnly = proptools.NinjaEscape(bparams.OrderOnly)
936 bparams.Depfile = proptools.NinjaEscape([]string{bparams.Depfile})[0]
937
Colin Cross0875c522017-11-28 17:34:01 -0800938 return bparams
939}
940
941func (a *androidModuleContext) Variable(pctx PackageContext, name, value string) {
Jaewoong Jung38e4fb22018-12-12 09:01:34 -0800942 if a.config.captureBuild {
943 a.variables[name] = value
944 }
945
Colin Cross0875c522017-11-28 17:34:01 -0800946 a.ModuleContext.Variable(pctx.PackageContext, name, value)
947}
948
949func (a *androidModuleContext) Rule(pctx PackageContext, name string, params blueprint.RuleParams,
950 argNames ...string) blueprint.Rule {
951
952 return a.ModuleContext.Rule(pctx.PackageContext, name, params, argNames...)
953}
954
955func (a *androidModuleContext) Build(pctx PackageContext, params BuildParams) {
956 if a.config.captureBuild {
957 a.buildParams = append(a.buildParams, params)
958 }
959
960 bparams := convertBuildParams(params)
961
962 if bparams.Description != "" {
963 bparams.Description = "${moduleDesc}" + params.Description + "${moduleDescSuffix}"
964 }
965
Colin Cross6ff51382015-12-17 16:39:19 -0800966 if a.missingDeps != nil {
Colin Cross67a5c132017-05-09 13:45:28 -0700967 a.ninjaError(bparams.Description, bparams.Outputs,
968 fmt.Errorf("module %s missing dependencies: %s\n",
969 a.ModuleName(), strings.Join(a.missingDeps, ", ")))
Colin Cross6ff51382015-12-17 16:39:19 -0800970 return
971 }
972
Colin Cross0875c522017-11-28 17:34:01 -0800973 a.ModuleContext.Build(pctx.PackageContext, bparams)
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700974}
975
Colin Cross6ff51382015-12-17 16:39:19 -0800976func (a *androidModuleContext) GetMissingDependencies() []string {
977 return a.missingDeps
978}
979
Dan Willemsen6553f5e2016-03-10 18:14:25 -0800980func (a *androidModuleContext) AddMissingDependencies(deps []string) {
981 if deps != nil {
982 a.missingDeps = append(a.missingDeps, deps...)
Colin Crossd11fcda2017-10-23 17:59:01 -0700983 a.missingDeps = FirstUniqueStrings(a.missingDeps)
Dan Willemsen6553f5e2016-03-10 18:14:25 -0800984 }
985}
986
Colin Crossd11fcda2017-10-23 17:59:01 -0700987func (a *androidModuleContext) validateAndroidModule(module blueprint.Module) Module {
988 aModule, _ := module.(Module)
989 if aModule == nil {
990 a.ModuleErrorf("module %q not an android module", a.OtherModuleName(aModule))
991 return nil
992 }
993
994 if !aModule.Enabled() {
Colin Cross6510f912017-11-29 00:27:14 -0800995 if a.Config().AllowMissingDependencies() {
Colin Crossd11fcda2017-10-23 17:59:01 -0700996 a.AddMissingDependencies([]string{a.OtherModuleName(aModule)})
997 } else {
998 a.ModuleErrorf("depends on disabled module %q", a.OtherModuleName(aModule))
999 }
1000 return nil
1001 }
1002
1003 return aModule
1004}
1005
Colin Cross35143d02017-11-16 00:11:20 -08001006func (a *androidModuleContext) VisitDirectDepsBlueprint(visit func(blueprint.Module)) {
1007 a.ModuleContext.VisitDirectDeps(visit)
1008}
1009
Colin Crossd11fcda2017-10-23 17:59:01 -07001010func (a *androidModuleContext) VisitDirectDeps(visit func(Module)) {
1011 a.ModuleContext.VisitDirectDeps(func(module blueprint.Module) {
1012 if aModule := a.validateAndroidModule(module); aModule != nil {
1013 visit(aModule)
1014 }
1015 })
1016}
1017
Colin Crossee6143c2017-12-30 17:54:27 -08001018func (a *androidModuleContext) VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) {
1019 a.ModuleContext.VisitDirectDeps(func(module blueprint.Module) {
1020 if aModule := a.validateAndroidModule(module); aModule != nil {
1021 if a.ModuleContext.OtherModuleDependencyTag(aModule) == tag {
1022 visit(aModule)
1023 }
1024 }
1025 })
1026}
1027
Colin Crossd11fcda2017-10-23 17:59:01 -07001028func (a *androidModuleContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) {
1029 a.ModuleContext.VisitDirectDepsIf(
1030 // pred
1031 func(module blueprint.Module) bool {
1032 if aModule := a.validateAndroidModule(module); aModule != nil {
1033 return pred(aModule)
1034 } else {
1035 return false
1036 }
1037 },
1038 // visit
1039 func(module blueprint.Module) {
1040 visit(module.(Module))
1041 })
1042}
1043
1044func (a *androidModuleContext) VisitDepsDepthFirst(visit func(Module)) {
1045 a.ModuleContext.VisitDepsDepthFirst(func(module blueprint.Module) {
1046 if aModule := a.validateAndroidModule(module); aModule != nil {
1047 visit(aModule)
1048 }
1049 })
1050}
1051
1052func (a *androidModuleContext) VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module)) {
1053 a.ModuleContext.VisitDepsDepthFirstIf(
1054 // pred
1055 func(module blueprint.Module) bool {
1056 if aModule := a.validateAndroidModule(module); aModule != nil {
1057 return pred(aModule)
1058 } else {
1059 return false
1060 }
1061 },
1062 // visit
1063 func(module blueprint.Module) {
1064 visit(module.(Module))
1065 })
1066}
1067
1068func (a *androidModuleContext) WalkDeps(visit func(Module, Module) bool) {
1069 a.ModuleContext.WalkDeps(func(child, parent blueprint.Module) bool {
1070 childAndroidModule := a.validateAndroidModule(child)
1071 parentAndroidModule := a.validateAndroidModule(parent)
1072 if childAndroidModule != nil && parentAndroidModule != nil {
1073 return visit(childAndroidModule, parentAndroidModule)
1074 } else {
1075 return false
1076 }
1077 })
1078}
1079
Colin Cross0875c522017-11-28 17:34:01 -08001080func (a *androidModuleContext) VisitAllModuleVariants(visit func(Module)) {
1081 a.ModuleContext.VisitAllModuleVariants(func(module blueprint.Module) {
1082 visit(module.(Module))
1083 })
1084}
1085
1086func (a *androidModuleContext) PrimaryModule() Module {
1087 return a.ModuleContext.PrimaryModule().(Module)
1088}
1089
1090func (a *androidModuleContext) FinalModule() Module {
1091 return a.ModuleContext.FinalModule().(Module)
1092}
1093
Colin Crossa1ad8d12016-06-01 17:09:44 -07001094func (a *androidBaseContextImpl) Target() Target {
1095 return a.target
1096}
1097
Colin Cross8b74d172016-09-13 09:59:14 -07001098func (a *androidBaseContextImpl) TargetPrimary() bool {
1099 return a.targetPrimary
1100}
1101
Colin Crossee0bc3b2018-10-02 22:01:37 -07001102func (a *androidBaseContextImpl) MultiTargets() []Target {
1103 return a.multiTargets
1104}
1105
Colin Crossf6566ed2015-03-24 11:13:38 -07001106func (a *androidBaseContextImpl) Arch() Arch {
Colin Crossa1ad8d12016-06-01 17:09:44 -07001107 return a.target.Arch
Colin Cross3f40fa42015-01-30 17:27:36 -08001108}
1109
Colin Crossa1ad8d12016-06-01 17:09:44 -07001110func (a *androidBaseContextImpl) Os() OsType {
1111 return a.target.Os
Dan Willemsen490fd492015-11-24 17:53:15 -08001112}
1113
Colin Crossf6566ed2015-03-24 11:13:38 -07001114func (a *androidBaseContextImpl) Host() bool {
Colin Crossa1ad8d12016-06-01 17:09:44 -07001115 return a.target.Os.Class == Host || a.target.Os.Class == HostCross
Colin Crossf6566ed2015-03-24 11:13:38 -07001116}
1117
1118func (a *androidBaseContextImpl) Device() bool {
Colin Crossa1ad8d12016-06-01 17:09:44 -07001119 return a.target.Os.Class == Device
Colin Crossf6566ed2015-03-24 11:13:38 -07001120}
1121
Colin Cross0af4b842015-04-30 16:36:18 -07001122func (a *androidBaseContextImpl) Darwin() bool {
Colin Crossa1ad8d12016-06-01 17:09:44 -07001123 return a.target.Os == Darwin
Colin Cross0af4b842015-04-30 16:36:18 -07001124}
1125
Doug Horn21b94272019-01-16 12:06:11 -08001126func (a *androidBaseContextImpl) Fuchsia() bool {
1127 return a.target.Os == Fuchsia
1128}
1129
Colin Cross3edeee12017-04-04 12:59:48 -07001130func (a *androidBaseContextImpl) Windows() bool {
1131 return a.target.Os == Windows
1132}
1133
Colin Crossf6566ed2015-03-24 11:13:38 -07001134func (a *androidBaseContextImpl) Debug() bool {
1135 return a.debug
1136}
1137
Colin Cross1e7d3702016-08-24 15:25:47 -07001138func (a *androidBaseContextImpl) PrimaryArch() bool {
Dan Willemsen0ef639b2018-10-10 17:02:29 -07001139 if len(a.config.Targets[a.target.Os]) <= 1 {
Colin Cross67a5c132017-05-09 13:45:28 -07001140 return true
1141 }
Dan Willemsen0ef639b2018-10-10 17:02:29 -07001142 return a.target.Arch.ArchType == a.config.Targets[a.target.Os][0].Arch.ArchType
Colin Cross1e7d3702016-08-24 15:25:47 -07001143}
1144
Colin Cross1332b002015-04-07 17:11:30 -07001145func (a *androidBaseContextImpl) AConfig() Config {
1146 return a.config
1147}
1148
Colin Cross9272ade2016-08-17 15:24:12 -07001149func (a *androidBaseContextImpl) DeviceConfig() DeviceConfig {
1150 return DeviceConfig{a.config.deviceConfig}
1151}
1152
Jiyong Park2db76922017-11-08 16:03:48 +09001153func (a *androidBaseContextImpl) Platform() bool {
1154 return a.kind == platformModule
1155}
1156
1157func (a *androidBaseContextImpl) DeviceSpecific() bool {
1158 return a.kind == deviceSpecificModule
1159}
1160
1161func (a *androidBaseContextImpl) SocSpecific() bool {
1162 return a.kind == socSpecificModule
1163}
1164
1165func (a *androidBaseContextImpl) ProductSpecific() bool {
1166 return a.kind == productSpecificModule
Dan Willemsen782a2d12015-12-21 14:55:28 -08001167}
1168
Dario Frenifd05a742018-05-29 13:28:54 +01001169func (a *androidBaseContextImpl) ProductServicesSpecific() bool {
1170 return a.kind == productServicesSpecificModule
1171}
1172
Jiyong Park5baac542018-08-28 09:55:37 +09001173// Makes this module a platform module, i.e. not specific to soc, device,
1174// product, or product_services.
1175func (a *ModuleBase) MakeAsPlatform() {
1176 a.commonProperties.Vendor = boolPtr(false)
1177 a.commonProperties.Proprietary = boolPtr(false)
1178 a.commonProperties.Soc_specific = boolPtr(false)
1179 a.commonProperties.Product_specific = boolPtr(false)
1180 a.commonProperties.Product_services_specific = boolPtr(false)
1181}
1182
Colin Cross8d8f8e22016-08-03 11:57:50 -07001183func (a *androidModuleContext) InstallInData() bool {
1184 return a.module.InstallInData()
Dan Willemsen782a2d12015-12-21 14:55:28 -08001185}
1186
Vishwath Mohan1dd88392017-03-29 22:00:18 -07001187func (a *androidModuleContext) InstallInSanitizerDir() bool {
1188 return a.module.InstallInSanitizerDir()
1189}
1190
Jiyong Parkf9332f12018-02-01 00:54:12 +09001191func (a *androidModuleContext) InstallInRecovery() bool {
1192 return a.module.InstallInRecovery()
1193}
1194
Colin Cross893d8162017-04-26 17:34:03 -07001195func (a *androidModuleContext) skipInstall(fullInstallPath OutputPath) bool {
1196 if a.module.base().commonProperties.SkipInstall {
1197 return true
1198 }
1199
Colin Cross3607f212018-05-07 15:28:05 -07001200 // We'll need a solution for choosing which of modules with the same name in different
1201 // namespaces to install. For now, reuse the list of namespaces exported to Make as the
1202 // list of namespaces to install in a Soong-only build.
1203 if !a.module.base().commonProperties.NamespaceExportedToMake {
1204 return true
1205 }
1206
Colin Cross893d8162017-04-26 17:34:03 -07001207 if a.Device() {
Colin Cross6510f912017-11-29 00:27:14 -08001208 if a.Config().SkipDeviceInstall() {
Colin Cross893d8162017-04-26 17:34:03 -07001209 return true
1210 }
1211
Colin Cross6510f912017-11-29 00:27:14 -08001212 if a.Config().SkipMegaDeviceInstall(fullInstallPath.String()) {
Colin Cross893d8162017-04-26 17:34:03 -07001213 return true
1214 }
1215 }
1216
1217 return false
1218}
1219
Colin Cross5c517922017-08-31 12:29:17 -07001220func (a *androidModuleContext) InstallFile(installPath OutputPath, name string, srcPath Path,
Colin Crossa2344662016-03-24 13:14:12 -07001221 deps ...Path) OutputPath {
Colin Cross5c517922017-08-31 12:29:17 -07001222 return a.installFile(installPath, name, srcPath, Cp, deps)
1223}
1224
1225func (a *androidModuleContext) InstallExecutable(installPath OutputPath, name string, srcPath Path,
1226 deps ...Path) OutputPath {
1227 return a.installFile(installPath, name, srcPath, CpExecutable, deps)
1228}
1229
1230func (a *androidModuleContext) installFile(installPath OutputPath, name string, srcPath Path,
1231 rule blueprint.Rule, deps []Path) OutputPath {
Colin Cross35cec122015-04-02 14:37:16 -07001232
Dan Willemsen782a2d12015-12-21 14:55:28 -08001233 fullInstallPath := installPath.Join(a, name)
Colin Cross178a5092016-09-13 13:42:32 -07001234 a.module.base().hooks.runInstallHooks(a, fullInstallPath, false)
Colin Cross3f40fa42015-01-30 17:27:36 -08001235
Colin Cross893d8162017-04-26 17:34:03 -07001236 if !a.skipInstall(fullInstallPath) {
Colin Crossce75d2c2016-10-06 16:12:58 -07001237
Dan Willemsen322acaf2016-01-12 23:07:05 -08001238 deps = append(deps, a.installDeps...)
Colin Cross35cec122015-04-02 14:37:16 -07001239
Colin Cross89562dc2016-10-03 17:47:19 -07001240 var implicitDeps, orderOnlyDeps Paths
1241
1242 if a.Host() {
1243 // Installed host modules might be used during the build, depend directly on their
1244 // dependencies so their timestamp is updated whenever their dependency is updated
1245 implicitDeps = deps
1246 } else {
1247 orderOnlyDeps = deps
1248 }
1249
Colin Crossae887032017-10-23 17:16:14 -07001250 a.Build(pctx, BuildParams{
Colin Cross5c517922017-08-31 12:29:17 -07001251 Rule: rule,
Colin Cross67a5c132017-05-09 13:45:28 -07001252 Description: "install " + fullInstallPath.Base(),
1253 Output: fullInstallPath,
1254 Input: srcPath,
1255 Implicits: implicitDeps,
1256 OrderOnly: orderOnlyDeps,
Colin Cross6510f912017-11-29 00:27:14 -08001257 Default: !a.Config().EmbeddedInMake(),
Dan Willemsen322acaf2016-01-12 23:07:05 -08001258 })
Colin Cross3f40fa42015-01-30 17:27:36 -08001259
Dan Willemsen322acaf2016-01-12 23:07:05 -08001260 a.installFiles = append(a.installFiles, fullInstallPath)
1261 }
Colin Cross1f8c52b2015-06-16 16:38:17 -07001262 a.checkbuildFiles = append(a.checkbuildFiles, srcPath)
Colin Cross35cec122015-04-02 14:37:16 -07001263 return fullInstallPath
1264}
1265
Colin Cross3854a602016-01-11 12:49:11 -08001266func (a *androidModuleContext) InstallSymlink(installPath OutputPath, name string, srcPath OutputPath) OutputPath {
1267 fullInstallPath := installPath.Join(a, name)
Colin Cross178a5092016-09-13 13:42:32 -07001268 a.module.base().hooks.runInstallHooks(a, fullInstallPath, true)
Colin Cross3854a602016-01-11 12:49:11 -08001269
Colin Cross893d8162017-04-26 17:34:03 -07001270 if !a.skipInstall(fullInstallPath) {
Colin Crossce75d2c2016-10-06 16:12:58 -07001271
Alex Lightfb4353d2019-01-17 13:57:45 -08001272 relPath, err := filepath.Rel(path.Dir(fullInstallPath.String()), srcPath.String())
1273 if err != nil {
1274 panic(fmt.Sprintf("Unable to generate symlink between %q and %q: %s", fullInstallPath.Base(), srcPath.Base(), err))
1275 }
Colin Crossae887032017-10-23 17:16:14 -07001276 a.Build(pctx, BuildParams{
Colin Cross67a5c132017-05-09 13:45:28 -07001277 Rule: Symlink,
1278 Description: "install symlink " + fullInstallPath.Base(),
1279 Output: fullInstallPath,
1280 OrderOnly: Paths{srcPath},
Colin Cross6510f912017-11-29 00:27:14 -08001281 Default: !a.Config().EmbeddedInMake(),
Colin Cross12fc4972016-01-11 12:49:11 -08001282 Args: map[string]string{
Alex Lightfb4353d2019-01-17 13:57:45 -08001283 "fromPath": relPath,
Colin Cross12fc4972016-01-11 12:49:11 -08001284 },
1285 })
Colin Cross3854a602016-01-11 12:49:11 -08001286
Colin Cross12fc4972016-01-11 12:49:11 -08001287 a.installFiles = append(a.installFiles, fullInstallPath)
1288 a.checkbuildFiles = append(a.checkbuildFiles, srcPath)
1289 }
Colin Cross3854a602016-01-11 12:49:11 -08001290 return fullInstallPath
1291}
1292
Dan Willemsen34cc69e2015-09-23 15:26:20 -07001293func (a *androidModuleContext) CheckbuildFile(srcPath Path) {
Colin Cross3f40fa42015-01-30 17:27:36 -08001294 a.checkbuildFiles = append(a.checkbuildFiles, srcPath)
1295}
1296
Colin Cross3f40fa42015-01-30 17:27:36 -08001297type fileInstaller interface {
Dan Willemsen34cc69e2015-09-23 15:26:20 -07001298 filesToInstall() Paths
Colin Cross3f40fa42015-01-30 17:27:36 -08001299}
1300
1301func isFileInstaller(m blueprint.Module) bool {
1302 _, ok := m.(fileInstaller)
1303 return ok
1304}
1305
1306func isAndroidModule(m blueprint.Module) bool {
Colin Cross635c3b02016-05-18 15:37:25 -07001307 _, ok := m.(Module)
Colin Cross3f40fa42015-01-30 17:27:36 -08001308 return ok
1309}
Colin Crossfce53272015-04-08 11:21:40 -07001310
Dan Willemsen2ef08f42015-06-30 18:15:24 -07001311func findStringInSlice(str string, slice []string) int {
1312 for i, s := range slice {
1313 if s == str {
1314 return i
Colin Crossfce53272015-04-08 11:21:40 -07001315 }
1316 }
Dan Willemsen2ef08f42015-06-30 18:15:24 -07001317 return -1
1318}
1319
Colin Cross068e0fe2016-12-13 15:23:47 -08001320func SrcIsModule(s string) string {
1321 if len(s) > 1 && s[0] == ':' {
1322 return s[1:]
1323 }
1324 return ""
1325}
1326
1327type sourceDependencyTag struct {
1328 blueprint.BaseDependencyTag
1329}
1330
1331var SourceDepTag sourceDependencyTag
1332
Colin Cross366938f2017-12-11 16:29:02 -08001333// Adds necessary dependencies to satisfy filegroup or generated sources modules listed in srcFiles
1334// using ":module" syntax, if any.
Colin Cross068e0fe2016-12-13 15:23:47 -08001335func ExtractSourcesDeps(ctx BottomUpMutatorContext, srcFiles []string) {
1336 var deps []string
Nan Zhang2439eb72017-04-10 11:27:50 -07001337 set := make(map[string]bool)
1338
Colin Cross068e0fe2016-12-13 15:23:47 -08001339 for _, s := range srcFiles {
1340 if m := SrcIsModule(s); m != "" {
Nan Zhang2439eb72017-04-10 11:27:50 -07001341 if _, found := set[m]; found {
1342 ctx.ModuleErrorf("found source dependency duplicate: %q!", m)
1343 } else {
1344 set[m] = true
1345 deps = append(deps, m)
1346 }
Colin Cross068e0fe2016-12-13 15:23:47 -08001347 }
1348 }
1349
1350 ctx.AddDependency(ctx.Module(), SourceDepTag, deps...)
1351}
1352
Colin Cross366938f2017-12-11 16:29:02 -08001353// Adds necessary dependencies to satisfy filegroup or generated sources modules specified in s
1354// using ":module" syntax, if any.
1355func ExtractSourceDeps(ctx BottomUpMutatorContext, s *string) {
1356 if s != nil {
1357 if m := SrcIsModule(*s); m != "" {
1358 ctx.AddDependency(ctx.Module(), SourceDepTag, m)
1359 }
1360 }
1361}
1362
Colin Cross068e0fe2016-12-13 15:23:47 -08001363type SourceFileProducer interface {
1364 Srcs() Paths
1365}
1366
1367// Returns a list of paths expanded from globs and modules referenced using ":module" syntax.
Colin Crossfaeb7aa2017-02-01 14:12:44 -08001368// ExtractSourcesDeps must have already been called during the dependency resolution phase.
Dan Willemsen34cc69e2015-09-23 15:26:20 -07001369func (ctx *androidModuleContext) ExpandSources(srcFiles, excludes []string) Paths {
Colin Crossfaeb7aa2017-02-01 14:12:44 -08001370 return ctx.ExpandSourcesSubDir(srcFiles, excludes, "")
1371}
1372
Colin Cross366938f2017-12-11 16:29:02 -08001373// Returns a single path expanded from globs and modules referenced using ":module" syntax.
1374// ExtractSourceDeps must have already been called during the dependency resolution phase.
1375func (ctx *androidModuleContext) ExpandSource(srcFile, prop string) Path {
1376 srcFiles := ctx.ExpandSourcesSubDir([]string{srcFile}, nil, "")
1377 if len(srcFiles) == 1 {
1378 return srcFiles[0]
Jaewoong Jung62707f72018-11-16 13:26:43 -08001379 } else if len(srcFiles) == 0 {
1380 if ctx.Config().AllowMissingDependencies() {
1381 ctx.AddMissingDependencies([]string{srcFile})
1382 } else {
1383 ctx.PropertyErrorf(prop, "%s path %s does not exist", prop, srcFile)
1384 }
1385 return nil
Colin Cross366938f2017-12-11 16:29:02 -08001386 } else {
1387 ctx.PropertyErrorf(prop, "module providing %s must produce exactly one file", prop)
1388 return nil
1389 }
1390}
1391
Colin Cross2383f3b2018-02-06 14:40:13 -08001392// Returns an optional single path expanded from globs and modules referenced using ":module" syntax if
1393// the srcFile is non-nil.
1394// ExtractSourceDeps must have already been called during the dependency resolution phase.
1395func (ctx *androidModuleContext) ExpandOptionalSource(srcFile *string, prop string) OptionalPath {
1396 if srcFile != nil {
1397 return OptionalPathForPath(ctx.ExpandSource(*srcFile, prop))
1398 }
1399 return OptionalPath{}
1400}
1401
Colin Crossfaeb7aa2017-02-01 14:12:44 -08001402func (ctx *androidModuleContext) ExpandSourcesSubDir(srcFiles, excludes []string, subDir string) Paths {
Dan Willemsen34cc69e2015-09-23 15:26:20 -07001403 prefix := PathForModuleSrc(ctx).String()
Colin Crossfaeb7aa2017-02-01 14:12:44 -08001404
Colin Cross461b4452018-02-23 09:22:42 -08001405 var expandedExcludes []string
1406 if excludes != nil {
1407 expandedExcludes = make([]string, 0, len(excludes))
1408 }
Nan Zhang27e284d2018-02-09 21:03:53 +00001409
1410 for _, e := range excludes {
1411 if m := SrcIsModule(e); m != "" {
1412 module := ctx.GetDirectDepWithTag(m, SourceDepTag)
1413 if module == nil {
1414 // Error will have been handled by ExtractSourcesDeps
1415 continue
1416 }
1417 if srcProducer, ok := module.(SourceFileProducer); ok {
1418 expandedExcludes = append(expandedExcludes, srcProducer.Srcs().Strings()...)
1419 } else {
1420 ctx.ModuleErrorf("srcs dependency %q is not a source file producing module", m)
1421 }
1422 } else {
1423 expandedExcludes = append(expandedExcludes, filepath.Join(prefix, e))
Dan Willemsen2ef08f42015-06-30 18:15:24 -07001424 }
Dan Willemsen2ef08f42015-06-30 18:15:24 -07001425 }
Colin Crossfaeb7aa2017-02-01 14:12:44 -08001426 expandedSrcFiles := make(Paths, 0, len(srcFiles))
Colin Cross8f101b42015-06-17 15:09:06 -07001427 for _, s := range srcFiles {
Colin Cross068e0fe2016-12-13 15:23:47 -08001428 if m := SrcIsModule(s); m != "" {
1429 module := ctx.GetDirectDepWithTag(m, SourceDepTag)
Colin Cross0617bb82017-10-24 13:01:18 -07001430 if module == nil {
1431 // Error will have been handled by ExtractSourcesDeps
1432 continue
1433 }
Colin Cross068e0fe2016-12-13 15:23:47 -08001434 if srcProducer, ok := module.(SourceFileProducer); ok {
Nan Zhang27e284d2018-02-09 21:03:53 +00001435 moduleSrcs := srcProducer.Srcs()
1436 for _, e := range expandedExcludes {
1437 for j, ms := range moduleSrcs {
1438 if ms.String() == e {
1439 moduleSrcs = append(moduleSrcs[:j], moduleSrcs[j+1:]...)
1440 }
1441 }
1442 }
1443 expandedSrcFiles = append(expandedSrcFiles, moduleSrcs...)
Colin Cross068e0fe2016-12-13 15:23:47 -08001444 } else {
1445 ctx.ModuleErrorf("srcs dependency %q is not a source file producing module", m)
1446 }
1447 } else if pathtools.IsGlob(s) {
Dan Willemsen540a78c2018-02-26 21:50:08 -08001448 globbedSrcFiles := ctx.GlobFiles(filepath.Join(prefix, s), expandedExcludes)
Colin Cross05a39cb2017-10-09 13:35:19 -07001449 for i, s := range globbedSrcFiles {
1450 globbedSrcFiles[i] = s.(ModuleSrcPath).WithSubDir(ctx, subDir)
Colin Crossfaeb7aa2017-02-01 14:12:44 -08001451 }
Colin Cross05a39cb2017-10-09 13:35:19 -07001452 expandedSrcFiles = append(expandedSrcFiles, globbedSrcFiles...)
Colin Cross8f101b42015-06-17 15:09:06 -07001453 } else {
Nan Zhang27e284d2018-02-09 21:03:53 +00001454 p := PathForModuleSrc(ctx, s).WithSubDir(ctx, subDir)
1455 j := findStringInSlice(p.String(), expandedExcludes)
1456 if j == -1 {
1457 expandedSrcFiles = append(expandedSrcFiles, p)
1458 }
1459
Colin Cross8f101b42015-06-17 15:09:06 -07001460 }
1461 }
Colin Crossfaeb7aa2017-02-01 14:12:44 -08001462 return expandedSrcFiles
Colin Cross8f101b42015-06-17 15:09:06 -07001463}
1464
Nan Zhang6d34b302017-02-04 17:47:46 -08001465func (ctx *androidModuleContext) RequiredModuleNames() []string {
1466 return ctx.module.base().commonProperties.Required
1467}
1468
Colin Cross7f19f372016-11-01 11:10:25 -07001469func (ctx *androidModuleContext) Glob(globPattern string, excludes []string) Paths {
1470 ret, err := ctx.GlobWithDeps(globPattern, excludes)
Colin Cross8f101b42015-06-17 15:09:06 -07001471 if err != nil {
1472 ctx.ModuleErrorf("glob: %s", err.Error())
1473 }
Dan Willemsen540a78c2018-02-26 21:50:08 -08001474 return pathsForModuleSrcFromFullPath(ctx, ret, true)
Colin Crossfce53272015-04-08 11:21:40 -07001475}
Colin Cross1f8c52b2015-06-16 16:38:17 -07001476
Nan Zhang581fd212018-01-10 16:06:12 -08001477func (ctx *androidModuleContext) GlobFiles(globPattern string, excludes []string) Paths {
Dan Willemsen540a78c2018-02-26 21:50:08 -08001478 ret, err := ctx.GlobWithDeps(globPattern, excludes)
Nan Zhang581fd212018-01-10 16:06:12 -08001479 if err != nil {
1480 ctx.ModuleErrorf("glob: %s", err.Error())
1481 }
Dan Willemsen540a78c2018-02-26 21:50:08 -08001482 return pathsForModuleSrcFromFullPath(ctx, ret, false)
Nan Zhang581fd212018-01-10 16:06:12 -08001483}
1484
Colin Cross463a90e2015-06-17 14:20:06 -07001485func init() {
Colin Cross798bfce2016-10-12 14:28:16 -07001486 RegisterSingletonType("buildtarget", BuildTargetSingleton)
Colin Cross463a90e2015-06-17 14:20:06 -07001487}
1488
Colin Cross0875c522017-11-28 17:34:01 -08001489func BuildTargetSingleton() Singleton {
Colin Cross1f8c52b2015-06-16 16:38:17 -07001490 return &buildTargetSingleton{}
1491}
1492
Colin Cross87d8b562017-04-25 10:01:55 -07001493func parentDir(dir string) string {
1494 dir, _ = filepath.Split(dir)
1495 return filepath.Clean(dir)
1496}
1497
Colin Cross1f8c52b2015-06-16 16:38:17 -07001498type buildTargetSingleton struct{}
1499
Colin Cross0875c522017-11-28 17:34:01 -08001500func (c *buildTargetSingleton) GenerateBuildActions(ctx SingletonContext) {
1501 var checkbuildDeps Paths
Colin Cross1f8c52b2015-06-16 16:38:17 -07001502
Colin Cross0875c522017-11-28 17:34:01 -08001503 mmTarget := func(dir string) WritablePath {
1504 return PathForPhony(ctx,
1505 "MODULES-IN-"+strings.Replace(filepath.Clean(dir), "/", "-", -1))
Colin Cross87d8b562017-04-25 10:01:55 -07001506 }
1507
Colin Cross0875c522017-11-28 17:34:01 -08001508 modulesInDir := make(map[string]Paths)
Colin Cross1f8c52b2015-06-16 16:38:17 -07001509
Colin Cross0875c522017-11-28 17:34:01 -08001510 ctx.VisitAllModules(func(module Module) {
1511 blueprintDir := module.base().blueprintDir
1512 installTarget := module.base().installTarget
1513 checkbuildTarget := module.base().checkbuildTarget
Colin Cross1f8c52b2015-06-16 16:38:17 -07001514
Colin Cross0875c522017-11-28 17:34:01 -08001515 if checkbuildTarget != nil {
1516 checkbuildDeps = append(checkbuildDeps, checkbuildTarget)
1517 modulesInDir[blueprintDir] = append(modulesInDir[blueprintDir], checkbuildTarget)
1518 }
Colin Cross1f8c52b2015-06-16 16:38:17 -07001519
Colin Cross0875c522017-11-28 17:34:01 -08001520 if installTarget != nil {
1521 modulesInDir[blueprintDir] = append(modulesInDir[blueprintDir], installTarget)
Colin Cross1f8c52b2015-06-16 16:38:17 -07001522 }
1523 })
1524
Dan Willemsen5ba07e82015-12-11 13:51:06 -08001525 suffix := ""
Colin Crossaabf6792017-11-29 00:27:14 -08001526 if ctx.Config().EmbeddedInMake() {
Dan Willemsen5ba07e82015-12-11 13:51:06 -08001527 suffix = "-soong"
1528 }
1529
Colin Cross1f8c52b2015-06-16 16:38:17 -07001530 // Create a top-level checkbuild target that depends on all modules
Colin Cross0875c522017-11-28 17:34:01 -08001531 ctx.Build(pctx, BuildParams{
Colin Cross1f8c52b2015-06-16 16:38:17 -07001532 Rule: blueprint.Phony,
Colin Cross0875c522017-11-28 17:34:01 -08001533 Output: PathForPhony(ctx, "checkbuild"+suffix),
Colin Cross1f8c52b2015-06-16 16:38:17 -07001534 Implicits: checkbuildDeps,
Colin Cross1f8c52b2015-06-16 16:38:17 -07001535 })
1536
Dan Willemsend2e95fb2017-09-20 14:30:50 -07001537 // Make will generate the MODULES-IN-* targets
Colin Crossaabf6792017-11-29 00:27:14 -08001538 if ctx.Config().EmbeddedInMake() {
Dan Willemsend2e95fb2017-09-20 14:30:50 -07001539 return
1540 }
1541
Colin Cross0875c522017-11-28 17:34:01 -08001542 sortedKeys := func(m map[string]Paths) []string {
1543 s := make([]string, 0, len(m))
1544 for k := range m {
1545 s = append(s, k)
1546 }
1547 sort.Strings(s)
1548 return s
1549 }
1550
Colin Cross87d8b562017-04-25 10:01:55 -07001551 // Ensure ancestor directories are in modulesInDir
1552 dirs := sortedKeys(modulesInDir)
1553 for _, dir := range dirs {
1554 dir := parentDir(dir)
1555 for dir != "." && dir != "/" {
1556 if _, exists := modulesInDir[dir]; exists {
1557 break
1558 }
1559 modulesInDir[dir] = nil
1560 dir = parentDir(dir)
1561 }
1562 }
1563
1564 // Make directories build their direct subdirectories
1565 dirs = sortedKeys(modulesInDir)
1566 for _, dir := range dirs {
1567 p := parentDir(dir)
1568 if p != "." && p != "/" {
1569 modulesInDir[p] = append(modulesInDir[p], mmTarget(dir))
1570 }
1571 }
1572
Dan Willemsend2e95fb2017-09-20 14:30:50 -07001573 // Create a MODULES-IN-<directory> target that depends on all modules in a directory, and
1574 // depends on the MODULES-IN-* targets of all of its subdirectories that contain Android.bp
1575 // files.
Colin Cross1f8c52b2015-06-16 16:38:17 -07001576 for _, dir := range dirs {
Colin Cross0875c522017-11-28 17:34:01 -08001577 ctx.Build(pctx, BuildParams{
Colin Cross1f8c52b2015-06-16 16:38:17 -07001578 Rule: blueprint.Phony,
Colin Cross0875c522017-11-28 17:34:01 -08001579 Output: mmTarget(dir),
Colin Cross87d8b562017-04-25 10:01:55 -07001580 Implicits: modulesInDir[dir],
Dan Willemsen5ba07e82015-12-11 13:51:06 -08001581 // HACK: checkbuild should be an optional build, but force it
1582 // enabled for now in standalone builds
Colin Crossaabf6792017-11-29 00:27:14 -08001583 Default: !ctx.Config().EmbeddedInMake(),
Colin Cross1f8c52b2015-06-16 16:38:17 -07001584 })
1585 }
Dan Willemsen61d88b82017-09-20 17:29:08 -07001586
1587 // Create (host|host-cross|target)-<OS> phony rules to build a reduced checkbuild.
1588 osDeps := map[OsType]Paths{}
Colin Cross0875c522017-11-28 17:34:01 -08001589 ctx.VisitAllModules(func(module Module) {
1590 if module.Enabled() {
1591 os := module.Target().Os
1592 osDeps[os] = append(osDeps[os], module.base().checkbuildFiles...)
Dan Willemsen61d88b82017-09-20 17:29:08 -07001593 }
1594 })
1595
Colin Cross0875c522017-11-28 17:34:01 -08001596 osClass := make(map[string]Paths)
Dan Willemsen61d88b82017-09-20 17:29:08 -07001597 for os, deps := range osDeps {
1598 var className string
1599
1600 switch os.Class {
1601 case Host:
1602 className = "host"
1603 case HostCross:
1604 className = "host-cross"
1605 case Device:
1606 className = "target"
1607 default:
1608 continue
1609 }
1610
Colin Cross0875c522017-11-28 17:34:01 -08001611 name := PathForPhony(ctx, className+"-"+os.Name)
Dan Willemsen61d88b82017-09-20 17:29:08 -07001612 osClass[className] = append(osClass[className], name)
1613
Colin Cross0875c522017-11-28 17:34:01 -08001614 ctx.Build(pctx, BuildParams{
Dan Willemsen61d88b82017-09-20 17:29:08 -07001615 Rule: blueprint.Phony,
Colin Cross0875c522017-11-28 17:34:01 -08001616 Output: name,
1617 Implicits: deps,
Dan Willemsen61d88b82017-09-20 17:29:08 -07001618 })
1619 }
1620
1621 // Wrap those into host|host-cross|target phony rules
1622 osClasses := sortedKeys(osClass)
1623 for _, class := range osClasses {
Colin Cross0875c522017-11-28 17:34:01 -08001624 ctx.Build(pctx, BuildParams{
Dan Willemsen61d88b82017-09-20 17:29:08 -07001625 Rule: blueprint.Phony,
Colin Cross0875c522017-11-28 17:34:01 -08001626 Output: PathForPhony(ctx, class),
Dan Willemsen61d88b82017-09-20 17:29:08 -07001627 Implicits: osClass[class],
Dan Willemsen61d88b82017-09-20 17:29:08 -07001628 })
1629 }
Colin Cross1f8c52b2015-06-16 16:38:17 -07001630}
Colin Crossd779da42015-12-17 18:00:23 -08001631
Brandon Lee5d45c6f2018-08-15 15:35:38 -07001632// Collect information for opening IDE project files in java/jdeps.go.
1633type IDEInfo interface {
1634 IDEInfo(ideInfo *IdeInfo)
1635 BaseModuleName() string
1636}
1637
1638// Extract the base module name from the Import name.
1639// Often the Import name has a prefix "prebuilt_".
1640// Remove the prefix explicitly if needed
1641// until we find a better solution to get the Import name.
1642type IDECustomizedModuleName interface {
1643 IDECustomizedModuleName() string
1644}
1645
1646type IdeInfo struct {
1647 Deps []string `json:"dependencies,omitempty"`
1648 Srcs []string `json:"srcs,omitempty"`
1649 Aidl_include_dirs []string `json:"aidl_include_dirs,omitempty"`
1650 Jarjar_rules []string `json:"jarjar_rules,omitempty"`
1651 Jars []string `json:"jars,omitempty"`
1652 Classes []string `json:"class,omitempty"`
1653 Installed_paths []string `json:"installed,omitempty"`
1654}