blob: 0b4d28c54764b048178d9b54b866c29f7ab36fc3 [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"
19 "github.com/google/blueprint"
20 "github.com/google/blueprint/proptools"
21 "path"
22 "path/filepath"
23 "strings"
24)
25
26// BuildParameters describes the set of potential parameters to build a Ninja rule.
27// In general, these correspond to a Ninja concept.
28type BuildParams struct {
29 // A Ninja Rule that will be written to the Ninja file. This allows factoring out common code
30 // among multiple modules to reduce repetition in the Ninja file of action requirements. A rule
31 // can contain variables that should be provided in Args.
32 Rule blueprint.Rule
33 // Deps represents the depfile format. When using RuleBuilder, this defaults to GCC when depfiles
34 // are used.
35 Deps blueprint.Deps
36 // Depfile is a writeable path that allows correct incremental builds when the inputs have not
37 // been fully specified by the Ninja rule. Ninja supports a subset of the Makefile depfile syntax.
38 Depfile WritablePath
39 // A description of the build action.
40 Description string
41 // Output is an output file of the action. When using this field, references to $out in the Ninja
42 // command will refer to this file.
43 Output WritablePath
44 // Outputs is a slice of output file of the action. When using this field, references to $out in
45 // the Ninja command will refer to these files.
46 Outputs WritablePaths
47 // SymlinkOutput is an output file specifically that is a symlink.
48 SymlinkOutput WritablePath
49 // SymlinkOutputs is a slice of output files specifically that is a symlink.
50 SymlinkOutputs WritablePaths
51 // ImplicitOutput is an output file generated by the action. Note: references to `$out` in the
52 // Ninja command will NOT include references to this file.
53 ImplicitOutput WritablePath
54 // ImplicitOutputs is a slice of output files generated by the action. Note: references to `$out`
55 // in the Ninja command will NOT include references to these files.
56 ImplicitOutputs WritablePaths
57 // Input is an input file to the Ninja action. When using this field, references to $in in the
58 // Ninja command will refer to this file.
59 Input Path
60 // Inputs is a slice of input files to the Ninja action. When using this field, references to $in
61 // in the Ninja command will refer to these files.
62 Inputs Paths
63 // Implicit is an input file to the Ninja action. Note: references to `$in` in the Ninja command
64 // will NOT include references to this file.
65 Implicit Path
66 // Implicits is a slice of input files to the Ninja action. Note: references to `$in` in the Ninja
67 // command will NOT include references to these files.
68 Implicits Paths
69 // OrderOnly are Ninja order-only inputs to the action. When these are out of date, the output is
70 // not rebuilt until they are built, but changes in order-only dependencies alone do not cause the
71 // output to be rebuilt.
72 OrderOnly Paths
73 // Validation is an output path for a validation action. Validation outputs imply lower
74 // non-blocking priority to building non-validation outputs.
75 Validation Path
76 // Validations is a slice of output path for a validation action. Validation outputs imply lower
77 // non-blocking priority to building non-validation outputs.
78 Validations Paths
79 // Whether to skip outputting a default target statement which will be built by Ninja when no
80 // targets are specified on Ninja's command line.
81 Default bool
82 // Args is a key value mapping for replacements of variables within the Rule
83 Args map[string]string
84}
85
86type ModuleBuildParams BuildParams
87
88type ModuleContext interface {
89 BaseModuleContext
90
91 blueprintModuleContext() blueprint.ModuleContext
92
93 // Deprecated: use ModuleContext.Build instead.
94 ModuleBuild(pctx PackageContext, params ModuleBuildParams)
95
96 // Returns a list of paths expanded from globs and modules referenced using ":module" syntax. The property must
97 // be tagged with `android:"path" to support automatic source module dependency resolution.
98 //
99 // Deprecated: use PathsForModuleSrc or PathsForModuleSrcExcludes instead.
100 ExpandSources(srcFiles, excludes []string) Paths
101
102 // Returns a single path expanded from globs and modules referenced using ":module" syntax. The property must
103 // be tagged with `android:"path" to support automatic source module dependency resolution.
104 //
105 // Deprecated: use PathForModuleSrc instead.
106 ExpandSource(srcFile, prop string) Path
107
108 ExpandOptionalSource(srcFile *string, prop string) OptionalPath
109
110 // InstallExecutable creates a rule to copy srcPath to name in the installPath directory,
111 // with the given additional dependencies. The file is marked executable after copying.
112 //
113 // The installed file will be returned by FilesToInstall(), and the PackagingSpec for the
114 // installed file will be returned by PackagingSpecs() on this module or by
115 // TransitivePackagingSpecs() on modules that depend on this module through dependency tags
116 // for which IsInstallDepNeeded returns true.
117 InstallExecutable(installPath InstallPath, name string, srcPath Path, deps ...Path) InstallPath
118
119 // InstallFile creates a rule to copy srcPath to name in the installPath directory,
120 // with the given additional dependencies.
121 //
122 // The installed file will be returned by FilesToInstall(), and the PackagingSpec for the
123 // installed file will be returned by PackagingSpecs() on this module or by
124 // TransitivePackagingSpecs() on modules that depend on this module through dependency tags
125 // for which IsInstallDepNeeded returns true.
126 InstallFile(installPath InstallPath, name string, srcPath Path, deps ...Path) InstallPath
127
128 // InstallFileWithExtraFilesZip creates a rule to copy srcPath to name in the installPath
129 // directory, and also unzip a zip file containing extra files to install into the same
130 // directory.
131 //
132 // The installed file will be returned by FilesToInstall(), and the PackagingSpec for the
133 // installed file will be returned by PackagingSpecs() on this module or by
134 // TransitivePackagingSpecs() on modules that depend on this module through dependency tags
135 // for which IsInstallDepNeeded returns true.
136 InstallFileWithExtraFilesZip(installPath InstallPath, name string, srcPath Path, extraZip Path, deps ...Path) InstallPath
137
138 // InstallSymlink creates a rule to create a symlink from src srcPath to name in the installPath
139 // directory.
140 //
141 // The installed symlink will be returned by FilesToInstall(), and the PackagingSpec for the
142 // installed file will be returned by PackagingSpecs() on this module or by
143 // TransitivePackagingSpecs() on modules that depend on this module through dependency tags
144 // for which IsInstallDepNeeded returns true.
145 InstallSymlink(installPath InstallPath, name string, srcPath InstallPath) InstallPath
146
147 // InstallAbsoluteSymlink creates a rule to create an absolute symlink from src srcPath to name
148 // in the installPath directory.
149 //
150 // The installed symlink will be returned by FilesToInstall(), and the PackagingSpec for the
151 // installed file will be returned by PackagingSpecs() on this module or by
152 // TransitivePackagingSpecs() on modules that depend on this module through dependency tags
153 // for which IsInstallDepNeeded returns true.
154 InstallAbsoluteSymlink(installPath InstallPath, name string, absPath string) InstallPath
155
156 // PackageFile creates a PackagingSpec as if InstallFile was called, but without creating
157 // the rule to copy the file. This is useful to define how a module would be packaged
158 // without installing it into the global installation directories.
159 //
160 // The created PackagingSpec for the will be returned by PackagingSpecs() on this module or by
161 // TransitivePackagingSpecs() on modules that depend on this module through dependency tags
162 // for which IsInstallDepNeeded returns true.
163 PackageFile(installPath InstallPath, name string, srcPath Path) PackagingSpec
164
165 CheckbuildFile(srcPath Path)
166
167 InstallInData() bool
168 InstallInTestcases() bool
169 InstallInSanitizerDir() bool
170 InstallInRamdisk() bool
171 InstallInVendorRamdisk() bool
172 InstallInDebugRamdisk() bool
173 InstallInRecovery() bool
174 InstallInRoot() bool
175 InstallInVendor() bool
176 InstallForceOS() (*OsType, *ArchType)
177
178 RequiredModuleNames() []string
179 HostRequiredModuleNames() []string
180 TargetRequiredModuleNames() []string
181
182 ModuleSubDir() string
183 SoongConfigTraceHash() string
184
185 Variable(pctx PackageContext, name, value string)
186 Rule(pctx PackageContext, name string, params blueprint.RuleParams, argNames ...string) blueprint.Rule
187 // Similar to blueprint.ModuleContext.Build, but takes Paths instead of []string,
188 // and performs more verification.
189 Build(pctx PackageContext, params BuildParams)
190 // Phony creates a Make-style phony rule, a rule with no commands that can depend on other
191 // phony rules or real files. Phony can be called on the same name multiple times to add
192 // additional dependencies.
193 Phony(phony string, deps ...Path)
194
195 // GetMissingDependencies returns the list of dependencies that were passed to AddDependencies or related methods,
196 // but do not exist.
197 GetMissingDependencies() []string
198
199 // LicenseMetadataFile returns the path where the license metadata for this module will be
200 // generated.
201 LicenseMetadataFile() Path
202}
203
204type moduleContext struct {
205 bp blueprint.ModuleContext
206 baseModuleContext
207 packagingSpecs []PackagingSpec
208 installFiles InstallPaths
209 checkbuildFiles Paths
210 module Module
211 phonies map[string]Paths
212
213 katiInstalls []katiInstall
214 katiSymlinks []katiInstall
215
216 // For tests
217 buildParams []BuildParams
218 ruleParams map[blueprint.Rule]blueprint.RuleParams
219 variables map[string]string
220}
221
222func (m *moduleContext) ninjaError(params BuildParams, err error) (PackageContext, BuildParams) {
223 return pctx, BuildParams{
224 Rule: ErrorRule,
225 Description: params.Description,
226 Output: params.Output,
227 Outputs: params.Outputs,
228 ImplicitOutput: params.ImplicitOutput,
229 ImplicitOutputs: params.ImplicitOutputs,
230 Args: map[string]string{
231 "error": err.Error(),
232 },
233 }
234}
235
236func (m *moduleContext) ModuleBuild(pctx PackageContext, params ModuleBuildParams) {
237 m.Build(pctx, BuildParams(params))
238}
239
240func validateBuildParams(params blueprint.BuildParams) error {
241 // Validate that the symlink outputs are declared outputs or implicit outputs
242 allOutputs := map[string]bool{}
243 for _, output := range params.Outputs {
244 allOutputs[output] = true
245 }
246 for _, output := range params.ImplicitOutputs {
247 allOutputs[output] = true
248 }
249 for _, symlinkOutput := range params.SymlinkOutputs {
250 if !allOutputs[symlinkOutput] {
251 return fmt.Errorf(
252 "Symlink output %s is not a declared output or implicit output",
253 symlinkOutput)
254 }
255 }
256 return nil
257}
258
259// Convert build parameters from their concrete Android types into their string representations,
260// and combine the singular and plural fields of the same type (e.g. Output and Outputs).
261func convertBuildParams(params BuildParams) blueprint.BuildParams {
262 bparams := blueprint.BuildParams{
263 Rule: params.Rule,
264 Description: params.Description,
265 Deps: params.Deps,
266 Outputs: params.Outputs.Strings(),
267 ImplicitOutputs: params.ImplicitOutputs.Strings(),
268 SymlinkOutputs: params.SymlinkOutputs.Strings(),
269 Inputs: params.Inputs.Strings(),
270 Implicits: params.Implicits.Strings(),
271 OrderOnly: params.OrderOnly.Strings(),
272 Validations: params.Validations.Strings(),
273 Args: params.Args,
274 Optional: !params.Default,
275 }
276
277 if params.Depfile != nil {
278 bparams.Depfile = params.Depfile.String()
279 }
280 if params.Output != nil {
281 bparams.Outputs = append(bparams.Outputs, params.Output.String())
282 }
283 if params.SymlinkOutput != nil {
284 bparams.SymlinkOutputs = append(bparams.SymlinkOutputs, params.SymlinkOutput.String())
285 }
286 if params.ImplicitOutput != nil {
287 bparams.ImplicitOutputs = append(bparams.ImplicitOutputs, params.ImplicitOutput.String())
288 }
289 if params.Input != nil {
290 bparams.Inputs = append(bparams.Inputs, params.Input.String())
291 }
292 if params.Implicit != nil {
293 bparams.Implicits = append(bparams.Implicits, params.Implicit.String())
294 }
295 if params.Validation != nil {
296 bparams.Validations = append(bparams.Validations, params.Validation.String())
297 }
298
299 bparams.Outputs = proptools.NinjaEscapeList(bparams.Outputs)
300 bparams.ImplicitOutputs = proptools.NinjaEscapeList(bparams.ImplicitOutputs)
301 bparams.SymlinkOutputs = proptools.NinjaEscapeList(bparams.SymlinkOutputs)
302 bparams.Inputs = proptools.NinjaEscapeList(bparams.Inputs)
303 bparams.Implicits = proptools.NinjaEscapeList(bparams.Implicits)
304 bparams.OrderOnly = proptools.NinjaEscapeList(bparams.OrderOnly)
305 bparams.Validations = proptools.NinjaEscapeList(bparams.Validations)
306 bparams.Depfile = proptools.NinjaEscape(bparams.Depfile)
307
308 return bparams
309}
310
311func (m *moduleContext) Variable(pctx PackageContext, name, value string) {
312 if m.config.captureBuild {
313 m.variables[name] = value
314 }
315
316 m.bp.Variable(pctx.PackageContext, name, value)
317}
318
319func (m *moduleContext) Rule(pctx PackageContext, name string, params blueprint.RuleParams,
320 argNames ...string) blueprint.Rule {
321
322 if m.config.UseRemoteBuild() {
323 if params.Pool == nil {
324 // When USE_GOMA=true or USE_RBE=true are set and the rule is not supported by goma/RBE, restrict
325 // jobs to the local parallelism value
326 params.Pool = localPool
327 } else if params.Pool == remotePool {
328 // remotePool is a fake pool used to identify rule that are supported for remoting. If the rule's
329 // pool is the remotePool, replace with nil so that ninja runs it at NINJA_REMOTE_NUM_JOBS
330 // parallelism.
331 params.Pool = nil
332 }
333 }
334
335 rule := m.bp.Rule(pctx.PackageContext, name, params, argNames...)
336
337 if m.config.captureBuild {
338 m.ruleParams[rule] = params
339 }
340
341 return rule
342}
343
344func (m *moduleContext) Build(pctx PackageContext, params BuildParams) {
345 if params.Description != "" {
346 params.Description = "${moduleDesc}" + params.Description + "${moduleDescSuffix}"
347 }
348
349 if missingDeps := m.GetMissingDependencies(); len(missingDeps) > 0 {
350 pctx, params = m.ninjaError(params, fmt.Errorf("module %s missing dependencies: %s\n",
351 m.ModuleName(), strings.Join(missingDeps, ", ")))
352 }
353
354 if m.config.captureBuild {
355 m.buildParams = append(m.buildParams, params)
356 }
357
358 bparams := convertBuildParams(params)
359 err := validateBuildParams(bparams)
360 if err != nil {
361 m.ModuleErrorf(
362 "%s: build parameter validation failed: %s",
363 m.ModuleName(),
364 err.Error())
365 }
366 m.bp.Build(pctx.PackageContext, bparams)
367}
368
369func (m *moduleContext) Phony(name string, deps ...Path) {
370 addPhony(m.config, name, deps...)
371}
372
373func (m *moduleContext) GetMissingDependencies() []string {
374 var missingDeps []string
375 missingDeps = append(missingDeps, m.Module().base().commonProperties.MissingDeps...)
376 missingDeps = append(missingDeps, m.bp.GetMissingDependencies()...)
377 missingDeps = FirstUniqueStrings(missingDeps)
378 return missingDeps
379}
380
381func (m *moduleContext) GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module {
382 module, _ := m.getDirectDepInternal(name, tag)
383 return module
384}
385
386func (m *moduleContext) ModuleSubDir() string {
387 return m.bp.ModuleSubDir()
388}
389
390func (m *moduleContext) SoongConfigTraceHash() string {
391 return m.module.base().commonProperties.SoongConfigTraceHash
392}
393
394func (m *moduleContext) InstallInData() bool {
395 return m.module.InstallInData()
396}
397
398func (m *moduleContext) InstallInTestcases() bool {
399 return m.module.InstallInTestcases()
400}
401
402func (m *moduleContext) InstallInSanitizerDir() bool {
403 return m.module.InstallInSanitizerDir()
404}
405
406func (m *moduleContext) InstallInRamdisk() bool {
407 return m.module.InstallInRamdisk()
408}
409
410func (m *moduleContext) InstallInVendorRamdisk() bool {
411 return m.module.InstallInVendorRamdisk()
412}
413
414func (m *moduleContext) InstallInDebugRamdisk() bool {
415 return m.module.InstallInDebugRamdisk()
416}
417
418func (m *moduleContext) InstallInRecovery() bool {
419 return m.module.InstallInRecovery()
420}
421
422func (m *moduleContext) InstallInRoot() bool {
423 return m.module.InstallInRoot()
424}
425
426func (m *moduleContext) InstallForceOS() (*OsType, *ArchType) {
427 return m.module.InstallForceOS()
428}
429
430func (m *moduleContext) InstallInVendor() bool {
431 return m.module.InstallInVendor()
432}
433
434func (m *moduleContext) skipInstall() bool {
435 if m.module.base().commonProperties.SkipInstall {
436 return true
437 }
438
439 if m.module.base().commonProperties.HideFromMake {
440 return true
441 }
442
443 // We'll need a solution for choosing which of modules with the same name in different
444 // namespaces to install. For now, reuse the list of namespaces exported to Make as the
445 // list of namespaces to install in a Soong-only build.
446 if !m.module.base().commonProperties.NamespaceExportedToMake {
447 return true
448 }
449
450 return false
451}
452
453func (m *moduleContext) InstallFile(installPath InstallPath, name string, srcPath Path,
454 deps ...Path) InstallPath {
455 return m.installFile(installPath, name, srcPath, deps, false, nil)
456}
457
458func (m *moduleContext) InstallExecutable(installPath InstallPath, name string, srcPath Path,
459 deps ...Path) InstallPath {
460 return m.installFile(installPath, name, srcPath, deps, true, nil)
461}
462
463func (m *moduleContext) InstallFileWithExtraFilesZip(installPath InstallPath, name string, srcPath Path,
464 extraZip Path, deps ...Path) InstallPath {
465 return m.installFile(installPath, name, srcPath, deps, false, &extraFilesZip{
466 zip: extraZip,
467 dir: installPath,
468 })
469}
470
471func (m *moduleContext) PackageFile(installPath InstallPath, name string, srcPath Path) PackagingSpec {
472 fullInstallPath := installPath.Join(m, name)
473 return m.packageFile(fullInstallPath, srcPath, false)
474}
475
476func (m *moduleContext) packageFile(fullInstallPath InstallPath, srcPath Path, executable bool) PackagingSpec {
477 licenseFiles := m.Module().EffectiveLicenseFiles()
478 spec := PackagingSpec{
479 relPathInPackage: Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()),
480 srcPath: srcPath,
481 symlinkTarget: "",
482 executable: executable,
483 effectiveLicenseFiles: &licenseFiles,
484 partition: fullInstallPath.partition,
485 }
486 m.packagingSpecs = append(m.packagingSpecs, spec)
487 return spec
488}
489
490func (m *moduleContext) installFile(installPath InstallPath, name string, srcPath Path, deps []Path,
491 executable bool, extraZip *extraFilesZip) InstallPath {
492
493 fullInstallPath := installPath.Join(m, name)
494 m.module.base().hooks.runInstallHooks(m, srcPath, fullInstallPath, false)
495
496 if !m.skipInstall() {
497 deps = append(deps, InstallPaths(m.module.base().installFilesDepSet.ToList()).Paths()...)
498
499 var implicitDeps, orderOnlyDeps Paths
500
501 if m.Host() {
502 // Installed host modules might be used during the build, depend directly on their
503 // dependencies so their timestamp is updated whenever their dependency is updated
504 implicitDeps = deps
505 } else {
506 orderOnlyDeps = deps
507 }
508
509 if m.Config().KatiEnabled() {
510 // When creating the install rule in Soong but embedding in Make, write the rule to a
511 // makefile instead of directly to the ninja file so that main.mk can add the
512 // dependencies from the `required` property that are hard to resolve in Soong.
513 m.katiInstalls = append(m.katiInstalls, katiInstall{
514 from: srcPath,
515 to: fullInstallPath,
516 implicitDeps: implicitDeps,
517 orderOnlyDeps: orderOnlyDeps,
518 executable: executable,
519 extraFiles: extraZip,
520 })
521 } else {
522 rule := Cp
523 if executable {
524 rule = CpExecutable
525 }
526
527 extraCmds := ""
528 if extraZip != nil {
529 extraCmds += fmt.Sprintf(" && ( unzip -qDD -d '%s' '%s' 2>&1 | grep -v \"zipfile is empty\"; exit $${PIPESTATUS[0]} )",
530 extraZip.dir.String(), extraZip.zip.String())
531 extraCmds += " || ( code=$$?; if [ $$code -ne 0 -a $$code -ne 1 ]; then exit $$code; fi )"
532 implicitDeps = append(implicitDeps, extraZip.zip)
533 }
534
535 m.Build(pctx, BuildParams{
536 Rule: rule,
537 Description: "install " + fullInstallPath.Base(),
538 Output: fullInstallPath,
539 Input: srcPath,
540 Implicits: implicitDeps,
541 OrderOnly: orderOnlyDeps,
542 Default: !m.Config().KatiEnabled(),
543 Args: map[string]string{
544 "extraCmds": extraCmds,
545 },
546 })
547 }
548
549 m.installFiles = append(m.installFiles, fullInstallPath)
550 }
551
552 m.packageFile(fullInstallPath, srcPath, executable)
553
554 m.checkbuildFiles = append(m.checkbuildFiles, srcPath)
555
556 return fullInstallPath
557}
558
559func (m *moduleContext) InstallSymlink(installPath InstallPath, name string, srcPath InstallPath) InstallPath {
560 fullInstallPath := installPath.Join(m, name)
561 m.module.base().hooks.runInstallHooks(m, srcPath, fullInstallPath, true)
562
563 relPath, err := filepath.Rel(path.Dir(fullInstallPath.String()), srcPath.String())
564 if err != nil {
565 panic(fmt.Sprintf("Unable to generate symlink between %q and %q: %s", fullInstallPath.Base(), srcPath.Base(), err))
566 }
567 if !m.skipInstall() {
568
569 if m.Config().KatiEnabled() {
570 // When creating the symlink rule in Soong but embedding in Make, write the rule to a
571 // makefile instead of directly to the ninja file so that main.mk can add the
572 // dependencies from the `required` property that are hard to resolve in Soong.
573 m.katiSymlinks = append(m.katiSymlinks, katiInstall{
574 from: srcPath,
575 to: fullInstallPath,
576 })
577 } else {
578 // The symlink doesn't need updating when the target is modified, but we sometimes
579 // have a dependency on a symlink to a binary instead of to the binary directly, and
580 // the mtime of the symlink must be updated when the binary is modified, so use a
581 // normal dependency here instead of an order-only dependency.
582 m.Build(pctx, BuildParams{
583 Rule: Symlink,
584 Description: "install symlink " + fullInstallPath.Base(),
585 Output: fullInstallPath,
586 Input: srcPath,
587 Default: !m.Config().KatiEnabled(),
588 Args: map[string]string{
589 "fromPath": relPath,
590 },
591 })
592 }
593
594 m.installFiles = append(m.installFiles, fullInstallPath)
595 m.checkbuildFiles = append(m.checkbuildFiles, srcPath)
596 }
597
598 m.packagingSpecs = append(m.packagingSpecs, PackagingSpec{
599 relPathInPackage: Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()),
600 srcPath: nil,
601 symlinkTarget: relPath,
602 executable: false,
603 partition: fullInstallPath.partition,
604 })
605
606 return fullInstallPath
607}
608
609// installPath/name -> absPath where absPath might be a path that is available only at runtime
610// (e.g. /apex/...)
611func (m *moduleContext) InstallAbsoluteSymlink(installPath InstallPath, name string, absPath string) InstallPath {
612 fullInstallPath := installPath.Join(m, name)
613 m.module.base().hooks.runInstallHooks(m, nil, fullInstallPath, true)
614
615 if !m.skipInstall() {
616 if m.Config().KatiEnabled() {
617 // When creating the symlink rule in Soong but embedding in Make, write the rule to a
618 // makefile instead of directly to the ninja file so that main.mk can add the
619 // dependencies from the `required` property that are hard to resolve in Soong.
620 m.katiSymlinks = append(m.katiSymlinks, katiInstall{
621 absFrom: absPath,
622 to: fullInstallPath,
623 })
624 } else {
625 m.Build(pctx, BuildParams{
626 Rule: Symlink,
627 Description: "install symlink " + fullInstallPath.Base() + " -> " + absPath,
628 Output: fullInstallPath,
629 Default: !m.Config().KatiEnabled(),
630 Args: map[string]string{
631 "fromPath": absPath,
632 },
633 })
634 }
635
636 m.installFiles = append(m.installFiles, fullInstallPath)
637 }
638
639 m.packagingSpecs = append(m.packagingSpecs, PackagingSpec{
640 relPathInPackage: Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()),
641 srcPath: nil,
642 symlinkTarget: absPath,
643 executable: false,
644 partition: fullInstallPath.partition,
645 })
646
647 return fullInstallPath
648}
649
650func (m *moduleContext) CheckbuildFile(srcPath Path) {
651 m.checkbuildFiles = append(m.checkbuildFiles, srcPath)
652}
653
654func (m *moduleContext) blueprintModuleContext() blueprint.ModuleContext {
655 return m.bp
656}
657
658func (m *moduleContext) LicenseMetadataFile() Path {
659 return m.module.base().licenseMetadataFile
660}
661
662// Returns a list of paths expanded from globs and modules referenced using ":module" syntax. The property must
663// be tagged with `android:"path" to support automatic source module dependency resolution.
664//
665// Deprecated: use PathsForModuleSrc or PathsForModuleSrcExcludes instead.
666func (m *moduleContext) ExpandSources(srcFiles, excludes []string) Paths {
667 return PathsForModuleSrcExcludes(m, srcFiles, excludes)
668}
669
670// Returns a single path expanded from globs and modules referenced using ":module" syntax. The property must
671// be tagged with `android:"path" to support automatic source module dependency resolution.
672//
673// Deprecated: use PathForModuleSrc instead.
674func (m *moduleContext) ExpandSource(srcFile, _ string) Path {
675 return PathForModuleSrc(m, srcFile)
676}
677
678// Returns an optional single path expanded from globs and modules referenced using ":module" syntax if
679// the srcFile is non-nil. The property must be tagged with `android:"path" to support automatic source module
680// dependency resolution.
681func (m *moduleContext) ExpandOptionalSource(srcFile *string, _ string) OptionalPath {
682 if srcFile != nil {
683 return OptionalPathForPath(PathForModuleSrc(m, *srcFile))
684 }
685 return OptionalPath{}
686}
687
688func (m *moduleContext) RequiredModuleNames() []string {
689 return m.module.RequiredModuleNames()
690}
691
692func (m *moduleContext) HostRequiredModuleNames() []string {
693 return m.module.HostRequiredModuleNames()
694}
695
696func (m *moduleContext) TargetRequiredModuleNames() []string {
697 return m.module.TargetRequiredModuleNames()
698}