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 15// This file offers AndroidMkEntriesProvider, which individual modules implement to output 16// Android.mk entries that contain information about the modules built through Soong. Kati reads 17// and combines them with the legacy Make-based module definitions to produce the complete view of 18// the source tree, which makes this a critical point of Make-Soong interoperability. 19// 20// Naturally, Soong-only builds do not rely on this mechanism. 21 22package android 23 24import ( 25 "bytes" 26 "fmt" 27 "io" 28 "os" 29 "path/filepath" 30 "reflect" 31 "runtime" 32 "sort" 33 "strconv" 34 "strings" 35 36 "github.com/google/blueprint" 37 "github.com/google/blueprint/pathtools" 38 "github.com/google/blueprint/proptools" 39) 40 41func init() { 42 RegisterAndroidMkBuildComponents(InitRegistrationContext) 43} 44 45func RegisterAndroidMkBuildComponents(ctx RegistrationContext) { 46 ctx.RegisterParallelSingletonType("androidmk", AndroidMkSingleton) 47} 48 49// Enable androidmk support. 50// * Register the singleton 51// * Configure that we are inside make 52var PrepareForTestWithAndroidMk = GroupFixturePreparers( 53 FixtureRegisterWithContext(RegisterAndroidMkBuildComponents), 54 FixtureModifyConfig(SetKatiEnabledForTests), 55) 56 57// Deprecated: Use AndroidMkEntriesProvider instead, especially if you're not going to use the 58// Custom function. It's easier to use and test. 59type AndroidMkDataProvider interface { 60 AndroidMk() AndroidMkData 61 BaseModuleName() string 62} 63 64type AndroidMkData struct { 65 Class string 66 SubName string 67 DistFiles TaggedDistFiles 68 OutputFile OptionalPath 69 Disabled bool 70 Include string 71 Required []string 72 Host_required []string 73 Target_required []string 74 75 Custom func(w io.Writer, name, prefix, moduleDir string, data AndroidMkData) 76 77 Extra []AndroidMkExtraFunc 78 79 Entries AndroidMkEntries 80} 81 82type AndroidMkExtraFunc func(w io.Writer, outputFile Path) 83 84// Interface for modules to declare their Android.mk outputs. Note that every module needs to 85// implement this in order to be included in the final Android-<product_name>.mk output, even if 86// they only need to output the common set of entries without any customizations. 87type AndroidMkEntriesProvider interface { 88 // Returns AndroidMkEntries objects that contain all basic info plus extra customization data 89 // if needed. This is the core func to implement. 90 // Note that one can return multiple objects. For example, java_library may return an additional 91 // AndroidMkEntries object for its hostdex sub-module. 92 AndroidMkEntries() []AndroidMkEntries 93 // Modules don't need to implement this as it's already implemented by ModuleBase. 94 // AndroidMkEntries uses BaseModuleName() instead of ModuleName() because certain modules 95 // e.g. Prebuilts, override the Name() func and return modified names. 96 // If a different name is preferred, use SubName or OverrideName in AndroidMkEntries. 97 BaseModuleName() string 98} 99 100// The core data struct that modules use to provide their Android.mk data. 101type AndroidMkEntries struct { 102 // Android.mk class string, e.g EXECUTABLES, JAVA_LIBRARIES, ETC 103 Class string 104 // Optional suffix to append to the module name. Useful when a module wants to return multiple 105 // AndroidMkEntries objects. For example, when a java_library returns an additional entry for 106 // its hostdex sub-module, this SubName field is set to "-hostdex" so that it can have a 107 // different name than the parent's. 108 SubName string 109 // If set, this value overrides the base module name. SubName is still appended. 110 OverrideName string 111 // Dist files to output 112 DistFiles TaggedDistFiles 113 // The output file for Kati to process and/or install. If absent, the module is skipped. 114 OutputFile OptionalPath 115 // If true, the module is skipped and does not appear on the final Android-<product name>.mk 116 // file. Useful when a module needs to be skipped conditionally. 117 Disabled bool 118 // The postprocessing mk file to include, e.g. $(BUILD_SYSTEM)/soong_cc_rust_prebuilt.mk 119 // If not set, $(BUILD_SYSTEM)/prebuilt.mk is used. 120 Include string 121 // Required modules that need to be built and included in the final build output when building 122 // this module. 123 Required []string 124 // Required host modules that need to be built and included in the final build output when 125 // building this module. 126 Host_required []string 127 // Required device modules that need to be built and included in the final build output when 128 // building this module. 129 Target_required []string 130 131 header bytes.Buffer 132 footer bytes.Buffer 133 134 // Funcs to append additional Android.mk entries or modify the common ones. Multiple funcs are 135 // accepted so that common logic can be factored out as a shared func. 136 ExtraEntries []AndroidMkExtraEntriesFunc 137 // Funcs to add extra lines to the module's Android.mk output. Unlike AndroidMkExtraEntriesFunc, 138 // which simply sets Make variable values, this can be used for anything since it can write any 139 // Make statements directly to the final Android-*.mk file. 140 // Primarily used to call macros or declare/update Make targets. 141 ExtraFooters []AndroidMkExtraFootersFunc 142 143 // A map that holds the up-to-date Make variable values. Can be accessed from tests. 144 EntryMap map[string][]string 145 // A list of EntryMap keys in insertion order. This serves a few purposes: 146 // 1. Prevents churns. Golang map doesn't provide consistent iteration order, so without this, 147 // the outputted Android-*.mk file may change even though there have been no content changes. 148 // 2. Allows modules to refer to other variables, like LOCAL_BAR_VAR := $(LOCAL_FOO_VAR), 149 // without worrying about the variables being mixed up in the actual mk file. 150 // 3. Makes troubleshooting and spotting errors easier. 151 entryOrder []string 152 153 // Provides data typically stored by Context objects that are commonly needed by 154 //AndroidMkEntries objects. 155 entryContext AndroidMkEntriesContext 156} 157 158type AndroidMkEntriesContext interface { 159 OtherModuleProviderContext 160 Config() Config 161} 162 163type AndroidMkExtraEntriesContext interface { 164 Provider(provider blueprint.AnyProviderKey) (any, bool) 165} 166 167type androidMkExtraEntriesContext struct { 168 ctx fillInEntriesContext 169 mod blueprint.Module 170} 171 172func (a *androidMkExtraEntriesContext) Provider(provider blueprint.AnyProviderKey) (any, bool) { 173 return a.ctx.otherModuleProvider(a.mod, provider) 174} 175 176type AndroidMkExtraEntriesFunc func(ctx AndroidMkExtraEntriesContext, entries *AndroidMkEntries) 177type AndroidMkExtraFootersFunc func(w io.Writer, name, prefix, moduleDir string) 178 179// Utility funcs to manipulate Android.mk variable entries. 180 181// SetString sets a Make variable with the given name to the given value. 182func (a *AndroidMkEntries) SetString(name, value string) { 183 if _, ok := a.EntryMap[name]; !ok { 184 a.entryOrder = append(a.entryOrder, name) 185 } 186 a.EntryMap[name] = []string{value} 187} 188 189// SetPath sets a Make variable with the given name to the given path string. 190func (a *AndroidMkEntries) SetPath(name string, path Path) { 191 if _, ok := a.EntryMap[name]; !ok { 192 a.entryOrder = append(a.entryOrder, name) 193 } 194 a.EntryMap[name] = []string{path.String()} 195} 196 197// SetOptionalPath sets a Make variable with the given name to the given path string if it is valid. 198// It is a no-op if the given path is invalid. 199func (a *AndroidMkEntries) SetOptionalPath(name string, path OptionalPath) { 200 if path.Valid() { 201 a.SetPath(name, path.Path()) 202 } 203} 204 205// AddPath appends the given path string to a Make variable with the given name. 206func (a *AndroidMkEntries) AddPath(name string, path Path) { 207 if _, ok := a.EntryMap[name]; !ok { 208 a.entryOrder = append(a.entryOrder, name) 209 } 210 a.EntryMap[name] = append(a.EntryMap[name], path.String()) 211} 212 213// AddOptionalPath appends the given path string to a Make variable with the given name if it is 214// valid. It is a no-op if the given path is invalid. 215func (a *AndroidMkEntries) AddOptionalPath(name string, path OptionalPath) { 216 if path.Valid() { 217 a.AddPath(name, path.Path()) 218 } 219} 220 221// SetPaths sets a Make variable with the given name to a slice of the given path strings. 222func (a *AndroidMkEntries) SetPaths(name string, paths Paths) { 223 if _, ok := a.EntryMap[name]; !ok { 224 a.entryOrder = append(a.entryOrder, name) 225 } 226 a.EntryMap[name] = paths.Strings() 227} 228 229// SetOptionalPaths sets a Make variable with the given name to a slice of the given path strings 230// only if there are a non-zero amount of paths. 231func (a *AndroidMkEntries) SetOptionalPaths(name string, paths Paths) { 232 if len(paths) > 0 { 233 a.SetPaths(name, paths) 234 } 235} 236 237// AddPaths appends the given path strings to a Make variable with the given name. 238func (a *AndroidMkEntries) AddPaths(name string, paths Paths) { 239 if _, ok := a.EntryMap[name]; !ok { 240 a.entryOrder = append(a.entryOrder, name) 241 } 242 a.EntryMap[name] = append(a.EntryMap[name], paths.Strings()...) 243} 244 245// SetBoolIfTrue sets a Make variable with the given name to true if the given flag is true. 246// It is a no-op if the given flag is false. 247func (a *AndroidMkEntries) SetBoolIfTrue(name string, flag bool) { 248 if flag { 249 if _, ok := a.EntryMap[name]; !ok { 250 a.entryOrder = append(a.entryOrder, name) 251 } 252 a.EntryMap[name] = []string{"true"} 253 } 254} 255 256// SetBool sets a Make variable with the given name to if the given bool flag value. 257func (a *AndroidMkEntries) SetBool(name string, flag bool) { 258 if _, ok := a.EntryMap[name]; !ok { 259 a.entryOrder = append(a.entryOrder, name) 260 } 261 if flag { 262 a.EntryMap[name] = []string{"true"} 263 } else { 264 a.EntryMap[name] = []string{"false"} 265 } 266} 267 268// AddStrings appends the given strings to a Make variable with the given name. 269func (a *AndroidMkEntries) AddStrings(name string, value ...string) { 270 if len(value) == 0 { 271 return 272 } 273 if _, ok := a.EntryMap[name]; !ok { 274 a.entryOrder = append(a.entryOrder, name) 275 } 276 a.EntryMap[name] = append(a.EntryMap[name], value...) 277} 278 279// AddCompatibilityTestSuites adds the supplied test suites to the EntryMap, with special handling 280// for partial MTS and MCTS test suites. 281func (a *AndroidMkEntries) AddCompatibilityTestSuites(suites ...string) { 282 // M(C)TS supports a full test suite and partial per-module MTS test suites, with naming mts-${MODULE}. 283 // To reduce repetition, if we find a partial M(C)TS test suite without an full M(C)TS test suite, 284 // we add the full test suite to our list. 285 if PrefixInList(suites, "mts-") && !InList("mts", suites) { 286 suites = append(suites, "mts") 287 } 288 if PrefixInList(suites, "mcts-") && !InList("mcts", suites) { 289 suites = append(suites, "mcts") 290 } 291 a.AddStrings("LOCAL_COMPATIBILITY_SUITE", suites...) 292} 293 294// The contributions to the dist. 295type distContributions struct { 296 // Path to license metadata file. 297 licenseMetadataFile Path 298 // List of goals and the dist copy instructions. 299 copiesForGoals []*copiesForGoals 300} 301 302// getCopiesForGoals returns a copiesForGoals into which copy instructions that 303// must be processed when building one or more of those goals can be added. 304func (d *distContributions) getCopiesForGoals(goals string) *copiesForGoals { 305 copiesForGoals := &copiesForGoals{goals: goals} 306 d.copiesForGoals = append(d.copiesForGoals, copiesForGoals) 307 return copiesForGoals 308} 309 310// Associates a list of dist copy instructions with a set of goals for which they 311// should be run. 312type copiesForGoals struct { 313 // goals are a space separated list of build targets that will trigger the 314 // copy instructions. 315 goals string 316 317 // A list of instructions to copy a module's output files to somewhere in the 318 // dist directory. 319 copies []distCopy 320} 321 322// Adds a copy instruction. 323func (d *copiesForGoals) addCopyInstruction(from Path, dest string) { 324 d.copies = append(d.copies, distCopy{from, dest}) 325} 326 327// Instruction on a path that must be copied into the dist. 328type distCopy struct { 329 // The path to copy from. 330 from Path 331 332 // The destination within the dist directory to copy to. 333 dest string 334} 335 336// Compute the contributions that the module makes to the dist. 337func (a *AndroidMkEntries) getDistContributions(mod blueprint.Module) *distContributions { 338 amod := mod.(Module).base() 339 name := amod.BaseModuleName() 340 341 // Collate the set of associated tag/paths available for copying to the dist. 342 // Start with an empty (nil) set. 343 var availableTaggedDists TaggedDistFiles 344 345 // Then merge in any that are provided explicitly by the module. 346 if a.DistFiles != nil { 347 // Merge the DistFiles into the set. 348 availableTaggedDists = availableTaggedDists.merge(a.DistFiles) 349 } 350 351 // If no paths have been provided for the DefaultDistTag and the output file is 352 // valid then add that as the default dist path. 353 if _, ok := availableTaggedDists[DefaultDistTag]; !ok && a.OutputFile.Valid() { 354 availableTaggedDists = availableTaggedDists.addPathsForTag(DefaultDistTag, a.OutputFile.Path()) 355 } 356 357 info := OtherModuleProviderOrDefault(a.entryContext, mod, InstallFilesProvider) 358 // If the distFiles created by GenerateTaggedDistFiles contains paths for the 359 // DefaultDistTag then that takes priority so delete any existing paths. 360 if _, ok := info.DistFiles[DefaultDistTag]; ok { 361 delete(availableTaggedDists, DefaultDistTag) 362 } 363 364 // Finally, merge the distFiles created by GenerateTaggedDistFiles. 365 availableTaggedDists = availableTaggedDists.merge(info.DistFiles) 366 367 if len(availableTaggedDists) == 0 { 368 // Nothing dist-able for this module. 369 return nil 370 } 371 372 // Collate the contributions this module makes to the dist. 373 distContributions := &distContributions{} 374 375 if !exemptFromRequiredApplicableLicensesProperty(mod.(Module)) { 376 distContributions.licenseMetadataFile = info.LicenseMetadataFile 377 } 378 379 // Iterate over this module's dist structs, merged from the dist and dists properties. 380 for _, dist := range amod.Dists() { 381 // Get the list of goals this dist should be enabled for. e.g. sdk, droidcore 382 goals := strings.Join(dist.Targets, " ") 383 384 // Get the tag representing the output files to be dist'd. e.g. ".jar", ".proguard_map" 385 var tag string 386 if dist.Tag == nil { 387 // If the dist struct does not specify a tag, use the default output files tag. 388 tag = DefaultDistTag 389 } else { 390 tag = *dist.Tag 391 } 392 393 // Get the paths of the output files to be dist'd, represented by the tag. 394 // Can be an empty list. 395 tagPaths := availableTaggedDists[tag] 396 if len(tagPaths) == 0 { 397 // Nothing to dist for this tag, continue to the next dist. 398 continue 399 } 400 401 if len(tagPaths) > 1 && (dist.Dest != nil || dist.Suffix != nil) { 402 errorMessage := "%s: Cannot apply dest/suffix for more than one dist " + 403 "file for %q goals tag %q in module %s. The list of dist files, " + 404 "which should have a single element, is:\n%s" 405 panic(fmt.Errorf(errorMessage, mod, goals, tag, name, tagPaths)) 406 } 407 408 copiesForGoals := distContributions.getCopiesForGoals(goals) 409 410 // Iterate over each path adding a copy instruction to copiesForGoals 411 for _, path := range tagPaths { 412 // It's possible that the Path is nil from errant modules. Be defensive here. 413 if path == nil { 414 tagName := "default" // for error message readability 415 if dist.Tag != nil { 416 tagName = *dist.Tag 417 } 418 panic(fmt.Errorf("Dist file should not be nil for the %s tag in %s", tagName, name)) 419 } 420 421 dest := filepath.Base(path.String()) 422 423 if dist.Dest != nil { 424 var err error 425 if dest, err = validateSafePath(*dist.Dest); err != nil { 426 // This was checked in ModuleBase.GenerateBuildActions 427 panic(err) 428 } 429 } 430 431 ext := filepath.Ext(dest) 432 suffix := "" 433 if dist.Suffix != nil { 434 suffix = *dist.Suffix 435 } 436 437 productString := "" 438 if dist.Append_artifact_with_product != nil && *dist.Append_artifact_with_product { 439 productString = fmt.Sprintf("_%s", a.entryContext.Config().DeviceProduct()) 440 } 441 442 if suffix != "" || productString != "" { 443 dest = strings.TrimSuffix(dest, ext) + suffix + productString + ext 444 } 445 446 if dist.Dir != nil { 447 var err error 448 if dest, err = validateSafePath(*dist.Dir, dest); err != nil { 449 // This was checked in ModuleBase.GenerateBuildActions 450 panic(err) 451 } 452 } 453 454 copiesForGoals.addCopyInstruction(path, dest) 455 } 456 } 457 458 return distContributions 459} 460 461// generateDistContributionsForMake generates make rules that will generate the 462// dist according to the instructions in the supplied distContribution. 463func generateDistContributionsForMake(distContributions *distContributions) []string { 464 var ret []string 465 for _, d := range distContributions.copiesForGoals { 466 ret = append(ret, fmt.Sprintf(".PHONY: %s", d.goals)) 467 // Create dist-for-goals calls for each of the copy instructions. 468 for _, c := range d.copies { 469 if distContributions.licenseMetadataFile != nil { 470 ret = append( 471 ret, 472 fmt.Sprintf("$(if $(strip $(ALL_TARGETS.%s.META_LIC)),,$(eval ALL_TARGETS.%s.META_LIC := %s))", 473 c.from.String(), c.from.String(), distContributions.licenseMetadataFile.String())) 474 } 475 ret = append( 476 ret, 477 fmt.Sprintf("$(call dist-for-goals,%s,%s:%s)", d.goals, c.from.String(), c.dest)) 478 } 479 } 480 481 return ret 482} 483 484// Compute the list of Make strings to declare phony goals and dist-for-goals 485// calls from the module's dist and dists properties. 486func (a *AndroidMkEntries) GetDistForGoals(mod blueprint.Module) []string { 487 distContributions := a.getDistContributions(mod) 488 if distContributions == nil { 489 return nil 490 } 491 492 return generateDistContributionsForMake(distContributions) 493} 494 495// fillInEntries goes through the common variable processing and calls the extra data funcs to 496// generate and fill in AndroidMkEntries's in-struct data, ready to be flushed to a file. 497type fillInEntriesContext interface { 498 ModuleDir(module blueprint.Module) string 499 ModuleSubDir(module blueprint.Module) string 500 Config() Config 501 otherModuleProvider(module blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) 502 ModuleType(module blueprint.Module) string 503 OtherModulePropertyErrorf(module Module, property string, fmt string, args ...interface{}) 504 HasMutatorFinished(mutatorName string) bool 505} 506 507func (a *AndroidMkEntries) fillInEntries(ctx fillInEntriesContext, mod blueprint.Module) { 508 a.entryContext = ctx 509 a.EntryMap = make(map[string][]string) 510 amod := mod.(Module) 511 base := amod.base() 512 name := base.BaseModuleName() 513 if a.OverrideName != "" { 514 name = a.OverrideName 515 } 516 517 if a.Include == "" { 518 a.Include = "$(BUILD_PREBUILT)" 519 } 520 a.Required = append(a.Required, amod.RequiredModuleNames(ctx)...) 521 a.Required = append(a.Required, amod.VintfFragmentModuleNames(ctx)...) 522 a.Host_required = append(a.Host_required, amod.HostRequiredModuleNames()...) 523 a.Target_required = append(a.Target_required, amod.TargetRequiredModuleNames()...) 524 525 for _, distString := range a.GetDistForGoals(mod) { 526 fmt.Fprintln(&a.header, distString) 527 } 528 529 fmt.Fprintf(&a.header, "\ninclude $(CLEAR_VARS) # type: %s, name: %s, variant: %s\n", ctx.ModuleType(mod), base.BaseModuleName(), ctx.ModuleSubDir(mod)) 530 531 // Collect make variable assignment entries. 532 a.SetString("LOCAL_PATH", ctx.ModuleDir(mod)) 533 a.SetString("LOCAL_MODULE", name+a.SubName) 534 a.SetString("LOCAL_MODULE_CLASS", a.Class) 535 a.SetString("LOCAL_PREBUILT_MODULE_FILE", a.OutputFile.String()) 536 a.AddStrings("LOCAL_REQUIRED_MODULES", a.Required...) 537 a.AddStrings("LOCAL_HOST_REQUIRED_MODULES", a.Host_required...) 538 a.AddStrings("LOCAL_TARGET_REQUIRED_MODULES", a.Target_required...) 539 a.AddStrings("LOCAL_SOONG_MODULE_TYPE", ctx.ModuleType(amod)) 540 541 // If the install rule was generated by Soong tell Make about it. 542 info := OtherModuleProviderOrDefault(ctx, mod, InstallFilesProvider) 543 if len(info.KatiInstalls) > 0 { 544 // Assume the primary install file is last since it probably needs to depend on any other 545 // installed files. If that is not the case we can add a method to specify the primary 546 // installed file. 547 a.SetPath("LOCAL_SOONG_INSTALLED_MODULE", info.KatiInstalls[len(info.KatiInstalls)-1].to) 548 a.SetString("LOCAL_SOONG_INSTALL_PAIRS", info.KatiInstalls.BuiltInstalled()) 549 a.SetPaths("LOCAL_SOONG_INSTALL_SYMLINKS", info.KatiSymlinks.InstallPaths().Paths()) 550 } else { 551 // Soong may not have generated the install rule also when `no_full_install: true`. 552 // Mark this module as uninstallable in order to prevent Make from creating an 553 // install rule there. 554 a.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", proptools.Bool(base.commonProperties.No_full_install)) 555 } 556 557 if info.UncheckedModule { 558 a.SetBool("LOCAL_DONT_CHECK_MODULE", true) 559 } else if info.CheckbuildTarget != nil { 560 a.SetPath("LOCAL_CHECKED_MODULE", info.CheckbuildTarget) 561 } else { 562 a.SetOptionalPath("LOCAL_CHECKED_MODULE", a.OutputFile) 563 } 564 565 if len(info.TestData) > 0 { 566 a.AddStrings("LOCAL_TEST_DATA", androidMkDataPaths(info.TestData)...) 567 } 568 569 if am, ok := mod.(ApexModule); ok { 570 a.SetBoolIfTrue("LOCAL_NOT_AVAILABLE_FOR_PLATFORM", am.NotAvailableForPlatform()) 571 } 572 573 archStr := base.Arch().ArchType.String() 574 host := false 575 switch base.Os().Class { 576 case Host: 577 if base.Target().HostCross { 578 // Make cannot identify LOCAL_MODULE_HOST_CROSS_ARCH:= common. 579 if base.Arch().ArchType != Common { 580 a.SetString("LOCAL_MODULE_HOST_CROSS_ARCH", archStr) 581 } 582 } else { 583 // Make cannot identify LOCAL_MODULE_HOST_ARCH:= common. 584 if base.Arch().ArchType != Common { 585 a.SetString("LOCAL_MODULE_HOST_ARCH", archStr) 586 } 587 } 588 host = true 589 case Device: 590 // Make cannot identify LOCAL_MODULE_TARGET_ARCH:= common. 591 if base.Arch().ArchType != Common { 592 if base.Target().NativeBridge { 593 hostArchStr := base.Target().NativeBridgeHostArchName 594 if hostArchStr != "" { 595 a.SetString("LOCAL_MODULE_TARGET_ARCH", hostArchStr) 596 } 597 } else { 598 a.SetString("LOCAL_MODULE_TARGET_ARCH", archStr) 599 } 600 } 601 602 if !base.InVendorRamdisk() { 603 a.AddPaths("LOCAL_FULL_INIT_RC", info.InitRcPaths) 604 } 605 if len(info.VintfFragmentsPaths) > 0 { 606 a.AddPaths("LOCAL_FULL_VINTF_FRAGMENTS", info.VintfFragmentsPaths) 607 } 608 a.SetBoolIfTrue("LOCAL_PROPRIETARY_MODULE", Bool(base.commonProperties.Proprietary)) 609 if Bool(base.commonProperties.Vendor) || Bool(base.commonProperties.Soc_specific) { 610 a.SetString("LOCAL_VENDOR_MODULE", "true") 611 } 612 a.SetBoolIfTrue("LOCAL_ODM_MODULE", Bool(base.commonProperties.Device_specific)) 613 a.SetBoolIfTrue("LOCAL_PRODUCT_MODULE", Bool(base.commonProperties.Product_specific)) 614 a.SetBoolIfTrue("LOCAL_SYSTEM_EXT_MODULE", Bool(base.commonProperties.System_ext_specific)) 615 if base.commonProperties.Owner != nil { 616 a.SetString("LOCAL_MODULE_OWNER", *base.commonProperties.Owner) 617 } 618 } 619 620 if host { 621 makeOs := base.Os().String() 622 if base.Os() == Linux || base.Os() == LinuxBionic || base.Os() == LinuxMusl { 623 makeOs = "linux" 624 } 625 a.SetString("LOCAL_MODULE_HOST_OS", makeOs) 626 a.SetString("LOCAL_IS_HOST_MODULE", "true") 627 } 628 629 prefix := "" 630 if base.ArchSpecific() { 631 switch base.Os().Class { 632 case Host: 633 if base.Target().HostCross { 634 prefix = "HOST_CROSS_" 635 } else { 636 prefix = "HOST_" 637 } 638 case Device: 639 prefix = "TARGET_" 640 641 } 642 643 if base.Arch().ArchType != ctx.Config().Targets[base.Os()][0].Arch.ArchType { 644 prefix = "2ND_" + prefix 645 } 646 } 647 648 if licenseMetadata, ok := OtherModuleProvider(ctx, mod, LicenseMetadataProvider); ok { 649 a.SetPath("LOCAL_SOONG_LICENSE_METADATA", licenseMetadata.LicenseMetadataPath) 650 } 651 652 if _, ok := OtherModuleProvider(ctx, mod, ModuleInfoJSONProvider); ok { 653 a.SetBool("LOCAL_SOONG_MODULE_INFO_JSON", true) 654 } 655 656 extraCtx := &androidMkExtraEntriesContext{ 657 ctx: ctx, 658 mod: mod, 659 } 660 661 for _, extra := range a.ExtraEntries { 662 extra(extraCtx, a) 663 } 664 665 // Write to footer. 666 fmt.Fprintln(&a.footer, "include "+a.Include) 667 blueprintDir := ctx.ModuleDir(mod) 668 for _, footerFunc := range a.ExtraFooters { 669 footerFunc(&a.footer, name, prefix, blueprintDir) 670 } 671} 672 673func (a *AndroidMkEntries) disabled() bool { 674 return a.Disabled || !a.OutputFile.Valid() 675} 676 677// write flushes the AndroidMkEntries's in-struct data populated by AndroidMkEntries into the 678// given Writer object. 679func (a *AndroidMkEntries) write(w io.Writer) { 680 if a.disabled() { 681 return 682 } 683 684 w.Write(a.header.Bytes()) 685 for _, name := range a.entryOrder { 686 AndroidMkEmitAssignList(w, name, a.EntryMap[name]) 687 } 688 w.Write(a.footer.Bytes()) 689} 690 691func (a *AndroidMkEntries) FooterLinesForTests() []string { 692 return strings.Split(string(a.footer.Bytes()), "\n") 693} 694 695// AndroidMkSingleton is a singleton to collect Android.mk data from all modules and dump them into 696// the final Android-<product_name>.mk file output. 697func AndroidMkSingleton() Singleton { 698 return &androidMkSingleton{} 699} 700 701type androidMkSingleton struct{} 702 703func (c *androidMkSingleton) GenerateBuildActions(ctx SingletonContext) { 704 // Skip if Soong wasn't invoked from Make. 705 if !ctx.Config().KatiEnabled() { 706 return 707 } 708 709 var androidMkModulesList []blueprint.Module 710 711 ctx.VisitAllModulesBlueprint(func(module blueprint.Module) { 712 androidMkModulesList = append(androidMkModulesList, module) 713 }) 714 715 // Sort the module list by the module names to eliminate random churns, which may erroneously 716 // invoke additional build processes. 717 sort.SliceStable(androidMkModulesList, func(i, j int) bool { 718 return ctx.ModuleName(androidMkModulesList[i]) < ctx.ModuleName(androidMkModulesList[j]) 719 }) 720 721 transMk := PathForOutput(ctx, "Android"+String(ctx.Config().productVariables.Make_suffix)+".mk") 722 if ctx.Failed() { 723 return 724 } 725 726 moduleInfoJSON := PathForOutput(ctx, "module-info"+String(ctx.Config().productVariables.Make_suffix)+".json") 727 728 err := translateAndroidMk(ctx, absolutePath(transMk.String()), moduleInfoJSON, androidMkModulesList) 729 if err != nil { 730 ctx.Errorf(err.Error()) 731 } 732 733 ctx.Build(pctx, BuildParams{ 734 Rule: blueprint.Phony, 735 Output: transMk, 736 }) 737} 738 739func translateAndroidMk(ctx SingletonContext, absMkFile string, moduleInfoJSONPath WritablePath, mods []blueprint.Module) error { 740 buf := &bytes.Buffer{} 741 742 var moduleInfoJSONs []*ModuleInfoJSON 743 744 fmt.Fprintln(buf, "LOCAL_MODULE_MAKEFILE := $(lastword $(MAKEFILE_LIST))") 745 746 typeStats := make(map[string]int) 747 for _, mod := range mods { 748 err := translateAndroidMkModule(ctx, buf, &moduleInfoJSONs, mod) 749 if err != nil { 750 os.Remove(absMkFile) 751 return err 752 } 753 754 if amod, ok := mod.(Module); ok && ctx.PrimaryModule(amod) == amod { 755 typeStats[ctx.ModuleType(amod)] += 1 756 } 757 } 758 759 keys := []string{} 760 fmt.Fprintln(buf, "\nSTATS.SOONG_MODULE_TYPE :=") 761 for k := range typeStats { 762 keys = append(keys, k) 763 } 764 sort.Strings(keys) 765 for _, mod_type := range keys { 766 fmt.Fprintln(buf, "STATS.SOONG_MODULE_TYPE +=", mod_type) 767 fmt.Fprintf(buf, "STATS.SOONG_MODULE_TYPE.%s := %d\n", mod_type, typeStats[mod_type]) 768 } 769 770 err := pathtools.WriteFileIfChanged(absMkFile, buf.Bytes(), 0666) 771 if err != nil { 772 return err 773 } 774 775 return writeModuleInfoJSON(ctx, moduleInfoJSONs, moduleInfoJSONPath) 776} 777 778func writeModuleInfoJSON(ctx SingletonContext, moduleInfoJSONs []*ModuleInfoJSON, moduleInfoJSONPath WritablePath) error { 779 moduleInfoJSONBuf := &strings.Builder{} 780 moduleInfoJSONBuf.WriteString("[") 781 for i, moduleInfoJSON := range moduleInfoJSONs { 782 if i != 0 { 783 moduleInfoJSONBuf.WriteString(",\n") 784 } 785 moduleInfoJSONBuf.WriteString("{") 786 moduleInfoJSONBuf.WriteString(strconv.Quote(moduleInfoJSON.core.RegisterName)) 787 moduleInfoJSONBuf.WriteString(":") 788 err := encodeModuleInfoJSON(moduleInfoJSONBuf, moduleInfoJSON) 789 moduleInfoJSONBuf.WriteString("}") 790 if err != nil { 791 return err 792 } 793 } 794 moduleInfoJSONBuf.WriteString("]") 795 WriteFileRule(ctx, moduleInfoJSONPath, moduleInfoJSONBuf.String()) 796 return nil 797} 798 799func translateAndroidMkModule(ctx SingletonContext, w io.Writer, moduleInfoJSONs *[]*ModuleInfoJSON, mod blueprint.Module) error { 800 defer func() { 801 if r := recover(); r != nil { 802 panic(fmt.Errorf("%s in translateAndroidMkModule for module %s variant %s", 803 r, ctx.ModuleName(mod), ctx.ModuleSubDir(mod))) 804 } 805 }() 806 807 // Additional cases here require review for correct license propagation to make. 808 var err error 809 810 if info, ok := OtherModuleProvider(ctx, mod, AndroidMkInfoProvider); ok { 811 err = translateAndroidMkEntriesInfoModule(ctx, w, moduleInfoJSONs, mod, info) 812 } else { 813 switch x := mod.(type) { 814 case AndroidMkDataProvider: 815 err = translateAndroidModule(ctx, w, moduleInfoJSONs, mod, x) 816 case AndroidMkEntriesProvider: 817 err = translateAndroidMkEntriesModule(ctx, w, moduleInfoJSONs, mod, x) 818 default: 819 // Not exported to make so no make variables to set. 820 } 821 } 822 823 if err != nil { 824 return err 825 } 826 827 return err 828} 829 830func (data *AndroidMkData) fillInData(ctx fillInEntriesContext, mod blueprint.Module) { 831 // Get the preamble content through AndroidMkEntries logic. 832 data.Entries = AndroidMkEntries{ 833 Class: data.Class, 834 SubName: data.SubName, 835 DistFiles: data.DistFiles, 836 OutputFile: data.OutputFile, 837 Disabled: data.Disabled, 838 Include: data.Include, 839 Required: data.Required, 840 Host_required: data.Host_required, 841 Target_required: data.Target_required, 842 } 843 data.Entries.fillInEntries(ctx, mod) 844 845 // copy entries back to data since it is used in Custom 846 data.Required = data.Entries.Required 847 data.Host_required = data.Entries.Host_required 848 data.Target_required = data.Entries.Target_required 849} 850 851// A support func for the deprecated AndroidMkDataProvider interface. Use AndroidMkEntryProvider 852// instead. 853func translateAndroidModule(ctx SingletonContext, w io.Writer, moduleInfoJSONs *[]*ModuleInfoJSON, 854 mod blueprint.Module, provider AndroidMkDataProvider) error { 855 856 amod := mod.(Module).base() 857 if shouldSkipAndroidMkProcessing(ctx, amod) { 858 return nil 859 } 860 861 data := provider.AndroidMk() 862 863 if data.Include == "" { 864 data.Include = "$(BUILD_PREBUILT)" 865 } 866 867 data.fillInData(ctx, mod) 868 aconfigUpdateAndroidMkData(ctx, mod.(Module), &data) 869 870 prefix := "" 871 if amod.ArchSpecific() { 872 switch amod.Os().Class { 873 case Host: 874 if amod.Target().HostCross { 875 prefix = "HOST_CROSS_" 876 } else { 877 prefix = "HOST_" 878 } 879 case Device: 880 prefix = "TARGET_" 881 882 } 883 884 if amod.Arch().ArchType != ctx.Config().Targets[amod.Os()][0].Arch.ArchType { 885 prefix = "2ND_" + prefix 886 } 887 } 888 889 name := provider.BaseModuleName() 890 blueprintDir := filepath.Dir(ctx.BlueprintFile(mod)) 891 892 if data.Custom != nil { 893 // List of module types allowed to use .Custom(...) 894 // Additions to the list require careful review for proper license handling. 895 switch reflect.TypeOf(mod).String() { // ctx.ModuleType(mod) doesn't work: aidl_interface creates phony without type 896 case "*aidl.aidlApi": // writes non-custom before adding .phony 897 case "*aidl.aidlMapping": // writes non-custom before adding .phony 898 case "*android.customModule": // appears in tests only 899 case "*android_sdk.sdkRepoHost": // doesn't go through base_rules 900 case "*apex.apexBundle": // license properties written 901 case "*bpf.bpf": // license properties written (both for module and objs) 902 case "*libbpf_prog.libbpfProg": // license properties written (both for module and objs) 903 case "*genrule.Module": // writes non-custom before adding .phony 904 case "*java.SystemModules": // doesn't go through base_rules 905 case "*java.systemModulesImport": // doesn't go through base_rules 906 case "*phony.phony": // license properties written 907 case "*phony.PhonyRule": // writes phony deps and acts like `.PHONY` 908 case "*selinux.selinuxContextsModule": // license properties written 909 case "*sysprop.syspropLibrary": // license properties written 910 case "*vintf.vintfCompatibilityMatrixRule": // use case like phony 911 default: 912 if !ctx.Config().IsEnvFalse("ANDROID_REQUIRE_LICENSES") { 913 return fmt.Errorf("custom make rules not allowed for %q (%q) module %q", ctx.ModuleType(mod), reflect.TypeOf(mod), ctx.ModuleName(mod)) 914 } 915 } 916 data.Custom(w, name, prefix, blueprintDir, data) 917 } else { 918 WriteAndroidMkData(w, data) 919 } 920 921 if !data.Entries.disabled() { 922 if moduleInfoJSON, ok := OtherModuleProvider(ctx, mod, ModuleInfoJSONProvider); ok { 923 *moduleInfoJSONs = append(*moduleInfoJSONs, moduleInfoJSON) 924 } 925 } 926 927 return nil 928} 929 930// A support func for the deprecated AndroidMkDataProvider interface. Use AndroidMkEntryProvider 931// instead. 932func WriteAndroidMkData(w io.Writer, data AndroidMkData) { 933 if data.Entries.disabled() { 934 return 935 } 936 937 // write preamble via Entries 938 data.Entries.footer = bytes.Buffer{} 939 data.Entries.write(w) 940 941 for _, extra := range data.Extra { 942 extra(w, data.OutputFile.Path()) 943 } 944 945 fmt.Fprintln(w, "include "+data.Include) 946} 947 948func translateAndroidMkEntriesModule(ctx SingletonContext, w io.Writer, moduleInfoJSONs *[]*ModuleInfoJSON, 949 mod blueprint.Module, provider AndroidMkEntriesProvider) error { 950 if shouldSkipAndroidMkProcessing(ctx, mod.(Module).base()) { 951 return nil 952 } 953 954 entriesList := provider.AndroidMkEntries() 955 aconfigUpdateAndroidMkEntries(ctx, mod.(Module), &entriesList) 956 957 // Any new or special cases here need review to verify correct propagation of license information. 958 for _, entries := range entriesList { 959 entries.fillInEntries(ctx, mod) 960 entries.write(w) 961 } 962 963 if len(entriesList) > 0 && !entriesList[0].disabled() { 964 if moduleInfoJSON, ok := OtherModuleProvider(ctx, mod, ModuleInfoJSONProvider); ok { 965 *moduleInfoJSONs = append(*moduleInfoJSONs, moduleInfoJSON) 966 } 967 } 968 969 return nil 970} 971 972func ShouldSkipAndroidMkProcessing(ctx ConfigurableEvaluatorContext, module Module) bool { 973 return shouldSkipAndroidMkProcessing(ctx, module.base()) 974} 975 976func shouldSkipAndroidMkProcessing(ctx ConfigurableEvaluatorContext, module *ModuleBase) bool { 977 if !module.commonProperties.NamespaceExportedToMake { 978 // TODO(jeffrygaston) do we want to validate that there are no modules being 979 // exported to Kati that depend on this module? 980 return true 981 } 982 983 // On Mac, only expose host darwin modules to Make, as that's all we claim to support. 984 // In reality, some of them depend on device-built (Java) modules, so we can't disable all 985 // device modules in Soong, but we can hide them from Make (and thus the build user interface) 986 if runtime.GOOS == "darwin" && module.Os() != Darwin { 987 return true 988 } 989 990 // Only expose the primary Darwin target, as Make does not understand Darwin+Arm64 991 if module.Os() == Darwin && module.Target().HostCross { 992 return true 993 } 994 995 return !module.Enabled(ctx) || 996 module.commonProperties.HideFromMake || 997 // Make does not understand LinuxBionic 998 module.Os() == LinuxBionic || 999 // Make does not understand LinuxMusl, except when we are building with USE_HOST_MUSL=true 1000 // and all host binaries are LinuxMusl 1001 (module.Os() == LinuxMusl && module.Target().HostCross) 1002} 1003 1004// A utility func to format LOCAL_TEST_DATA outputs. See the comments on DataPath to understand how 1005// to use this func. 1006func androidMkDataPaths(data []DataPath) []string { 1007 var testFiles []string 1008 for _, d := range data { 1009 rel := d.SrcPath.Rel() 1010 if d.WithoutRel { 1011 rel = d.SrcPath.Base() 1012 } 1013 path := d.SrcPath.String() 1014 // LOCAL_TEST_DATA requires the rel portion of the path to be removed from the path. 1015 if !strings.HasSuffix(path, rel) { 1016 panic(fmt.Errorf("path %q does not end with %q", path, rel)) 1017 } 1018 path = strings.TrimSuffix(path, rel) 1019 testFileString := path + ":" + rel 1020 if len(d.RelativeInstallPath) > 0 { 1021 testFileString += ":" + d.RelativeInstallPath 1022 } 1023 testFiles = append(testFiles, testFileString) 1024 } 1025 return testFiles 1026} 1027 1028// AndroidMkEmitAssignList emits the line 1029// 1030// VAR := ITEM ... 1031// 1032// Items are the elements to the given set of lists 1033// If all the passed lists are empty, no line will be emitted 1034func AndroidMkEmitAssignList(w io.Writer, varName string, lists ...[]string) { 1035 doPrint := false 1036 for _, l := range lists { 1037 if doPrint = len(l) > 0; doPrint { 1038 break 1039 } 1040 } 1041 if !doPrint { 1042 return 1043 } 1044 fmt.Fprint(w, varName, " :=") 1045 for _, l := range lists { 1046 for _, item := range l { 1047 fmt.Fprint(w, " ", item) 1048 } 1049 } 1050 fmt.Fprintln(w) 1051} 1052 1053type AndroidMkProviderInfo struct { 1054 PrimaryInfo AndroidMkInfo 1055 ExtraInfo []AndroidMkInfo 1056} 1057 1058type AndroidMkInfo struct { 1059 // Android.mk class string, e.g. EXECUTABLES, JAVA_LIBRARIES, ETC 1060 Class string 1061 // Optional suffix to append to the module name. Useful when a module wants to return multiple 1062 // AndroidMkEntries objects. For example, when a java_library returns an additional entry for 1063 // its hostdex sub-module, this SubName field is set to "-hostdex" so that it can have a 1064 // different name than the parent's. 1065 SubName string 1066 // If set, this value overrides the base module name. SubName is still appended. 1067 OverrideName string 1068 // Dist files to output 1069 DistFiles TaggedDistFiles 1070 // The output file for Kati to process and/or install. If absent, the module is skipped. 1071 OutputFile OptionalPath 1072 // If true, the module is skipped and does not appear on the final Android-<product name>.mk 1073 // file. Useful when a module needs to be skipped conditionally. 1074 Disabled bool 1075 // The postprocessing mk file to include, e.g. $(BUILD_SYSTEM)/soong_cc_rust_prebuilt.mk 1076 // If not set, $(BUILD_SYSTEM)/prebuilt.mk is used. 1077 Include string 1078 // Required modules that need to be built and included in the final build output when building 1079 // this module. 1080 Required []string 1081 // Required host modules that need to be built and included in the final build output when 1082 // building this module. 1083 Host_required []string 1084 // Required device modules that need to be built and included in the final build output when 1085 // building this module. 1086 Target_required []string 1087 1088 HeaderStrings []string 1089 FooterStrings []string 1090 1091 // A map that holds the up-to-date Make variable values. Can be accessed from tests. 1092 EntryMap map[string][]string 1093 // A list of EntryMap keys in insertion order. This serves a few purposes: 1094 // 1. Prevents churns. Golang map doesn't provide consistent iteration order, so without this, 1095 // the outputted Android-*.mk file may change even though there have been no content changes. 1096 // 2. Allows modules to refer to other variables, like LOCAL_BAR_VAR := $(LOCAL_FOO_VAR), 1097 // without worrying about the variables being mixed up in the actual mk file. 1098 // 3. Makes troubleshooting and spotting errors easier. 1099 EntryOrder []string 1100} 1101 1102type AndroidMkProviderInfoProducer interface { 1103 PrepareAndroidMKProviderInfo(config Config) *AndroidMkProviderInfo 1104} 1105 1106// TODO: rename it to AndroidMkEntriesProvider after AndroidMkEntriesProvider interface is gone. 1107var AndroidMkInfoProvider = blueprint.NewProvider[*AndroidMkProviderInfo]() 1108 1109func translateAndroidMkEntriesInfoModule(ctx SingletonContext, w io.Writer, moduleInfoJSONs *[]*ModuleInfoJSON, 1110 mod blueprint.Module, providerInfo *AndroidMkProviderInfo) error { 1111 if shouldSkipAndroidMkProcessing(ctx, mod.(Module).base()) { 1112 return nil 1113 } 1114 1115 // Deep copy the provider info since we need to modify the info later 1116 info := deepCopyAndroidMkProviderInfo(providerInfo) 1117 1118 aconfigUpdateAndroidMkInfos(ctx, mod.(Module), &info) 1119 1120 // Any new or special cases here need review to verify correct propagation of license information. 1121 info.PrimaryInfo.fillInEntries(ctx, mod) 1122 info.PrimaryInfo.write(w) 1123 if len(info.ExtraInfo) > 0 { 1124 for _, ei := range info.ExtraInfo { 1125 ei.fillInEntries(ctx, mod) 1126 ei.write(w) 1127 } 1128 } 1129 1130 if !info.PrimaryInfo.disabled() { 1131 if moduleInfoJSON, ok := OtherModuleProvider(ctx, mod, ModuleInfoJSONProvider); ok { 1132 *moduleInfoJSONs = append(*moduleInfoJSONs, moduleInfoJSON) 1133 } 1134 } 1135 1136 return nil 1137} 1138 1139// Utility funcs to manipulate Android.mk variable entries. 1140 1141// SetString sets a Make variable with the given name to the given value. 1142func (a *AndroidMkInfo) SetString(name, value string) { 1143 if _, ok := a.EntryMap[name]; !ok { 1144 a.EntryOrder = append(a.EntryOrder, name) 1145 } 1146 a.EntryMap[name] = []string{value} 1147} 1148 1149// SetPath sets a Make variable with the given name to the given path string. 1150func (a *AndroidMkInfo) SetPath(name string, path Path) { 1151 if _, ok := a.EntryMap[name]; !ok { 1152 a.EntryOrder = append(a.EntryOrder, name) 1153 } 1154 a.EntryMap[name] = []string{path.String()} 1155} 1156 1157// SetOptionalPath sets a Make variable with the given name to the given path string if it is valid. 1158// It is a no-op if the given path is invalid. 1159func (a *AndroidMkInfo) SetOptionalPath(name string, path OptionalPath) { 1160 if path.Valid() { 1161 a.SetPath(name, path.Path()) 1162 } 1163} 1164 1165// AddPath appends the given path string to a Make variable with the given name. 1166func (a *AndroidMkInfo) AddPath(name string, path Path) { 1167 if _, ok := a.EntryMap[name]; !ok { 1168 a.EntryOrder = append(a.EntryOrder, name) 1169 } 1170 a.EntryMap[name] = append(a.EntryMap[name], path.String()) 1171} 1172 1173// AddOptionalPath appends the given path string to a Make variable with the given name if it is 1174// valid. It is a no-op if the given path is invalid. 1175func (a *AndroidMkInfo) AddOptionalPath(name string, path OptionalPath) { 1176 if path.Valid() { 1177 a.AddPath(name, path.Path()) 1178 } 1179} 1180 1181// SetPaths sets a Make variable with the given name to a slice of the given path strings. 1182func (a *AndroidMkInfo) SetPaths(name string, paths Paths) { 1183 if _, ok := a.EntryMap[name]; !ok { 1184 a.EntryOrder = append(a.EntryOrder, name) 1185 } 1186 a.EntryMap[name] = paths.Strings() 1187} 1188 1189// SetOptionalPaths sets a Make variable with the given name to a slice of the given path strings 1190// only if there are a non-zero amount of paths. 1191func (a *AndroidMkInfo) SetOptionalPaths(name string, paths Paths) { 1192 if len(paths) > 0 { 1193 a.SetPaths(name, paths) 1194 } 1195} 1196 1197// AddPaths appends the given path strings to a Make variable with the given name. 1198func (a *AndroidMkInfo) AddPaths(name string, paths Paths) { 1199 if _, ok := a.EntryMap[name]; !ok { 1200 a.EntryOrder = append(a.EntryOrder, name) 1201 } 1202 a.EntryMap[name] = append(a.EntryMap[name], paths.Strings()...) 1203} 1204 1205// SetBoolIfTrue sets a Make variable with the given name to true if the given flag is true. 1206// It is a no-op if the given flag is false. 1207func (a *AndroidMkInfo) SetBoolIfTrue(name string, flag bool) { 1208 if flag { 1209 if _, ok := a.EntryMap[name]; !ok { 1210 a.EntryOrder = append(a.EntryOrder, name) 1211 } 1212 a.EntryMap[name] = []string{"true"} 1213 } 1214} 1215 1216// SetBool sets a Make variable with the given name to if the given bool flag value. 1217func (a *AndroidMkInfo) SetBool(name string, flag bool) { 1218 if _, ok := a.EntryMap[name]; !ok { 1219 a.EntryOrder = append(a.EntryOrder, name) 1220 } 1221 if flag { 1222 a.EntryMap[name] = []string{"true"} 1223 } else { 1224 a.EntryMap[name] = []string{"false"} 1225 } 1226} 1227 1228// AddStrings appends the given strings to a Make variable with the given name. 1229func (a *AndroidMkInfo) AddStrings(name string, value ...string) { 1230 if len(value) == 0 { 1231 return 1232 } 1233 if _, ok := a.EntryMap[name]; !ok { 1234 a.EntryOrder = append(a.EntryOrder, name) 1235 } 1236 a.EntryMap[name] = append(a.EntryMap[name], value...) 1237} 1238 1239// AddCompatibilityTestSuites adds the supplied test suites to the EntryMap, with special handling 1240// for partial MTS and MCTS test suites. 1241func (a *AndroidMkInfo) AddCompatibilityTestSuites(suites ...string) { 1242 // M(C)TS supports a full test suite and partial per-module MTS test suites, with naming mts-${MODULE}. 1243 // To reduce repetition, if we find a partial M(C)TS test suite without an full M(C)TS test suite, 1244 // we add the full test suite to our list. 1245 if PrefixInList(suites, "mts-") && !InList("mts", suites) { 1246 suites = append(suites, "mts") 1247 } 1248 if PrefixInList(suites, "mcts-") && !InList("mcts", suites) { 1249 suites = append(suites, "mcts") 1250 } 1251 a.AddStrings("LOCAL_COMPATIBILITY_SUITE", suites...) 1252} 1253 1254func (a *AndroidMkInfo) fillInEntries(ctx fillInEntriesContext, mod blueprint.Module) { 1255 helperInfo := AndroidMkInfo{ 1256 EntryMap: make(map[string][]string), 1257 } 1258 1259 amod := mod.(Module) 1260 base := amod.base() 1261 name := base.BaseModuleName() 1262 if a.OverrideName != "" { 1263 name = a.OverrideName 1264 } 1265 1266 if a.Include == "" { 1267 a.Include = "$(BUILD_PREBUILT)" 1268 } 1269 a.Required = append(a.Required, amod.RequiredModuleNames(ctx)...) 1270 a.Required = append(a.Required, amod.VintfFragmentModuleNames(ctx)...) 1271 a.Host_required = append(a.Host_required, amod.HostRequiredModuleNames()...) 1272 a.Target_required = append(a.Target_required, amod.TargetRequiredModuleNames()...) 1273 1274 for _, distString := range a.GetDistForGoals(ctx, mod) { 1275 a.HeaderStrings = append(a.HeaderStrings, distString) 1276 } 1277 1278 a.HeaderStrings = append(a.HeaderStrings, fmt.Sprintf("\ninclude $(CLEAR_VARS) # type: %s, name: %s, variant: %s", ctx.ModuleType(mod), base.BaseModuleName(), ctx.ModuleSubDir(mod))) 1279 1280 // Collect make variable assignment entries. 1281 helperInfo.SetString("LOCAL_PATH", ctx.ModuleDir(mod)) 1282 helperInfo.SetString("LOCAL_MODULE", name+a.SubName) 1283 helperInfo.SetString("LOCAL_MODULE_CLASS", a.Class) 1284 helperInfo.SetString("LOCAL_PREBUILT_MODULE_FILE", a.OutputFile.String()) 1285 helperInfo.AddStrings("LOCAL_REQUIRED_MODULES", a.Required...) 1286 helperInfo.AddStrings("LOCAL_HOST_REQUIRED_MODULES", a.Host_required...) 1287 helperInfo.AddStrings("LOCAL_TARGET_REQUIRED_MODULES", a.Target_required...) 1288 helperInfo.AddStrings("LOCAL_SOONG_MODULE_TYPE", ctx.ModuleType(amod)) 1289 1290 // If the install rule was generated by Soong tell Make about it. 1291 info := OtherModuleProviderOrDefault(ctx, mod, InstallFilesProvider) 1292 if len(info.KatiInstalls) > 0 { 1293 // Assume the primary install file is last since it probably needs to depend on any other 1294 // installed files. If that is not the case we can add a method to specify the primary 1295 // installed file. 1296 helperInfo.SetPath("LOCAL_SOONG_INSTALLED_MODULE", info.KatiInstalls[len(info.KatiInstalls)-1].to) 1297 helperInfo.SetString("LOCAL_SOONG_INSTALL_PAIRS", info.KatiInstalls.BuiltInstalled()) 1298 helperInfo.SetPaths("LOCAL_SOONG_INSTALL_SYMLINKS", info.KatiSymlinks.InstallPaths().Paths()) 1299 } else { 1300 // Soong may not have generated the install rule also when `no_full_install: true`. 1301 // Mark this module as uninstallable in order to prevent Make from creating an 1302 // install rule there. 1303 helperInfo.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", proptools.Bool(base.commonProperties.No_full_install)) 1304 } 1305 1306 if info.UncheckedModule { 1307 helperInfo.SetBool("LOCAL_DONT_CHECK_MODULE", true) 1308 } else if info.CheckbuildTarget != nil { 1309 helperInfo.SetPath("LOCAL_CHECKED_MODULE", info.CheckbuildTarget) 1310 } else { 1311 helperInfo.SetOptionalPath("LOCAL_CHECKED_MODULE", a.OutputFile) 1312 } 1313 1314 if len(info.TestData) > 0 { 1315 helperInfo.AddStrings("LOCAL_TEST_DATA", androidMkDataPaths(info.TestData)...) 1316 } 1317 1318 if am, ok := mod.(ApexModule); ok { 1319 helperInfo.SetBoolIfTrue("LOCAL_NOT_AVAILABLE_FOR_PLATFORM", am.NotAvailableForPlatform()) 1320 } 1321 1322 archStr := base.Arch().ArchType.String() 1323 host := false 1324 switch base.Os().Class { 1325 case Host: 1326 if base.Target().HostCross { 1327 // Make cannot identify LOCAL_MODULE_HOST_CROSS_ARCH:= common. 1328 if base.Arch().ArchType != Common { 1329 helperInfo.SetString("LOCAL_MODULE_HOST_CROSS_ARCH", archStr) 1330 } 1331 } else { 1332 // Make cannot identify LOCAL_MODULE_HOST_ARCH:= common. 1333 if base.Arch().ArchType != Common { 1334 helperInfo.SetString("LOCAL_MODULE_HOST_ARCH", archStr) 1335 } 1336 } 1337 host = true 1338 case Device: 1339 // Make cannot identify LOCAL_MODULE_TARGET_ARCH:= common. 1340 if base.Arch().ArchType != Common { 1341 if base.Target().NativeBridge { 1342 hostArchStr := base.Target().NativeBridgeHostArchName 1343 if hostArchStr != "" { 1344 helperInfo.SetString("LOCAL_MODULE_TARGET_ARCH", hostArchStr) 1345 } 1346 } else { 1347 helperInfo.SetString("LOCAL_MODULE_TARGET_ARCH", archStr) 1348 } 1349 } 1350 1351 if !base.InVendorRamdisk() { 1352 helperInfo.AddPaths("LOCAL_FULL_INIT_RC", info.InitRcPaths) 1353 } 1354 if len(info.VintfFragmentsPaths) > 0 { 1355 helperInfo.AddPaths("LOCAL_FULL_VINTF_FRAGMENTS", info.VintfFragmentsPaths) 1356 } 1357 helperInfo.SetBoolIfTrue("LOCAL_PROPRIETARY_MODULE", Bool(base.commonProperties.Proprietary)) 1358 if Bool(base.commonProperties.Vendor) || Bool(base.commonProperties.Soc_specific) { 1359 helperInfo.SetString("LOCAL_VENDOR_MODULE", "true") 1360 } 1361 helperInfo.SetBoolIfTrue("LOCAL_ODM_MODULE", Bool(base.commonProperties.Device_specific)) 1362 helperInfo.SetBoolIfTrue("LOCAL_PRODUCT_MODULE", Bool(base.commonProperties.Product_specific)) 1363 helperInfo.SetBoolIfTrue("LOCAL_SYSTEM_EXT_MODULE", Bool(base.commonProperties.System_ext_specific)) 1364 if base.commonProperties.Owner != nil { 1365 helperInfo.SetString("LOCAL_MODULE_OWNER", *base.commonProperties.Owner) 1366 } 1367 } 1368 1369 if host { 1370 makeOs := base.Os().String() 1371 if base.Os() == Linux || base.Os() == LinuxBionic || base.Os() == LinuxMusl { 1372 makeOs = "linux" 1373 } 1374 helperInfo.SetString("LOCAL_MODULE_HOST_OS", makeOs) 1375 helperInfo.SetString("LOCAL_IS_HOST_MODULE", "true") 1376 } 1377 1378 if licenseMetadata, ok := OtherModuleProvider(ctx, mod, LicenseMetadataProvider); ok { 1379 helperInfo.SetPath("LOCAL_SOONG_LICENSE_METADATA", licenseMetadata.LicenseMetadataPath) 1380 } 1381 1382 if _, ok := OtherModuleProvider(ctx, mod, ModuleInfoJSONProvider); ok { 1383 helperInfo.SetBool("LOCAL_SOONG_MODULE_INFO_JSON", true) 1384 } 1385 1386 a.mergeEntries(&helperInfo) 1387 1388 // Write to footer. 1389 a.FooterStrings = append([]string{"include " + a.Include}, a.FooterStrings...) 1390} 1391 1392// This method merges the entries to helperInfo, then replaces a's EntryMap and 1393// EntryOrder with helperInfo's 1394func (a *AndroidMkInfo) mergeEntries(helperInfo *AndroidMkInfo) { 1395 for _, extraEntry := range a.EntryOrder { 1396 if v, ok := helperInfo.EntryMap[extraEntry]; ok { 1397 v = append(v, a.EntryMap[extraEntry]...) 1398 } else { 1399 helperInfo.EntryMap[extraEntry] = a.EntryMap[extraEntry] 1400 helperInfo.EntryOrder = append(helperInfo.EntryOrder, extraEntry) 1401 } 1402 } 1403 a.EntryOrder = helperInfo.EntryOrder 1404 a.EntryMap = helperInfo.EntryMap 1405} 1406 1407func (a *AndroidMkInfo) disabled() bool { 1408 return a.Disabled || !a.OutputFile.Valid() 1409} 1410 1411// write flushes the AndroidMkEntries's in-struct data populated by AndroidMkEntries into the 1412// given Writer object. 1413func (a *AndroidMkInfo) write(w io.Writer) { 1414 if a.disabled() { 1415 return 1416 } 1417 1418 combinedHeaderString := strings.Join(a.HeaderStrings, "\n") + "\n" 1419 combinedFooterString := strings.Join(a.FooterStrings, "\n") + "\n" 1420 w.Write([]byte(combinedHeaderString)) 1421 for _, name := range a.EntryOrder { 1422 AndroidMkEmitAssignList(w, name, a.EntryMap[name]) 1423 } 1424 w.Write([]byte(combinedFooterString)) 1425} 1426 1427// Compute the list of Make strings to declare phony goals and dist-for-goals 1428// calls from the module's dist and dists properties. 1429func (a *AndroidMkInfo) GetDistForGoals(ctx fillInEntriesContext, mod blueprint.Module) []string { 1430 distContributions := a.getDistContributions(ctx, mod) 1431 if distContributions == nil { 1432 return nil 1433 } 1434 1435 return generateDistContributionsForMake(distContributions) 1436} 1437 1438// Compute the contributions that the module makes to the dist. 1439func (a *AndroidMkInfo) getDistContributions(ctx fillInEntriesContext, mod blueprint.Module) *distContributions { 1440 amod := mod.(Module).base() 1441 name := amod.BaseModuleName() 1442 1443 // Collate the set of associated tag/paths available for copying to the dist. 1444 // Start with an empty (nil) set. 1445 var availableTaggedDists TaggedDistFiles 1446 1447 // Then merge in any that are provided explicitly by the module. 1448 if a.DistFiles != nil { 1449 // Merge the DistFiles into the set. 1450 availableTaggedDists = availableTaggedDists.merge(a.DistFiles) 1451 } 1452 1453 // If no paths have been provided for the DefaultDistTag and the output file is 1454 // valid then add that as the default dist path. 1455 if _, ok := availableTaggedDists[DefaultDistTag]; !ok && a.OutputFile.Valid() { 1456 availableTaggedDists = availableTaggedDists.addPathsForTag(DefaultDistTag, a.OutputFile.Path()) 1457 } 1458 1459 info := OtherModuleProviderOrDefault(ctx, mod, InstallFilesProvider) 1460 // If the distFiles created by GenerateTaggedDistFiles contains paths for the 1461 // DefaultDistTag then that takes priority so delete any existing paths. 1462 if _, ok := info.DistFiles[DefaultDistTag]; ok { 1463 delete(availableTaggedDists, DefaultDistTag) 1464 } 1465 1466 // Finally, merge the distFiles created by GenerateTaggedDistFiles. 1467 availableTaggedDists = availableTaggedDists.merge(info.DistFiles) 1468 1469 if len(availableTaggedDists) == 0 { 1470 // Nothing dist-able for this module. 1471 return nil 1472 } 1473 1474 // Collate the contributions this module makes to the dist. 1475 distContributions := &distContributions{} 1476 1477 if !exemptFromRequiredApplicableLicensesProperty(mod.(Module)) { 1478 distContributions.licenseMetadataFile = info.LicenseMetadataFile 1479 } 1480 1481 // Iterate over this module's dist structs, merged from the dist and dists properties. 1482 for _, dist := range amod.Dists() { 1483 // Get the list of goals this dist should be enabled for. e.g. sdk, droidcore 1484 goals := strings.Join(dist.Targets, " ") 1485 1486 // Get the tag representing the output files to be dist'd. e.g. ".jar", ".proguard_map" 1487 var tag string 1488 if dist.Tag == nil { 1489 // If the dist struct does not specify a tag, use the default output files tag. 1490 tag = DefaultDistTag 1491 } else { 1492 tag = *dist.Tag 1493 } 1494 1495 // Get the paths of the output files to be dist'd, represented by the tag. 1496 // Can be an empty list. 1497 tagPaths := availableTaggedDists[tag] 1498 if len(tagPaths) == 0 { 1499 // Nothing to dist for this tag, continue to the next dist. 1500 continue 1501 } 1502 1503 if len(tagPaths) > 1 && (dist.Dest != nil || dist.Suffix != nil) { 1504 errorMessage := "%s: Cannot apply dest/suffix for more than one dist " + 1505 "file for %q goals tag %q in module %s. The list of dist files, " + 1506 "which should have a single element, is:\n%s" 1507 panic(fmt.Errorf(errorMessage, mod, goals, tag, name, tagPaths)) 1508 } 1509 1510 copiesForGoals := distContributions.getCopiesForGoals(goals) 1511 1512 // Iterate over each path adding a copy instruction to copiesForGoals 1513 for _, path := range tagPaths { 1514 // It's possible that the Path is nil from errant modules. Be defensive here. 1515 if path == nil { 1516 tagName := "default" // for error message readability 1517 if dist.Tag != nil { 1518 tagName = *dist.Tag 1519 } 1520 panic(fmt.Errorf("Dist file should not be nil for the %s tag in %s", tagName, name)) 1521 } 1522 1523 dest := filepath.Base(path.String()) 1524 1525 if dist.Dest != nil { 1526 var err error 1527 if dest, err = validateSafePath(*dist.Dest); err != nil { 1528 // This was checked in ModuleBase.GenerateBuildActions 1529 panic(err) 1530 } 1531 } 1532 1533 ext := filepath.Ext(dest) 1534 suffix := "" 1535 if dist.Suffix != nil { 1536 suffix = *dist.Suffix 1537 } 1538 1539 productString := "" 1540 if dist.Append_artifact_with_product != nil && *dist.Append_artifact_with_product { 1541 productString = fmt.Sprintf("_%s", ctx.Config().DeviceProduct()) 1542 } 1543 1544 if suffix != "" || productString != "" { 1545 dest = strings.TrimSuffix(dest, ext) + suffix + productString + ext 1546 } 1547 1548 if dist.Dir != nil { 1549 var err error 1550 if dest, err = validateSafePath(*dist.Dir, dest); err != nil { 1551 // This was checked in ModuleBase.GenerateBuildActions 1552 panic(err) 1553 } 1554 } 1555 1556 copiesForGoals.addCopyInstruction(path, dest) 1557 } 1558 } 1559 1560 return distContributions 1561} 1562 1563func deepCopyAndroidMkProviderInfo(providerInfo *AndroidMkProviderInfo) AndroidMkProviderInfo { 1564 info := AndroidMkProviderInfo{ 1565 PrimaryInfo: deepCopyAndroidMkInfo(&providerInfo.PrimaryInfo), 1566 } 1567 if len(providerInfo.ExtraInfo) > 0 { 1568 for _, i := range providerInfo.ExtraInfo { 1569 info.ExtraInfo = append(info.ExtraInfo, deepCopyAndroidMkInfo(&i)) 1570 } 1571 } 1572 return info 1573} 1574 1575func deepCopyAndroidMkInfo(mkinfo *AndroidMkInfo) AndroidMkInfo { 1576 info := AndroidMkInfo{ 1577 Class: mkinfo.Class, 1578 SubName: mkinfo.SubName, 1579 OverrideName: mkinfo.OverrideName, 1580 // There is no modification on DistFiles or OutputFile, so no need to 1581 // make their deep copy. 1582 DistFiles: mkinfo.DistFiles, 1583 OutputFile: mkinfo.OutputFile, 1584 Disabled: mkinfo.Disabled, 1585 Include: mkinfo.Include, 1586 Required: deepCopyStringSlice(mkinfo.Required), 1587 Host_required: deepCopyStringSlice(mkinfo.Host_required), 1588 Target_required: deepCopyStringSlice(mkinfo.Target_required), 1589 HeaderStrings: deepCopyStringSlice(mkinfo.HeaderStrings), 1590 FooterStrings: deepCopyStringSlice(mkinfo.FooterStrings), 1591 EntryOrder: deepCopyStringSlice(mkinfo.EntryOrder), 1592 } 1593 info.EntryMap = make(map[string][]string) 1594 for k, v := range mkinfo.EntryMap { 1595 info.EntryMap[k] = deepCopyStringSlice(v) 1596 } 1597 1598 return info 1599} 1600 1601func deepCopyStringSlice(original []string) []string { 1602 result := make([]string, len(original)) 1603 copy(result, original) 1604 return result 1605} 1606