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