blob: 2bf2a8f00ddf8aa4bb17a17f6a97bbda9eb14b03 [file] [log] [blame]
Colin Cross69452e12023-11-15 11:20:53 -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 android
16
17import (
18 "fmt"
Colin Cross69452e12023-11-15 11:20:53 -080019 "path"
20 "path/filepath"
21 "strings"
Cole Faust9a346f62024-01-18 20:12:02 +000022
23 "github.com/google/blueprint"
24 "github.com/google/blueprint/proptools"
Colin Cross69452e12023-11-15 11:20:53 -080025)
26
27// BuildParameters describes the set of potential parameters to build a Ninja rule.
28// In general, these correspond to a Ninja concept.
29type BuildParams struct {
30 // A Ninja Rule that will be written to the Ninja file. This allows factoring out common code
31 // among multiple modules to reduce repetition in the Ninja file of action requirements. A rule
32 // can contain variables that should be provided in Args.
33 Rule blueprint.Rule
34 // Deps represents the depfile format. When using RuleBuilder, this defaults to GCC when depfiles
35 // are used.
36 Deps blueprint.Deps
37 // Depfile is a writeable path that allows correct incremental builds when the inputs have not
38 // been fully specified by the Ninja rule. Ninja supports a subset of the Makefile depfile syntax.
39 Depfile WritablePath
40 // A description of the build action.
41 Description string
42 // Output is an output file of the action. When using this field, references to $out in the Ninja
43 // command will refer to this file.
44 Output WritablePath
45 // Outputs is a slice of output file of the action. When using this field, references to $out in
46 // the Ninja command will refer to these files.
47 Outputs WritablePaths
Colin Cross69452e12023-11-15 11:20:53 -080048 // ImplicitOutput is an output file generated by the action. Note: references to `$out` in the
49 // Ninja command will NOT include references to this file.
50 ImplicitOutput WritablePath
51 // ImplicitOutputs is a slice of output files generated by the action. Note: references to `$out`
52 // in the Ninja command will NOT include references to these files.
53 ImplicitOutputs WritablePaths
54 // Input is an input file to the Ninja action. When using this field, references to $in in the
55 // Ninja command will refer to this file.
56 Input Path
57 // Inputs is a slice of input files to the Ninja action. When using this field, references to $in
58 // in the Ninja command will refer to these files.
59 Inputs Paths
60 // Implicit is an input file to the Ninja action. Note: references to `$in` in the Ninja command
61 // will NOT include references to this file.
62 Implicit Path
63 // Implicits is a slice of input files to the Ninja action. Note: references to `$in` in the Ninja
64 // command will NOT include references to these files.
65 Implicits Paths
66 // OrderOnly are Ninja order-only inputs to the action. When these are out of date, the output is
67 // not rebuilt until they are built, but changes in order-only dependencies alone do not cause the
68 // output to be rebuilt.
69 OrderOnly Paths
70 // Validation is an output path for a validation action. Validation outputs imply lower
71 // non-blocking priority to building non-validation outputs.
72 Validation Path
73 // Validations is a slice of output path for a validation action. Validation outputs imply lower
74 // non-blocking priority to building non-validation outputs.
75 Validations Paths
76 // Whether to skip outputting a default target statement which will be built by Ninja when no
77 // targets are specified on Ninja's command line.
78 Default bool
79 // Args is a key value mapping for replacements of variables within the Rule
80 Args map[string]string
81}
82
83type ModuleBuildParams BuildParams
84
85type ModuleContext interface {
86 BaseModuleContext
87
Colin Cross1496fb12024-09-09 16:44:10 -070088 // BlueprintModuleContext returns the blueprint.ModuleContext that the ModuleContext wraps. It may only be
89 // used by the golang module types that need to call into the bootstrap module types.
90 BlueprintModuleContext() blueprint.ModuleContext
Colin Cross69452e12023-11-15 11:20:53 -080091
92 // Deprecated: use ModuleContext.Build instead.
93 ModuleBuild(pctx PackageContext, params ModuleBuildParams)
94
95 // Returns a list of paths expanded from globs and modules referenced using ":module" syntax. The property must
96 // be tagged with `android:"path" to support automatic source module dependency resolution.
97 //
98 // Deprecated: use PathsForModuleSrc or PathsForModuleSrcExcludes instead.
99 ExpandSources(srcFiles, excludes []string) Paths
100
101 // Returns a single path expanded from globs and modules referenced using ":module" syntax. The property must
102 // be tagged with `android:"path" to support automatic source module dependency resolution.
103 //
104 // Deprecated: use PathForModuleSrc instead.
105 ExpandSource(srcFile, prop string) Path
106
107 ExpandOptionalSource(srcFile *string, prop string) OptionalPath
108
109 // InstallExecutable creates a rule to copy srcPath to name in the installPath directory,
110 // with the given additional dependencies. The file is marked executable after copying.
111 //
Yu Liubad1eef2024-08-21 22:37:35 +0000112 // The installed file can be accessed by InstallFilesInfo.InstallFiles, and the PackagingSpec
113 // for the installed file can be accessed by InstallFilesInfo.PackagingSpecs on this module
114 // or by InstallFilesInfo.TransitivePackagingSpecs on modules that depend on this module through
115 // dependency tags for which IsInstallDepNeeded returns true.
Colin Cross09ad3a62023-11-15 12:29:33 -0800116 InstallExecutable(installPath InstallPath, name string, srcPath Path, deps ...InstallPath) InstallPath
Colin Cross69452e12023-11-15 11:20:53 -0800117
118 // InstallFile creates a rule to copy srcPath to name in the installPath directory,
119 // with the given additional dependencies.
120 //
Yu Liubad1eef2024-08-21 22:37:35 +0000121 // The installed file can be accessed by InstallFilesInfo.InstallFiles, and the PackagingSpec
122 // for the installed file can be accessed by InstallFilesInfo.PackagingSpecs on this module
123 // or by InstallFilesInfo.TransitivePackagingSpecs on modules that depend on this module through
124 // dependency tags for which IsInstallDepNeeded returns true.
Colin Cross09ad3a62023-11-15 12:29:33 -0800125 InstallFile(installPath InstallPath, name string, srcPath Path, deps ...InstallPath) InstallPath
Colin Cross69452e12023-11-15 11:20:53 -0800126
Colin Crossa6182ab2024-08-21 10:47:44 -0700127 // InstallFileWithoutCheckbuild creates a rule to copy srcPath to name in the installPath directory,
128 // with the given additional dependencies, but does not add the file to the list of files to build
129 // during `m checkbuild`.
130 //
131 // The installed file will be returned by FilesToInstall(), and the PackagingSpec for the
132 // installed file will be returned by PackagingSpecs() on this module or by
133 // TransitivePackagingSpecs() on modules that depend on this module through dependency tags
134 // for which IsInstallDepNeeded returns true.
135 InstallFileWithoutCheckbuild(installPath InstallPath, name string, srcPath Path, deps ...InstallPath) InstallPath
136
Colin Cross69452e12023-11-15 11:20:53 -0800137 // InstallFileWithExtraFilesZip creates a rule to copy srcPath to name in the installPath
138 // directory, and also unzip a zip file containing extra files to install into the same
139 // directory.
140 //
Yu Liubad1eef2024-08-21 22:37:35 +0000141 // The installed file can be accessed by InstallFilesInfo.InstallFiles, and the PackagingSpec
142 // for the installed file can be accessed by InstallFilesInfo.PackagingSpecs on this module
143 // or by InstallFilesInfo.TransitivePackagingSpecs on modules that depend on this module through
144 // dependency tags for which IsInstallDepNeeded returns true.
Colin Cross09ad3a62023-11-15 12:29:33 -0800145 InstallFileWithExtraFilesZip(installPath InstallPath, name string, srcPath Path, extraZip Path, deps ...InstallPath) InstallPath
Colin Cross69452e12023-11-15 11:20:53 -0800146
147 // InstallSymlink creates a rule to create a symlink from src srcPath to name in the installPath
148 // directory.
149 //
Yu Liubad1eef2024-08-21 22:37:35 +0000150 // The installed symlink can be accessed by InstallFilesInfo.InstallFiles, and the PackagingSpec
151 // for the installed file can be accessed by InstallFilesInfo.PackagingSpecs on this module
152 // or by InstallFilesInfo.TransitivePackagingSpecs on modules that depend on this module through
153 // dependency tags for which IsInstallDepNeeded returns true.
Colin Cross69452e12023-11-15 11:20:53 -0800154 InstallSymlink(installPath InstallPath, name string, srcPath InstallPath) InstallPath
155
156 // InstallAbsoluteSymlink creates a rule to create an absolute symlink from src srcPath to name
157 // in the installPath directory.
158 //
Yu Liubad1eef2024-08-21 22:37:35 +0000159 // The installed symlink can be accessed by InstallFilesInfo.InstallFiles, and the PackagingSpec
160 // for the installed file can be accessed by InstallFilesInfo.PackagingSpecs on this module
161 // or by InstallFilesInfo.TransitivePackagingSpecs on modules that depend on this module through
162 // dependency tags for which IsInstallDepNeeded returns true.
Colin Cross69452e12023-11-15 11:20:53 -0800163 InstallAbsoluteSymlink(installPath InstallPath, name string, absPath string) InstallPath
164
Colin Cross5c1d5fb2023-11-15 12:39:40 -0800165 // InstallTestData creates rules to install test data (e.g. data files used during a test) into
166 // the installPath directory.
167 //
Yu Liubad1eef2024-08-21 22:37:35 +0000168 // The installed files can be accessed by InstallFilesInfo.InstallFiles, and the PackagingSpec
169 // for the installed files can be accessed by InstallFilesInfo.PackagingSpecs on this module
170 // or by InstallFilesInfo.TransitivePackagingSpecs on modules that depend on this module through
171 // dependency tags for which IsInstallDepNeeded returns true.
Colin Cross5c1d5fb2023-11-15 12:39:40 -0800172 InstallTestData(installPath InstallPath, data []DataPath) InstallPaths
173
Colin Cross69452e12023-11-15 11:20:53 -0800174 // PackageFile creates a PackagingSpec as if InstallFile was called, but without creating
175 // the rule to copy the file. This is useful to define how a module would be packaged
176 // without installing it into the global installation directories.
177 //
Yu Liubad1eef2024-08-21 22:37:35 +0000178 // The created PackagingSpec can be accessed by InstallFilesInfo.PackagingSpecs on this module
179 // or by InstallFilesInfo.TransitivePackagingSpecs on modules that depend on this module through
180 // dependency tags for which IsInstallDepNeeded returns true.
Colin Cross69452e12023-11-15 11:20:53 -0800181 PackageFile(installPath InstallPath, name string, srcPath Path) PackagingSpec
182
Colin Crossa6182ab2024-08-21 10:47:44 -0700183 CheckbuildFile(srcPaths ...Path)
184 UncheckedModule()
Colin Cross69452e12023-11-15 11:20:53 -0800185
186 InstallInData() bool
187 InstallInTestcases() bool
188 InstallInSanitizerDir() bool
189 InstallInRamdisk() bool
190 InstallInVendorRamdisk() bool
191 InstallInDebugRamdisk() bool
192 InstallInRecovery() bool
193 InstallInRoot() bool
Colin Crossea30d852023-11-29 16:00:16 -0800194 InstallInOdm() bool
195 InstallInProduct() bool
Colin Cross69452e12023-11-15 11:20:53 -0800196 InstallInVendor() bool
197 InstallForceOS() (*OsType, *ArchType)
198
Cole Fauste8a87832024-09-11 11:35:46 -0700199 RequiredModuleNames(ctx ConfigurableEvaluatorContext) []string
Colin Cross69452e12023-11-15 11:20:53 -0800200 HostRequiredModuleNames() []string
201 TargetRequiredModuleNames() []string
202
203 ModuleSubDir() string
Colin Cross69452e12023-11-15 11:20:53 -0800204
205 Variable(pctx PackageContext, name, value string)
206 Rule(pctx PackageContext, name string, params blueprint.RuleParams, argNames ...string) blueprint.Rule
207 // Similar to blueprint.ModuleContext.Build, but takes Paths instead of []string,
208 // and performs more verification.
209 Build(pctx PackageContext, params BuildParams)
210 // Phony creates a Make-style phony rule, a rule with no commands that can depend on other
211 // phony rules or real files. Phony can be called on the same name multiple times to add
212 // additional dependencies.
213 Phony(phony string, deps ...Path)
214
215 // GetMissingDependencies returns the list of dependencies that were passed to AddDependencies or related methods,
216 // but do not exist.
217 GetMissingDependencies() []string
218
219 // LicenseMetadataFile returns the path where the license metadata for this module will be
220 // generated.
221 LicenseMetadataFile() Path
Colin Crossd6fd0132023-11-06 13:54:06 -0800222
223 // ModuleInfoJSON returns a pointer to the ModuleInfoJSON struct that can be filled out by
224 // GenerateAndroidBuildActions. If it is called then the struct will be written out and included in
225 // the module-info.json generated by Make, and Make will not generate its own data for this module.
226 ModuleInfoJSON() *ModuleInfoJSON
mrziwange6c85812024-05-22 14:36:09 -0700227
228 // SetOutputFiles stores the outputFiles to outputFiles property, which is used
229 // to set the OutputFilesProvider later.
230 SetOutputFiles(outputFiles Paths, tag string)
Wei Lia1aa2972024-06-21 13:08:51 -0700231
Yu Liu876b7ce2024-08-21 18:20:13 +0000232 GetOutputFiles() OutputFilesInfo
233
Yu Liubad1eef2024-08-21 22:37:35 +0000234 // SetLicenseInstallMap stores the set of dependency module:location mappings for files in an
235 // apex container for use when generation the license metadata file.
236 SetLicenseInstallMap(installMap []string)
237
Wei Lia1aa2972024-06-21 13:08:51 -0700238 // ComplianceMetadataInfo returns a ComplianceMetadataInfo instance for different module types to dump metadata,
239 // which usually happens in GenerateAndroidBuildActions() of a module type.
240 // See android.ModuleBase.complianceMetadataInfo
241 ComplianceMetadataInfo() *ComplianceMetadataInfo
Yu Liu9a993132024-08-27 23:21:06 +0000242
243 // Get the information about the containers this module belongs to.
244 getContainersInfo() ContainersInfo
245 setContainersInfo(info ContainersInfo)
246
247 setAconfigPaths(paths Paths)
Colin Cross69452e12023-11-15 11:20:53 -0800248}
249
250type moduleContext struct {
251 bp blueprint.ModuleContext
252 baseModuleContext
Colin Crossa6182ab2024-08-21 10:47:44 -0700253 packagingSpecs []PackagingSpec
254 installFiles InstallPaths
255 checkbuildFiles Paths
256 checkbuildTarget Path
257 uncheckedModule bool
258 module Module
259 phonies map[string]Paths
Yu Liu876b7ce2024-08-21 18:20:13 +0000260 // outputFiles stores the output of a module by tag and is used to set
261 // the OutputFilesProvider in GenerateBuildActions
262 outputFiles OutputFilesInfo
Colin Cross69452e12023-11-15 11:20:53 -0800263
Yu Liubad1eef2024-08-21 22:37:35 +0000264 TransitiveInstallFiles *DepSet[InstallPath]
265
266 // set of dependency module:location mappings used to populate the license metadata for
267 // apex containers.
268 licenseInstallMap []string
269
Yu Liuec810542024-08-26 18:09:15 +0000270 // The path to the generated license metadata file for the module.
271 licenseMetadataFile WritablePath
272
Yu Liud46e5ae2024-08-15 18:46:17 +0000273 katiInstalls katiInstalls
274 katiSymlinks katiInstalls
Yu Liu82a6d142024-08-27 19:02:29 +0000275 // katiInitRcInstalls and katiVintfInstalls track the install rules created by Soong that are
276 // allowed to have duplicates across modules and variants.
277 katiInitRcInstalls katiInstalls
278 katiVintfInstalls katiInstalls
279 initRcPaths Paths
280 vintfFragmentsPaths Paths
281 installedInitRcPaths InstallPaths
282 installedVintfFragmentsPaths InstallPaths
Colin Cross69452e12023-11-15 11:20:53 -0800283
Colin Cross5c1d5fb2023-11-15 12:39:40 -0800284 testData []DataPath
285
Colin Cross69452e12023-11-15 11:20:53 -0800286 // For tests
287 buildParams []BuildParams
288 ruleParams map[blueprint.Rule]blueprint.RuleParams
289 variables map[string]string
Yu Liu4297ad92024-08-27 19:50:13 +0000290
291 // moduleInfoJSON can be filled out by GenerateAndroidBuildActions to write a JSON file that will
292 // be included in the final module-info.json produced by Make.
293 moduleInfoJSON *ModuleInfoJSON
Yu Liu9a993132024-08-27 23:21:06 +0000294
295 // containersInfo stores the information about the containers and the information of the
296 // apexes the module belongs to.
297 containersInfo ContainersInfo
298
299 // Merged Aconfig files for all transitive deps.
300 aconfigFilePaths Paths
301
302 // complianceMetadataInfo is for different module types to dump metadata.
303 // See android.ModuleContext interface.
304 complianceMetadataInfo *ComplianceMetadataInfo
Colin Cross69452e12023-11-15 11:20:53 -0800305}
306
Cole Faust02987bd2024-03-21 17:58:43 -0700307var _ ModuleContext = &moduleContext{}
308
Colin Cross69452e12023-11-15 11:20:53 -0800309func (m *moduleContext) ninjaError(params BuildParams, err error) (PackageContext, BuildParams) {
310 return pctx, BuildParams{
311 Rule: ErrorRule,
312 Description: params.Description,
313 Output: params.Output,
314 Outputs: params.Outputs,
315 ImplicitOutput: params.ImplicitOutput,
316 ImplicitOutputs: params.ImplicitOutputs,
317 Args: map[string]string{
318 "error": err.Error(),
319 },
320 }
321}
322
323func (m *moduleContext) ModuleBuild(pctx PackageContext, params ModuleBuildParams) {
324 m.Build(pctx, BuildParams(params))
325}
326
Colin Cross69452e12023-11-15 11:20:53 -0800327// Convert build parameters from their concrete Android types into their string representations,
328// and combine the singular and plural fields of the same type (e.g. Output and Outputs).
329func convertBuildParams(params BuildParams) blueprint.BuildParams {
330 bparams := blueprint.BuildParams{
331 Rule: params.Rule,
332 Description: params.Description,
333 Deps: params.Deps,
334 Outputs: params.Outputs.Strings(),
335 ImplicitOutputs: params.ImplicitOutputs.Strings(),
Colin Cross69452e12023-11-15 11:20:53 -0800336 Inputs: params.Inputs.Strings(),
337 Implicits: params.Implicits.Strings(),
338 OrderOnly: params.OrderOnly.Strings(),
339 Validations: params.Validations.Strings(),
340 Args: params.Args,
341 Optional: !params.Default,
342 }
343
344 if params.Depfile != nil {
345 bparams.Depfile = params.Depfile.String()
346 }
347 if params.Output != nil {
348 bparams.Outputs = append(bparams.Outputs, params.Output.String())
349 }
Colin Cross69452e12023-11-15 11:20:53 -0800350 if params.ImplicitOutput != nil {
351 bparams.ImplicitOutputs = append(bparams.ImplicitOutputs, params.ImplicitOutput.String())
352 }
353 if params.Input != nil {
354 bparams.Inputs = append(bparams.Inputs, params.Input.String())
355 }
356 if params.Implicit != nil {
357 bparams.Implicits = append(bparams.Implicits, params.Implicit.String())
358 }
359 if params.Validation != nil {
360 bparams.Validations = append(bparams.Validations, params.Validation.String())
361 }
362
363 bparams.Outputs = proptools.NinjaEscapeList(bparams.Outputs)
364 bparams.ImplicitOutputs = proptools.NinjaEscapeList(bparams.ImplicitOutputs)
Colin Cross69452e12023-11-15 11:20:53 -0800365 bparams.Inputs = proptools.NinjaEscapeList(bparams.Inputs)
366 bparams.Implicits = proptools.NinjaEscapeList(bparams.Implicits)
367 bparams.OrderOnly = proptools.NinjaEscapeList(bparams.OrderOnly)
368 bparams.Validations = proptools.NinjaEscapeList(bparams.Validations)
369 bparams.Depfile = proptools.NinjaEscape(bparams.Depfile)
370
371 return bparams
372}
373
374func (m *moduleContext) Variable(pctx PackageContext, name, value string) {
375 if m.config.captureBuild {
376 m.variables[name] = value
377 }
378
379 m.bp.Variable(pctx.PackageContext, name, value)
380}
381
382func (m *moduleContext) Rule(pctx PackageContext, name string, params blueprint.RuleParams,
383 argNames ...string) blueprint.Rule {
384
385 if m.config.UseRemoteBuild() {
386 if params.Pool == nil {
387 // When USE_GOMA=true or USE_RBE=true are set and the rule is not supported by goma/RBE, restrict
388 // jobs to the local parallelism value
389 params.Pool = localPool
390 } else if params.Pool == remotePool {
391 // remotePool is a fake pool used to identify rule that are supported for remoting. If the rule's
392 // pool is the remotePool, replace with nil so that ninja runs it at NINJA_REMOTE_NUM_JOBS
393 // parallelism.
394 params.Pool = nil
395 }
396 }
397
398 rule := m.bp.Rule(pctx.PackageContext, name, params, argNames...)
399
400 if m.config.captureBuild {
401 m.ruleParams[rule] = params
402 }
403
404 return rule
405}
406
407func (m *moduleContext) Build(pctx PackageContext, params BuildParams) {
408 if params.Description != "" {
409 params.Description = "${moduleDesc}" + params.Description + "${moduleDescSuffix}"
410 }
411
412 if missingDeps := m.GetMissingDependencies(); len(missingDeps) > 0 {
413 pctx, params = m.ninjaError(params, fmt.Errorf("module %s missing dependencies: %s\n",
414 m.ModuleName(), strings.Join(missingDeps, ", ")))
415 }
416
417 if m.config.captureBuild {
418 m.buildParams = append(m.buildParams, params)
419 }
420
421 bparams := convertBuildParams(params)
Colin Cross69452e12023-11-15 11:20:53 -0800422 m.bp.Build(pctx.PackageContext, bparams)
423}
424
425func (m *moduleContext) Phony(name string, deps ...Path) {
Yu Liu54513622024-08-19 20:00:32 +0000426 m.phonies[name] = append(m.phonies[name], deps...)
Colin Cross69452e12023-11-15 11:20:53 -0800427}
428
429func (m *moduleContext) GetMissingDependencies() []string {
430 var missingDeps []string
431 missingDeps = append(missingDeps, m.Module().base().commonProperties.MissingDeps...)
432 missingDeps = append(missingDeps, m.bp.GetMissingDependencies()...)
433 missingDeps = FirstUniqueStrings(missingDeps)
434 return missingDeps
435}
436
437func (m *moduleContext) GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module {
438 module, _ := m.getDirectDepInternal(name, tag)
439 return module
440}
441
442func (m *moduleContext) ModuleSubDir() string {
443 return m.bp.ModuleSubDir()
444}
445
Colin Cross69452e12023-11-15 11:20:53 -0800446func (m *moduleContext) InstallInData() bool {
447 return m.module.InstallInData()
448}
449
450func (m *moduleContext) InstallInTestcases() bool {
451 return m.module.InstallInTestcases()
452}
453
454func (m *moduleContext) InstallInSanitizerDir() bool {
455 return m.module.InstallInSanitizerDir()
456}
457
458func (m *moduleContext) InstallInRamdisk() bool {
459 return m.module.InstallInRamdisk()
460}
461
462func (m *moduleContext) InstallInVendorRamdisk() bool {
463 return m.module.InstallInVendorRamdisk()
464}
465
466func (m *moduleContext) InstallInDebugRamdisk() bool {
467 return m.module.InstallInDebugRamdisk()
468}
469
470func (m *moduleContext) InstallInRecovery() bool {
471 return m.module.InstallInRecovery()
472}
473
474func (m *moduleContext) InstallInRoot() bool {
475 return m.module.InstallInRoot()
476}
477
478func (m *moduleContext) InstallForceOS() (*OsType, *ArchType) {
479 return m.module.InstallForceOS()
480}
481
Colin Crossea30d852023-11-29 16:00:16 -0800482func (m *moduleContext) InstallInOdm() bool {
483 return m.module.InstallInOdm()
484}
485
486func (m *moduleContext) InstallInProduct() bool {
487 return m.module.InstallInProduct()
488}
489
Colin Cross69452e12023-11-15 11:20:53 -0800490func (m *moduleContext) InstallInVendor() bool {
491 return m.module.InstallInVendor()
492}
493
494func (m *moduleContext) skipInstall() bool {
495 if m.module.base().commonProperties.SkipInstall {
496 return true
497 }
498
499 if m.module.base().commonProperties.HideFromMake {
500 return true
501 }
502
503 // We'll need a solution for choosing which of modules with the same name in different
504 // namespaces to install. For now, reuse the list of namespaces exported to Make as the
505 // list of namespaces to install in a Soong-only build.
506 if !m.module.base().commonProperties.NamespaceExportedToMake {
507 return true
508 }
509
510 return false
511}
512
Jiyong Park3f627e62024-05-01 16:14:38 +0900513// Tells whether this module is installed to the full install path (ex:
514// out/target/product/<name>/<partition>) or not. If this returns false, the install build rule is
515// not created and this module can only be installed to packaging modules like android_filesystem.
516func (m *moduleContext) requiresFullInstall() bool {
517 if m.skipInstall() {
518 return false
519 }
520
521 if proptools.Bool(m.module.base().commonProperties.No_full_install) {
522 return false
523 }
524
525 return true
526}
527
Colin Cross69452e12023-11-15 11:20:53 -0800528func (m *moduleContext) InstallFile(installPath InstallPath, name string, srcPath Path,
Colin Cross09ad3a62023-11-15 12:29:33 -0800529 deps ...InstallPath) InstallPath {
Colin Crossa6182ab2024-08-21 10:47:44 -0700530 return m.installFile(installPath, name, srcPath, deps, false, true, true, nil)
531}
532
533func (m *moduleContext) InstallFileWithoutCheckbuild(installPath InstallPath, name string, srcPath Path,
534 deps ...InstallPath) InstallPath {
535 return m.installFile(installPath, name, srcPath, deps, false, true, false, nil)
Colin Cross69452e12023-11-15 11:20:53 -0800536}
537
538func (m *moduleContext) InstallExecutable(installPath InstallPath, name string, srcPath Path,
Colin Cross09ad3a62023-11-15 12:29:33 -0800539 deps ...InstallPath) InstallPath {
Colin Crossa6182ab2024-08-21 10:47:44 -0700540 return m.installFile(installPath, name, srcPath, deps, true, true, true, nil)
Colin Cross69452e12023-11-15 11:20:53 -0800541}
542
543func (m *moduleContext) InstallFileWithExtraFilesZip(installPath InstallPath, name string, srcPath Path,
Colin Cross09ad3a62023-11-15 12:29:33 -0800544 extraZip Path, deps ...InstallPath) InstallPath {
Colin Crossa6182ab2024-08-21 10:47:44 -0700545 return m.installFile(installPath, name, srcPath, deps, false, true, true, &extraFilesZip{
Colin Cross69452e12023-11-15 11:20:53 -0800546 zip: extraZip,
547 dir: installPath,
548 })
549}
550
551func (m *moduleContext) PackageFile(installPath InstallPath, name string, srcPath Path) PackagingSpec {
552 fullInstallPath := installPath.Join(m, name)
553 return m.packageFile(fullInstallPath, srcPath, false)
554}
555
Justin Yun74f3f302024-05-07 14:32:14 +0900556func (m *moduleContext) getAconfigPaths() *Paths {
Yu Liu9a993132024-08-27 23:21:06 +0000557 return &m.aconfigFilePaths
558}
559
560func (m *moduleContext) setAconfigPaths(paths Paths) {
561 m.aconfigFilePaths = paths
Justin Yun74f3f302024-05-07 14:32:14 +0900562}
563
Colin Cross69452e12023-11-15 11:20:53 -0800564func (m *moduleContext) packageFile(fullInstallPath InstallPath, srcPath Path, executable bool) PackagingSpec {
565 licenseFiles := m.Module().EffectiveLicenseFiles()
Jiyong Parka574d532024-08-28 18:06:43 +0900566 overrides := CopyOf(m.Module().base().commonProperties.Overrides)
Colin Cross69452e12023-11-15 11:20:53 -0800567 spec := PackagingSpec{
568 relPathInPackage: Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()),
569 srcPath: srcPath,
570 symlinkTarget: "",
571 executable: executable,
572 effectiveLicenseFiles: &licenseFiles,
573 partition: fullInstallPath.partition,
Jiyong Park4152b192024-04-30 21:24:21 +0900574 skipInstall: m.skipInstall(),
Justin Yun74f3f302024-05-07 14:32:14 +0900575 aconfigPaths: m.getAconfigPaths(),
Jiyong Parkc6a773d2024-05-14 21:49:11 +0900576 archType: m.target.Arch.ArchType,
Jiyong Parka574d532024-08-28 18:06:43 +0900577 overrides: &overrides,
578 owner: m.ModuleName(),
Colin Cross69452e12023-11-15 11:20:53 -0800579 }
580 m.packagingSpecs = append(m.packagingSpecs, spec)
581 return spec
582}
583
Colin Cross09ad3a62023-11-15 12:29:33 -0800584func (m *moduleContext) installFile(installPath InstallPath, name string, srcPath Path, deps []InstallPath,
Colin Crossa6182ab2024-08-21 10:47:44 -0700585 executable bool, hooks bool, checkbuild bool, extraZip *extraFilesZip) InstallPath {
Colin Cross69452e12023-11-15 11:20:53 -0800586
587 fullInstallPath := installPath.Join(m, name)
Colin Cross5c1d5fb2023-11-15 12:39:40 -0800588 if hooks {
589 m.module.base().hooks.runInstallHooks(m, srcPath, fullInstallPath, false)
590 }
Colin Cross69452e12023-11-15 11:20:53 -0800591
Jiyong Park3f627e62024-05-01 16:14:38 +0900592 if m.requiresFullInstall() {
Yu Liubad1eef2024-08-21 22:37:35 +0000593 deps = append(deps, InstallPaths(m.TransitiveInstallFiles.ToList())...)
Yu Liu82a6d142024-08-27 19:02:29 +0000594 deps = append(deps, m.installedInitRcPaths...)
595 deps = append(deps, m.installedVintfFragmentsPaths...)
Colin Cross69452e12023-11-15 11:20:53 -0800596
597 var implicitDeps, orderOnlyDeps Paths
598
599 if m.Host() {
600 // Installed host modules might be used during the build, depend directly on their
601 // dependencies so their timestamp is updated whenever their dependency is updated
Colin Cross09ad3a62023-11-15 12:29:33 -0800602 implicitDeps = InstallPaths(deps).Paths()
Colin Cross69452e12023-11-15 11:20:53 -0800603 } else {
Colin Cross09ad3a62023-11-15 12:29:33 -0800604 orderOnlyDeps = InstallPaths(deps).Paths()
Colin Cross69452e12023-11-15 11:20:53 -0800605 }
606
607 if m.Config().KatiEnabled() {
608 // When creating the install rule in Soong but embedding in Make, write the rule to a
609 // makefile instead of directly to the ninja file so that main.mk can add the
610 // dependencies from the `required` property that are hard to resolve in Soong.
611 m.katiInstalls = append(m.katiInstalls, katiInstall{
612 from: srcPath,
613 to: fullInstallPath,
614 implicitDeps: implicitDeps,
615 orderOnlyDeps: orderOnlyDeps,
616 executable: executable,
617 extraFiles: extraZip,
618 })
619 } else {
620 rule := Cp
621 if executable {
622 rule = CpExecutable
623 }
624
625 extraCmds := ""
626 if extraZip != nil {
627 extraCmds += fmt.Sprintf(" && ( unzip -qDD -d '%s' '%s' 2>&1 | grep -v \"zipfile is empty\"; exit $${PIPESTATUS[0]} )",
628 extraZip.dir.String(), extraZip.zip.String())
629 extraCmds += " || ( code=$$?; if [ $$code -ne 0 -a $$code -ne 1 ]; then exit $$code; fi )"
630 implicitDeps = append(implicitDeps, extraZip.zip)
631 }
632
633 m.Build(pctx, BuildParams{
634 Rule: rule,
635 Description: "install " + fullInstallPath.Base(),
636 Output: fullInstallPath,
637 Input: srcPath,
638 Implicits: implicitDeps,
639 OrderOnly: orderOnlyDeps,
640 Default: !m.Config().KatiEnabled(),
641 Args: map[string]string{
642 "extraCmds": extraCmds,
643 },
644 })
645 }
646
647 m.installFiles = append(m.installFiles, fullInstallPath)
648 }
649
650 m.packageFile(fullInstallPath, srcPath, executable)
651
Colin Crossa6182ab2024-08-21 10:47:44 -0700652 if checkbuild {
653 m.checkbuildFiles = append(m.checkbuildFiles, srcPath)
654 }
Colin Cross69452e12023-11-15 11:20:53 -0800655
656 return fullInstallPath
657}
658
659func (m *moduleContext) InstallSymlink(installPath InstallPath, name string, srcPath InstallPath) InstallPath {
660 fullInstallPath := installPath.Join(m, name)
661 m.module.base().hooks.runInstallHooks(m, srcPath, fullInstallPath, true)
662
663 relPath, err := filepath.Rel(path.Dir(fullInstallPath.String()), srcPath.String())
664 if err != nil {
665 panic(fmt.Sprintf("Unable to generate symlink between %q and %q: %s", fullInstallPath.Base(), srcPath.Base(), err))
666 }
Jiyong Park3f627e62024-05-01 16:14:38 +0900667 if m.requiresFullInstall() {
Colin Cross69452e12023-11-15 11:20:53 -0800668
669 if m.Config().KatiEnabled() {
670 // When creating the symlink rule in Soong but embedding in Make, write the rule to a
671 // makefile instead of directly to the ninja file so that main.mk can add the
672 // dependencies from the `required` property that are hard to resolve in Soong.
673 m.katiSymlinks = append(m.katiSymlinks, katiInstall{
674 from: srcPath,
675 to: fullInstallPath,
676 })
677 } else {
678 // The symlink doesn't need updating when the target is modified, but we sometimes
679 // have a dependency on a symlink to a binary instead of to the binary directly, and
680 // the mtime of the symlink must be updated when the binary is modified, so use a
681 // normal dependency here instead of an order-only dependency.
682 m.Build(pctx, BuildParams{
683 Rule: Symlink,
684 Description: "install symlink " + fullInstallPath.Base(),
685 Output: fullInstallPath,
686 Input: srcPath,
687 Default: !m.Config().KatiEnabled(),
688 Args: map[string]string{
689 "fromPath": relPath,
690 },
691 })
692 }
693
694 m.installFiles = append(m.installFiles, fullInstallPath)
Colin Cross69452e12023-11-15 11:20:53 -0800695 }
696
Jiyong Parka574d532024-08-28 18:06:43 +0900697 overrides := CopyOf(m.Module().base().commonProperties.Overrides)
Colin Cross69452e12023-11-15 11:20:53 -0800698 m.packagingSpecs = append(m.packagingSpecs, PackagingSpec{
699 relPathInPackage: Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()),
700 srcPath: nil,
701 symlinkTarget: relPath,
702 executable: false,
703 partition: fullInstallPath.partition,
Jiyong Park4152b192024-04-30 21:24:21 +0900704 skipInstall: m.skipInstall(),
Justin Yun74f3f302024-05-07 14:32:14 +0900705 aconfigPaths: m.getAconfigPaths(),
Jiyong Parkc6a773d2024-05-14 21:49:11 +0900706 archType: m.target.Arch.ArchType,
Jiyong Parka574d532024-08-28 18:06:43 +0900707 overrides: &overrides,
708 owner: m.ModuleName(),
Colin Cross69452e12023-11-15 11:20:53 -0800709 })
710
711 return fullInstallPath
712}
713
714// installPath/name -> absPath where absPath might be a path that is available only at runtime
715// (e.g. /apex/...)
716func (m *moduleContext) InstallAbsoluteSymlink(installPath InstallPath, name string, absPath string) InstallPath {
717 fullInstallPath := installPath.Join(m, name)
718 m.module.base().hooks.runInstallHooks(m, nil, fullInstallPath, true)
719
Jiyong Park3f627e62024-05-01 16:14:38 +0900720 if m.requiresFullInstall() {
Colin Cross69452e12023-11-15 11:20:53 -0800721 if m.Config().KatiEnabled() {
722 // When creating the symlink rule in Soong but embedding in Make, write the rule to a
723 // makefile instead of directly to the ninja file so that main.mk can add the
724 // dependencies from the `required` property that are hard to resolve in Soong.
725 m.katiSymlinks = append(m.katiSymlinks, katiInstall{
726 absFrom: absPath,
727 to: fullInstallPath,
728 })
729 } else {
730 m.Build(pctx, BuildParams{
731 Rule: Symlink,
732 Description: "install symlink " + fullInstallPath.Base() + " -> " + absPath,
733 Output: fullInstallPath,
734 Default: !m.Config().KatiEnabled(),
735 Args: map[string]string{
736 "fromPath": absPath,
737 },
738 })
739 }
740
741 m.installFiles = append(m.installFiles, fullInstallPath)
742 }
743
Jiyong Parka574d532024-08-28 18:06:43 +0900744 overrides := CopyOf(m.Module().base().commonProperties.Overrides)
Colin Cross69452e12023-11-15 11:20:53 -0800745 m.packagingSpecs = append(m.packagingSpecs, PackagingSpec{
746 relPathInPackage: Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()),
747 srcPath: nil,
748 symlinkTarget: absPath,
749 executable: false,
750 partition: fullInstallPath.partition,
Jiyong Park4152b192024-04-30 21:24:21 +0900751 skipInstall: m.skipInstall(),
Justin Yun74f3f302024-05-07 14:32:14 +0900752 aconfigPaths: m.getAconfigPaths(),
Jiyong Parkc6a773d2024-05-14 21:49:11 +0900753 archType: m.target.Arch.ArchType,
Jiyong Parka574d532024-08-28 18:06:43 +0900754 overrides: &overrides,
755 owner: m.ModuleName(),
Colin Cross69452e12023-11-15 11:20:53 -0800756 })
757
758 return fullInstallPath
759}
760
Colin Cross5c1d5fb2023-11-15 12:39:40 -0800761func (m *moduleContext) InstallTestData(installPath InstallPath, data []DataPath) InstallPaths {
762 m.testData = append(m.testData, data...)
763
764 ret := make(InstallPaths, 0, len(data))
765 for _, d := range data {
766 relPath := d.ToRelativeInstallPath()
Colin Crossa6182ab2024-08-21 10:47:44 -0700767 installed := m.installFile(installPath, relPath, d.SrcPath, nil, false, false, true, nil)
Colin Cross5c1d5fb2023-11-15 12:39:40 -0800768 ret = append(ret, installed)
769 }
770
771 return ret
772}
773
Colin Crossa6182ab2024-08-21 10:47:44 -0700774// CheckbuildFile specifies the output files that should be built by checkbuild.
775func (m *moduleContext) CheckbuildFile(srcPaths ...Path) {
776 m.checkbuildFiles = append(m.checkbuildFiles, srcPaths...)
777}
778
779// UncheckedModule marks the current module has having no files that should be built by checkbuild.
780func (m *moduleContext) UncheckedModule() {
781 m.uncheckedModule = true
Colin Cross69452e12023-11-15 11:20:53 -0800782}
783
Colin Cross1496fb12024-09-09 16:44:10 -0700784func (m *moduleContext) BlueprintModuleContext() blueprint.ModuleContext {
Colin Cross69452e12023-11-15 11:20:53 -0800785 return m.bp
786}
787
788func (m *moduleContext) LicenseMetadataFile() Path {
Yu Liuec810542024-08-26 18:09:15 +0000789 return m.licenseMetadataFile
Colin Cross69452e12023-11-15 11:20:53 -0800790}
791
Colin Crossd6fd0132023-11-06 13:54:06 -0800792func (m *moduleContext) ModuleInfoJSON() *ModuleInfoJSON {
Yu Liu4297ad92024-08-27 19:50:13 +0000793 if moduleInfoJSON := m.moduleInfoJSON; moduleInfoJSON != nil {
Colin Crossd6fd0132023-11-06 13:54:06 -0800794 return moduleInfoJSON
795 }
796 moduleInfoJSON := &ModuleInfoJSON{}
Yu Liu4297ad92024-08-27 19:50:13 +0000797 m.moduleInfoJSON = moduleInfoJSON
Colin Crossd6fd0132023-11-06 13:54:06 -0800798 return moduleInfoJSON
799}
800
mrziwange6c85812024-05-22 14:36:09 -0700801func (m *moduleContext) SetOutputFiles(outputFiles Paths, tag string) {
802 if tag == "" {
Yu Liu876b7ce2024-08-21 18:20:13 +0000803 if len(m.outputFiles.DefaultOutputFiles) > 0 {
mrziwange6c85812024-05-22 14:36:09 -0700804 m.ModuleErrorf("Module %s default OutputFiles cannot be overwritten", m.ModuleName())
805 }
Yu Liu876b7ce2024-08-21 18:20:13 +0000806 m.outputFiles.DefaultOutputFiles = outputFiles
mrziwange6c85812024-05-22 14:36:09 -0700807 } else {
Yu Liu876b7ce2024-08-21 18:20:13 +0000808 if m.outputFiles.TaggedOutputFiles == nil {
809 m.outputFiles.TaggedOutputFiles = make(map[string]Paths)
mrziwang57768d72024-06-06 11:31:51 -0700810 }
Yu Liu876b7ce2024-08-21 18:20:13 +0000811 if _, exists := m.outputFiles.TaggedOutputFiles[tag]; exists {
mrziwange6c85812024-05-22 14:36:09 -0700812 m.ModuleErrorf("Module %s OutputFiles at tag %s cannot be overwritten", m.ModuleName(), tag)
813 } else {
Yu Liu876b7ce2024-08-21 18:20:13 +0000814 m.outputFiles.TaggedOutputFiles[tag] = outputFiles
mrziwange6c85812024-05-22 14:36:09 -0700815 }
816 }
817}
818
Yu Liu876b7ce2024-08-21 18:20:13 +0000819func (m *moduleContext) GetOutputFiles() OutputFilesInfo {
820 return m.outputFiles
821}
822
Yu Liubad1eef2024-08-21 22:37:35 +0000823func (m *moduleContext) SetLicenseInstallMap(installMap []string) {
824 m.licenseInstallMap = append(m.licenseInstallMap, installMap...)
825}
826
Wei Lia1aa2972024-06-21 13:08:51 -0700827func (m *moduleContext) ComplianceMetadataInfo() *ComplianceMetadataInfo {
Yu Liu9a993132024-08-27 23:21:06 +0000828 if m.complianceMetadataInfo == nil {
829 m.complianceMetadataInfo = NewComplianceMetadataInfo()
Wei Lia1aa2972024-06-21 13:08:51 -0700830 }
Yu Liu9a993132024-08-27 23:21:06 +0000831 return m.complianceMetadataInfo
Wei Lia1aa2972024-06-21 13:08:51 -0700832}
833
Colin Cross69452e12023-11-15 11:20:53 -0800834// Returns a list of paths expanded from globs and modules referenced using ":module" syntax. The property must
835// be tagged with `android:"path" to support automatic source module dependency resolution.
836//
837// Deprecated: use PathsForModuleSrc or PathsForModuleSrcExcludes instead.
838func (m *moduleContext) ExpandSources(srcFiles, excludes []string) Paths {
839 return PathsForModuleSrcExcludes(m, srcFiles, excludes)
840}
841
842// Returns a single path expanded from globs and modules referenced using ":module" syntax. The property must
843// be tagged with `android:"path" to support automatic source module dependency resolution.
844//
845// Deprecated: use PathForModuleSrc instead.
846func (m *moduleContext) ExpandSource(srcFile, _ string) Path {
847 return PathForModuleSrc(m, srcFile)
848}
849
850// Returns an optional single path expanded from globs and modules referenced using ":module" syntax if
851// the srcFile is non-nil. The property must be tagged with `android:"path" to support automatic source module
852// dependency resolution.
853func (m *moduleContext) ExpandOptionalSource(srcFile *string, _ string) OptionalPath {
854 if srcFile != nil {
855 return OptionalPathForPath(PathForModuleSrc(m, *srcFile))
856 }
857 return OptionalPath{}
858}
859
Cole Fauste8a87832024-09-11 11:35:46 -0700860func (m *moduleContext) RequiredModuleNames(ctx ConfigurableEvaluatorContext) []string {
Cole Faust43ddd082024-06-17 12:32:40 -0700861 return m.module.RequiredModuleNames(ctx)
Colin Cross69452e12023-11-15 11:20:53 -0800862}
863
864func (m *moduleContext) HostRequiredModuleNames() []string {
865 return m.module.HostRequiredModuleNames()
866}
867
868func (m *moduleContext) TargetRequiredModuleNames() []string {
869 return m.module.TargetRequiredModuleNames()
870}
Yu Liu9a993132024-08-27 23:21:06 +0000871
872func (m *moduleContext) getContainersInfo() ContainersInfo {
873 return m.containersInfo
874}
875
876func (m *moduleContext) setContainersInfo(info ContainersInfo) {
877 m.containersInfo = info
878}