blob: e772f8bc4e7e06608ff082dc31660893a54fd52b [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.
Colin Cross09ad3a62023-11-15 12:29:33 -0800117 InstallExecutable(installPath InstallPath, name string, srcPath Path, deps ...InstallPath) InstallPath
Colin Cross69452e12023-11-15 11:20:53 -0800118
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.
Colin Cross09ad3a62023-11-15 12:29:33 -0800126 InstallFile(installPath InstallPath, name string, srcPath Path, deps ...InstallPath) InstallPath
Colin Cross69452e12023-11-15 11:20:53 -0800127
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.
Colin Cross09ad3a62023-11-15 12:29:33 -0800136 InstallFileWithExtraFilesZip(installPath InstallPath, name string, srcPath Path, extraZip Path, deps ...InstallPath) InstallPath
Colin Cross69452e12023-11-15 11:20:53 -0800137
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
Colin Cross5c1d5fb2023-11-15 12:39:40 -0800156 // InstallTestData creates rules to install test data (e.g. data files used during a test) into
157 // the installPath directory.
158 //
159 // The installed files will be returned by FilesToInstall(), and the PackagingSpec for the
160 // installed files 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 InstallTestData(installPath InstallPath, data []DataPath) InstallPaths
164
Colin Cross69452e12023-11-15 11:20:53 -0800165 // PackageFile creates a PackagingSpec as if InstallFile was called, but without creating
166 // the rule to copy the file. This is useful to define how a module would be packaged
167 // without installing it into the global installation directories.
168 //
169 // The created PackagingSpec for the will be returned by PackagingSpecs() on this module or by
170 // TransitivePackagingSpecs() on modules that depend on this module through dependency tags
171 // for which IsInstallDepNeeded returns true.
172 PackageFile(installPath InstallPath, name string, srcPath Path) PackagingSpec
173
174 CheckbuildFile(srcPath Path)
175
176 InstallInData() bool
177 InstallInTestcases() bool
178 InstallInSanitizerDir() bool
179 InstallInRamdisk() bool
180 InstallInVendorRamdisk() bool
181 InstallInDebugRamdisk() bool
182 InstallInRecovery() bool
183 InstallInRoot() bool
Colin Crossea30d852023-11-29 16:00:16 -0800184 InstallInOdm() bool
185 InstallInProduct() bool
Colin Cross69452e12023-11-15 11:20:53 -0800186 InstallInVendor() bool
187 InstallForceOS() (*OsType, *ArchType)
188
189 RequiredModuleNames() []string
190 HostRequiredModuleNames() []string
191 TargetRequiredModuleNames() []string
192
193 ModuleSubDir() string
194 SoongConfigTraceHash() string
195
196 Variable(pctx PackageContext, name, value string)
197 Rule(pctx PackageContext, name string, params blueprint.RuleParams, argNames ...string) blueprint.Rule
198 // Similar to blueprint.ModuleContext.Build, but takes Paths instead of []string,
199 // and performs more verification.
200 Build(pctx PackageContext, params BuildParams)
201 // Phony creates a Make-style phony rule, a rule with no commands that can depend on other
202 // phony rules or real files. Phony can be called on the same name multiple times to add
203 // additional dependencies.
204 Phony(phony string, deps ...Path)
205
206 // GetMissingDependencies returns the list of dependencies that were passed to AddDependencies or related methods,
207 // but do not exist.
208 GetMissingDependencies() []string
209
210 // LicenseMetadataFile returns the path where the license metadata for this module will be
211 // generated.
212 LicenseMetadataFile() Path
Colin Crossd6fd0132023-11-06 13:54:06 -0800213
214 // ModuleInfoJSON returns a pointer to the ModuleInfoJSON struct that can be filled out by
215 // GenerateAndroidBuildActions. If it is called then the struct will be written out and included in
216 // the module-info.json generated by Make, and Make will not generate its own data for this module.
217 ModuleInfoJSON() *ModuleInfoJSON
Colin Cross69452e12023-11-15 11:20:53 -0800218}
219
220type moduleContext struct {
221 bp blueprint.ModuleContext
222 baseModuleContext
223 packagingSpecs []PackagingSpec
224 installFiles InstallPaths
225 checkbuildFiles Paths
226 module Module
227 phonies map[string]Paths
228
229 katiInstalls []katiInstall
230 katiSymlinks []katiInstall
231
Colin Cross5c1d5fb2023-11-15 12:39:40 -0800232 testData []DataPath
233
Colin Cross69452e12023-11-15 11:20:53 -0800234 // For tests
235 buildParams []BuildParams
236 ruleParams map[blueprint.Rule]blueprint.RuleParams
237 variables map[string]string
238}
239
240func (m *moduleContext) ninjaError(params BuildParams, err error) (PackageContext, BuildParams) {
241 return pctx, BuildParams{
242 Rule: ErrorRule,
243 Description: params.Description,
244 Output: params.Output,
245 Outputs: params.Outputs,
246 ImplicitOutput: params.ImplicitOutput,
247 ImplicitOutputs: params.ImplicitOutputs,
248 Args: map[string]string{
249 "error": err.Error(),
250 },
251 }
252}
253
254func (m *moduleContext) ModuleBuild(pctx PackageContext, params ModuleBuildParams) {
255 m.Build(pctx, BuildParams(params))
256}
257
258func validateBuildParams(params blueprint.BuildParams) error {
259 // Validate that the symlink outputs are declared outputs or implicit outputs
260 allOutputs := map[string]bool{}
261 for _, output := range params.Outputs {
262 allOutputs[output] = true
263 }
264 for _, output := range params.ImplicitOutputs {
265 allOutputs[output] = true
266 }
267 for _, symlinkOutput := range params.SymlinkOutputs {
268 if !allOutputs[symlinkOutput] {
269 return fmt.Errorf(
270 "Symlink output %s is not a declared output or implicit output",
271 symlinkOutput)
272 }
273 }
274 return nil
275}
276
277// Convert build parameters from their concrete Android types into their string representations,
278// and combine the singular and plural fields of the same type (e.g. Output and Outputs).
279func convertBuildParams(params BuildParams) blueprint.BuildParams {
280 bparams := blueprint.BuildParams{
281 Rule: params.Rule,
282 Description: params.Description,
283 Deps: params.Deps,
284 Outputs: params.Outputs.Strings(),
285 ImplicitOutputs: params.ImplicitOutputs.Strings(),
286 SymlinkOutputs: params.SymlinkOutputs.Strings(),
287 Inputs: params.Inputs.Strings(),
288 Implicits: params.Implicits.Strings(),
289 OrderOnly: params.OrderOnly.Strings(),
290 Validations: params.Validations.Strings(),
291 Args: params.Args,
292 Optional: !params.Default,
293 }
294
295 if params.Depfile != nil {
296 bparams.Depfile = params.Depfile.String()
297 }
298 if params.Output != nil {
299 bparams.Outputs = append(bparams.Outputs, params.Output.String())
300 }
301 if params.SymlinkOutput != nil {
302 bparams.SymlinkOutputs = append(bparams.SymlinkOutputs, params.SymlinkOutput.String())
303 }
304 if params.ImplicitOutput != nil {
305 bparams.ImplicitOutputs = append(bparams.ImplicitOutputs, params.ImplicitOutput.String())
306 }
307 if params.Input != nil {
308 bparams.Inputs = append(bparams.Inputs, params.Input.String())
309 }
310 if params.Implicit != nil {
311 bparams.Implicits = append(bparams.Implicits, params.Implicit.String())
312 }
313 if params.Validation != nil {
314 bparams.Validations = append(bparams.Validations, params.Validation.String())
315 }
316
317 bparams.Outputs = proptools.NinjaEscapeList(bparams.Outputs)
318 bparams.ImplicitOutputs = proptools.NinjaEscapeList(bparams.ImplicitOutputs)
319 bparams.SymlinkOutputs = proptools.NinjaEscapeList(bparams.SymlinkOutputs)
320 bparams.Inputs = proptools.NinjaEscapeList(bparams.Inputs)
321 bparams.Implicits = proptools.NinjaEscapeList(bparams.Implicits)
322 bparams.OrderOnly = proptools.NinjaEscapeList(bparams.OrderOnly)
323 bparams.Validations = proptools.NinjaEscapeList(bparams.Validations)
324 bparams.Depfile = proptools.NinjaEscape(bparams.Depfile)
325
326 return bparams
327}
328
329func (m *moduleContext) Variable(pctx PackageContext, name, value string) {
330 if m.config.captureBuild {
331 m.variables[name] = value
332 }
333
334 m.bp.Variable(pctx.PackageContext, name, value)
335}
336
337func (m *moduleContext) Rule(pctx PackageContext, name string, params blueprint.RuleParams,
338 argNames ...string) blueprint.Rule {
339
340 if m.config.UseRemoteBuild() {
341 if params.Pool == nil {
342 // When USE_GOMA=true or USE_RBE=true are set and the rule is not supported by goma/RBE, restrict
343 // jobs to the local parallelism value
344 params.Pool = localPool
345 } else if params.Pool == remotePool {
346 // remotePool is a fake pool used to identify rule that are supported for remoting. If the rule's
347 // pool is the remotePool, replace with nil so that ninja runs it at NINJA_REMOTE_NUM_JOBS
348 // parallelism.
349 params.Pool = nil
350 }
351 }
352
353 rule := m.bp.Rule(pctx.PackageContext, name, params, argNames...)
354
355 if m.config.captureBuild {
356 m.ruleParams[rule] = params
357 }
358
359 return rule
360}
361
362func (m *moduleContext) Build(pctx PackageContext, params BuildParams) {
363 if params.Description != "" {
364 params.Description = "${moduleDesc}" + params.Description + "${moduleDescSuffix}"
365 }
366
367 if missingDeps := m.GetMissingDependencies(); len(missingDeps) > 0 {
368 pctx, params = m.ninjaError(params, fmt.Errorf("module %s missing dependencies: %s\n",
369 m.ModuleName(), strings.Join(missingDeps, ", ")))
370 }
371
372 if m.config.captureBuild {
373 m.buildParams = append(m.buildParams, params)
374 }
375
376 bparams := convertBuildParams(params)
377 err := validateBuildParams(bparams)
378 if err != nil {
379 m.ModuleErrorf(
380 "%s: build parameter validation failed: %s",
381 m.ModuleName(),
382 err.Error())
383 }
384 m.bp.Build(pctx.PackageContext, bparams)
385}
386
387func (m *moduleContext) Phony(name string, deps ...Path) {
388 addPhony(m.config, name, deps...)
389}
390
391func (m *moduleContext) GetMissingDependencies() []string {
392 var missingDeps []string
393 missingDeps = append(missingDeps, m.Module().base().commonProperties.MissingDeps...)
394 missingDeps = append(missingDeps, m.bp.GetMissingDependencies()...)
395 missingDeps = FirstUniqueStrings(missingDeps)
396 return missingDeps
397}
398
399func (m *moduleContext) GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module {
400 module, _ := m.getDirectDepInternal(name, tag)
401 return module
402}
403
404func (m *moduleContext) ModuleSubDir() string {
405 return m.bp.ModuleSubDir()
406}
407
408func (m *moduleContext) SoongConfigTraceHash() string {
409 return m.module.base().commonProperties.SoongConfigTraceHash
410}
411
412func (m *moduleContext) InstallInData() bool {
413 return m.module.InstallInData()
414}
415
416func (m *moduleContext) InstallInTestcases() bool {
417 return m.module.InstallInTestcases()
418}
419
420func (m *moduleContext) InstallInSanitizerDir() bool {
421 return m.module.InstallInSanitizerDir()
422}
423
424func (m *moduleContext) InstallInRamdisk() bool {
425 return m.module.InstallInRamdisk()
426}
427
428func (m *moduleContext) InstallInVendorRamdisk() bool {
429 return m.module.InstallInVendorRamdisk()
430}
431
432func (m *moduleContext) InstallInDebugRamdisk() bool {
433 return m.module.InstallInDebugRamdisk()
434}
435
436func (m *moduleContext) InstallInRecovery() bool {
437 return m.module.InstallInRecovery()
438}
439
440func (m *moduleContext) InstallInRoot() bool {
441 return m.module.InstallInRoot()
442}
443
444func (m *moduleContext) InstallForceOS() (*OsType, *ArchType) {
445 return m.module.InstallForceOS()
446}
447
Colin Crossea30d852023-11-29 16:00:16 -0800448func (m *moduleContext) InstallInOdm() bool {
449 return m.module.InstallInOdm()
450}
451
452func (m *moduleContext) InstallInProduct() bool {
453 return m.module.InstallInProduct()
454}
455
Colin Cross69452e12023-11-15 11:20:53 -0800456func (m *moduleContext) InstallInVendor() bool {
457 return m.module.InstallInVendor()
458}
459
460func (m *moduleContext) skipInstall() bool {
461 if m.module.base().commonProperties.SkipInstall {
462 return true
463 }
464
465 if m.module.base().commonProperties.HideFromMake {
466 return true
467 }
468
469 // We'll need a solution for choosing which of modules with the same name in different
470 // namespaces to install. For now, reuse the list of namespaces exported to Make as the
471 // list of namespaces to install in a Soong-only build.
472 if !m.module.base().commonProperties.NamespaceExportedToMake {
473 return true
474 }
475
476 return false
477}
478
479func (m *moduleContext) InstallFile(installPath InstallPath, name string, srcPath Path,
Colin Cross09ad3a62023-11-15 12:29:33 -0800480 deps ...InstallPath) InstallPath {
Colin Cross5c1d5fb2023-11-15 12:39:40 -0800481 return m.installFile(installPath, name, srcPath, deps, false, true, nil)
Colin Cross69452e12023-11-15 11:20:53 -0800482}
483
484func (m *moduleContext) InstallExecutable(installPath InstallPath, name string, srcPath Path,
Colin Cross09ad3a62023-11-15 12:29:33 -0800485 deps ...InstallPath) InstallPath {
Colin Cross5c1d5fb2023-11-15 12:39:40 -0800486 return m.installFile(installPath, name, srcPath, deps, true, true, nil)
Colin Cross69452e12023-11-15 11:20:53 -0800487}
488
489func (m *moduleContext) InstallFileWithExtraFilesZip(installPath InstallPath, name string, srcPath Path,
Colin Cross09ad3a62023-11-15 12:29:33 -0800490 extraZip Path, deps ...InstallPath) InstallPath {
Colin Cross5c1d5fb2023-11-15 12:39:40 -0800491 return m.installFile(installPath, name, srcPath, deps, false, true, &extraFilesZip{
Colin Cross69452e12023-11-15 11:20:53 -0800492 zip: extraZip,
493 dir: installPath,
494 })
495}
496
497func (m *moduleContext) PackageFile(installPath InstallPath, name string, srcPath Path) PackagingSpec {
498 fullInstallPath := installPath.Join(m, name)
499 return m.packageFile(fullInstallPath, srcPath, false)
500}
501
502func (m *moduleContext) packageFile(fullInstallPath InstallPath, srcPath Path, executable bool) PackagingSpec {
503 licenseFiles := m.Module().EffectiveLicenseFiles()
504 spec := PackagingSpec{
505 relPathInPackage: Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()),
506 srcPath: srcPath,
507 symlinkTarget: "",
508 executable: executable,
509 effectiveLicenseFiles: &licenseFiles,
510 partition: fullInstallPath.partition,
511 }
512 m.packagingSpecs = append(m.packagingSpecs, spec)
513 return spec
514}
515
Colin Cross09ad3a62023-11-15 12:29:33 -0800516func (m *moduleContext) installFile(installPath InstallPath, name string, srcPath Path, deps []InstallPath,
Colin Cross5c1d5fb2023-11-15 12:39:40 -0800517 executable bool, hooks bool, extraZip *extraFilesZip) InstallPath {
Colin Cross69452e12023-11-15 11:20:53 -0800518
519 fullInstallPath := installPath.Join(m, name)
Colin Cross5c1d5fb2023-11-15 12:39:40 -0800520 if hooks {
521 m.module.base().hooks.runInstallHooks(m, srcPath, fullInstallPath, false)
522 }
Colin Cross69452e12023-11-15 11:20:53 -0800523
524 if !m.skipInstall() {
Colin Cross09ad3a62023-11-15 12:29:33 -0800525 deps = append(deps, InstallPaths(m.module.base().installFilesDepSet.ToList())...)
Colin Crossd6fd0132023-11-06 13:54:06 -0800526 deps = append(deps, m.module.base().installedInitRcPaths...)
527 deps = append(deps, m.module.base().installedVintfFragmentsPaths...)
Colin Cross69452e12023-11-15 11:20:53 -0800528
529 var implicitDeps, orderOnlyDeps Paths
530
531 if m.Host() {
532 // Installed host modules might be used during the build, depend directly on their
533 // dependencies so their timestamp is updated whenever their dependency is updated
Colin Cross09ad3a62023-11-15 12:29:33 -0800534 implicitDeps = InstallPaths(deps).Paths()
Colin Cross69452e12023-11-15 11:20:53 -0800535 } else {
Colin Cross09ad3a62023-11-15 12:29:33 -0800536 orderOnlyDeps = InstallPaths(deps).Paths()
Colin Cross69452e12023-11-15 11:20:53 -0800537 }
538
539 if m.Config().KatiEnabled() {
540 // When creating the install rule in Soong but embedding in Make, write the rule to a
541 // makefile instead of directly to the ninja file so that main.mk can add the
542 // dependencies from the `required` property that are hard to resolve in Soong.
543 m.katiInstalls = append(m.katiInstalls, katiInstall{
544 from: srcPath,
545 to: fullInstallPath,
546 implicitDeps: implicitDeps,
547 orderOnlyDeps: orderOnlyDeps,
548 executable: executable,
549 extraFiles: extraZip,
550 })
551 } else {
552 rule := Cp
553 if executable {
554 rule = CpExecutable
555 }
556
557 extraCmds := ""
558 if extraZip != nil {
559 extraCmds += fmt.Sprintf(" && ( unzip -qDD -d '%s' '%s' 2>&1 | grep -v \"zipfile is empty\"; exit $${PIPESTATUS[0]} )",
560 extraZip.dir.String(), extraZip.zip.String())
561 extraCmds += " || ( code=$$?; if [ $$code -ne 0 -a $$code -ne 1 ]; then exit $$code; fi )"
562 implicitDeps = append(implicitDeps, extraZip.zip)
563 }
564
565 m.Build(pctx, BuildParams{
566 Rule: rule,
567 Description: "install " + fullInstallPath.Base(),
568 Output: fullInstallPath,
569 Input: srcPath,
570 Implicits: implicitDeps,
571 OrderOnly: orderOnlyDeps,
572 Default: !m.Config().KatiEnabled(),
573 Args: map[string]string{
574 "extraCmds": extraCmds,
575 },
576 })
577 }
578
579 m.installFiles = append(m.installFiles, fullInstallPath)
580 }
581
582 m.packageFile(fullInstallPath, srcPath, executable)
583
584 m.checkbuildFiles = append(m.checkbuildFiles, srcPath)
585
586 return fullInstallPath
587}
588
589func (m *moduleContext) InstallSymlink(installPath InstallPath, name string, srcPath InstallPath) InstallPath {
590 fullInstallPath := installPath.Join(m, name)
591 m.module.base().hooks.runInstallHooks(m, srcPath, fullInstallPath, true)
592
593 relPath, err := filepath.Rel(path.Dir(fullInstallPath.String()), srcPath.String())
594 if err != nil {
595 panic(fmt.Sprintf("Unable to generate symlink between %q and %q: %s", fullInstallPath.Base(), srcPath.Base(), err))
596 }
597 if !m.skipInstall() {
598
599 if m.Config().KatiEnabled() {
600 // When creating the symlink rule in Soong but embedding in Make, write the rule to a
601 // makefile instead of directly to the ninja file so that main.mk can add the
602 // dependencies from the `required` property that are hard to resolve in Soong.
603 m.katiSymlinks = append(m.katiSymlinks, katiInstall{
604 from: srcPath,
605 to: fullInstallPath,
606 })
607 } else {
608 // The symlink doesn't need updating when the target is modified, but we sometimes
609 // have a dependency on a symlink to a binary instead of to the binary directly, and
610 // the mtime of the symlink must be updated when the binary is modified, so use a
611 // normal dependency here instead of an order-only dependency.
612 m.Build(pctx, BuildParams{
613 Rule: Symlink,
614 Description: "install symlink " + fullInstallPath.Base(),
615 Output: fullInstallPath,
616 Input: srcPath,
617 Default: !m.Config().KatiEnabled(),
618 Args: map[string]string{
619 "fromPath": relPath,
620 },
621 })
622 }
623
624 m.installFiles = append(m.installFiles, fullInstallPath)
625 m.checkbuildFiles = append(m.checkbuildFiles, srcPath)
626 }
627
628 m.packagingSpecs = append(m.packagingSpecs, PackagingSpec{
629 relPathInPackage: Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()),
630 srcPath: nil,
631 symlinkTarget: relPath,
632 executable: false,
633 partition: fullInstallPath.partition,
634 })
635
636 return fullInstallPath
637}
638
639// installPath/name -> absPath where absPath might be a path that is available only at runtime
640// (e.g. /apex/...)
641func (m *moduleContext) InstallAbsoluteSymlink(installPath InstallPath, name string, absPath string) InstallPath {
642 fullInstallPath := installPath.Join(m, name)
643 m.module.base().hooks.runInstallHooks(m, nil, fullInstallPath, true)
644
645 if !m.skipInstall() {
646 if m.Config().KatiEnabled() {
647 // When creating the symlink rule in Soong but embedding in Make, write the rule to a
648 // makefile instead of directly to the ninja file so that main.mk can add the
649 // dependencies from the `required` property that are hard to resolve in Soong.
650 m.katiSymlinks = append(m.katiSymlinks, katiInstall{
651 absFrom: absPath,
652 to: fullInstallPath,
653 })
654 } else {
655 m.Build(pctx, BuildParams{
656 Rule: Symlink,
657 Description: "install symlink " + fullInstallPath.Base() + " -> " + absPath,
658 Output: fullInstallPath,
659 Default: !m.Config().KatiEnabled(),
660 Args: map[string]string{
661 "fromPath": absPath,
662 },
663 })
664 }
665
666 m.installFiles = append(m.installFiles, fullInstallPath)
667 }
668
669 m.packagingSpecs = append(m.packagingSpecs, PackagingSpec{
670 relPathInPackage: Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()),
671 srcPath: nil,
672 symlinkTarget: absPath,
673 executable: false,
674 partition: fullInstallPath.partition,
675 })
676
677 return fullInstallPath
678}
679
Colin Cross5c1d5fb2023-11-15 12:39:40 -0800680func (m *moduleContext) InstallTestData(installPath InstallPath, data []DataPath) InstallPaths {
681 m.testData = append(m.testData, data...)
682
683 ret := make(InstallPaths, 0, len(data))
684 for _, d := range data {
685 relPath := d.ToRelativeInstallPath()
686 installed := m.installFile(installPath, relPath, d.SrcPath, nil, false, false, nil)
687 ret = append(ret, installed)
688 }
689
690 return ret
691}
692
Colin Cross69452e12023-11-15 11:20:53 -0800693func (m *moduleContext) CheckbuildFile(srcPath Path) {
694 m.checkbuildFiles = append(m.checkbuildFiles, srcPath)
695}
696
697func (m *moduleContext) blueprintModuleContext() blueprint.ModuleContext {
698 return m.bp
699}
700
701func (m *moduleContext) LicenseMetadataFile() Path {
702 return m.module.base().licenseMetadataFile
703}
704
Colin Crossd6fd0132023-11-06 13:54:06 -0800705func (m *moduleContext) ModuleInfoJSON() *ModuleInfoJSON {
706 if moduleInfoJSON := m.module.base().moduleInfoJSON; moduleInfoJSON != nil {
707 return moduleInfoJSON
708 }
709 moduleInfoJSON := &ModuleInfoJSON{}
710 m.module.base().moduleInfoJSON = moduleInfoJSON
711 return moduleInfoJSON
712}
713
Colin Cross69452e12023-11-15 11:20:53 -0800714// Returns a list of paths expanded from globs and modules referenced using ":module" syntax. The property must
715// be tagged with `android:"path" to support automatic source module dependency resolution.
716//
717// Deprecated: use PathsForModuleSrc or PathsForModuleSrcExcludes instead.
718func (m *moduleContext) ExpandSources(srcFiles, excludes []string) Paths {
719 return PathsForModuleSrcExcludes(m, srcFiles, excludes)
720}
721
722// Returns a single path expanded from globs and modules referenced using ":module" syntax. The property must
723// be tagged with `android:"path" to support automatic source module dependency resolution.
724//
725// Deprecated: use PathForModuleSrc instead.
726func (m *moduleContext) ExpandSource(srcFile, _ string) Path {
727 return PathForModuleSrc(m, srcFile)
728}
729
730// Returns an optional single path expanded from globs and modules referenced using ":module" syntax if
731// the srcFile is non-nil. The property must be tagged with `android:"path" to support automatic source module
732// dependency resolution.
733func (m *moduleContext) ExpandOptionalSource(srcFile *string, _ string) OptionalPath {
734 if srcFile != nil {
735 return OptionalPathForPath(PathForModuleSrc(m, *srcFile))
736 }
737 return OptionalPath{}
738}
739
740func (m *moduleContext) RequiredModuleNames() []string {
741 return m.module.RequiredModuleNames()
742}
743
744func (m *moduleContext) HostRequiredModuleNames() []string {
745 return m.module.HostRequiredModuleNames()
746}
747
748func (m *moduleContext) TargetRequiredModuleNames() []string {
749 return m.module.TargetRequiredModuleNames()
750}