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