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 "strings" 21 22 "github.com/google/blueprint" 23 "github.com/google/blueprint/pathtools" 24) 25 26var ( 27 DeviceSharedLibrary = "shared_library" 28 DeviceStaticLibrary = "static_library" 29 DeviceExecutable = "executable" 30 HostSharedLibrary = "host_shared_library" 31 HostStaticLibrary = "host_static_library" 32 HostExecutable = "host_executable" 33) 34 35type ModuleBuildParams struct { 36 Rule blueprint.Rule 37 Deps blueprint.Deps 38 Depfile WritablePath 39 Output WritablePath 40 Outputs WritablePaths 41 ImplicitOutput WritablePath 42 ImplicitOutputs WritablePaths 43 Input Path 44 Inputs Paths 45 Implicit Path 46 Implicits Paths 47 OrderOnly Paths 48 Default bool 49 Args map[string]string 50} 51 52type androidBaseContext interface { 53 Target() Target 54 TargetPrimary() bool 55 Arch() Arch 56 Os() OsType 57 Host() bool 58 Device() bool 59 Darwin() bool 60 Debug() bool 61 PrimaryArch() bool 62 Vendor() bool 63 AConfig() Config 64 DeviceConfig() DeviceConfig 65} 66 67type BaseContext interface { 68 blueprint.BaseModuleContext 69 androidBaseContext 70} 71 72type ModuleContext interface { 73 blueprint.ModuleContext 74 androidBaseContext 75 76 // Similar to Build, but takes Paths instead of []string, 77 // and performs more verification. 78 ModuleBuild(pctx blueprint.PackageContext, params ModuleBuildParams) 79 80 ExpandSources(srcFiles, excludes []string) Paths 81 ExpandSourcesSubDir(srcFiles, excludes []string, subDir string) Paths 82 Glob(globPattern string, excludes []string) Paths 83 84 InstallFile(installPath OutputPath, srcPath Path, deps ...Path) OutputPath 85 InstallFileName(installPath OutputPath, name string, srcPath Path, deps ...Path) OutputPath 86 InstallSymlink(installPath OutputPath, name string, srcPath OutputPath) OutputPath 87 CheckbuildFile(srcPath Path) 88 89 AddMissingDependencies(deps []string) 90 91 InstallInData() bool 92 InstallInSanitizerDir() bool 93 94 RequiredModuleNames() []string 95} 96 97type Module interface { 98 blueprint.Module 99 100 GenerateAndroidBuildActions(ModuleContext) 101 DepsMutator(BottomUpMutatorContext) 102 103 base() *ModuleBase 104 Enabled() bool 105 Target() Target 106 InstallInData() bool 107 InstallInSanitizerDir() bool 108 SkipInstall() 109} 110 111type nameProperties struct { 112 // The name of the module. Must be unique across all modules. 113 Name string 114} 115 116type commonProperties struct { 117 Tags []string 118 119 // emit build rules for this module 120 Enabled *bool `android:"arch_variant"` 121 122 // control whether this module compiles for 32-bit, 64-bit, or both. Possible values 123 // are "32" (compile for 32-bit only), "64" (compile for 64-bit only), "both" (compile for both 124 // architectures), or "first" (compile for 64-bit on a 64-bit platform, and 32-bit on a 32-bit 125 // platform 126 Compile_multilib string `android:"arch_variant"` 127 128 Target struct { 129 Host struct { 130 Compile_multilib string 131 } 132 Android struct { 133 Compile_multilib string 134 } 135 } 136 137 Default_multilib string `blueprint:"mutated"` 138 139 // whether this is a proprietary vendor module, and should be installed into /vendor 140 Proprietary bool 141 142 // vendor who owns this module 143 Owner string 144 145 // whether this module is device specific and should be installed into /vendor 146 Vendor bool 147 148 // *.logtags files, to combine together in order to generate the /system/etc/event-log-tags 149 // file 150 Logtags []string 151 152 // init.rc files to be installed if this module is installed 153 Init_rc []string 154 155 // names of other modules to install if this module is installed 156 Required []string 157 158 // Set by TargetMutator 159 CompileTarget Target `blueprint:"mutated"` 160 CompilePrimary bool `blueprint:"mutated"` 161 162 // Set by InitAndroidModule 163 HostOrDeviceSupported HostOrDeviceSupported `blueprint:"mutated"` 164 ArchSpecific bool `blueprint:"mutated"` 165 166 SkipInstall bool `blueprint:"mutated"` 167} 168 169type hostAndDeviceProperties struct { 170 Host_supported *bool 171 Device_supported *bool 172} 173 174type Multilib string 175 176const ( 177 MultilibBoth Multilib = "both" 178 MultilibFirst Multilib = "first" 179 MultilibCommon Multilib = "common" 180 MultilibDefault Multilib = "" 181) 182 183type HostOrDeviceSupported int 184 185const ( 186 _ HostOrDeviceSupported = iota 187 HostSupported 188 HostSupportedNoCross 189 DeviceSupported 190 HostAndDeviceSupported 191 HostAndDeviceDefault 192 NeitherHostNorDeviceSupported 193) 194 195func InitAndroidModule(m Module, 196 propertyStructs ...interface{}) (blueprint.Module, []interface{}) { 197 198 base := m.base() 199 base.module = m 200 201 propertyStructs = append(propertyStructs, 202 &base.nameProperties, 203 &base.commonProperties, 204 &base.variableProperties) 205 206 return m, propertyStructs 207} 208 209func InitAndroidArchModule(m Module, hod HostOrDeviceSupported, defaultMultilib Multilib, 210 propertyStructs ...interface{}) (blueprint.Module, []interface{}) { 211 212 _, propertyStructs = InitAndroidModule(m, propertyStructs...) 213 214 base := m.base() 215 base.commonProperties.HostOrDeviceSupported = hod 216 base.commonProperties.Default_multilib = string(defaultMultilib) 217 base.commonProperties.ArchSpecific = true 218 219 switch hod { 220 case HostAndDeviceSupported: 221 // Default to module to device supported, host not supported, can override in module 222 // properties 223 base.hostAndDeviceProperties.Device_supported = boolPtr(true) 224 fallthrough 225 case HostAndDeviceDefault: 226 propertyStructs = append(propertyStructs, &base.hostAndDeviceProperties) 227 } 228 229 return InitArchModule(m, propertyStructs...) 230} 231 232// A ModuleBase object contains the properties that are common to all Android 233// modules. It should be included as an anonymous field in every module 234// struct definition. InitAndroidModule should then be called from the module's 235// factory function, and the return values from InitAndroidModule should be 236// returned from the factory function. 237// 238// The ModuleBase type is responsible for implementing the GenerateBuildActions 239// method to support the blueprint.Module interface. This method will then call 240// the module's GenerateAndroidBuildActions method once for each build variant 241// that is to be built. GenerateAndroidBuildActions is passed a 242// AndroidModuleContext rather than the usual blueprint.ModuleContext. 243// AndroidModuleContext exposes extra functionality specific to the Android build 244// system including details about the particular build variant that is to be 245// generated. 246// 247// For example: 248// 249// import ( 250// "android/soong/android" 251// "github.com/google/blueprint" 252// ) 253// 254// type myModule struct { 255// android.ModuleBase 256// properties struct { 257// MyProperty string 258// } 259// } 260// 261// func NewMyModule() (blueprint.Module, []interface{}) { 262// m := &myModule{} 263// return android.InitAndroidModule(m, &m.properties) 264// } 265// 266// func (m *myModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { 267// // Get the CPU architecture for the current build variant. 268// variantArch := ctx.Arch() 269// 270// // ... 271// } 272type ModuleBase struct { 273 // Putting the curiously recurring thing pointing to the thing that contains 274 // the thing pattern to good use. 275 module Module 276 277 nameProperties nameProperties 278 commonProperties commonProperties 279 variableProperties variableProperties 280 hostAndDeviceProperties hostAndDeviceProperties 281 generalProperties []interface{} 282 archProperties []interface{} 283 customizableProperties []interface{} 284 285 noAddressSanitizer bool 286 installFiles Paths 287 checkbuildFiles Paths 288 289 // Used by buildTargetSingleton to create checkbuild and per-directory build targets 290 // Only set on the final variant of each module 291 installTarget string 292 checkbuildTarget string 293 blueprintDir string 294 295 hooks hooks 296} 297 298// Name returns the name of the module. It may be overridden by individual module types, for 299// example prebuilts will prepend prebuilt_ to the name. 300func (a *ModuleBase) Name() string { 301 return a.nameProperties.Name 302} 303 304// BaseModuleName returns the name of the module as specified in the blueprints file. 305func (a *ModuleBase) BaseModuleName() string { 306 return a.nameProperties.Name 307} 308 309func (a *ModuleBase) base() *ModuleBase { 310 return a 311} 312 313func (a *ModuleBase) SetTarget(target Target, primary bool) { 314 a.commonProperties.CompileTarget = target 315 a.commonProperties.CompilePrimary = primary 316} 317 318func (a *ModuleBase) Target() Target { 319 return a.commonProperties.CompileTarget 320} 321 322func (a *ModuleBase) TargetPrimary() bool { 323 return a.commonProperties.CompilePrimary 324} 325 326func (a *ModuleBase) Os() OsType { 327 return a.Target().Os 328} 329 330func (a *ModuleBase) Host() bool { 331 return a.Os().Class == Host || a.Os().Class == HostCross 332} 333 334func (a *ModuleBase) Arch() Arch { 335 return a.Target().Arch 336} 337 338func (a *ModuleBase) ArchSpecific() bool { 339 return a.commonProperties.ArchSpecific 340} 341 342func (a *ModuleBase) OsClassSupported() []OsClass { 343 switch a.commonProperties.HostOrDeviceSupported { 344 case HostSupported: 345 return []OsClass{Host, HostCross} 346 case HostSupportedNoCross: 347 return []OsClass{Host} 348 case DeviceSupported: 349 return []OsClass{Device} 350 case HostAndDeviceSupported: 351 var supported []OsClass 352 if Bool(a.hostAndDeviceProperties.Host_supported) { 353 supported = append(supported, Host, HostCross) 354 } 355 if Bool(a.hostAndDeviceProperties.Device_supported) { 356 supported = append(supported, Device) 357 } 358 return supported 359 default: 360 return nil 361 } 362} 363 364func (a *ModuleBase) DeviceSupported() bool { 365 return a.commonProperties.HostOrDeviceSupported == DeviceSupported || 366 a.commonProperties.HostOrDeviceSupported == HostAndDeviceSupported && 367 Bool(a.hostAndDeviceProperties.Device_supported) 368} 369 370func (a *ModuleBase) Enabled() bool { 371 if a.commonProperties.Enabled == nil { 372 return !a.Os().DefaultDisabled 373 } 374 return *a.commonProperties.Enabled 375} 376 377func (a *ModuleBase) SkipInstall() { 378 a.commonProperties.SkipInstall = true 379} 380 381func (a *ModuleBase) computeInstallDeps( 382 ctx blueprint.ModuleContext) Paths { 383 384 result := Paths{} 385 ctx.VisitDepsDepthFirstIf(isFileInstaller, 386 func(m blueprint.Module) { 387 fileInstaller := m.(fileInstaller) 388 files := fileInstaller.filesToInstall() 389 result = append(result, files...) 390 }) 391 392 return result 393} 394 395func (a *ModuleBase) filesToInstall() Paths { 396 return a.installFiles 397} 398 399func (p *ModuleBase) NoAddressSanitizer() bool { 400 return p.noAddressSanitizer 401} 402 403func (p *ModuleBase) InstallInData() bool { 404 return false 405} 406 407func (p *ModuleBase) InstallInSanitizerDir() bool { 408 return false 409} 410 411func (a *ModuleBase) generateModuleTarget(ctx blueprint.ModuleContext) { 412 allInstalledFiles := Paths{} 413 allCheckbuildFiles := Paths{} 414 ctx.VisitAllModuleVariants(func(module blueprint.Module) { 415 a := module.(Module).base() 416 allInstalledFiles = append(allInstalledFiles, a.installFiles...) 417 allCheckbuildFiles = append(allCheckbuildFiles, a.checkbuildFiles...) 418 }) 419 420 deps := []string{} 421 422 if len(allInstalledFiles) > 0 { 423 name := ctx.ModuleName() + "-install" 424 ctx.Build(pctx, blueprint.BuildParams{ 425 Rule: blueprint.Phony, 426 Outputs: []string{name}, 427 Implicits: allInstalledFiles.Strings(), 428 Optional: ctx.Config().(Config).EmbeddedInMake(), 429 }) 430 deps = append(deps, name) 431 a.installTarget = name 432 } 433 434 if len(allCheckbuildFiles) > 0 { 435 name := ctx.ModuleName() + "-checkbuild" 436 ctx.Build(pctx, blueprint.BuildParams{ 437 Rule: blueprint.Phony, 438 Outputs: []string{name}, 439 Implicits: allCheckbuildFiles.Strings(), 440 Optional: true, 441 }) 442 deps = append(deps, name) 443 a.checkbuildTarget = name 444 } 445 446 if len(deps) > 0 { 447 suffix := "" 448 if ctx.Config().(Config).EmbeddedInMake() { 449 suffix = "-soong" 450 } 451 452 ctx.Build(pctx, blueprint.BuildParams{ 453 Rule: blueprint.Phony, 454 Outputs: []string{ctx.ModuleName() + suffix}, 455 Implicits: deps, 456 Optional: true, 457 }) 458 459 a.blueprintDir = ctx.ModuleDir() 460 } 461} 462 463func (a *ModuleBase) androidBaseContextFactory(ctx blueprint.BaseModuleContext) androidBaseContextImpl { 464 return androidBaseContextImpl{ 465 target: a.commonProperties.CompileTarget, 466 targetPrimary: a.commonProperties.CompilePrimary, 467 vendor: a.commonProperties.Proprietary || a.commonProperties.Vendor, 468 config: ctx.Config().(Config), 469 } 470} 471 472func (a *ModuleBase) GenerateBuildActions(ctx blueprint.ModuleContext) { 473 androidCtx := &androidModuleContext{ 474 module: a.module, 475 ModuleContext: ctx, 476 androidBaseContextImpl: a.androidBaseContextFactory(ctx), 477 installDeps: a.computeInstallDeps(ctx), 478 installFiles: a.installFiles, 479 missingDeps: ctx.GetMissingDependencies(), 480 } 481 482 if a.Enabled() { 483 a.module.GenerateAndroidBuildActions(androidCtx) 484 if ctx.Failed() { 485 return 486 } 487 488 a.installFiles = append(a.installFiles, androidCtx.installFiles...) 489 a.checkbuildFiles = append(a.checkbuildFiles, androidCtx.checkbuildFiles...) 490 } 491 492 if a == ctx.FinalModule().(Module).base() { 493 a.generateModuleTarget(ctx) 494 if ctx.Failed() { 495 return 496 } 497 } 498} 499 500type androidBaseContextImpl struct { 501 target Target 502 targetPrimary bool 503 debug bool 504 vendor bool 505 config Config 506} 507 508type androidModuleContext struct { 509 blueprint.ModuleContext 510 androidBaseContextImpl 511 installDeps Paths 512 installFiles Paths 513 checkbuildFiles Paths 514 missingDeps []string 515 module Module 516} 517 518func (a *androidModuleContext) ninjaError(outputs []string, err error) { 519 a.ModuleContext.Build(pctx, blueprint.BuildParams{ 520 Rule: ErrorRule, 521 Outputs: outputs, 522 Optional: true, 523 Args: map[string]string{ 524 "error": err.Error(), 525 }, 526 }) 527 return 528} 529 530func (a *androidModuleContext) Build(pctx blueprint.PackageContext, params blueprint.BuildParams) { 531 if a.missingDeps != nil { 532 a.ninjaError(params.Outputs, fmt.Errorf("module %s missing dependencies: %s\n", 533 a.ModuleName(), strings.Join(a.missingDeps, ", "))) 534 return 535 } 536 537 params.Optional = true 538 a.ModuleContext.Build(pctx, params) 539} 540 541func (a *androidModuleContext) ModuleBuild(pctx blueprint.PackageContext, params ModuleBuildParams) { 542 bparams := blueprint.BuildParams{ 543 Rule: params.Rule, 544 Deps: params.Deps, 545 Outputs: params.Outputs.Strings(), 546 ImplicitOutputs: params.ImplicitOutputs.Strings(), 547 Inputs: params.Inputs.Strings(), 548 Implicits: params.Implicits.Strings(), 549 OrderOnly: params.OrderOnly.Strings(), 550 Args: params.Args, 551 Optional: !params.Default, 552 } 553 554 if params.Depfile != nil { 555 bparams.Depfile = params.Depfile.String() 556 } 557 if params.Output != nil { 558 bparams.Outputs = append(bparams.Outputs, params.Output.String()) 559 } 560 if params.ImplicitOutput != nil { 561 bparams.ImplicitOutputs = append(bparams.ImplicitOutputs, params.ImplicitOutput.String()) 562 } 563 if params.Input != nil { 564 bparams.Inputs = append(bparams.Inputs, params.Input.String()) 565 } 566 if params.Implicit != nil { 567 bparams.Implicits = append(bparams.Implicits, params.Implicit.String()) 568 } 569 570 if a.missingDeps != nil { 571 a.ninjaError(bparams.Outputs, fmt.Errorf("module %s missing dependencies: %s\n", 572 a.ModuleName(), strings.Join(a.missingDeps, ", "))) 573 return 574 } 575 576 a.ModuleContext.Build(pctx, bparams) 577} 578 579func (a *androidModuleContext) GetMissingDependencies() []string { 580 return a.missingDeps 581} 582 583func (a *androidModuleContext) AddMissingDependencies(deps []string) { 584 if deps != nil { 585 a.missingDeps = append(a.missingDeps, deps...) 586 } 587} 588 589func (a *androidBaseContextImpl) Target() Target { 590 return a.target 591} 592 593func (a *androidBaseContextImpl) TargetPrimary() bool { 594 return a.targetPrimary 595} 596 597func (a *androidBaseContextImpl) Arch() Arch { 598 return a.target.Arch 599} 600 601func (a *androidBaseContextImpl) Os() OsType { 602 return a.target.Os 603} 604 605func (a *androidBaseContextImpl) Host() bool { 606 return a.target.Os.Class == Host || a.target.Os.Class == HostCross 607} 608 609func (a *androidBaseContextImpl) Device() bool { 610 return a.target.Os.Class == Device 611} 612 613func (a *androidBaseContextImpl) Darwin() bool { 614 return a.target.Os == Darwin 615} 616 617func (a *androidBaseContextImpl) Debug() bool { 618 return a.debug 619} 620 621func (a *androidBaseContextImpl) PrimaryArch() bool { 622 return a.target.Arch.ArchType == a.config.Targets[a.target.Os.Class][0].Arch.ArchType 623} 624 625func (a *androidBaseContextImpl) AConfig() Config { 626 return a.config 627} 628 629func (a *androidBaseContextImpl) DeviceConfig() DeviceConfig { 630 return DeviceConfig{a.config.deviceConfig} 631} 632 633func (a *androidBaseContextImpl) Vendor() bool { 634 return a.vendor 635} 636 637func (a *androidModuleContext) InstallInData() bool { 638 return a.module.InstallInData() 639} 640 641func (a *androidModuleContext) InstallInSanitizerDir() bool { 642 return a.module.InstallInSanitizerDir() 643} 644 645func (a *androidModuleContext) InstallFileName(installPath OutputPath, name string, srcPath Path, 646 deps ...Path) OutputPath { 647 648 fullInstallPath := installPath.Join(a, name) 649 a.module.base().hooks.runInstallHooks(a, fullInstallPath, false) 650 651 if !a.module.base().commonProperties.SkipInstall && 652 (!a.Device() || !a.AConfig().SkipDeviceInstall()) { 653 654 deps = append(deps, a.installDeps...) 655 656 var implicitDeps, orderOnlyDeps Paths 657 658 if a.Host() { 659 // Installed host modules might be used during the build, depend directly on their 660 // dependencies so their timestamp is updated whenever their dependency is updated 661 implicitDeps = deps 662 } else { 663 orderOnlyDeps = deps 664 } 665 666 a.ModuleBuild(pctx, ModuleBuildParams{ 667 Rule: Cp, 668 Output: fullInstallPath, 669 Input: srcPath, 670 Implicits: implicitDeps, 671 OrderOnly: orderOnlyDeps, 672 Default: !a.AConfig().EmbeddedInMake(), 673 }) 674 675 a.installFiles = append(a.installFiles, fullInstallPath) 676 } 677 a.checkbuildFiles = append(a.checkbuildFiles, srcPath) 678 return fullInstallPath 679} 680 681func (a *androidModuleContext) InstallFile(installPath OutputPath, srcPath Path, deps ...Path) OutputPath { 682 return a.InstallFileName(installPath, filepath.Base(srcPath.String()), srcPath, deps...) 683} 684 685func (a *androidModuleContext) InstallSymlink(installPath OutputPath, name string, srcPath OutputPath) OutputPath { 686 fullInstallPath := installPath.Join(a, name) 687 a.module.base().hooks.runInstallHooks(a, fullInstallPath, true) 688 689 if !a.module.base().commonProperties.SkipInstall && 690 (!a.Device() || !a.AConfig().SkipDeviceInstall()) { 691 692 a.ModuleBuild(pctx, ModuleBuildParams{ 693 Rule: Symlink, 694 Output: fullInstallPath, 695 OrderOnly: Paths{srcPath}, 696 Default: !a.AConfig().EmbeddedInMake(), 697 Args: map[string]string{ 698 "fromPath": srcPath.String(), 699 }, 700 }) 701 702 a.installFiles = append(a.installFiles, fullInstallPath) 703 a.checkbuildFiles = append(a.checkbuildFiles, srcPath) 704 } 705 return fullInstallPath 706} 707 708func (a *androidModuleContext) CheckbuildFile(srcPath Path) { 709 a.checkbuildFiles = append(a.checkbuildFiles, srcPath) 710} 711 712type fileInstaller interface { 713 filesToInstall() Paths 714} 715 716func isFileInstaller(m blueprint.Module) bool { 717 _, ok := m.(fileInstaller) 718 return ok 719} 720 721func isAndroidModule(m blueprint.Module) bool { 722 _, ok := m.(Module) 723 return ok 724} 725 726func findStringInSlice(str string, slice []string) int { 727 for i, s := range slice { 728 if s == str { 729 return i 730 } 731 } 732 return -1 733} 734 735func SrcIsModule(s string) string { 736 if len(s) > 1 && s[0] == ':' { 737 return s[1:] 738 } 739 return "" 740} 741 742type sourceDependencyTag struct { 743 blueprint.BaseDependencyTag 744} 745 746var SourceDepTag sourceDependencyTag 747 748// Returns a list of modules that must be depended on to satisfy filegroup or generated sources 749// modules listed in srcFiles using ":module" syntax 750func ExtractSourcesDeps(ctx BottomUpMutatorContext, srcFiles []string) { 751 var deps []string 752 for _, s := range srcFiles { 753 if m := SrcIsModule(s); m != "" { 754 deps = append(deps, m) 755 } 756 } 757 758 ctx.AddDependency(ctx.Module(), SourceDepTag, deps...) 759} 760 761type SourceFileProducer interface { 762 Srcs() Paths 763} 764 765// Returns a list of paths expanded from globs and modules referenced using ":module" syntax. 766// ExtractSourcesDeps must have already been called during the dependency resolution phase. 767func (ctx *androidModuleContext) ExpandSources(srcFiles, excludes []string) Paths { 768 return ctx.ExpandSourcesSubDir(srcFiles, excludes, "") 769} 770 771func (ctx *androidModuleContext) ExpandSourcesSubDir(srcFiles, excludes []string, subDir string) Paths { 772 prefix := PathForModuleSrc(ctx).String() 773 774 for i, e := range excludes { 775 j := findStringInSlice(e, srcFiles) 776 if j != -1 { 777 srcFiles = append(srcFiles[:j], srcFiles[j+1:]...) 778 } 779 780 excludes[i] = filepath.Join(prefix, e) 781 } 782 783 expandedSrcFiles := make(Paths, 0, len(srcFiles)) 784 for _, s := range srcFiles { 785 if m := SrcIsModule(s); m != "" { 786 module := ctx.GetDirectDepWithTag(m, SourceDepTag) 787 if srcProducer, ok := module.(SourceFileProducer); ok { 788 expandedSrcFiles = append(expandedSrcFiles, srcProducer.Srcs()...) 789 } else { 790 ctx.ModuleErrorf("srcs dependency %q is not a source file producing module", m) 791 } 792 } else if pathtools.IsGlob(s) { 793 globbedSrcFiles := ctx.Glob(filepath.Join(prefix, s), excludes) 794 expandedSrcFiles = append(expandedSrcFiles, globbedSrcFiles...) 795 for i, s := range expandedSrcFiles { 796 expandedSrcFiles[i] = s.(ModuleSrcPath).WithSubDir(ctx, subDir) 797 } 798 } else { 799 s := PathForModuleSrc(ctx, s).WithSubDir(ctx, subDir) 800 expandedSrcFiles = append(expandedSrcFiles, s) 801 } 802 } 803 804 return expandedSrcFiles 805} 806 807func (ctx *androidModuleContext) RequiredModuleNames() []string { 808 return ctx.module.base().commonProperties.Required 809} 810 811func (ctx *androidModuleContext) Glob(globPattern string, excludes []string) Paths { 812 ret, err := ctx.GlobWithDeps(globPattern, excludes) 813 if err != nil { 814 ctx.ModuleErrorf("glob: %s", err.Error()) 815 } 816 return pathsForModuleSrcFromFullPath(ctx, ret) 817} 818 819func init() { 820 RegisterSingletonType("buildtarget", BuildTargetSingleton) 821} 822 823func BuildTargetSingleton() blueprint.Singleton { 824 return &buildTargetSingleton{} 825} 826 827type buildTargetSingleton struct{} 828 829func (c *buildTargetSingleton) GenerateBuildActions(ctx blueprint.SingletonContext) { 830 checkbuildDeps := []string{} 831 832 dirModules := make(map[string][]string) 833 834 ctx.VisitAllModules(func(module blueprint.Module) { 835 if a, ok := module.(Module); ok { 836 blueprintDir := a.base().blueprintDir 837 installTarget := a.base().installTarget 838 checkbuildTarget := a.base().checkbuildTarget 839 840 if checkbuildTarget != "" { 841 checkbuildDeps = append(checkbuildDeps, checkbuildTarget) 842 dirModules[blueprintDir] = append(dirModules[blueprintDir], checkbuildTarget) 843 } 844 845 if installTarget != "" { 846 dirModules[blueprintDir] = append(dirModules[blueprintDir], installTarget) 847 } 848 } 849 }) 850 851 suffix := "" 852 if ctx.Config().(Config).EmbeddedInMake() { 853 suffix = "-soong" 854 } 855 856 // Create a top-level checkbuild target that depends on all modules 857 ctx.Build(pctx, blueprint.BuildParams{ 858 Rule: blueprint.Phony, 859 Outputs: []string{"checkbuild" + suffix}, 860 Implicits: checkbuildDeps, 861 Optional: true, 862 }) 863 864 // Create a mm/<directory> target that depends on all modules in a directory 865 dirs := sortedKeys(dirModules) 866 for _, dir := range dirs { 867 ctx.Build(pctx, blueprint.BuildParams{ 868 Rule: blueprint.Phony, 869 Outputs: []string{filepath.Join("mm", dir)}, 870 Implicits: dirModules[dir], 871 // HACK: checkbuild should be an optional build, but force it 872 // enabled for now in standalone builds 873 Optional: ctx.Config().(Config).EmbeddedInMake(), 874 }) 875 } 876} 877 878type AndroidModulesByName struct { 879 slice []Module 880 ctx interface { 881 ModuleName(blueprint.Module) string 882 ModuleSubDir(blueprint.Module) string 883 } 884} 885 886func (s AndroidModulesByName) Len() int { return len(s.slice) } 887func (s AndroidModulesByName) Less(i, j int) bool { 888 mi, mj := s.slice[i], s.slice[j] 889 ni, nj := s.ctx.ModuleName(mi), s.ctx.ModuleName(mj) 890 891 if ni != nj { 892 return ni < nj 893 } else { 894 return s.ctx.ModuleSubDir(mi) < s.ctx.ModuleSubDir(mj) 895 } 896} 897func (s AndroidModulesByName) Swap(i, j int) { s.slice[i], s.slice[j] = s.slice[j], s.slice[i] } 898