blob: 6c52a7e39a54dd9e96aa76e9384b4c371c724bf2 [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
88 blueprintModuleContext() blueprint.ModuleContext
89
90 // Deprecated: use ModuleContext.Build instead.
91 ModuleBuild(pctx PackageContext, params ModuleBuildParams)
92
93 // Returns a list of paths expanded from globs and modules referenced using ":module" syntax. The property must
94 // be tagged with `android:"path" to support automatic source module dependency resolution.
95 //
96 // Deprecated: use PathsForModuleSrc or PathsForModuleSrcExcludes instead.
97 ExpandSources(srcFiles, excludes []string) Paths
98
99 // Returns a single path expanded from globs and modules referenced using ":module" syntax. The property must
100 // be tagged with `android:"path" to support automatic source module dependency resolution.
101 //
102 // Deprecated: use PathForModuleSrc instead.
103 ExpandSource(srcFile, prop string) Path
104
105 ExpandOptionalSource(srcFile *string, prop string) OptionalPath
106
107 // InstallExecutable creates a rule to copy srcPath to name in the installPath directory,
108 // with the given additional dependencies. The file is marked executable after copying.
109 //
Yu Liubad1eef2024-08-21 22:37:35 +0000110 // The installed file can be accessed by InstallFilesInfo.InstallFiles, and the PackagingSpec
111 // for the installed file can be accessed by InstallFilesInfo.PackagingSpecs on this module
112 // or by InstallFilesInfo.TransitivePackagingSpecs on modules that depend on this module through
113 // dependency tags for which IsInstallDepNeeded returns true.
Colin Cross09ad3a62023-11-15 12:29:33 -0800114 InstallExecutable(installPath InstallPath, name string, srcPath Path, deps ...InstallPath) InstallPath
Colin Cross69452e12023-11-15 11:20:53 -0800115
116 // InstallFile creates a rule to copy srcPath to name in the installPath directory,
117 // with the given additional dependencies.
118 //
Yu Liubad1eef2024-08-21 22:37:35 +0000119 // The installed file can be accessed by InstallFilesInfo.InstallFiles, and the PackagingSpec
120 // for the installed file can be accessed by InstallFilesInfo.PackagingSpecs on this module
121 // or by InstallFilesInfo.TransitivePackagingSpecs on modules that depend on this module through
122 // dependency tags for which IsInstallDepNeeded returns true.
Colin Cross09ad3a62023-11-15 12:29:33 -0800123 InstallFile(installPath InstallPath, name string, srcPath Path, deps ...InstallPath) InstallPath
Colin Cross69452e12023-11-15 11:20:53 -0800124
Colin Crossa6182ab2024-08-21 10:47:44 -0700125 // InstallFileWithoutCheckbuild creates a rule to copy srcPath to name in the installPath directory,
126 // with the given additional dependencies, but does not add the file to the list of files to build
127 // during `m checkbuild`.
128 //
129 // The installed file will be returned by FilesToInstall(), and the PackagingSpec for the
130 // installed file will be returned by PackagingSpecs() on this module or by
131 // TransitivePackagingSpecs() on modules that depend on this module through dependency tags
132 // for which IsInstallDepNeeded returns true.
133 InstallFileWithoutCheckbuild(installPath InstallPath, name string, srcPath Path, deps ...InstallPath) InstallPath
134
Colin Cross69452e12023-11-15 11:20:53 -0800135 // InstallFileWithExtraFilesZip creates a rule to copy srcPath to name in the installPath
136 // directory, and also unzip a zip file containing extra files to install into the same
137 // directory.
138 //
Yu Liubad1eef2024-08-21 22:37:35 +0000139 // The installed file can be accessed by InstallFilesInfo.InstallFiles, and the PackagingSpec
140 // for the installed file can be accessed by InstallFilesInfo.PackagingSpecs on this module
141 // or by InstallFilesInfo.TransitivePackagingSpecs on modules that depend on this module through
142 // dependency tags for which IsInstallDepNeeded returns true.
Colin Cross09ad3a62023-11-15 12:29:33 -0800143 InstallFileWithExtraFilesZip(installPath InstallPath, name string, srcPath Path, extraZip Path, deps ...InstallPath) InstallPath
Colin Cross69452e12023-11-15 11:20:53 -0800144
145 // InstallSymlink creates a rule to create a symlink from src srcPath to name in the installPath
146 // directory.
147 //
Yu Liubad1eef2024-08-21 22:37:35 +0000148 // The installed symlink can be accessed by InstallFilesInfo.InstallFiles, and the PackagingSpec
149 // for the installed file can be accessed by InstallFilesInfo.PackagingSpecs on this module
150 // or by InstallFilesInfo.TransitivePackagingSpecs on modules that depend on this module through
151 // dependency tags for which IsInstallDepNeeded returns true.
Colin Cross69452e12023-11-15 11:20:53 -0800152 InstallSymlink(installPath InstallPath, name string, srcPath InstallPath) InstallPath
153
154 // InstallAbsoluteSymlink creates a rule to create an absolute symlink from src srcPath to name
155 // in the installPath directory.
156 //
Yu Liubad1eef2024-08-21 22:37:35 +0000157 // The installed symlink can be accessed by InstallFilesInfo.InstallFiles, and the PackagingSpec
158 // for the installed file can be accessed by InstallFilesInfo.PackagingSpecs on this module
159 // or by InstallFilesInfo.TransitivePackagingSpecs on modules that depend on this module through
160 // dependency tags for which IsInstallDepNeeded returns true.
Colin Cross69452e12023-11-15 11:20:53 -0800161 InstallAbsoluteSymlink(installPath InstallPath, name string, absPath string) InstallPath
162
Colin Cross5c1d5fb2023-11-15 12:39:40 -0800163 // InstallTestData creates rules to install test data (e.g. data files used during a test) into
164 // the installPath directory.
165 //
Yu Liubad1eef2024-08-21 22:37:35 +0000166 // The installed files can be accessed by InstallFilesInfo.InstallFiles, and the PackagingSpec
167 // for the installed files can be accessed by InstallFilesInfo.PackagingSpecs on this module
168 // or by InstallFilesInfo.TransitivePackagingSpecs on modules that depend on this module through
169 // dependency tags for which IsInstallDepNeeded returns true.
Colin Cross5c1d5fb2023-11-15 12:39:40 -0800170 InstallTestData(installPath InstallPath, data []DataPath) InstallPaths
171
Colin Cross69452e12023-11-15 11:20:53 -0800172 // PackageFile creates a PackagingSpec as if InstallFile was called, but without creating
173 // the rule to copy the file. This is useful to define how a module would be packaged
174 // without installing it into the global installation directories.
175 //
Yu Liubad1eef2024-08-21 22:37:35 +0000176 // The created PackagingSpec can be accessed by InstallFilesInfo.PackagingSpecs on this module
177 // or by InstallFilesInfo.TransitivePackagingSpecs on modules that depend on this module through
178 // dependency tags for which IsInstallDepNeeded returns true.
Colin Cross69452e12023-11-15 11:20:53 -0800179 PackageFile(installPath InstallPath, name string, srcPath Path) PackagingSpec
180
Colin Crossa6182ab2024-08-21 10:47:44 -0700181 CheckbuildFile(srcPaths ...Path)
182 UncheckedModule()
Colin Cross69452e12023-11-15 11:20:53 -0800183
184 InstallInData() bool
185 InstallInTestcases() bool
186 InstallInSanitizerDir() bool
187 InstallInRamdisk() bool
188 InstallInVendorRamdisk() bool
189 InstallInDebugRamdisk() bool
190 InstallInRecovery() bool
191 InstallInRoot() bool
Colin Crossea30d852023-11-29 16:00:16 -0800192 InstallInOdm() bool
193 InstallInProduct() bool
Colin Cross69452e12023-11-15 11:20:53 -0800194 InstallInVendor() bool
195 InstallForceOS() (*OsType, *ArchType)
196
Cole Faust43ddd082024-06-17 12:32:40 -0700197 RequiredModuleNames(ctx ConfigAndErrorContext) []string
Colin Cross69452e12023-11-15 11:20:53 -0800198 HostRequiredModuleNames() []string
199 TargetRequiredModuleNames() []string
200
201 ModuleSubDir() string
Colin Cross69452e12023-11-15 11:20:53 -0800202
203 Variable(pctx PackageContext, name, value string)
204 Rule(pctx PackageContext, name string, params blueprint.RuleParams, argNames ...string) blueprint.Rule
205 // Similar to blueprint.ModuleContext.Build, but takes Paths instead of []string,
206 // and performs more verification.
207 Build(pctx PackageContext, params BuildParams)
208 // Phony creates a Make-style phony rule, a rule with no commands that can depend on other
209 // phony rules or real files. Phony can be called on the same name multiple times to add
210 // additional dependencies.
211 Phony(phony string, deps ...Path)
212
213 // GetMissingDependencies returns the list of dependencies that were passed to AddDependencies or related methods,
214 // but do not exist.
215 GetMissingDependencies() []string
216
217 // LicenseMetadataFile returns the path where the license metadata for this module will be
218 // generated.
219 LicenseMetadataFile() Path
Colin Crossd6fd0132023-11-06 13:54:06 -0800220
221 // ModuleInfoJSON returns a pointer to the ModuleInfoJSON struct that can be filled out by
222 // GenerateAndroidBuildActions. If it is called then the struct will be written out and included in
223 // the module-info.json generated by Make, and Make will not generate its own data for this module.
224 ModuleInfoJSON() *ModuleInfoJSON
mrziwange6c85812024-05-22 14:36:09 -0700225
226 // SetOutputFiles stores the outputFiles to outputFiles property, which is used
227 // to set the OutputFilesProvider later.
228 SetOutputFiles(outputFiles Paths, tag string)
Wei Lia1aa2972024-06-21 13:08:51 -0700229
Yu Liu876b7ce2024-08-21 18:20:13 +0000230 GetOutputFiles() OutputFilesInfo
231
Yu Liubad1eef2024-08-21 22:37:35 +0000232 // SetLicenseInstallMap stores the set of dependency module:location mappings for files in an
233 // apex container for use when generation the license metadata file.
234 SetLicenseInstallMap(installMap []string)
235
Wei Lia1aa2972024-06-21 13:08:51 -0700236 // ComplianceMetadataInfo returns a ComplianceMetadataInfo instance for different module types to dump metadata,
237 // which usually happens in GenerateAndroidBuildActions() of a module type.
238 // See android.ModuleBase.complianceMetadataInfo
239 ComplianceMetadataInfo() *ComplianceMetadataInfo
Yu Liu9a993132024-08-27 23:21:06 +0000240
241 // Get the information about the containers this module belongs to.
242 getContainersInfo() ContainersInfo
243 setContainersInfo(info ContainersInfo)
244
245 setAconfigPaths(paths Paths)
Colin Cross69452e12023-11-15 11:20:53 -0800246}
247
248type moduleContext struct {
249 bp blueprint.ModuleContext
250 baseModuleContext
Colin Crossa6182ab2024-08-21 10:47:44 -0700251 packagingSpecs []PackagingSpec
252 installFiles InstallPaths
253 checkbuildFiles Paths
254 checkbuildTarget Path
255 uncheckedModule bool
256 module Module
257 phonies map[string]Paths
Yu Liu876b7ce2024-08-21 18:20:13 +0000258 // outputFiles stores the output of a module by tag and is used to set
259 // the OutputFilesProvider in GenerateBuildActions
260 outputFiles OutputFilesInfo
Colin Cross69452e12023-11-15 11:20:53 -0800261
Yu Liubad1eef2024-08-21 22:37:35 +0000262 TransitiveInstallFiles *DepSet[InstallPath]
263
264 // set of dependency module:location mappings used to populate the license metadata for
265 // apex containers.
266 licenseInstallMap []string
267
Yu Liuec810542024-08-26 18:09:15 +0000268 // The path to the generated license metadata file for the module.
269 licenseMetadataFile WritablePath
270
Yu Liud46e5ae2024-08-15 18:46:17 +0000271 katiInstalls katiInstalls
272 katiSymlinks katiInstalls
Yu Liu82a6d142024-08-27 19:02:29 +0000273 // katiInitRcInstalls and katiVintfInstalls track the install rules created by Soong that are
274 // allowed to have duplicates across modules and variants.
275 katiInitRcInstalls katiInstalls
276 katiVintfInstalls katiInstalls
277 initRcPaths Paths
278 vintfFragmentsPaths Paths
279 installedInitRcPaths InstallPaths
280 installedVintfFragmentsPaths InstallPaths
Colin Cross69452e12023-11-15 11:20:53 -0800281
Colin Cross5c1d5fb2023-11-15 12:39:40 -0800282 testData []DataPath
283
Colin Cross69452e12023-11-15 11:20:53 -0800284 // For tests
285 buildParams []BuildParams
286 ruleParams map[blueprint.Rule]blueprint.RuleParams
287 variables map[string]string
Yu Liu4297ad92024-08-27 19:50:13 +0000288
289 // moduleInfoJSON can be filled out by GenerateAndroidBuildActions to write a JSON file that will
290 // be included in the final module-info.json produced by Make.
291 moduleInfoJSON *ModuleInfoJSON
Yu Liu9a993132024-08-27 23:21:06 +0000292
293 // containersInfo stores the information about the containers and the information of the
294 // apexes the module belongs to.
295 containersInfo ContainersInfo
296
297 // Merged Aconfig files for all transitive deps.
298 aconfigFilePaths Paths
299
300 // complianceMetadataInfo is for different module types to dump metadata.
301 // See android.ModuleContext interface.
302 complianceMetadataInfo *ComplianceMetadataInfo
Colin Cross69452e12023-11-15 11:20:53 -0800303}
304
Cole Faust02987bd2024-03-21 17:58:43 -0700305var _ ModuleContext = &moduleContext{}
306
Colin Cross69452e12023-11-15 11:20:53 -0800307func (m *moduleContext) ninjaError(params BuildParams, err error) (PackageContext, BuildParams) {
308 return pctx, BuildParams{
309 Rule: ErrorRule,
310 Description: params.Description,
311 Output: params.Output,
312 Outputs: params.Outputs,
313 ImplicitOutput: params.ImplicitOutput,
314 ImplicitOutputs: params.ImplicitOutputs,
315 Args: map[string]string{
316 "error": err.Error(),
317 },
318 }
319}
320
321func (m *moduleContext) ModuleBuild(pctx PackageContext, params ModuleBuildParams) {
322 m.Build(pctx, BuildParams(params))
323}
324
Colin Cross69452e12023-11-15 11:20:53 -0800325// Convert build parameters from their concrete Android types into their string representations,
326// and combine the singular and plural fields of the same type (e.g. Output and Outputs).
327func convertBuildParams(params BuildParams) blueprint.BuildParams {
328 bparams := blueprint.BuildParams{
329 Rule: params.Rule,
330 Description: params.Description,
331 Deps: params.Deps,
332 Outputs: params.Outputs.Strings(),
333 ImplicitOutputs: params.ImplicitOutputs.Strings(),
Colin Cross69452e12023-11-15 11:20:53 -0800334 Inputs: params.Inputs.Strings(),
335 Implicits: params.Implicits.Strings(),
336 OrderOnly: params.OrderOnly.Strings(),
337 Validations: params.Validations.Strings(),
338 Args: params.Args,
339 Optional: !params.Default,
340 }
341
342 if params.Depfile != nil {
343 bparams.Depfile = params.Depfile.String()
344 }
345 if params.Output != nil {
346 bparams.Outputs = append(bparams.Outputs, params.Output.String())
347 }
Colin Cross69452e12023-11-15 11:20:53 -0800348 if params.ImplicitOutput != nil {
349 bparams.ImplicitOutputs = append(bparams.ImplicitOutputs, params.ImplicitOutput.String())
350 }
351 if params.Input != nil {
352 bparams.Inputs = append(bparams.Inputs, params.Input.String())
353 }
354 if params.Implicit != nil {
355 bparams.Implicits = append(bparams.Implicits, params.Implicit.String())
356 }
357 if params.Validation != nil {
358 bparams.Validations = append(bparams.Validations, params.Validation.String())
359 }
360
361 bparams.Outputs = proptools.NinjaEscapeList(bparams.Outputs)
362 bparams.ImplicitOutputs = proptools.NinjaEscapeList(bparams.ImplicitOutputs)
Colin Cross69452e12023-11-15 11:20:53 -0800363 bparams.Inputs = proptools.NinjaEscapeList(bparams.Inputs)
364 bparams.Implicits = proptools.NinjaEscapeList(bparams.Implicits)
365 bparams.OrderOnly = proptools.NinjaEscapeList(bparams.OrderOnly)
366 bparams.Validations = proptools.NinjaEscapeList(bparams.Validations)
367 bparams.Depfile = proptools.NinjaEscape(bparams.Depfile)
368
369 return bparams
370}
371
372func (m *moduleContext) Variable(pctx PackageContext, name, value string) {
373 if m.config.captureBuild {
374 m.variables[name] = value
375 }
376
377 m.bp.Variable(pctx.PackageContext, name, value)
378}
379
380func (m *moduleContext) Rule(pctx PackageContext, name string, params blueprint.RuleParams,
381 argNames ...string) blueprint.Rule {
382
383 if m.config.UseRemoteBuild() {
384 if params.Pool == nil {
385 // When USE_GOMA=true or USE_RBE=true are set and the rule is not supported by goma/RBE, restrict
386 // jobs to the local parallelism value
387 params.Pool = localPool
388 } else if params.Pool == remotePool {
389 // remotePool is a fake pool used to identify rule that are supported for remoting. If the rule's
390 // pool is the remotePool, replace with nil so that ninja runs it at NINJA_REMOTE_NUM_JOBS
391 // parallelism.
392 params.Pool = nil
393 }
394 }
395
396 rule := m.bp.Rule(pctx.PackageContext, name, params, argNames...)
397
398 if m.config.captureBuild {
399 m.ruleParams[rule] = params
400 }
401
402 return rule
403}
404
405func (m *moduleContext) Build(pctx PackageContext, params BuildParams) {
406 if params.Description != "" {
407 params.Description = "${moduleDesc}" + params.Description + "${moduleDescSuffix}"
408 }
409
410 if missingDeps := m.GetMissingDependencies(); len(missingDeps) > 0 {
411 pctx, params = m.ninjaError(params, fmt.Errorf("module %s missing dependencies: %s\n",
412 m.ModuleName(), strings.Join(missingDeps, ", ")))
413 }
414
415 if m.config.captureBuild {
416 m.buildParams = append(m.buildParams, params)
417 }
418
419 bparams := convertBuildParams(params)
Colin Cross69452e12023-11-15 11:20:53 -0800420 m.bp.Build(pctx.PackageContext, bparams)
421}
422
423func (m *moduleContext) Phony(name string, deps ...Path) {
Yu Liu54513622024-08-19 20:00:32 +0000424 m.phonies[name] = append(m.phonies[name], deps...)
Colin Cross69452e12023-11-15 11:20:53 -0800425}
426
427func (m *moduleContext) GetMissingDependencies() []string {
428 var missingDeps []string
429 missingDeps = append(missingDeps, m.Module().base().commonProperties.MissingDeps...)
430 missingDeps = append(missingDeps, m.bp.GetMissingDependencies()...)
431 missingDeps = FirstUniqueStrings(missingDeps)
432 return missingDeps
433}
434
435func (m *moduleContext) GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module {
436 module, _ := m.getDirectDepInternal(name, tag)
437 return module
438}
439
440func (m *moduleContext) ModuleSubDir() string {
441 return m.bp.ModuleSubDir()
442}
443
Colin Cross69452e12023-11-15 11:20:53 -0800444func (m *moduleContext) InstallInData() bool {
445 return m.module.InstallInData()
446}
447
448func (m *moduleContext) InstallInTestcases() bool {
449 return m.module.InstallInTestcases()
450}
451
452func (m *moduleContext) InstallInSanitizerDir() bool {
453 return m.module.InstallInSanitizerDir()
454}
455
456func (m *moduleContext) InstallInRamdisk() bool {
457 return m.module.InstallInRamdisk()
458}
459
460func (m *moduleContext) InstallInVendorRamdisk() bool {
461 return m.module.InstallInVendorRamdisk()
462}
463
464func (m *moduleContext) InstallInDebugRamdisk() bool {
465 return m.module.InstallInDebugRamdisk()
466}
467
468func (m *moduleContext) InstallInRecovery() bool {
469 return m.module.InstallInRecovery()
470}
471
472func (m *moduleContext) InstallInRoot() bool {
473 return m.module.InstallInRoot()
474}
475
476func (m *moduleContext) InstallForceOS() (*OsType, *ArchType) {
477 return m.module.InstallForceOS()
478}
479
Colin Crossea30d852023-11-29 16:00:16 -0800480func (m *moduleContext) InstallInOdm() bool {
481 return m.module.InstallInOdm()
482}
483
484func (m *moduleContext) InstallInProduct() bool {
485 return m.module.InstallInProduct()
486}
487
Colin Cross69452e12023-11-15 11:20:53 -0800488func (m *moduleContext) InstallInVendor() bool {
489 return m.module.InstallInVendor()
490}
491
492func (m *moduleContext) skipInstall() bool {
493 if m.module.base().commonProperties.SkipInstall {
494 return true
495 }
496
497 if m.module.base().commonProperties.HideFromMake {
498 return true
499 }
500
501 // We'll need a solution for choosing which of modules with the same name in different
502 // namespaces to install. For now, reuse the list of namespaces exported to Make as the
503 // list of namespaces to install in a Soong-only build.
504 if !m.module.base().commonProperties.NamespaceExportedToMake {
505 return true
506 }
507
508 return false
509}
510
Jiyong Park3f627e62024-05-01 16:14:38 +0900511// Tells whether this module is installed to the full install path (ex:
512// out/target/product/<name>/<partition>) or not. If this returns false, the install build rule is
513// not created and this module can only be installed to packaging modules like android_filesystem.
514func (m *moduleContext) requiresFullInstall() bool {
515 if m.skipInstall() {
516 return false
517 }
518
519 if proptools.Bool(m.module.base().commonProperties.No_full_install) {
520 return false
521 }
522
523 return true
524}
525
Colin Cross69452e12023-11-15 11:20:53 -0800526func (m *moduleContext) InstallFile(installPath InstallPath, name string, srcPath Path,
Colin Cross09ad3a62023-11-15 12:29:33 -0800527 deps ...InstallPath) InstallPath {
Colin Crossa6182ab2024-08-21 10:47:44 -0700528 return m.installFile(installPath, name, srcPath, deps, false, true, true, nil)
529}
530
531func (m *moduleContext) InstallFileWithoutCheckbuild(installPath InstallPath, name string, srcPath Path,
532 deps ...InstallPath) InstallPath {
533 return m.installFile(installPath, name, srcPath, deps, false, true, false, nil)
Colin Cross69452e12023-11-15 11:20:53 -0800534}
535
536func (m *moduleContext) InstallExecutable(installPath InstallPath, name string, srcPath Path,
Colin Cross09ad3a62023-11-15 12:29:33 -0800537 deps ...InstallPath) InstallPath {
Colin Crossa6182ab2024-08-21 10:47:44 -0700538 return m.installFile(installPath, name, srcPath, deps, true, true, true, nil)
Colin Cross69452e12023-11-15 11:20:53 -0800539}
540
541func (m *moduleContext) InstallFileWithExtraFilesZip(installPath InstallPath, name string, srcPath Path,
Colin Cross09ad3a62023-11-15 12:29:33 -0800542 extraZip Path, deps ...InstallPath) InstallPath {
Colin Crossa6182ab2024-08-21 10:47:44 -0700543 return m.installFile(installPath, name, srcPath, deps, false, true, true, &extraFilesZip{
Colin Cross69452e12023-11-15 11:20:53 -0800544 zip: extraZip,
545 dir: installPath,
546 })
547}
548
549func (m *moduleContext) PackageFile(installPath InstallPath, name string, srcPath Path) PackagingSpec {
550 fullInstallPath := installPath.Join(m, name)
551 return m.packageFile(fullInstallPath, srcPath, false)
552}
553
Justin Yun74f3f302024-05-07 14:32:14 +0900554func (m *moduleContext) getAconfigPaths() *Paths {
Yu Liu9a993132024-08-27 23:21:06 +0000555 return &m.aconfigFilePaths
556}
557
558func (m *moduleContext) setAconfigPaths(paths Paths) {
559 m.aconfigFilePaths = paths
Justin Yun74f3f302024-05-07 14:32:14 +0900560}
561
Colin Cross69452e12023-11-15 11:20:53 -0800562func (m *moduleContext) packageFile(fullInstallPath InstallPath, srcPath Path, executable bool) PackagingSpec {
563 licenseFiles := m.Module().EffectiveLicenseFiles()
564 spec := PackagingSpec{
565 relPathInPackage: Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()),
566 srcPath: srcPath,
567 symlinkTarget: "",
568 executable: executable,
569 effectiveLicenseFiles: &licenseFiles,
570 partition: fullInstallPath.partition,
Jiyong Park4152b192024-04-30 21:24:21 +0900571 skipInstall: m.skipInstall(),
Justin Yun74f3f302024-05-07 14:32:14 +0900572 aconfigPaths: m.getAconfigPaths(),
Jiyong Parkc6a773d2024-05-14 21:49:11 +0900573 archType: m.target.Arch.ArchType,
Colin Cross69452e12023-11-15 11:20:53 -0800574 }
575 m.packagingSpecs = append(m.packagingSpecs, spec)
576 return spec
577}
578
Colin Cross09ad3a62023-11-15 12:29:33 -0800579func (m *moduleContext) installFile(installPath InstallPath, name string, srcPath Path, deps []InstallPath,
Colin Crossa6182ab2024-08-21 10:47:44 -0700580 executable bool, hooks bool, checkbuild bool, extraZip *extraFilesZip) InstallPath {
Colin Cross69452e12023-11-15 11:20:53 -0800581
582 fullInstallPath := installPath.Join(m, name)
Colin Cross5c1d5fb2023-11-15 12:39:40 -0800583 if hooks {
584 m.module.base().hooks.runInstallHooks(m, srcPath, fullInstallPath, false)
585 }
Colin Cross69452e12023-11-15 11:20:53 -0800586
Jiyong Park3f627e62024-05-01 16:14:38 +0900587 if m.requiresFullInstall() {
Yu Liubad1eef2024-08-21 22:37:35 +0000588 deps = append(deps, InstallPaths(m.TransitiveInstallFiles.ToList())...)
Yu Liu82a6d142024-08-27 19:02:29 +0000589 deps = append(deps, m.installedInitRcPaths...)
590 deps = append(deps, m.installedVintfFragmentsPaths...)
Colin Cross69452e12023-11-15 11:20:53 -0800591
592 var implicitDeps, orderOnlyDeps Paths
593
594 if m.Host() {
595 // Installed host modules might be used during the build, depend directly on their
596 // dependencies so their timestamp is updated whenever their dependency is updated
Colin Cross09ad3a62023-11-15 12:29:33 -0800597 implicitDeps = InstallPaths(deps).Paths()
Colin Cross69452e12023-11-15 11:20:53 -0800598 } else {
Colin Cross09ad3a62023-11-15 12:29:33 -0800599 orderOnlyDeps = InstallPaths(deps).Paths()
Colin Cross69452e12023-11-15 11:20:53 -0800600 }
601
602 if m.Config().KatiEnabled() {
603 // When creating the install rule in Soong but embedding in Make, write the rule to a
604 // makefile instead of directly to the ninja file so that main.mk can add the
605 // dependencies from the `required` property that are hard to resolve in Soong.
606 m.katiInstalls = append(m.katiInstalls, katiInstall{
607 from: srcPath,
608 to: fullInstallPath,
609 implicitDeps: implicitDeps,
610 orderOnlyDeps: orderOnlyDeps,
611 executable: executable,
612 extraFiles: extraZip,
613 })
614 } else {
615 rule := Cp
616 if executable {
617 rule = CpExecutable
618 }
619
620 extraCmds := ""
621 if extraZip != nil {
622 extraCmds += fmt.Sprintf(" && ( unzip -qDD -d '%s' '%s' 2>&1 | grep -v \"zipfile is empty\"; exit $${PIPESTATUS[0]} )",
623 extraZip.dir.String(), extraZip.zip.String())
624 extraCmds += " || ( code=$$?; if [ $$code -ne 0 -a $$code -ne 1 ]; then exit $$code; fi )"
625 implicitDeps = append(implicitDeps, extraZip.zip)
626 }
627
628 m.Build(pctx, BuildParams{
629 Rule: rule,
630 Description: "install " + fullInstallPath.Base(),
631 Output: fullInstallPath,
632 Input: srcPath,
633 Implicits: implicitDeps,
634 OrderOnly: orderOnlyDeps,
635 Default: !m.Config().KatiEnabled(),
636 Args: map[string]string{
637 "extraCmds": extraCmds,
638 },
639 })
640 }
641
642 m.installFiles = append(m.installFiles, fullInstallPath)
643 }
644
645 m.packageFile(fullInstallPath, srcPath, executable)
646
Colin Crossa6182ab2024-08-21 10:47:44 -0700647 if checkbuild {
648 m.checkbuildFiles = append(m.checkbuildFiles, srcPath)
649 }
Colin Cross69452e12023-11-15 11:20:53 -0800650
651 return fullInstallPath
652}
653
654func (m *moduleContext) InstallSymlink(installPath InstallPath, name string, srcPath InstallPath) InstallPath {
655 fullInstallPath := installPath.Join(m, name)
656 m.module.base().hooks.runInstallHooks(m, srcPath, fullInstallPath, true)
657
658 relPath, err := filepath.Rel(path.Dir(fullInstallPath.String()), srcPath.String())
659 if err != nil {
660 panic(fmt.Sprintf("Unable to generate symlink between %q and %q: %s", fullInstallPath.Base(), srcPath.Base(), err))
661 }
Jiyong Park3f627e62024-05-01 16:14:38 +0900662 if m.requiresFullInstall() {
Colin Cross69452e12023-11-15 11:20:53 -0800663
664 if m.Config().KatiEnabled() {
665 // When creating the symlink rule in Soong but embedding in Make, write the rule to a
666 // makefile instead of directly to the ninja file so that main.mk can add the
667 // dependencies from the `required` property that are hard to resolve in Soong.
668 m.katiSymlinks = append(m.katiSymlinks, katiInstall{
669 from: srcPath,
670 to: fullInstallPath,
671 })
672 } else {
673 // The symlink doesn't need updating when the target is modified, but we sometimes
674 // have a dependency on a symlink to a binary instead of to the binary directly, and
675 // the mtime of the symlink must be updated when the binary is modified, so use a
676 // normal dependency here instead of an order-only dependency.
677 m.Build(pctx, BuildParams{
678 Rule: Symlink,
679 Description: "install symlink " + fullInstallPath.Base(),
680 Output: fullInstallPath,
681 Input: srcPath,
682 Default: !m.Config().KatiEnabled(),
683 Args: map[string]string{
684 "fromPath": relPath,
685 },
686 })
687 }
688
689 m.installFiles = append(m.installFiles, fullInstallPath)
Colin Cross69452e12023-11-15 11:20:53 -0800690 }
691
692 m.packagingSpecs = append(m.packagingSpecs, PackagingSpec{
693 relPathInPackage: Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()),
694 srcPath: nil,
695 symlinkTarget: relPath,
696 executable: false,
697 partition: fullInstallPath.partition,
Jiyong Park4152b192024-04-30 21:24:21 +0900698 skipInstall: m.skipInstall(),
Justin Yun74f3f302024-05-07 14:32:14 +0900699 aconfigPaths: m.getAconfigPaths(),
Jiyong Parkc6a773d2024-05-14 21:49:11 +0900700 archType: m.target.Arch.ArchType,
Colin Cross69452e12023-11-15 11:20:53 -0800701 })
702
703 return fullInstallPath
704}
705
706// installPath/name -> absPath where absPath might be a path that is available only at runtime
707// (e.g. /apex/...)
708func (m *moduleContext) InstallAbsoluteSymlink(installPath InstallPath, name string, absPath string) InstallPath {
709 fullInstallPath := installPath.Join(m, name)
710 m.module.base().hooks.runInstallHooks(m, nil, fullInstallPath, true)
711
Jiyong Park3f627e62024-05-01 16:14:38 +0900712 if m.requiresFullInstall() {
Colin Cross69452e12023-11-15 11:20:53 -0800713 if m.Config().KatiEnabled() {
714 // When creating the symlink rule in Soong but embedding in Make, write the rule to a
715 // makefile instead of directly to the ninja file so that main.mk can add the
716 // dependencies from the `required` property that are hard to resolve in Soong.
717 m.katiSymlinks = append(m.katiSymlinks, katiInstall{
718 absFrom: absPath,
719 to: fullInstallPath,
720 })
721 } else {
722 m.Build(pctx, BuildParams{
723 Rule: Symlink,
724 Description: "install symlink " + fullInstallPath.Base() + " -> " + absPath,
725 Output: fullInstallPath,
726 Default: !m.Config().KatiEnabled(),
727 Args: map[string]string{
728 "fromPath": absPath,
729 },
730 })
731 }
732
733 m.installFiles = append(m.installFiles, fullInstallPath)
734 }
735
736 m.packagingSpecs = append(m.packagingSpecs, PackagingSpec{
737 relPathInPackage: Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()),
738 srcPath: nil,
739 symlinkTarget: absPath,
740 executable: false,
741 partition: fullInstallPath.partition,
Jiyong Park4152b192024-04-30 21:24:21 +0900742 skipInstall: m.skipInstall(),
Justin Yun74f3f302024-05-07 14:32:14 +0900743 aconfigPaths: m.getAconfigPaths(),
Jiyong Parkc6a773d2024-05-14 21:49:11 +0900744 archType: m.target.Arch.ArchType,
Colin Cross69452e12023-11-15 11:20:53 -0800745 })
746
747 return fullInstallPath
748}
749
Colin Cross5c1d5fb2023-11-15 12:39:40 -0800750func (m *moduleContext) InstallTestData(installPath InstallPath, data []DataPath) InstallPaths {
751 m.testData = append(m.testData, data...)
752
753 ret := make(InstallPaths, 0, len(data))
754 for _, d := range data {
755 relPath := d.ToRelativeInstallPath()
Colin Crossa6182ab2024-08-21 10:47:44 -0700756 installed := m.installFile(installPath, relPath, d.SrcPath, nil, false, false, true, nil)
Colin Cross5c1d5fb2023-11-15 12:39:40 -0800757 ret = append(ret, installed)
758 }
759
760 return ret
761}
762
Colin Crossa6182ab2024-08-21 10:47:44 -0700763// CheckbuildFile specifies the output files that should be built by checkbuild.
764func (m *moduleContext) CheckbuildFile(srcPaths ...Path) {
765 m.checkbuildFiles = append(m.checkbuildFiles, srcPaths...)
766}
767
768// UncheckedModule marks the current module has having no files that should be built by checkbuild.
769func (m *moduleContext) UncheckedModule() {
770 m.uncheckedModule = true
Colin Cross69452e12023-11-15 11:20:53 -0800771}
772
773func (m *moduleContext) blueprintModuleContext() blueprint.ModuleContext {
774 return m.bp
775}
776
777func (m *moduleContext) LicenseMetadataFile() Path {
Yu Liuec810542024-08-26 18:09:15 +0000778 return m.licenseMetadataFile
Colin Cross69452e12023-11-15 11:20:53 -0800779}
780
Colin Crossd6fd0132023-11-06 13:54:06 -0800781func (m *moduleContext) ModuleInfoJSON() *ModuleInfoJSON {
Yu Liu4297ad92024-08-27 19:50:13 +0000782 if moduleInfoJSON := m.moduleInfoJSON; moduleInfoJSON != nil {
Colin Crossd6fd0132023-11-06 13:54:06 -0800783 return moduleInfoJSON
784 }
785 moduleInfoJSON := &ModuleInfoJSON{}
Yu Liu4297ad92024-08-27 19:50:13 +0000786 m.moduleInfoJSON = moduleInfoJSON
Colin Crossd6fd0132023-11-06 13:54:06 -0800787 return moduleInfoJSON
788}
789
mrziwange6c85812024-05-22 14:36:09 -0700790func (m *moduleContext) SetOutputFiles(outputFiles Paths, tag string) {
791 if tag == "" {
Yu Liu876b7ce2024-08-21 18:20:13 +0000792 if len(m.outputFiles.DefaultOutputFiles) > 0 {
mrziwange6c85812024-05-22 14:36:09 -0700793 m.ModuleErrorf("Module %s default OutputFiles cannot be overwritten", m.ModuleName())
794 }
Yu Liu876b7ce2024-08-21 18:20:13 +0000795 m.outputFiles.DefaultOutputFiles = outputFiles
mrziwange6c85812024-05-22 14:36:09 -0700796 } else {
Yu Liu876b7ce2024-08-21 18:20:13 +0000797 if m.outputFiles.TaggedOutputFiles == nil {
798 m.outputFiles.TaggedOutputFiles = make(map[string]Paths)
mrziwang57768d72024-06-06 11:31:51 -0700799 }
Yu Liu876b7ce2024-08-21 18:20:13 +0000800 if _, exists := m.outputFiles.TaggedOutputFiles[tag]; exists {
mrziwange6c85812024-05-22 14:36:09 -0700801 m.ModuleErrorf("Module %s OutputFiles at tag %s cannot be overwritten", m.ModuleName(), tag)
802 } else {
Yu Liu876b7ce2024-08-21 18:20:13 +0000803 m.outputFiles.TaggedOutputFiles[tag] = outputFiles
mrziwange6c85812024-05-22 14:36:09 -0700804 }
805 }
806}
807
Yu Liu876b7ce2024-08-21 18:20:13 +0000808func (m *moduleContext) GetOutputFiles() OutputFilesInfo {
809 return m.outputFiles
810}
811
Yu Liubad1eef2024-08-21 22:37:35 +0000812func (m *moduleContext) SetLicenseInstallMap(installMap []string) {
813 m.licenseInstallMap = append(m.licenseInstallMap, installMap...)
814}
815
Wei Lia1aa2972024-06-21 13:08:51 -0700816func (m *moduleContext) ComplianceMetadataInfo() *ComplianceMetadataInfo {
Yu Liu9a993132024-08-27 23:21:06 +0000817 if m.complianceMetadataInfo == nil {
818 m.complianceMetadataInfo = NewComplianceMetadataInfo()
Wei Lia1aa2972024-06-21 13:08:51 -0700819 }
Yu Liu9a993132024-08-27 23:21:06 +0000820 return m.complianceMetadataInfo
Wei Lia1aa2972024-06-21 13:08:51 -0700821}
822
Colin Cross69452e12023-11-15 11:20:53 -0800823// Returns a list of paths expanded from globs and modules referenced using ":module" syntax. The property must
824// be tagged with `android:"path" to support automatic source module dependency resolution.
825//
826// Deprecated: use PathsForModuleSrc or PathsForModuleSrcExcludes instead.
827func (m *moduleContext) ExpandSources(srcFiles, excludes []string) Paths {
828 return PathsForModuleSrcExcludes(m, srcFiles, excludes)
829}
830
831// Returns a single path expanded from globs and modules referenced using ":module" syntax. The property must
832// be tagged with `android:"path" to support automatic source module dependency resolution.
833//
834// Deprecated: use PathForModuleSrc instead.
835func (m *moduleContext) ExpandSource(srcFile, _ string) Path {
836 return PathForModuleSrc(m, srcFile)
837}
838
839// Returns an optional single path expanded from globs and modules referenced using ":module" syntax if
840// the srcFile is non-nil. The property must be tagged with `android:"path" to support automatic source module
841// dependency resolution.
842func (m *moduleContext) ExpandOptionalSource(srcFile *string, _ string) OptionalPath {
843 if srcFile != nil {
844 return OptionalPathForPath(PathForModuleSrc(m, *srcFile))
845 }
846 return OptionalPath{}
847}
848
Cole Faust43ddd082024-06-17 12:32:40 -0700849func (m *moduleContext) RequiredModuleNames(ctx ConfigAndErrorContext) []string {
850 return m.module.RequiredModuleNames(ctx)
Colin Cross69452e12023-11-15 11:20:53 -0800851}
852
853func (m *moduleContext) HostRequiredModuleNames() []string {
854 return m.module.HostRequiredModuleNames()
855}
856
857func (m *moduleContext) TargetRequiredModuleNames() []string {
858 return m.module.TargetRequiredModuleNames()
859}
Yu Liu9a993132024-08-27 23:21:06 +0000860
861func (m *moduleContext) getContainersInfo() ContainersInfo {
862 return m.containersInfo
863}
864
865func (m *moduleContext) setContainersInfo(info ContainersInfo) {
866 m.containersInfo = info
867}