xref: /aosp_15_r20/build/soong/android/module_context.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1// 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"
19	"path"
20	"path/filepath"
21	"slices"
22	"strings"
23
24	"github.com/google/blueprint"
25	"github.com/google/blueprint/depset"
26	"github.com/google/blueprint/proptools"
27)
28
29// BuildParameters describes the set of potential parameters to build a Ninja rule.
30// In general, these correspond to a Ninja concept.
31type BuildParams struct {
32	// A Ninja Rule that will be written to the Ninja file. This allows factoring out common code
33	// among multiple modules to reduce repetition in the Ninja file of action requirements. A rule
34	// can contain variables that should be provided in Args.
35	Rule blueprint.Rule
36	// Deps represents the depfile format. When using RuleBuilder, this defaults to GCC when depfiles
37	// are used.
38	Deps blueprint.Deps
39	// Depfile is a writeable path that allows correct incremental builds when the inputs have not
40	// been fully specified by the Ninja rule. Ninja supports a subset of the Makefile depfile syntax.
41	Depfile WritablePath
42	// A description of the build action.
43	Description string
44	// Output is an output file of the action. When using this field, references to $out in the Ninja
45	// command will refer to this file.
46	Output WritablePath
47	// Outputs is a slice of output file of the action. When using this field, references to $out in
48	// the Ninja command will refer to these files.
49	Outputs WritablePaths
50	// ImplicitOutput is an output file generated by the action. Note: references to `$out` in the
51	// Ninja command will NOT include references to this file.
52	ImplicitOutput WritablePath
53	// ImplicitOutputs is a slice of output files generated by the action. Note: references to `$out`
54	// in the Ninja command will NOT include references to these files.
55	ImplicitOutputs WritablePaths
56	// Input is an input file to the Ninja action. When using this field, references to $in in the
57	// Ninja command will refer to this file.
58	Input Path
59	// Inputs is a slice of input files to the Ninja action. When using this field, references to $in
60	// in the Ninja command will refer to these files.
61	Inputs Paths
62	// Implicit is an input file to the Ninja action. Note: references to `$in` in the Ninja command
63	// will NOT include references to this file.
64	Implicit Path
65	// Implicits is a slice of input files to the Ninja action. Note: references to `$in` in the Ninja
66	// command will NOT include references to these files.
67	Implicits Paths
68	// OrderOnly are Ninja order-only inputs to the action. When these are out of date, the output is
69	// not rebuilt until they are built, but changes in order-only dependencies alone do not cause the
70	// output to be rebuilt.
71	OrderOnly Paths
72	// Validation is an output path for a validation action. Validation outputs imply lower
73	// non-blocking priority to building non-validation outputs.
74	Validation Path
75	// Validations is a slice of output path for a validation action. Validation outputs imply lower
76	// non-blocking priority to building non-validation outputs.
77	Validations Paths
78	// Whether to skip outputting a default target statement which will be built by Ninja when no
79	// targets are specified on Ninja's command line.
80	Default bool
81	// Args is a key value mapping for replacements of variables within the Rule
82	Args map[string]string
83}
84
85type ModuleBuildParams BuildParams
86
87type ModuleContext interface {
88	BaseModuleContext
89
90	// BlueprintModuleContext returns the blueprint.ModuleContext that the ModuleContext wraps.  It may only be
91	// used by the golang module types that need to call into the bootstrap module types.
92	BlueprintModuleContext() blueprint.ModuleContext
93
94	// Deprecated: use ModuleContext.Build instead.
95	ModuleBuild(pctx PackageContext, params ModuleBuildParams)
96
97	// Returns a list of paths expanded from globs and modules referenced using ":module" syntax.  The property must
98	// be tagged with `android:"path" to support automatic source module dependency resolution.
99	//
100	// Deprecated: use PathsForModuleSrc or PathsForModuleSrcExcludes instead.
101	ExpandSources(srcFiles, excludes []string) Paths
102
103	// Returns a single path expanded from globs and modules referenced using ":module" syntax.  The property must
104	// be tagged with `android:"path" to support automatic source module dependency resolution.
105	//
106	// Deprecated: use PathForModuleSrc instead.
107	ExpandSource(srcFile, prop string) Path
108
109	ExpandOptionalSource(srcFile *string, prop string) OptionalPath
110
111	// InstallExecutable creates a rule to copy srcPath to name in the installPath directory,
112	// with the given additional dependencies.  The file is marked executable after copying.
113	//
114	// The installed file can be accessed by InstallFilesInfo.InstallFiles, and the PackagingSpec
115	// for the installed file can be accessed by InstallFilesInfo.PackagingSpecs on this module
116	// or by InstallFilesInfo.TransitivePackagingSpecs on modules that depend on this module through
117	// dependency tags for which IsInstallDepNeeded returns true.
118	InstallExecutable(installPath InstallPath, name string, srcPath Path, deps ...InstallPath) InstallPath
119
120	// InstallFile creates a rule to copy srcPath to name in the installPath directory,
121	// with the given additional dependencies.
122	//
123	// The installed file can be accessed by InstallFilesInfo.InstallFiles, and the PackagingSpec
124	// for the installed file can be accessed by InstallFilesInfo.PackagingSpecs on this module
125	// or by InstallFilesInfo.TransitivePackagingSpecs on modules that depend on this module through
126	// dependency tags for which IsInstallDepNeeded returns true.
127	InstallFile(installPath InstallPath, name string, srcPath Path, deps ...InstallPath) InstallPath
128
129	// InstallFileWithoutCheckbuild creates a rule to copy srcPath to name in the installPath directory,
130	// with the given additional dependencies, but does not add the file to the list of files to build
131	// during `m checkbuild`.
132	//
133	// The installed file will be returned by FilesToInstall(), and the PackagingSpec for the
134	// installed file will be returned by PackagingSpecs() on this module or by
135	// TransitivePackagingSpecs() on modules that depend on this module through dependency tags
136	// for which IsInstallDepNeeded returns true.
137	InstallFileWithoutCheckbuild(installPath InstallPath, name string, srcPath Path, deps ...InstallPath) InstallPath
138
139	// InstallFileWithExtraFilesZip creates a rule to copy srcPath to name in the installPath
140	// directory, and also unzip a zip file containing extra files to install into the same
141	// directory.
142	//
143	// The installed file can be accessed by InstallFilesInfo.InstallFiles, and the PackagingSpec
144	// for the installed file can be accessed by InstallFilesInfo.PackagingSpecs on this module
145	// or by InstallFilesInfo.TransitivePackagingSpecs on modules that depend on this module through
146	// dependency tags for which IsInstallDepNeeded returns true.
147	InstallFileWithExtraFilesZip(installPath InstallPath, name string, srcPath Path, extraZip Path, deps ...InstallPath) InstallPath
148
149	// InstallSymlink creates a rule to create a symlink from src srcPath to name in the installPath
150	// directory.
151	//
152	// The installed symlink can be accessed by InstallFilesInfo.InstallFiles, and the PackagingSpec
153	// for the installed file can be accessed by InstallFilesInfo.PackagingSpecs on this module
154	// or by InstallFilesInfo.TransitivePackagingSpecs on modules that depend on this module through
155	// dependency tags for which IsInstallDepNeeded returns true.
156	InstallSymlink(installPath InstallPath, name string, srcPath InstallPath) InstallPath
157
158	// InstallAbsoluteSymlink creates a rule to create an absolute symlink from src srcPath to name
159	// in the installPath directory.
160	//
161	// The installed symlink can be accessed by InstallFilesInfo.InstallFiles, and the PackagingSpec
162	// for the installed file can be accessed by InstallFilesInfo.PackagingSpecs on this module
163	// or by InstallFilesInfo.TransitivePackagingSpecs on modules that depend on this module through
164	// dependency tags for which IsInstallDepNeeded returns true.
165	InstallAbsoluteSymlink(installPath InstallPath, name string, absPath string) InstallPath
166
167	// InstallTestData creates rules to install test data (e.g. data files used during a test) into
168	// the installPath directory.
169	//
170	// The installed files can be accessed by InstallFilesInfo.InstallFiles, and the PackagingSpec
171	// for the installed files can be accessed by InstallFilesInfo.PackagingSpecs on this module
172	// or by InstallFilesInfo.TransitivePackagingSpecs on modules that depend on this module through
173	// dependency tags for which IsInstallDepNeeded returns true.
174	InstallTestData(installPath InstallPath, data []DataPath) InstallPaths
175
176	// PackageFile creates a PackagingSpec as if InstallFile was called, but without creating
177	// the rule to copy the file.  This is useful to define how a module would be packaged
178	// without installing it into the global installation directories.
179	//
180	// The created PackagingSpec can be accessed by InstallFilesInfo.PackagingSpecs on this module
181	// or by InstallFilesInfo.TransitivePackagingSpecs on modules that depend on this module through
182	// dependency tags for which IsInstallDepNeeded returns true.
183	PackageFile(installPath InstallPath, name string, srcPath Path) PackagingSpec
184
185	CheckbuildFile(srcPaths ...Path)
186	UncheckedModule()
187
188	InstallInData() bool
189	InstallInTestcases() bool
190	InstallInSanitizerDir() bool
191	InstallInRamdisk() bool
192	InstallInVendorRamdisk() bool
193	InstallInDebugRamdisk() bool
194	InstallInRecovery() bool
195	InstallInRoot() bool
196	InstallInOdm() bool
197	InstallInProduct() bool
198	InstallInVendor() bool
199	InstallInSystemDlkm() bool
200	InstallInVendorDlkm() bool
201	InstallInOdmDlkm() bool
202	InstallForceOS() (*OsType, *ArchType)
203
204	RequiredModuleNames(ctx ConfigurableEvaluatorContext) []string
205	HostRequiredModuleNames() []string
206	TargetRequiredModuleNames() []string
207
208	ModuleSubDir() string
209
210	Variable(pctx PackageContext, name, value string)
211	Rule(pctx PackageContext, name string, params blueprint.RuleParams, argNames ...string) blueprint.Rule
212	// Similar to blueprint.ModuleContext.Build, but takes Paths instead of []string,
213	// and performs more verification.
214	Build(pctx PackageContext, params BuildParams)
215	// Phony creates a Make-style phony rule, a rule with no commands that can depend on other
216	// phony rules or real files.  Phony can be called on the same name multiple times to add
217	// additional dependencies.
218	Phony(phony string, deps ...Path)
219
220	// GetMissingDependencies returns the list of dependencies that were passed to AddDependencies or related methods,
221	// but do not exist.
222	GetMissingDependencies() []string
223
224	// LicenseMetadataFile returns the path where the license metadata for this module will be
225	// generated.
226	LicenseMetadataFile() Path
227
228	// ModuleInfoJSON returns a pointer to the ModuleInfoJSON struct that can be filled out by
229	// GenerateAndroidBuildActions.  If it is called then the struct will be written out and included in
230	// the module-info.json generated by Make, and Make will not generate its own data for this module.
231	ModuleInfoJSON() *ModuleInfoJSON
232
233	// SetOutputFiles stores the outputFiles to outputFiles property, which is used
234	// to set the OutputFilesProvider later.
235	SetOutputFiles(outputFiles Paths, tag string)
236
237	GetOutputFiles() OutputFilesInfo
238
239	// SetLicenseInstallMap stores the set of dependency module:location mappings for files in an
240	// apex container for use when generation the license metadata file.
241	SetLicenseInstallMap(installMap []string)
242
243	// ComplianceMetadataInfo returns a ComplianceMetadataInfo instance for different module types to dump metadata,
244	// which usually happens in GenerateAndroidBuildActions() of a module type.
245	// See android.ModuleBase.complianceMetadataInfo
246	ComplianceMetadataInfo() *ComplianceMetadataInfo
247
248	// Get the information about the containers this module belongs to.
249	getContainersInfo() ContainersInfo
250	setContainersInfo(info ContainersInfo)
251
252	setAconfigPaths(paths Paths)
253}
254
255type moduleContext struct {
256	bp blueprint.ModuleContext
257	baseModuleContext
258	packagingSpecs   []PackagingSpec
259	installFiles     InstallPaths
260	checkbuildFiles  Paths
261	checkbuildTarget Path
262	uncheckedModule  bool
263	module           Module
264	phonies          map[string]Paths
265	// outputFiles stores the output of a module by tag and is used to set
266	// the OutputFilesProvider in GenerateBuildActions
267	outputFiles OutputFilesInfo
268
269	TransitiveInstallFiles depset.DepSet[InstallPath]
270
271	// set of dependency module:location mappings used to populate the license metadata for
272	// apex containers.
273	licenseInstallMap []string
274
275	// The path to the generated license metadata file for the module.
276	licenseMetadataFile WritablePath
277
278	katiInstalls katiInstalls
279	katiSymlinks katiInstalls
280	// katiInitRcInstalls and katiVintfInstalls track the install rules created by Soong that are
281	// allowed to have duplicates across modules and variants.
282	katiInitRcInstalls           katiInstalls
283	katiVintfInstalls            katiInstalls
284	initRcPaths                  Paths
285	vintfFragmentsPaths          Paths
286	installedInitRcPaths         InstallPaths
287	installedVintfFragmentsPaths InstallPaths
288
289	testData []DataPath
290
291	// For tests
292	buildParams []BuildParams
293	ruleParams  map[blueprint.Rule]blueprint.RuleParams
294	variables   map[string]string
295
296	// moduleInfoJSON can be filled out by GenerateAndroidBuildActions to write a JSON file that will
297	// be included in the final module-info.json produced by Make.
298	moduleInfoJSON *ModuleInfoJSON
299
300	// containersInfo stores the information about the containers and the information of the
301	// apexes the module belongs to.
302	containersInfo ContainersInfo
303
304	// Merged Aconfig files for all transitive deps.
305	aconfigFilePaths Paths
306
307	// complianceMetadataInfo is for different module types to dump metadata.
308	// See android.ModuleContext interface.
309	complianceMetadataInfo *ComplianceMetadataInfo
310}
311
312var _ ModuleContext = &moduleContext{}
313
314func (m *moduleContext) ninjaError(params BuildParams, err error) (PackageContext, BuildParams) {
315	return pctx, BuildParams{
316		Rule:            ErrorRule,
317		Description:     params.Description,
318		Output:          params.Output,
319		Outputs:         params.Outputs,
320		ImplicitOutput:  params.ImplicitOutput,
321		ImplicitOutputs: params.ImplicitOutputs,
322		Args: map[string]string{
323			"error": err.Error(),
324		},
325	}
326}
327
328func (m *moduleContext) ModuleBuild(pctx PackageContext, params ModuleBuildParams) {
329	m.Build(pctx, BuildParams(params))
330}
331
332// Convert build parameters from their concrete Android types into their string representations,
333// and combine the singular and plural fields of the same type (e.g. Output and Outputs).
334func convertBuildParams(params BuildParams) blueprint.BuildParams {
335	bparams := blueprint.BuildParams{
336		Rule:            params.Rule,
337		Description:     params.Description,
338		Deps:            params.Deps,
339		Outputs:         params.Outputs.Strings(),
340		ImplicitOutputs: params.ImplicitOutputs.Strings(),
341		Inputs:          params.Inputs.Strings(),
342		Implicits:       params.Implicits.Strings(),
343		OrderOnly:       params.OrderOnly.Strings(),
344		Validations:     params.Validations.Strings(),
345		Args:            params.Args,
346		Optional:        !params.Default,
347	}
348
349	if params.Depfile != nil {
350		bparams.Depfile = params.Depfile.String()
351	}
352	if params.Output != nil {
353		bparams.Outputs = append(bparams.Outputs, params.Output.String())
354	}
355	if params.ImplicitOutput != nil {
356		bparams.ImplicitOutputs = append(bparams.ImplicitOutputs, params.ImplicitOutput.String())
357	}
358	if params.Input != nil {
359		bparams.Inputs = append(bparams.Inputs, params.Input.String())
360	}
361	if params.Implicit != nil {
362		bparams.Implicits = append(bparams.Implicits, params.Implicit.String())
363	}
364	if params.Validation != nil {
365		bparams.Validations = append(bparams.Validations, params.Validation.String())
366	}
367
368	bparams.Outputs = proptools.NinjaEscapeList(bparams.Outputs)
369	bparams.ImplicitOutputs = proptools.NinjaEscapeList(bparams.ImplicitOutputs)
370	bparams.Inputs = proptools.NinjaEscapeList(bparams.Inputs)
371	bparams.Implicits = proptools.NinjaEscapeList(bparams.Implicits)
372	bparams.OrderOnly = proptools.NinjaEscapeList(bparams.OrderOnly)
373	bparams.Validations = proptools.NinjaEscapeList(bparams.Validations)
374	bparams.Depfile = proptools.NinjaEscape(bparams.Depfile)
375
376	return bparams
377}
378
379func (m *moduleContext) Variable(pctx PackageContext, name, value string) {
380	if m.config.captureBuild {
381		m.variables[name] = value
382	}
383
384	m.bp.Variable(pctx.PackageContext, name, value)
385}
386
387func (m *moduleContext) Rule(pctx PackageContext, name string, params blueprint.RuleParams,
388	argNames ...string) blueprint.Rule {
389
390	if m.config.UseRemoteBuild() {
391		if params.Pool == nil {
392			// When USE_GOMA=true or USE_RBE=true are set and the rule is not supported by goma/RBE, restrict
393			// jobs to the local parallelism value
394			params.Pool = localPool
395		} else if params.Pool == remotePool {
396			// remotePool is a fake pool used to identify rule that are supported for remoting. If the rule's
397			// pool is the remotePool, replace with nil so that ninja runs it at NINJA_REMOTE_NUM_JOBS
398			// parallelism.
399			params.Pool = nil
400		}
401	}
402
403	rule := m.bp.Rule(pctx.PackageContext, name, params, argNames...)
404
405	if m.config.captureBuild {
406		m.ruleParams[rule] = params
407	}
408
409	return rule
410}
411
412func (m *moduleContext) Build(pctx PackageContext, params BuildParams) {
413	if params.Description != "" {
414		params.Description = "${moduleDesc}" + params.Description + "${moduleDescSuffix}"
415	}
416
417	if missingDeps := m.GetMissingDependencies(); len(missingDeps) > 0 {
418		pctx, params = m.ninjaError(params, fmt.Errorf("module %s missing dependencies: %s\n",
419			m.ModuleName(), strings.Join(missingDeps, ", ")))
420	}
421
422	if m.config.captureBuild {
423		m.buildParams = append(m.buildParams, params)
424	}
425
426	bparams := convertBuildParams(params)
427	m.bp.Build(pctx.PackageContext, bparams)
428}
429
430func (m *moduleContext) Phony(name string, deps ...Path) {
431	m.phonies[name] = append(m.phonies[name], deps...)
432}
433
434func (m *moduleContext) GetMissingDependencies() []string {
435	var missingDeps []string
436	missingDeps = append(missingDeps, m.Module().base().commonProperties.MissingDeps...)
437	missingDeps = append(missingDeps, m.bp.GetMissingDependencies()...)
438	missingDeps = FirstUniqueStrings(missingDeps)
439	return missingDeps
440}
441
442func (m *moduleContext) GetDirectDepWithTag(name string, tag blueprint.DependencyTag) Module {
443	if module, _ := m.getDirectDepInternal(name, tag); module != nil {
444		return module.(Module)
445	}
446	return nil
447}
448
449func (m *moduleContext) ModuleSubDir() string {
450	return m.bp.ModuleSubDir()
451}
452
453func (m *moduleContext) InstallInData() bool {
454	return m.module.InstallInData()
455}
456
457func (m *moduleContext) InstallInTestcases() bool {
458	return m.module.InstallInTestcases()
459}
460
461func (m *moduleContext) InstallInSanitizerDir() bool {
462	return m.module.InstallInSanitizerDir()
463}
464
465func (m *moduleContext) InstallInRamdisk() bool {
466	return m.module.InstallInRamdisk()
467}
468
469func (m *moduleContext) InstallInVendorRamdisk() bool {
470	return m.module.InstallInVendorRamdisk()
471}
472
473func (m *moduleContext) InstallInDebugRamdisk() bool {
474	return m.module.InstallInDebugRamdisk()
475}
476
477func (m *moduleContext) InstallInRecovery() bool {
478	return m.module.InstallInRecovery()
479}
480
481func (m *moduleContext) InstallInRoot() bool {
482	return m.module.InstallInRoot()
483}
484
485func (m *moduleContext) InstallForceOS() (*OsType, *ArchType) {
486	return m.module.InstallForceOS()
487}
488
489func (m *moduleContext) InstallInOdm() bool {
490	return m.module.InstallInOdm()
491}
492
493func (m *moduleContext) InstallInProduct() bool {
494	return m.module.InstallInProduct()
495}
496
497func (m *moduleContext) InstallInVendor() bool {
498	return m.module.InstallInVendor()
499}
500
501func (m *moduleContext) InstallInSystemDlkm() bool {
502	return m.module.InstallInSystemDlkm()
503}
504
505func (m *moduleContext) InstallInVendorDlkm() bool {
506	return m.module.InstallInVendorDlkm()
507}
508
509func (m *moduleContext) InstallInOdmDlkm() bool {
510	return m.module.InstallInOdmDlkm()
511}
512
513func (m *moduleContext) skipInstall() bool {
514	if m.module.base().commonProperties.SkipInstall {
515		return true
516	}
517
518	// We'll need a solution for choosing which of modules with the same name in different
519	// namespaces to install.  For now, reuse the list of namespaces exported to Make as the
520	// list of namespaces to install in a Soong-only build.
521	if !m.module.base().commonProperties.NamespaceExportedToMake {
522		return true
523	}
524
525	return false
526}
527
528// Tells whether this module is installed to the full install path (ex:
529// out/target/product/<name>/<partition>) or not. If this returns false, the install build rule is
530// not created and this module can only be installed to packaging modules like android_filesystem.
531func (m *moduleContext) requiresFullInstall() bool {
532	if m.skipInstall() {
533		return false
534	}
535
536	if m.module.base().commonProperties.HideFromMake {
537		return false
538	}
539
540	if proptools.Bool(m.module.base().commonProperties.No_full_install) {
541		return false
542	}
543
544	return true
545}
546
547func (m *moduleContext) InstallFile(installPath InstallPath, name string, srcPath Path,
548	deps ...InstallPath) InstallPath {
549	return m.installFile(installPath, name, srcPath, deps, false, true, true, nil)
550}
551
552func (m *moduleContext) InstallFileWithoutCheckbuild(installPath InstallPath, name string, srcPath Path,
553	deps ...InstallPath) InstallPath {
554	return m.installFile(installPath, name, srcPath, deps, false, true, false, nil)
555}
556
557func (m *moduleContext) InstallExecutable(installPath InstallPath, name string, srcPath Path,
558	deps ...InstallPath) InstallPath {
559	return m.installFile(installPath, name, srcPath, deps, true, true, true, nil)
560}
561
562func (m *moduleContext) InstallFileWithExtraFilesZip(installPath InstallPath, name string, srcPath Path,
563	extraZip Path, deps ...InstallPath) InstallPath {
564	return m.installFile(installPath, name, srcPath, deps, false, true, true, &extraFilesZip{
565		zip: extraZip,
566		dir: installPath,
567	})
568}
569
570func (m *moduleContext) PackageFile(installPath InstallPath, name string, srcPath Path) PackagingSpec {
571	fullInstallPath := installPath.Join(m, name)
572	return m.packageFile(fullInstallPath, srcPath, false)
573}
574
575func (m *moduleContext) getAconfigPaths() *Paths {
576	return &m.aconfigFilePaths
577}
578
579func (m *moduleContext) setAconfigPaths(paths Paths) {
580	m.aconfigFilePaths = paths
581}
582
583func (m *moduleContext) getOwnerAndOverrides() (string, []string) {
584	owner := m.ModuleName()
585	overrides := slices.Clone(m.Module().base().commonProperties.Overrides)
586	if b, ok := m.Module().(OverridableModule); ok {
587		if b.GetOverriddenBy() != "" {
588			// overriding variant of base module
589			overrides = append(overrides, m.ModuleName()) // com.android.foo
590			owner = m.Module().Name()                     // com.company.android.foo
591		}
592	}
593	return owner, overrides
594}
595
596func (m *moduleContext) packageFile(fullInstallPath InstallPath, srcPath Path, executable bool) PackagingSpec {
597	licenseFiles := m.Module().EffectiveLicenseFiles()
598	owner, overrides := m.getOwnerAndOverrides()
599	spec := PackagingSpec{
600		relPathInPackage:      Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()),
601		srcPath:               srcPath,
602		symlinkTarget:         "",
603		executable:            executable,
604		effectiveLicenseFiles: &licenseFiles,
605		partition:             fullInstallPath.partition,
606		skipInstall:           m.skipInstall(),
607		aconfigPaths:          m.getAconfigPaths(),
608		archType:              m.target.Arch.ArchType,
609		overrides:             &overrides,
610		owner:                 owner,
611	}
612	m.packagingSpecs = append(m.packagingSpecs, spec)
613	return spec
614}
615
616func (m *moduleContext) installFile(installPath InstallPath, name string, srcPath Path, deps []InstallPath,
617	executable bool, hooks bool, checkbuild bool, extraZip *extraFilesZip) InstallPath {
618
619	fullInstallPath := installPath.Join(m, name)
620	if hooks {
621		m.module.base().hooks.runInstallHooks(m, srcPath, fullInstallPath, false)
622	}
623
624	if m.requiresFullInstall() {
625		deps = append(deps, InstallPaths(m.TransitiveInstallFiles.ToList())...)
626		deps = append(deps, m.installedInitRcPaths...)
627		deps = append(deps, m.installedVintfFragmentsPaths...)
628
629		var implicitDeps, orderOnlyDeps Paths
630
631		if m.Host() {
632			// Installed host modules might be used during the build, depend directly on their
633			// dependencies so their timestamp is updated whenever their dependency is updated
634			implicitDeps = InstallPaths(deps).Paths()
635		} else {
636			orderOnlyDeps = InstallPaths(deps).Paths()
637		}
638
639		if m.Config().KatiEnabled() {
640			// When creating the install rule in Soong but embedding in Make, write the rule to a
641			// makefile instead of directly to the ninja file so that main.mk can add the
642			// dependencies from the `required` property that are hard to resolve in Soong.
643			m.katiInstalls = append(m.katiInstalls, katiInstall{
644				from:          srcPath,
645				to:            fullInstallPath,
646				implicitDeps:  implicitDeps,
647				orderOnlyDeps: orderOnlyDeps,
648				executable:    executable,
649				extraFiles:    extraZip,
650			})
651		} else {
652			rule := Cp
653			if executable {
654				rule = CpExecutable
655			}
656
657			extraCmds := ""
658			if extraZip != nil {
659				extraCmds += fmt.Sprintf(" && ( unzip -qDD -d '%s' '%s' 2>&1 | grep -v \"zipfile is empty\"; exit $${PIPESTATUS[0]} )",
660					extraZip.dir.String(), extraZip.zip.String())
661				extraCmds += " || ( code=$$?; if [ $$code -ne 0 -a $$code -ne 1 ]; then exit $$code; fi )"
662				implicitDeps = append(implicitDeps, extraZip.zip)
663			}
664
665			m.Build(pctx, BuildParams{
666				Rule:        rule,
667				Description: "install " + fullInstallPath.Base(),
668				Output:      fullInstallPath,
669				Input:       srcPath,
670				Implicits:   implicitDeps,
671				OrderOnly:   orderOnlyDeps,
672				Default:     !m.Config().KatiEnabled(),
673				Args: map[string]string{
674					"extraCmds": extraCmds,
675				},
676			})
677		}
678
679		m.installFiles = append(m.installFiles, fullInstallPath)
680	}
681
682	m.packageFile(fullInstallPath, srcPath, executable)
683
684	if checkbuild {
685		m.checkbuildFiles = append(m.checkbuildFiles, srcPath)
686	}
687
688	return fullInstallPath
689}
690
691func (m *moduleContext) InstallSymlink(installPath InstallPath, name string, srcPath InstallPath) InstallPath {
692	fullInstallPath := installPath.Join(m, name)
693	m.module.base().hooks.runInstallHooks(m, srcPath, fullInstallPath, true)
694
695	relPath, err := filepath.Rel(path.Dir(fullInstallPath.String()), srcPath.String())
696	if err != nil {
697		panic(fmt.Sprintf("Unable to generate symlink between %q and %q: %s", fullInstallPath.Base(), srcPath.Base(), err))
698	}
699	if m.requiresFullInstall() {
700
701		if m.Config().KatiEnabled() {
702			// When creating the symlink rule in Soong but embedding in Make, write the rule to a
703			// makefile instead of directly to the ninja file so that main.mk can add the
704			// dependencies from the `required` property that are hard to resolve in Soong.
705			m.katiSymlinks = append(m.katiSymlinks, katiInstall{
706				from: srcPath,
707				to:   fullInstallPath,
708			})
709		} else {
710			// The symlink doesn't need updating when the target is modified, but we sometimes
711			// have a dependency on a symlink to a binary instead of to the binary directly, and
712			// the mtime of the symlink must be updated when the binary is modified, so use a
713			// normal dependency here instead of an order-only dependency.
714			m.Build(pctx, BuildParams{
715				Rule:        Symlink,
716				Description: "install symlink " + fullInstallPath.Base(),
717				Output:      fullInstallPath,
718				Input:       srcPath,
719				Default:     !m.Config().KatiEnabled(),
720				Args: map[string]string{
721					"fromPath": relPath,
722				},
723			})
724		}
725
726		m.installFiles = append(m.installFiles, fullInstallPath)
727	}
728
729	owner, overrides := m.getOwnerAndOverrides()
730	m.packagingSpecs = append(m.packagingSpecs, PackagingSpec{
731		relPathInPackage: Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()),
732		srcPath:          nil,
733		symlinkTarget:    relPath,
734		executable:       false,
735		partition:        fullInstallPath.partition,
736		skipInstall:      m.skipInstall(),
737		aconfigPaths:     m.getAconfigPaths(),
738		archType:         m.target.Arch.ArchType,
739		overrides:        &overrides,
740		owner:            owner,
741	})
742
743	return fullInstallPath
744}
745
746// installPath/name -> absPath where absPath might be a path that is available only at runtime
747// (e.g. /apex/...)
748func (m *moduleContext) InstallAbsoluteSymlink(installPath InstallPath, name string, absPath string) InstallPath {
749	fullInstallPath := installPath.Join(m, name)
750	m.module.base().hooks.runInstallHooks(m, nil, fullInstallPath, true)
751
752	if m.requiresFullInstall() {
753		if m.Config().KatiEnabled() {
754			// When creating the symlink rule in Soong but embedding in Make, write the rule to a
755			// makefile instead of directly to the ninja file so that main.mk can add the
756			// dependencies from the `required` property that are hard to resolve in Soong.
757			m.katiSymlinks = append(m.katiSymlinks, katiInstall{
758				absFrom: absPath,
759				to:      fullInstallPath,
760			})
761		} else {
762			m.Build(pctx, BuildParams{
763				Rule:        Symlink,
764				Description: "install symlink " + fullInstallPath.Base() + " -> " + absPath,
765				Output:      fullInstallPath,
766				Default:     !m.Config().KatiEnabled(),
767				Args: map[string]string{
768					"fromPath": absPath,
769				},
770			})
771		}
772
773		m.installFiles = append(m.installFiles, fullInstallPath)
774	}
775
776	owner, overrides := m.getOwnerAndOverrides()
777	m.packagingSpecs = append(m.packagingSpecs, PackagingSpec{
778		relPathInPackage: Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()),
779		srcPath:          nil,
780		symlinkTarget:    absPath,
781		executable:       false,
782		partition:        fullInstallPath.partition,
783		skipInstall:      m.skipInstall(),
784		aconfigPaths:     m.getAconfigPaths(),
785		archType:         m.target.Arch.ArchType,
786		overrides:        &overrides,
787		owner:            owner,
788	})
789
790	return fullInstallPath
791}
792
793func (m *moduleContext) InstallTestData(installPath InstallPath, data []DataPath) InstallPaths {
794	m.testData = append(m.testData, data...)
795
796	ret := make(InstallPaths, 0, len(data))
797	for _, d := range data {
798		relPath := d.ToRelativeInstallPath()
799		installed := m.installFile(installPath, relPath, d.SrcPath, nil, false, false, true, nil)
800		ret = append(ret, installed)
801	}
802
803	return ret
804}
805
806// CheckbuildFile specifies the output files that should be built by checkbuild.
807func (m *moduleContext) CheckbuildFile(srcPaths ...Path) {
808	m.checkbuildFiles = append(m.checkbuildFiles, srcPaths...)
809}
810
811// UncheckedModule marks the current module has having no files that should be built by checkbuild.
812func (m *moduleContext) UncheckedModule() {
813	m.uncheckedModule = true
814}
815
816func (m *moduleContext) BlueprintModuleContext() blueprint.ModuleContext {
817	return m.bp
818}
819
820func (m *moduleContext) LicenseMetadataFile() Path {
821	return m.licenseMetadataFile
822}
823
824func (m *moduleContext) ModuleInfoJSON() *ModuleInfoJSON {
825	if moduleInfoJSON := m.moduleInfoJSON; moduleInfoJSON != nil {
826		return moduleInfoJSON
827	}
828	moduleInfoJSON := &ModuleInfoJSON{}
829	m.moduleInfoJSON = moduleInfoJSON
830	return moduleInfoJSON
831}
832
833func (m *moduleContext) SetOutputFiles(outputFiles Paths, tag string) {
834	for _, outputFile := range outputFiles {
835		if outputFile == nil {
836			panic("outputfiles cannot be nil")
837		}
838	}
839	if tag == "" {
840		if len(m.outputFiles.DefaultOutputFiles) > 0 {
841			m.ModuleErrorf("Module %s default OutputFiles cannot be overwritten", m.ModuleName())
842		}
843		m.outputFiles.DefaultOutputFiles = outputFiles
844	} else {
845		if m.outputFiles.TaggedOutputFiles == nil {
846			m.outputFiles.TaggedOutputFiles = make(map[string]Paths)
847		}
848		if _, exists := m.outputFiles.TaggedOutputFiles[tag]; exists {
849			m.ModuleErrorf("Module %s OutputFiles at tag %s cannot be overwritten", m.ModuleName(), tag)
850		} else {
851			m.outputFiles.TaggedOutputFiles[tag] = outputFiles
852		}
853	}
854}
855
856func (m *moduleContext) GetOutputFiles() OutputFilesInfo {
857	return m.outputFiles
858}
859
860func (m *moduleContext) SetLicenseInstallMap(installMap []string) {
861	m.licenseInstallMap = append(m.licenseInstallMap, installMap...)
862}
863
864func (m *moduleContext) ComplianceMetadataInfo() *ComplianceMetadataInfo {
865	if m.complianceMetadataInfo == nil {
866		m.complianceMetadataInfo = NewComplianceMetadataInfo()
867	}
868	return m.complianceMetadataInfo
869}
870
871// Returns a list of paths expanded from globs and modules referenced using ":module" syntax.  The property must
872// be tagged with `android:"path" to support automatic source module dependency resolution.
873//
874// Deprecated: use PathsForModuleSrc or PathsForModuleSrcExcludes instead.
875func (m *moduleContext) ExpandSources(srcFiles, excludes []string) Paths {
876	return PathsForModuleSrcExcludes(m, srcFiles, excludes)
877}
878
879// Returns a single path expanded from globs and modules referenced using ":module" syntax.  The property must
880// be tagged with `android:"path" to support automatic source module dependency resolution.
881//
882// Deprecated: use PathForModuleSrc instead.
883func (m *moduleContext) ExpandSource(srcFile, _ string) Path {
884	return PathForModuleSrc(m, srcFile)
885}
886
887// Returns an optional single path expanded from globs and modules referenced using ":module" syntax if
888// the srcFile is non-nil.  The property must be tagged with `android:"path" to support automatic source module
889// dependency resolution.
890func (m *moduleContext) ExpandOptionalSource(srcFile *string, _ string) OptionalPath {
891	if srcFile != nil {
892		return OptionalPathForPath(PathForModuleSrc(m, *srcFile))
893	}
894	return OptionalPath{}
895}
896
897func (m *moduleContext) RequiredModuleNames(ctx ConfigurableEvaluatorContext) []string {
898	return m.module.RequiredModuleNames(ctx)
899}
900
901func (m *moduleContext) HostRequiredModuleNames() []string {
902	return m.module.HostRequiredModuleNames()
903}
904
905func (m *moduleContext) TargetRequiredModuleNames() []string {
906	return m.module.TargetRequiredModuleNames()
907}
908
909func (m *moduleContext) getContainersInfo() ContainersInfo {
910	return m.containersInfo
911}
912
913func (m *moduleContext) setContainersInfo(info ContainersInfo) {
914	m.containersInfo = info
915}
916