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