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