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/filepath" 20 "sort" 21 "strings" 22 "text/scanner" 23 24 "github.com/google/blueprint" 25 "github.com/google/blueprint/pathtools" 26) 27 28var ( 29 DeviceSharedLibrary = "shared_library" 30 DeviceStaticLibrary = "static_library" 31 DeviceExecutable = "executable" 32 HostSharedLibrary = "host_shared_library" 33 HostStaticLibrary = "host_static_library" 34 HostExecutable = "host_executable" 35) 36 37type BuildParams struct { 38 Rule blueprint.Rule 39 Deps blueprint.Deps 40 Depfile WritablePath 41 Description string 42 Output WritablePath 43 Outputs WritablePaths 44 ImplicitOutput WritablePath 45 ImplicitOutputs WritablePaths 46 Input Path 47 Inputs Paths 48 Implicit Path 49 Implicits Paths 50 OrderOnly Paths 51 Default bool 52 Args map[string]string 53} 54 55type ModuleBuildParams BuildParams 56 57type androidBaseContext interface { 58 Target() Target 59 TargetPrimary() bool 60 Arch() Arch 61 Os() OsType 62 Host() bool 63 Device() bool 64 Darwin() bool 65 Windows() bool 66 Debug() bool 67 PrimaryArch() bool 68 Platform() bool 69 DeviceSpecific() bool 70 SocSpecific() bool 71 ProductSpecific() bool 72 AConfig() Config 73 DeviceConfig() DeviceConfig 74} 75 76type BaseContext interface { 77 BaseModuleContext 78 androidBaseContext 79} 80 81// BaseModuleContext is the same as blueprint.BaseModuleContext except that Config() returns 82// a Config instead of an interface{}. 83type BaseModuleContext interface { 84 ModuleName() string 85 ModuleDir() string 86 Config() Config 87 88 ContainsProperty(name string) bool 89 Errorf(pos scanner.Position, fmt string, args ...interface{}) 90 ModuleErrorf(fmt string, args ...interface{}) 91 PropertyErrorf(property, fmt string, args ...interface{}) 92 Failed() bool 93 94 // GlobWithDeps returns a list of files that match the specified pattern but do not match any 95 // of the patterns in excludes. It also adds efficient dependencies to rerun the primary 96 // builder whenever a file matching the pattern as added or removed, without rerunning if a 97 // file that does not match the pattern is added to a searched directory. 98 GlobWithDeps(pattern string, excludes []string) ([]string, error) 99 100 Fs() pathtools.FileSystem 101 AddNinjaFileDeps(deps ...string) 102} 103 104type ModuleContext interface { 105 androidBaseContext 106 BaseModuleContext 107 108 // Deprecated: use ModuleContext.Build instead. 109 ModuleBuild(pctx PackageContext, params ModuleBuildParams) 110 111 ExpandSources(srcFiles, excludes []string) Paths 112 ExpandSource(srcFile, prop string) Path 113 ExpandOptionalSource(srcFile *string, prop string) OptionalPath 114 ExpandSourcesSubDir(srcFiles, excludes []string, subDir string) Paths 115 Glob(globPattern string, excludes []string) Paths 116 GlobFiles(globPattern string, excludes []string) Paths 117 118 InstallExecutable(installPath OutputPath, name string, srcPath Path, deps ...Path) OutputPath 119 InstallFile(installPath OutputPath, name string, srcPath Path, deps ...Path) OutputPath 120 InstallSymlink(installPath OutputPath, name string, srcPath OutputPath) OutputPath 121 CheckbuildFile(srcPath Path) 122 123 AddMissingDependencies(deps []string) 124 125 InstallInData() bool 126 InstallInSanitizerDir() bool 127 128 RequiredModuleNames() []string 129 130 // android.ModuleContext methods 131 // These are duplicated instead of embedded so that can eventually be wrapped to take an 132 // android.Module instead of a blueprint.Module 133 OtherModuleName(m blueprint.Module) string 134 OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{}) 135 OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag 136 137 GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module 138 GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag) 139 140 ModuleSubDir() string 141 142 VisitDirectDepsBlueprint(visit func(blueprint.Module)) 143 VisitDirectDeps(visit func(Module)) 144 VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) 145 VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) 146 VisitDepsDepthFirst(visit func(Module)) 147 VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module)) 148 WalkDeps(visit func(Module, Module) bool) 149 150 Variable(pctx PackageContext, name, value string) 151 Rule(pctx PackageContext, name string, params blueprint.RuleParams, argNames ...string) blueprint.Rule 152 // Similar to blueprint.ModuleContext.Build, but takes Paths instead of []string, 153 // and performs more verification. 154 Build(pctx PackageContext, params BuildParams) 155 156 PrimaryModule() Module 157 FinalModule() Module 158 VisitAllModuleVariants(visit func(Module)) 159 160 GetMissingDependencies() []string 161 Namespace() blueprint.Namespace 162} 163 164type Module interface { 165 blueprint.Module 166 167 // GenerateAndroidBuildActions is analogous to Blueprints' GenerateBuildActions, 168 // but GenerateAndroidBuildActions also has access to Android-specific information. 169 // For more information, see Module.GenerateBuildActions within Blueprint's module_ctx.go 170 GenerateAndroidBuildActions(ModuleContext) 171 172 DepsMutator(BottomUpMutatorContext) 173 174 base() *ModuleBase 175 Enabled() bool 176 Target() Target 177 InstallInData() bool 178 InstallInSanitizerDir() bool 179 SkipInstall() 180 ExportedToMake() bool 181 182 AddProperties(props ...interface{}) 183 GetProperties() []interface{} 184 185 BuildParamsForTests() []BuildParams 186} 187 188type nameProperties struct { 189 // The name of the module. Must be unique across all modules. 190 Name *string 191} 192 193type commonProperties struct { 194 Tags []string 195 196 // emit build rules for this module 197 Enabled *bool `android:"arch_variant"` 198 199 // control whether this module compiles for 32-bit, 64-bit, or both. Possible values 200 // are "32" (compile for 32-bit only), "64" (compile for 64-bit only), "both" (compile for both 201 // architectures), or "first" (compile for 64-bit on a 64-bit platform, and 32-bit on a 32-bit 202 // platform 203 Compile_multilib *string `android:"arch_variant"` 204 205 Target struct { 206 Host struct { 207 Compile_multilib *string 208 } 209 Android struct { 210 Compile_multilib *string 211 } 212 } 213 214 Default_multilib string `blueprint:"mutated"` 215 216 // whether this is a proprietary vendor module, and should be installed into /vendor 217 Proprietary *bool 218 219 // vendor who owns this module 220 Owner *string 221 222 // whether this module is specific to an SoC (System-On-a-Chip). When set to true, 223 // it is installed into /vendor (or /system/vendor if vendor partition does not exist). 224 // Use `soc_specific` instead for better meaning. 225 Vendor *bool 226 227 // whether this module is specific to an SoC (System-On-a-Chip). When set to true, 228 // it is installed into /vendor (or /system/vendor if vendor partition does not exist). 229 Soc_specific *bool 230 231 // whether this module is specific to a device, not only for SoC, but also for off-chip 232 // peripherals. When set to true, it is installed into /odm (or /vendor/odm if odm partition 233 // does not exist, or /system/vendor/odm if both odm and vendor partitions do not exist). 234 // This implies `soc_specific:true`. 235 Device_specific *bool 236 237 // whether this module is specific to a software configuration of a product (e.g. country, 238 // network operator, etc). When set to true, it is installed into /product (or 239 // /system/product if product partition does not exist). 240 Product_specific *bool 241 242 // init.rc files to be installed if this module is installed 243 Init_rc []string 244 245 // names of other modules to install if this module is installed 246 Required []string `android:"arch_variant"` 247 248 // relative path to a file to include in the list of notices for the device 249 Notice *string 250 251 // Set by TargetMutator 252 CompileTarget Target `blueprint:"mutated"` 253 CompilePrimary bool `blueprint:"mutated"` 254 255 // Set by InitAndroidModule 256 HostOrDeviceSupported HostOrDeviceSupported `blueprint:"mutated"` 257 ArchSpecific bool `blueprint:"mutated"` 258 259 SkipInstall bool `blueprint:"mutated"` 260 261 NamespaceExportedToMake bool `blueprint:"mutated"` 262} 263 264type hostAndDeviceProperties struct { 265 Host_supported *bool 266 Device_supported *bool 267} 268 269type Multilib string 270 271const ( 272 MultilibBoth Multilib = "both" 273 MultilibFirst Multilib = "first" 274 MultilibCommon Multilib = "common" 275 MultilibCommonFirst Multilib = "common_first" 276 MultilibDefault Multilib = "" 277) 278 279type HostOrDeviceSupported int 280 281const ( 282 _ HostOrDeviceSupported = iota 283 HostSupported 284 HostSupportedNoCross 285 DeviceSupported 286 HostAndDeviceSupported 287 HostAndDeviceDefault 288 NeitherHostNorDeviceSupported 289) 290 291type moduleKind int 292 293const ( 294 platformModule moduleKind = iota 295 deviceSpecificModule 296 socSpecificModule 297 productSpecificModule 298) 299 300func (k moduleKind) String() string { 301 switch k { 302 case platformModule: 303 return "platform" 304 case deviceSpecificModule: 305 return "device-specific" 306 case socSpecificModule: 307 return "soc-specific" 308 case productSpecificModule: 309 return "product-specific" 310 default: 311 panic(fmt.Errorf("unknown module kind %d", k)) 312 } 313} 314 315func InitAndroidModule(m Module) { 316 base := m.base() 317 base.module = m 318 319 m.AddProperties( 320 &base.nameProperties, 321 &base.commonProperties, 322 &base.variableProperties) 323} 324 325func InitAndroidArchModule(m Module, hod HostOrDeviceSupported, defaultMultilib Multilib) { 326 InitAndroidModule(m) 327 328 base := m.base() 329 base.commonProperties.HostOrDeviceSupported = hod 330 base.commonProperties.Default_multilib = string(defaultMultilib) 331 base.commonProperties.ArchSpecific = true 332 333 switch hod { 334 case HostAndDeviceSupported, HostAndDeviceDefault: 335 m.AddProperties(&base.hostAndDeviceProperties) 336 } 337 338 InitArchModule(m) 339} 340 341// A ModuleBase object contains the properties that are common to all Android 342// modules. It should be included as an anonymous field in every module 343// struct definition. InitAndroidModule should then be called from the module's 344// factory function, and the return values from InitAndroidModule should be 345// returned from the factory function. 346// 347// The ModuleBase type is responsible for implementing the GenerateBuildActions 348// method to support the blueprint.Module interface. This method will then call 349// the module's GenerateAndroidBuildActions method once for each build variant 350// that is to be built. GenerateAndroidBuildActions is passed a 351// AndroidModuleContext rather than the usual blueprint.ModuleContext. 352// AndroidModuleContext exposes extra functionality specific to the Android build 353// system including details about the particular build variant that is to be 354// generated. 355// 356// For example: 357// 358// import ( 359// "android/soong/android" 360// ) 361// 362// type myModule struct { 363// android.ModuleBase 364// properties struct { 365// MyProperty string 366// } 367// } 368// 369// func NewMyModule() android.Module) { 370// m := &myModule{} 371// m.AddProperties(&m.properties) 372// android.InitAndroidModule(m) 373// return m 374// } 375// 376// func (m *myModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { 377// // Get the CPU architecture for the current build variant. 378// variantArch := ctx.Arch() 379// 380// // ... 381// } 382type ModuleBase struct { 383 // Putting the curiously recurring thing pointing to the thing that contains 384 // the thing pattern to good use. 385 // TODO: remove this 386 module Module 387 388 nameProperties nameProperties 389 commonProperties commonProperties 390 variableProperties variableProperties 391 hostAndDeviceProperties hostAndDeviceProperties 392 generalProperties []interface{} 393 archProperties []interface{} 394 customizableProperties []interface{} 395 396 noAddressSanitizer bool 397 installFiles Paths 398 checkbuildFiles Paths 399 400 // Used by buildTargetSingleton to create checkbuild and per-directory build targets 401 // Only set on the final variant of each module 402 installTarget WritablePath 403 checkbuildTarget WritablePath 404 blueprintDir string 405 406 hooks hooks 407 408 registerProps []interface{} 409 410 // For tests 411 buildParams []BuildParams 412} 413 414func (a *ModuleBase) AddProperties(props ...interface{}) { 415 a.registerProps = append(a.registerProps, props...) 416} 417 418func (a *ModuleBase) GetProperties() []interface{} { 419 return a.registerProps 420} 421 422func (a *ModuleBase) BuildParamsForTests() []BuildParams { 423 return a.buildParams 424} 425 426// Name returns the name of the module. It may be overridden by individual module types, for 427// example prebuilts will prepend prebuilt_ to the name. 428func (a *ModuleBase) Name() string { 429 return String(a.nameProperties.Name) 430} 431 432// BaseModuleName returns the name of the module as specified in the blueprints file. 433func (a *ModuleBase) BaseModuleName() string { 434 return String(a.nameProperties.Name) 435} 436 437func (a *ModuleBase) base() *ModuleBase { 438 return a 439} 440 441func (a *ModuleBase) SetTarget(target Target, primary bool) { 442 a.commonProperties.CompileTarget = target 443 a.commonProperties.CompilePrimary = primary 444} 445 446func (a *ModuleBase) Target() Target { 447 return a.commonProperties.CompileTarget 448} 449 450func (a *ModuleBase) TargetPrimary() bool { 451 return a.commonProperties.CompilePrimary 452} 453 454func (a *ModuleBase) Os() OsType { 455 return a.Target().Os 456} 457 458func (a *ModuleBase) Host() bool { 459 return a.Os().Class == Host || a.Os().Class == HostCross 460} 461 462func (a *ModuleBase) Arch() Arch { 463 return a.Target().Arch 464} 465 466func (a *ModuleBase) ArchSpecific() bool { 467 return a.commonProperties.ArchSpecific 468} 469 470func (a *ModuleBase) OsClassSupported() []OsClass { 471 switch a.commonProperties.HostOrDeviceSupported { 472 case HostSupported: 473 return []OsClass{Host, HostCross} 474 case HostSupportedNoCross: 475 return []OsClass{Host} 476 case DeviceSupported: 477 return []OsClass{Device} 478 case HostAndDeviceSupported: 479 var supported []OsClass 480 if Bool(a.hostAndDeviceProperties.Host_supported) { 481 supported = append(supported, Host, HostCross) 482 } 483 if a.hostAndDeviceProperties.Device_supported == nil || 484 *a.hostAndDeviceProperties.Device_supported { 485 supported = append(supported, Device) 486 } 487 return supported 488 default: 489 return nil 490 } 491} 492 493func (a *ModuleBase) DeviceSupported() bool { 494 return a.commonProperties.HostOrDeviceSupported == DeviceSupported || 495 a.commonProperties.HostOrDeviceSupported == HostAndDeviceSupported && 496 (a.hostAndDeviceProperties.Device_supported == nil || 497 *a.hostAndDeviceProperties.Device_supported) 498} 499 500func (a *ModuleBase) Enabled() bool { 501 if a.commonProperties.Enabled == nil { 502 return !a.Os().DefaultDisabled 503 } 504 return *a.commonProperties.Enabled 505} 506 507func (a *ModuleBase) SkipInstall() { 508 a.commonProperties.SkipInstall = true 509} 510 511func (a *ModuleBase) ExportedToMake() bool { 512 return a.commonProperties.NamespaceExportedToMake 513} 514 515func (a *ModuleBase) computeInstallDeps( 516 ctx blueprint.ModuleContext) Paths { 517 518 result := Paths{} 519 ctx.VisitDepsDepthFirstIf(isFileInstaller, 520 func(m blueprint.Module) { 521 fileInstaller := m.(fileInstaller) 522 files := fileInstaller.filesToInstall() 523 result = append(result, files...) 524 }) 525 526 return result 527} 528 529func (a *ModuleBase) filesToInstall() Paths { 530 return a.installFiles 531} 532 533func (p *ModuleBase) NoAddressSanitizer() bool { 534 return p.noAddressSanitizer 535} 536 537func (p *ModuleBase) InstallInData() bool { 538 return false 539} 540 541func (p *ModuleBase) InstallInSanitizerDir() bool { 542 return false 543} 544 545func (a *ModuleBase) generateModuleTarget(ctx ModuleContext) { 546 allInstalledFiles := Paths{} 547 allCheckbuildFiles := Paths{} 548 ctx.VisitAllModuleVariants(func(module Module) { 549 a := module.base() 550 allInstalledFiles = append(allInstalledFiles, a.installFiles...) 551 allCheckbuildFiles = append(allCheckbuildFiles, a.checkbuildFiles...) 552 }) 553 554 var deps Paths 555 556 namespacePrefix := ctx.Namespace().(*Namespace).id 557 if namespacePrefix != "" { 558 namespacePrefix = namespacePrefix + "-" 559 } 560 561 if len(allInstalledFiles) > 0 { 562 name := PathForPhony(ctx, namespacePrefix+ctx.ModuleName()+"-install") 563 ctx.Build(pctx, BuildParams{ 564 Rule: blueprint.Phony, 565 Output: name, 566 Implicits: allInstalledFiles, 567 Default: !ctx.Config().EmbeddedInMake(), 568 }) 569 deps = append(deps, name) 570 a.installTarget = name 571 } 572 573 if len(allCheckbuildFiles) > 0 { 574 name := PathForPhony(ctx, namespacePrefix+ctx.ModuleName()+"-checkbuild") 575 ctx.Build(pctx, BuildParams{ 576 Rule: blueprint.Phony, 577 Output: name, 578 Implicits: allCheckbuildFiles, 579 }) 580 deps = append(deps, name) 581 a.checkbuildTarget = name 582 } 583 584 if len(deps) > 0 { 585 suffix := "" 586 if ctx.Config().EmbeddedInMake() { 587 suffix = "-soong" 588 } 589 590 name := PathForPhony(ctx, namespacePrefix+ctx.ModuleName()+suffix) 591 ctx.Build(pctx, BuildParams{ 592 Rule: blueprint.Phony, 593 Outputs: []WritablePath{name}, 594 Implicits: deps, 595 }) 596 597 a.blueprintDir = ctx.ModuleDir() 598 } 599} 600 601func determineModuleKind(a *ModuleBase, ctx blueprint.BaseModuleContext) moduleKind { 602 var socSpecific = Bool(a.commonProperties.Vendor) || Bool(a.commonProperties.Proprietary) || Bool(a.commonProperties.Soc_specific) 603 var deviceSpecific = Bool(a.commonProperties.Device_specific) 604 var productSpecific = Bool(a.commonProperties.Product_specific) 605 606 if ((socSpecific || deviceSpecific) && productSpecific) || (socSpecific && deviceSpecific) { 607 msg := "conflicting value set here" 608 if productSpecific { 609 ctx.PropertyErrorf("product_specific", "a module cannot be specific to SoC or device and product at the same time.") 610 if deviceSpecific { 611 ctx.PropertyErrorf("device_specific", msg) 612 } 613 } else { 614 ctx.PropertyErrorf("device_specific", "a module cannot be specific to SoC and device at the same time.") 615 } 616 if Bool(a.commonProperties.Vendor) { 617 ctx.PropertyErrorf("vendor", msg) 618 } 619 if Bool(a.commonProperties.Proprietary) { 620 ctx.PropertyErrorf("proprietary", msg) 621 } 622 if Bool(a.commonProperties.Soc_specific) { 623 ctx.PropertyErrorf("soc_specific", msg) 624 } 625 } 626 627 if productSpecific { 628 return productSpecificModule 629 } else if deviceSpecific { 630 return deviceSpecificModule 631 } else if socSpecific { 632 return socSpecificModule 633 } else { 634 return platformModule 635 } 636} 637 638func (a *ModuleBase) androidBaseContextFactory(ctx blueprint.BaseModuleContext) androidBaseContextImpl { 639 return androidBaseContextImpl{ 640 target: a.commonProperties.CompileTarget, 641 targetPrimary: a.commonProperties.CompilePrimary, 642 kind: determineModuleKind(a, ctx), 643 config: ctx.Config().(Config), 644 } 645} 646 647func (a *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) { 648 ctx := &androidModuleContext{ 649 module: a.module, 650 ModuleContext: blueprintCtx, 651 androidBaseContextImpl: a.androidBaseContextFactory(blueprintCtx), 652 installDeps: a.computeInstallDeps(blueprintCtx), 653 installFiles: a.installFiles, 654 missingDeps: blueprintCtx.GetMissingDependencies(), 655 } 656 657 desc := "//" + ctx.ModuleDir() + ":" + ctx.ModuleName() + " " 658 var suffix []string 659 if ctx.Os().Class != Device && ctx.Os().Class != Generic { 660 suffix = append(suffix, ctx.Os().String()) 661 } 662 if !ctx.PrimaryArch() { 663 suffix = append(suffix, ctx.Arch().ArchType.String()) 664 } 665 666 ctx.Variable(pctx, "moduleDesc", desc) 667 668 s := "" 669 if len(suffix) > 0 { 670 s = " [" + strings.Join(suffix, " ") + "]" 671 } 672 ctx.Variable(pctx, "moduleDescSuffix", s) 673 674 if a.Enabled() { 675 a.module.GenerateAndroidBuildActions(ctx) 676 if ctx.Failed() { 677 return 678 } 679 680 a.installFiles = append(a.installFiles, ctx.installFiles...) 681 a.checkbuildFiles = append(a.checkbuildFiles, ctx.checkbuildFiles...) 682 } 683 684 if a == ctx.FinalModule().(Module).base() { 685 a.generateModuleTarget(ctx) 686 if ctx.Failed() { 687 return 688 } 689 } 690 691 a.buildParams = ctx.buildParams 692} 693 694type androidBaseContextImpl struct { 695 target Target 696 targetPrimary bool 697 debug bool 698 kind moduleKind 699 config Config 700} 701 702type androidModuleContext struct { 703 blueprint.ModuleContext 704 androidBaseContextImpl 705 installDeps Paths 706 installFiles Paths 707 checkbuildFiles Paths 708 missingDeps []string 709 module Module 710 711 // For tests 712 buildParams []BuildParams 713} 714 715func (a *androidModuleContext) ninjaError(desc string, outputs []string, err error) { 716 a.ModuleContext.Build(pctx.PackageContext, blueprint.BuildParams{ 717 Rule: ErrorRule, 718 Description: desc, 719 Outputs: outputs, 720 Optional: true, 721 Args: map[string]string{ 722 "error": err.Error(), 723 }, 724 }) 725 return 726} 727 728func (a *androidModuleContext) Config() Config { 729 return a.ModuleContext.Config().(Config) 730} 731 732func (a *androidModuleContext) ModuleBuild(pctx PackageContext, params ModuleBuildParams) { 733 a.Build(pctx, BuildParams(params)) 734} 735 736func convertBuildParams(params BuildParams) blueprint.BuildParams { 737 bparams := blueprint.BuildParams{ 738 Rule: params.Rule, 739 Description: params.Description, 740 Deps: params.Deps, 741 Outputs: params.Outputs.Strings(), 742 ImplicitOutputs: params.ImplicitOutputs.Strings(), 743 Inputs: params.Inputs.Strings(), 744 Implicits: params.Implicits.Strings(), 745 OrderOnly: params.OrderOnly.Strings(), 746 Args: params.Args, 747 Optional: !params.Default, 748 } 749 750 if params.Depfile != nil { 751 bparams.Depfile = params.Depfile.String() 752 } 753 if params.Output != nil { 754 bparams.Outputs = append(bparams.Outputs, params.Output.String()) 755 } 756 if params.ImplicitOutput != nil { 757 bparams.ImplicitOutputs = append(bparams.ImplicitOutputs, params.ImplicitOutput.String()) 758 } 759 if params.Input != nil { 760 bparams.Inputs = append(bparams.Inputs, params.Input.String()) 761 } 762 if params.Implicit != nil { 763 bparams.Implicits = append(bparams.Implicits, params.Implicit.String()) 764 } 765 766 return bparams 767} 768 769func (a *androidModuleContext) Variable(pctx PackageContext, name, value string) { 770 a.ModuleContext.Variable(pctx.PackageContext, name, value) 771} 772 773func (a *androidModuleContext) Rule(pctx PackageContext, name string, params blueprint.RuleParams, 774 argNames ...string) blueprint.Rule { 775 776 return a.ModuleContext.Rule(pctx.PackageContext, name, params, argNames...) 777} 778 779func (a *androidModuleContext) Build(pctx PackageContext, params BuildParams) { 780 if a.config.captureBuild { 781 a.buildParams = append(a.buildParams, params) 782 } 783 784 bparams := convertBuildParams(params) 785 786 if bparams.Description != "" { 787 bparams.Description = "${moduleDesc}" + params.Description + "${moduleDescSuffix}" 788 } 789 790 if a.missingDeps != nil { 791 a.ninjaError(bparams.Description, bparams.Outputs, 792 fmt.Errorf("module %s missing dependencies: %s\n", 793 a.ModuleName(), strings.Join(a.missingDeps, ", "))) 794 return 795 } 796 797 a.ModuleContext.Build(pctx.PackageContext, bparams) 798} 799 800func (a *androidModuleContext) GetMissingDependencies() []string { 801 return a.missingDeps 802} 803 804func (a *androidModuleContext) AddMissingDependencies(deps []string) { 805 if deps != nil { 806 a.missingDeps = append(a.missingDeps, deps...) 807 a.missingDeps = FirstUniqueStrings(a.missingDeps) 808 } 809} 810 811func (a *androidModuleContext) validateAndroidModule(module blueprint.Module) Module { 812 aModule, _ := module.(Module) 813 if aModule == nil { 814 a.ModuleErrorf("module %q not an android module", a.OtherModuleName(aModule)) 815 return nil 816 } 817 818 if !aModule.Enabled() { 819 if a.Config().AllowMissingDependencies() { 820 a.AddMissingDependencies([]string{a.OtherModuleName(aModule)}) 821 } else { 822 a.ModuleErrorf("depends on disabled module %q", a.OtherModuleName(aModule)) 823 } 824 return nil 825 } 826 827 return aModule 828} 829 830func (a *androidModuleContext) VisitDirectDepsBlueprint(visit func(blueprint.Module)) { 831 a.ModuleContext.VisitDirectDeps(visit) 832} 833 834func (a *androidModuleContext) VisitDirectDeps(visit func(Module)) { 835 a.ModuleContext.VisitDirectDeps(func(module blueprint.Module) { 836 if aModule := a.validateAndroidModule(module); aModule != nil { 837 visit(aModule) 838 } 839 }) 840} 841 842func (a *androidModuleContext) VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) { 843 a.ModuleContext.VisitDirectDeps(func(module blueprint.Module) { 844 if aModule := a.validateAndroidModule(module); aModule != nil { 845 if a.ModuleContext.OtherModuleDependencyTag(aModule) == tag { 846 visit(aModule) 847 } 848 } 849 }) 850} 851 852func (a *androidModuleContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) { 853 a.ModuleContext.VisitDirectDepsIf( 854 // pred 855 func(module blueprint.Module) bool { 856 if aModule := a.validateAndroidModule(module); aModule != nil { 857 return pred(aModule) 858 } else { 859 return false 860 } 861 }, 862 // visit 863 func(module blueprint.Module) { 864 visit(module.(Module)) 865 }) 866} 867 868func (a *androidModuleContext) VisitDepsDepthFirst(visit func(Module)) { 869 a.ModuleContext.VisitDepsDepthFirst(func(module blueprint.Module) { 870 if aModule := a.validateAndroidModule(module); aModule != nil { 871 visit(aModule) 872 } 873 }) 874} 875 876func (a *androidModuleContext) VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module)) { 877 a.ModuleContext.VisitDepsDepthFirstIf( 878 // pred 879 func(module blueprint.Module) bool { 880 if aModule := a.validateAndroidModule(module); aModule != nil { 881 return pred(aModule) 882 } else { 883 return false 884 } 885 }, 886 // visit 887 func(module blueprint.Module) { 888 visit(module.(Module)) 889 }) 890} 891 892func (a *androidModuleContext) WalkDeps(visit func(Module, Module) bool) { 893 a.ModuleContext.WalkDeps(func(child, parent blueprint.Module) bool { 894 childAndroidModule := a.validateAndroidModule(child) 895 parentAndroidModule := a.validateAndroidModule(parent) 896 if childAndroidModule != nil && parentAndroidModule != nil { 897 return visit(childAndroidModule, parentAndroidModule) 898 } else { 899 return false 900 } 901 }) 902} 903 904func (a *androidModuleContext) VisitAllModuleVariants(visit func(Module)) { 905 a.ModuleContext.VisitAllModuleVariants(func(module blueprint.Module) { 906 visit(module.(Module)) 907 }) 908} 909 910func (a *androidModuleContext) PrimaryModule() Module { 911 return a.ModuleContext.PrimaryModule().(Module) 912} 913 914func (a *androidModuleContext) FinalModule() Module { 915 return a.ModuleContext.FinalModule().(Module) 916} 917 918func (a *androidBaseContextImpl) Target() Target { 919 return a.target 920} 921 922func (a *androidBaseContextImpl) TargetPrimary() bool { 923 return a.targetPrimary 924} 925 926func (a *androidBaseContextImpl) Arch() Arch { 927 return a.target.Arch 928} 929 930func (a *androidBaseContextImpl) Os() OsType { 931 return a.target.Os 932} 933 934func (a *androidBaseContextImpl) Host() bool { 935 return a.target.Os.Class == Host || a.target.Os.Class == HostCross 936} 937 938func (a *androidBaseContextImpl) Device() bool { 939 return a.target.Os.Class == Device 940} 941 942func (a *androidBaseContextImpl) Darwin() bool { 943 return a.target.Os == Darwin 944} 945 946func (a *androidBaseContextImpl) Windows() bool { 947 return a.target.Os == Windows 948} 949 950func (a *androidBaseContextImpl) Debug() bool { 951 return a.debug 952} 953 954func (a *androidBaseContextImpl) PrimaryArch() bool { 955 if len(a.config.Targets[a.target.Os.Class]) <= 1 { 956 return true 957 } 958 return a.target.Arch.ArchType == a.config.Targets[a.target.Os.Class][0].Arch.ArchType 959} 960 961func (a *androidBaseContextImpl) AConfig() Config { 962 return a.config 963} 964 965func (a *androidBaseContextImpl) DeviceConfig() DeviceConfig { 966 return DeviceConfig{a.config.deviceConfig} 967} 968 969func (a *androidBaseContextImpl) Platform() bool { 970 return a.kind == platformModule 971} 972 973func (a *androidBaseContextImpl) DeviceSpecific() bool { 974 return a.kind == deviceSpecificModule 975} 976 977func (a *androidBaseContextImpl) SocSpecific() bool { 978 return a.kind == socSpecificModule 979} 980 981func (a *androidBaseContextImpl) ProductSpecific() bool { 982 return a.kind == productSpecificModule 983} 984 985func (a *androidModuleContext) InstallInData() bool { 986 return a.module.InstallInData() 987} 988 989func (a *androidModuleContext) InstallInSanitizerDir() bool { 990 return a.module.InstallInSanitizerDir() 991} 992 993func (a *androidModuleContext) skipInstall(fullInstallPath OutputPath) bool { 994 if a.module.base().commonProperties.SkipInstall { 995 return true 996 } 997 998 if a.Device() { 999 if a.Config().SkipDeviceInstall() { 1000 return true 1001 } 1002 1003 if a.Config().SkipMegaDeviceInstall(fullInstallPath.String()) { 1004 return true 1005 } 1006 } 1007 1008 return false 1009} 1010 1011func (a *androidModuleContext) InstallFile(installPath OutputPath, name string, srcPath Path, 1012 deps ...Path) OutputPath { 1013 return a.installFile(installPath, name, srcPath, Cp, deps) 1014} 1015 1016func (a *androidModuleContext) InstallExecutable(installPath OutputPath, name string, srcPath Path, 1017 deps ...Path) OutputPath { 1018 return a.installFile(installPath, name, srcPath, CpExecutable, deps) 1019} 1020 1021func (a *androidModuleContext) installFile(installPath OutputPath, name string, srcPath Path, 1022 rule blueprint.Rule, deps []Path) OutputPath { 1023 1024 fullInstallPath := installPath.Join(a, name) 1025 a.module.base().hooks.runInstallHooks(a, fullInstallPath, false) 1026 1027 if !a.skipInstall(fullInstallPath) { 1028 1029 deps = append(deps, a.installDeps...) 1030 1031 var implicitDeps, orderOnlyDeps Paths 1032 1033 if a.Host() { 1034 // Installed host modules might be used during the build, depend directly on their 1035 // dependencies so their timestamp is updated whenever their dependency is updated 1036 implicitDeps = deps 1037 } else { 1038 orderOnlyDeps = deps 1039 } 1040 1041 a.Build(pctx, BuildParams{ 1042 Rule: rule, 1043 Description: "install " + fullInstallPath.Base(), 1044 Output: fullInstallPath, 1045 Input: srcPath, 1046 Implicits: implicitDeps, 1047 OrderOnly: orderOnlyDeps, 1048 Default: !a.Config().EmbeddedInMake(), 1049 }) 1050 1051 a.installFiles = append(a.installFiles, fullInstallPath) 1052 } 1053 a.checkbuildFiles = append(a.checkbuildFiles, srcPath) 1054 return fullInstallPath 1055} 1056 1057func (a *androidModuleContext) InstallSymlink(installPath OutputPath, name string, srcPath OutputPath) OutputPath { 1058 fullInstallPath := installPath.Join(a, name) 1059 a.module.base().hooks.runInstallHooks(a, fullInstallPath, true) 1060 1061 if !a.skipInstall(fullInstallPath) { 1062 1063 a.Build(pctx, BuildParams{ 1064 Rule: Symlink, 1065 Description: "install symlink " + fullInstallPath.Base(), 1066 Output: fullInstallPath, 1067 OrderOnly: Paths{srcPath}, 1068 Default: !a.Config().EmbeddedInMake(), 1069 Args: map[string]string{ 1070 "fromPath": srcPath.String(), 1071 }, 1072 }) 1073 1074 a.installFiles = append(a.installFiles, fullInstallPath) 1075 a.checkbuildFiles = append(a.checkbuildFiles, srcPath) 1076 } 1077 return fullInstallPath 1078} 1079 1080func (a *androidModuleContext) CheckbuildFile(srcPath Path) { 1081 a.checkbuildFiles = append(a.checkbuildFiles, srcPath) 1082} 1083 1084type fileInstaller interface { 1085 filesToInstall() Paths 1086} 1087 1088func isFileInstaller(m blueprint.Module) bool { 1089 _, ok := m.(fileInstaller) 1090 return ok 1091} 1092 1093func isAndroidModule(m blueprint.Module) bool { 1094 _, ok := m.(Module) 1095 return ok 1096} 1097 1098func findStringInSlice(str string, slice []string) int { 1099 for i, s := range slice { 1100 if s == str { 1101 return i 1102 } 1103 } 1104 return -1 1105} 1106 1107func SrcIsModule(s string) string { 1108 if len(s) > 1 && s[0] == ':' { 1109 return s[1:] 1110 } 1111 return "" 1112} 1113 1114type sourceDependencyTag struct { 1115 blueprint.BaseDependencyTag 1116} 1117 1118var SourceDepTag sourceDependencyTag 1119 1120// Adds necessary dependencies to satisfy filegroup or generated sources modules listed in srcFiles 1121// using ":module" syntax, if any. 1122func ExtractSourcesDeps(ctx BottomUpMutatorContext, srcFiles []string) { 1123 var deps []string 1124 set := make(map[string]bool) 1125 1126 for _, s := range srcFiles { 1127 if m := SrcIsModule(s); m != "" { 1128 if _, found := set[m]; found { 1129 ctx.ModuleErrorf("found source dependency duplicate: %q!", m) 1130 } else { 1131 set[m] = true 1132 deps = append(deps, m) 1133 } 1134 } 1135 } 1136 1137 ctx.AddDependency(ctx.Module(), SourceDepTag, deps...) 1138} 1139 1140// Adds necessary dependencies to satisfy filegroup or generated sources modules specified in s 1141// using ":module" syntax, if any. 1142func ExtractSourceDeps(ctx BottomUpMutatorContext, s *string) { 1143 if s != nil { 1144 if m := SrcIsModule(*s); m != "" { 1145 ctx.AddDependency(ctx.Module(), SourceDepTag, m) 1146 } 1147 } 1148} 1149 1150type SourceFileProducer interface { 1151 Srcs() Paths 1152} 1153 1154// Returns a list of paths expanded from globs and modules referenced using ":module" syntax. 1155// ExtractSourcesDeps must have already been called during the dependency resolution phase. 1156func (ctx *androidModuleContext) ExpandSources(srcFiles, excludes []string) Paths { 1157 return ctx.ExpandSourcesSubDir(srcFiles, excludes, "") 1158} 1159 1160// Returns a single path expanded from globs and modules referenced using ":module" syntax. 1161// ExtractSourceDeps must have already been called during the dependency resolution phase. 1162func (ctx *androidModuleContext) ExpandSource(srcFile, prop string) Path { 1163 srcFiles := ctx.ExpandSourcesSubDir([]string{srcFile}, nil, "") 1164 if len(srcFiles) == 1 { 1165 return srcFiles[0] 1166 } else { 1167 ctx.PropertyErrorf(prop, "module providing %s must produce exactly one file", prop) 1168 return nil 1169 } 1170} 1171 1172// Returns an optional single path expanded from globs and modules referenced using ":module" syntax if 1173// the srcFile is non-nil. 1174// ExtractSourceDeps must have already been called during the dependency resolution phase. 1175func (ctx *androidModuleContext) ExpandOptionalSource(srcFile *string, prop string) OptionalPath { 1176 if srcFile != nil { 1177 return OptionalPathForPath(ctx.ExpandSource(*srcFile, prop)) 1178 } 1179 return OptionalPath{} 1180} 1181 1182func (ctx *androidModuleContext) ExpandSourcesSubDir(srcFiles, excludes []string, subDir string) Paths { 1183 prefix := PathForModuleSrc(ctx).String() 1184 1185 var expandedExcludes []string 1186 if excludes != nil { 1187 expandedExcludes = make([]string, 0, len(excludes)) 1188 } 1189 1190 for _, e := range excludes { 1191 if m := SrcIsModule(e); m != "" { 1192 module := ctx.GetDirectDepWithTag(m, SourceDepTag) 1193 if module == nil { 1194 // Error will have been handled by ExtractSourcesDeps 1195 continue 1196 } 1197 if srcProducer, ok := module.(SourceFileProducer); ok { 1198 expandedExcludes = append(expandedExcludes, srcProducer.Srcs().Strings()...) 1199 } else { 1200 ctx.ModuleErrorf("srcs dependency %q is not a source file producing module", m) 1201 } 1202 } else { 1203 expandedExcludes = append(expandedExcludes, filepath.Join(prefix, e)) 1204 } 1205 } 1206 expandedSrcFiles := make(Paths, 0, len(srcFiles)) 1207 for _, s := range srcFiles { 1208 if m := SrcIsModule(s); m != "" { 1209 module := ctx.GetDirectDepWithTag(m, SourceDepTag) 1210 if module == nil { 1211 // Error will have been handled by ExtractSourcesDeps 1212 continue 1213 } 1214 if srcProducer, ok := module.(SourceFileProducer); ok { 1215 moduleSrcs := srcProducer.Srcs() 1216 for _, e := range expandedExcludes { 1217 for j, ms := range moduleSrcs { 1218 if ms.String() == e { 1219 moduleSrcs = append(moduleSrcs[:j], moduleSrcs[j+1:]...) 1220 } 1221 } 1222 } 1223 expandedSrcFiles = append(expandedSrcFiles, moduleSrcs...) 1224 } else { 1225 ctx.ModuleErrorf("srcs dependency %q is not a source file producing module", m) 1226 } 1227 } else if pathtools.IsGlob(s) { 1228 globbedSrcFiles := ctx.GlobFiles(filepath.Join(prefix, s), expandedExcludes) 1229 for i, s := range globbedSrcFiles { 1230 globbedSrcFiles[i] = s.(ModuleSrcPath).WithSubDir(ctx, subDir) 1231 } 1232 expandedSrcFiles = append(expandedSrcFiles, globbedSrcFiles...) 1233 } else { 1234 p := PathForModuleSrc(ctx, s).WithSubDir(ctx, subDir) 1235 j := findStringInSlice(p.String(), expandedExcludes) 1236 if j == -1 { 1237 expandedSrcFiles = append(expandedSrcFiles, p) 1238 } 1239 1240 } 1241 } 1242 return expandedSrcFiles 1243} 1244 1245func (ctx *androidModuleContext) RequiredModuleNames() []string { 1246 return ctx.module.base().commonProperties.Required 1247} 1248 1249func (ctx *androidModuleContext) Glob(globPattern string, excludes []string) Paths { 1250 ret, err := ctx.GlobWithDeps(globPattern, excludes) 1251 if err != nil { 1252 ctx.ModuleErrorf("glob: %s", err.Error()) 1253 } 1254 return pathsForModuleSrcFromFullPath(ctx, ret, true) 1255} 1256 1257func (ctx *androidModuleContext) GlobFiles(globPattern string, excludes []string) Paths { 1258 ret, err := ctx.GlobWithDeps(globPattern, excludes) 1259 if err != nil { 1260 ctx.ModuleErrorf("glob: %s", err.Error()) 1261 } 1262 return pathsForModuleSrcFromFullPath(ctx, ret, false) 1263} 1264 1265func init() { 1266 RegisterSingletonType("buildtarget", BuildTargetSingleton) 1267} 1268 1269func BuildTargetSingleton() Singleton { 1270 return &buildTargetSingleton{} 1271} 1272 1273func parentDir(dir string) string { 1274 dir, _ = filepath.Split(dir) 1275 return filepath.Clean(dir) 1276} 1277 1278type buildTargetSingleton struct{} 1279 1280func (c *buildTargetSingleton) GenerateBuildActions(ctx SingletonContext) { 1281 var checkbuildDeps Paths 1282 1283 mmTarget := func(dir string) WritablePath { 1284 return PathForPhony(ctx, 1285 "MODULES-IN-"+strings.Replace(filepath.Clean(dir), "/", "-", -1)) 1286 } 1287 1288 modulesInDir := make(map[string]Paths) 1289 1290 ctx.VisitAllModules(func(module Module) { 1291 blueprintDir := module.base().blueprintDir 1292 installTarget := module.base().installTarget 1293 checkbuildTarget := module.base().checkbuildTarget 1294 1295 if checkbuildTarget != nil { 1296 checkbuildDeps = append(checkbuildDeps, checkbuildTarget) 1297 modulesInDir[blueprintDir] = append(modulesInDir[blueprintDir], checkbuildTarget) 1298 } 1299 1300 if installTarget != nil { 1301 modulesInDir[blueprintDir] = append(modulesInDir[blueprintDir], installTarget) 1302 } 1303 }) 1304 1305 suffix := "" 1306 if ctx.Config().EmbeddedInMake() { 1307 suffix = "-soong" 1308 } 1309 1310 // Create a top-level checkbuild target that depends on all modules 1311 ctx.Build(pctx, BuildParams{ 1312 Rule: blueprint.Phony, 1313 Output: PathForPhony(ctx, "checkbuild"+suffix), 1314 Implicits: checkbuildDeps, 1315 }) 1316 1317 // Make will generate the MODULES-IN-* targets 1318 if ctx.Config().EmbeddedInMake() { 1319 return 1320 } 1321 1322 sortedKeys := func(m map[string]Paths) []string { 1323 s := make([]string, 0, len(m)) 1324 for k := range m { 1325 s = append(s, k) 1326 } 1327 sort.Strings(s) 1328 return s 1329 } 1330 1331 // Ensure ancestor directories are in modulesInDir 1332 dirs := sortedKeys(modulesInDir) 1333 for _, dir := range dirs { 1334 dir := parentDir(dir) 1335 for dir != "." && dir != "/" { 1336 if _, exists := modulesInDir[dir]; exists { 1337 break 1338 } 1339 modulesInDir[dir] = nil 1340 dir = parentDir(dir) 1341 } 1342 } 1343 1344 // Make directories build their direct subdirectories 1345 dirs = sortedKeys(modulesInDir) 1346 for _, dir := range dirs { 1347 p := parentDir(dir) 1348 if p != "." && p != "/" { 1349 modulesInDir[p] = append(modulesInDir[p], mmTarget(dir)) 1350 } 1351 } 1352 1353 // Create a MODULES-IN-<directory> target that depends on all modules in a directory, and 1354 // depends on the MODULES-IN-* targets of all of its subdirectories that contain Android.bp 1355 // files. 1356 for _, dir := range dirs { 1357 ctx.Build(pctx, BuildParams{ 1358 Rule: blueprint.Phony, 1359 Output: mmTarget(dir), 1360 Implicits: modulesInDir[dir], 1361 // HACK: checkbuild should be an optional build, but force it 1362 // enabled for now in standalone builds 1363 Default: !ctx.Config().EmbeddedInMake(), 1364 }) 1365 } 1366 1367 // Create (host|host-cross|target)-<OS> phony rules to build a reduced checkbuild. 1368 osDeps := map[OsType]Paths{} 1369 ctx.VisitAllModules(func(module Module) { 1370 if module.Enabled() { 1371 os := module.Target().Os 1372 osDeps[os] = append(osDeps[os], module.base().checkbuildFiles...) 1373 } 1374 }) 1375 1376 osClass := make(map[string]Paths) 1377 for os, deps := range osDeps { 1378 var className string 1379 1380 switch os.Class { 1381 case Host: 1382 className = "host" 1383 case HostCross: 1384 className = "host-cross" 1385 case Device: 1386 className = "target" 1387 default: 1388 continue 1389 } 1390 1391 name := PathForPhony(ctx, className+"-"+os.Name) 1392 osClass[className] = append(osClass[className], name) 1393 1394 ctx.Build(pctx, BuildParams{ 1395 Rule: blueprint.Phony, 1396 Output: name, 1397 Implicits: deps, 1398 }) 1399 } 1400 1401 // Wrap those into host|host-cross|target phony rules 1402 osClasses := sortedKeys(osClass) 1403 for _, class := range osClasses { 1404 ctx.Build(pctx, BuildParams{ 1405 Rule: blueprint.Phony, 1406 Output: PathForPhony(ctx, class), 1407 Implicits: osClass[class], 1408 }) 1409 } 1410} 1411 1412type AndroidModulesByName struct { 1413 slice []Module 1414 ctx interface { 1415 ModuleName(blueprint.Module) string 1416 ModuleSubDir(blueprint.Module) string 1417 } 1418} 1419 1420func (s AndroidModulesByName) Len() int { return len(s.slice) } 1421func (s AndroidModulesByName) Less(i, j int) bool { 1422 mi, mj := s.slice[i], s.slice[j] 1423 ni, nj := s.ctx.ModuleName(mi), s.ctx.ModuleName(mj) 1424 1425 if ni != nj { 1426 return ni < nj 1427 } else { 1428 return s.ctx.ModuleSubDir(mi) < s.ctx.ModuleSubDir(mj) 1429 } 1430} 1431func (s AndroidModulesByName) Swap(i, j int) { s.slice[i], s.slice[j] = s.slice[j], s.slice[i] } 1432