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 "io/ioutil" 29 "os" 30 "path/filepath" 31 "reflect" 32 "sort" 33 "strings" 34 35 "github.com/google/blueprint" 36 "github.com/google/blueprint/bootstrap" 37) 38 39func init() { 40 RegisterAndroidMkBuildComponents(InitRegistrationContext) 41} 42 43func RegisterAndroidMkBuildComponents(ctx RegistrationContext) { 44 ctx.RegisterSingletonType("androidmk", AndroidMkSingleton) 45} 46 47// Enable androidmk support. 48// * Register the singleton 49// * Configure that we are inside make 50var PrepareForTestWithAndroidMk = GroupFixturePreparers( 51 FixtureRegisterWithContext(RegisterAndroidMkBuildComponents), 52 FixtureModifyConfig(SetKatiEnabledForTests), 53) 54 55// Deprecated: Use AndroidMkEntriesProvider instead, especially if you're not going to use the 56// Custom function. It's easier to use and test. 57type AndroidMkDataProvider interface { 58 AndroidMk() AndroidMkData 59 BaseModuleName() string 60} 61 62type AndroidMkData struct { 63 Class string 64 SubName string 65 DistFiles TaggedDistFiles 66 OutputFile OptionalPath 67 Disabled bool 68 Include string 69 Required []string 70 Host_required []string 71 Target_required []string 72 73 Custom func(w io.Writer, name, prefix, moduleDir string, data AndroidMkData) 74 75 Extra []AndroidMkExtraFunc 76 77 Entries AndroidMkEntries 78} 79 80type AndroidMkExtraFunc func(w io.Writer, outputFile Path) 81 82// Interface for modules to declare their Android.mk outputs. Note that every module needs to 83// implement this in order to be included in the final Android-<product_name>.mk output, even if 84// they only need to output the common set of entries without any customizations. 85type AndroidMkEntriesProvider interface { 86 // Returns AndroidMkEntries objects that contain all basic info plus extra customization data 87 // if needed. This is the core func to implement. 88 // Note that one can return multiple objects. For example, java_library may return an additional 89 // AndroidMkEntries object for its hostdex sub-module. 90 AndroidMkEntries() []AndroidMkEntries 91 // Modules don't need to implement this as it's already implemented by ModuleBase. 92 // AndroidMkEntries uses BaseModuleName() instead of ModuleName() because certain modules 93 // e.g. Prebuilts, override the Name() func and return modified names. 94 // If a different name is preferred, use SubName or OverrideName in AndroidMkEntries. 95 BaseModuleName() string 96} 97 98// The core data struct that modules use to provide their Android.mk data. 99type AndroidMkEntries struct { 100 // Android.mk class string, e.g EXECUTABLES, JAVA_LIBRARIES, ETC 101 Class string 102 // Optional suffix to append to the module name. Useful when a module wants to return multiple 103 // AndroidMkEntries objects. For example, when a java_library returns an additional entry for 104 // its hostdex sub-module, this SubName field is set to "-hostdex" so that it can have a 105 // different name than the parent's. 106 SubName string 107 // If set, this value overrides the base module name. SubName is still appended. 108 OverrideName string 109 // Dist files to output 110 DistFiles TaggedDistFiles 111 // The output file for Kati to process and/or install. If absent, the module is skipped. 112 OutputFile OptionalPath 113 // If true, the module is skipped and does not appear on the final Android-<product name>.mk 114 // file. Useful when a module needs to be skipped conditionally. 115 Disabled bool 116 // The postprocessing mk file to include, e.g. $(BUILD_SYSTEM)/soong_cc_prebuilt.mk 117 // If not set, $(BUILD_SYSTEM)/prebuilt.mk is used. 118 Include string 119 // Required modules that need to be built and included in the final build output when building 120 // this module. 121 Required []string 122 // Required host modules that need to be built and included in the final build output when 123 // building this module. 124 Host_required []string 125 // Required device modules that need to be built and included in the final build output when 126 // building this module. 127 Target_required []string 128 129 header bytes.Buffer 130 footer bytes.Buffer 131 132 // Funcs to append additional Android.mk entries or modify the common ones. Multiple funcs are 133 // accepted so that common logic can be factored out as a shared func. 134 ExtraEntries []AndroidMkExtraEntriesFunc 135 // Funcs to add extra lines to the module's Android.mk output. Unlike AndroidMkExtraEntriesFunc, 136 // which simply sets Make variable values, this can be used for anything since it can write any 137 // Make statements directly to the final Android-*.mk file. 138 // Primarily used to call macros or declare/update Make targets. 139 ExtraFooters []AndroidMkExtraFootersFunc 140 141 // A map that holds the up-to-date Make variable values. Can be accessed from tests. 142 EntryMap map[string][]string 143 // A list of EntryMap keys in insertion order. This serves a few purposes: 144 // 1. Prevents churns. Golang map doesn't provide consistent iteration order, so without this, 145 // the outputted Android-*.mk file may change even though there have been no content changes. 146 // 2. Allows modules to refer to other variables, like LOCAL_BAR_VAR := $(LOCAL_FOO_VAR), 147 // without worrying about the variables being mixed up in the actual mk file. 148 // 3. Makes troubleshooting and spotting errors easier. 149 entryOrder []string 150} 151 152type AndroidMkExtraEntriesContext interface { 153 Provider(provider blueprint.ProviderKey) interface{} 154} 155 156type androidMkExtraEntriesContext struct { 157 ctx fillInEntriesContext 158 mod blueprint.Module 159} 160 161func (a *androidMkExtraEntriesContext) Provider(provider blueprint.ProviderKey) interface{} { 162 return a.ctx.ModuleProvider(a.mod, provider) 163} 164 165type AndroidMkExtraEntriesFunc func(ctx AndroidMkExtraEntriesContext, entries *AndroidMkEntries) 166type AndroidMkExtraFootersFunc func(w io.Writer, name, prefix, moduleDir string) 167 168// Utility funcs to manipulate Android.mk variable entries. 169 170// SetString sets a Make variable with the given name to the given value. 171func (a *AndroidMkEntries) SetString(name, value string) { 172 if _, ok := a.EntryMap[name]; !ok { 173 a.entryOrder = append(a.entryOrder, name) 174 } 175 a.EntryMap[name] = []string{value} 176} 177 178// SetPath sets a Make variable with the given name to the given path string. 179func (a *AndroidMkEntries) SetPath(name string, path Path) { 180 if _, ok := a.EntryMap[name]; !ok { 181 a.entryOrder = append(a.entryOrder, name) 182 } 183 a.EntryMap[name] = []string{path.String()} 184} 185 186// SetOptionalPath sets a Make variable with the given name to the given path string if it is valid. 187// It is a no-op if the given path is invalid. 188func (a *AndroidMkEntries) SetOptionalPath(name string, path OptionalPath) { 189 if path.Valid() { 190 a.SetPath(name, path.Path()) 191 } 192} 193 194// AddPath appends the given path string to a Make variable with the given name. 195func (a *AndroidMkEntries) AddPath(name string, path Path) { 196 if _, ok := a.EntryMap[name]; !ok { 197 a.entryOrder = append(a.entryOrder, name) 198 } 199 a.EntryMap[name] = append(a.EntryMap[name], path.String()) 200} 201 202// AddOptionalPath appends the given path string to a Make variable with the given name if it is 203// valid. It is a no-op if the given path is invalid. 204func (a *AndroidMkEntries) AddOptionalPath(name string, path OptionalPath) { 205 if path.Valid() { 206 a.AddPath(name, path.Path()) 207 } 208} 209 210// SetPaths sets a Make variable with the given name to a slice of the given path strings. 211func (a *AndroidMkEntries) SetPaths(name string, paths Paths) { 212 if _, ok := a.EntryMap[name]; !ok { 213 a.entryOrder = append(a.entryOrder, name) 214 } 215 a.EntryMap[name] = paths.Strings() 216} 217 218// SetOptionalPaths sets a Make variable with the given name to a slice of the given path strings 219// only if there are a non-zero amount of paths. 220func (a *AndroidMkEntries) SetOptionalPaths(name string, paths Paths) { 221 if len(paths) > 0 { 222 a.SetPaths(name, paths) 223 } 224} 225 226// AddPaths appends the given path strings to a Make variable with the given name. 227func (a *AndroidMkEntries) AddPaths(name string, paths Paths) { 228 if _, ok := a.EntryMap[name]; !ok { 229 a.entryOrder = append(a.entryOrder, name) 230 } 231 a.EntryMap[name] = append(a.EntryMap[name], paths.Strings()...) 232} 233 234// SetBoolIfTrue sets a Make variable with the given name to true if the given flag is true. 235// It is a no-op if the given flag is false. 236func (a *AndroidMkEntries) SetBoolIfTrue(name string, flag bool) { 237 if flag { 238 if _, ok := a.EntryMap[name]; !ok { 239 a.entryOrder = append(a.entryOrder, name) 240 } 241 a.EntryMap[name] = []string{"true"} 242 } 243} 244 245// SetBool sets a Make variable with the given name to if the given bool flag value. 246func (a *AndroidMkEntries) SetBool(name string, flag bool) { 247 if _, ok := a.EntryMap[name]; !ok { 248 a.entryOrder = append(a.entryOrder, name) 249 } 250 if flag { 251 a.EntryMap[name] = []string{"true"} 252 } else { 253 a.EntryMap[name] = []string{"false"} 254 } 255} 256 257// AddStrings appends the given strings to a Make variable with the given name. 258func (a *AndroidMkEntries) AddStrings(name string, value ...string) { 259 if len(value) == 0 { 260 return 261 } 262 if _, ok := a.EntryMap[name]; !ok { 263 a.entryOrder = append(a.entryOrder, name) 264 } 265 a.EntryMap[name] = append(a.EntryMap[name], value...) 266} 267 268// AddCompatibilityTestSuites adds the supplied test suites to the EntryMap, with special handling 269// for partial MTS test suites. 270func (a *AndroidMkEntries) AddCompatibilityTestSuites(suites ...string) { 271 // MTS supports a full test suite and partial per-module MTS test suites, with naming mts-${MODULE}. 272 // To reduce repetition, if we find a partial MTS test suite without an full MTS test suite, 273 // we add the full test suite to our list. 274 if PrefixInList(suites, "mts-") && !InList("mts", suites) { 275 suites = append(suites, "mts") 276 } 277 a.AddStrings("LOCAL_COMPATIBILITY_SUITE", suites...) 278} 279 280// The contributions to the dist. 281type distContributions struct { 282 // List of goals and the dist copy instructions. 283 copiesForGoals []*copiesForGoals 284} 285 286// getCopiesForGoals returns a copiesForGoals into which copy instructions that 287// must be processed when building one or more of those goals can be added. 288func (d *distContributions) getCopiesForGoals(goals string) *copiesForGoals { 289 copiesForGoals := &copiesForGoals{goals: goals} 290 d.copiesForGoals = append(d.copiesForGoals, copiesForGoals) 291 return copiesForGoals 292} 293 294// Associates a list of dist copy instructions with a set of goals for which they 295// should be run. 296type copiesForGoals struct { 297 // goals are a space separated list of build targets that will trigger the 298 // copy instructions. 299 goals string 300 301 // A list of instructions to copy a module's output files to somewhere in the 302 // dist directory. 303 copies []distCopy 304} 305 306// Adds a copy instruction. 307func (d *copiesForGoals) addCopyInstruction(from Path, dest string) { 308 d.copies = append(d.copies, distCopy{from, dest}) 309} 310 311// Instruction on a path that must be copied into the dist. 312type distCopy struct { 313 // The path to copy from. 314 from Path 315 316 // The destination within the dist directory to copy to. 317 dest string 318} 319 320// Compute the contributions that the module makes to the dist. 321func (a *AndroidMkEntries) getDistContributions(mod blueprint.Module) *distContributions { 322 amod := mod.(Module).base() 323 name := amod.BaseModuleName() 324 325 // Collate the set of associated tag/paths available for copying to the dist. 326 // Start with an empty (nil) set. 327 var availableTaggedDists TaggedDistFiles 328 329 // Then merge in any that are provided explicitly by the module. 330 if a.DistFiles != nil { 331 // Merge the DistFiles into the set. 332 availableTaggedDists = availableTaggedDists.merge(a.DistFiles) 333 } 334 335 // If no paths have been provided for the DefaultDistTag and the output file is 336 // valid then add that as the default dist path. 337 if _, ok := availableTaggedDists[DefaultDistTag]; !ok && a.OutputFile.Valid() { 338 availableTaggedDists = availableTaggedDists.addPathsForTag(DefaultDistTag, a.OutputFile.Path()) 339 } 340 341 // If the distFiles created by GenerateTaggedDistFiles contains paths for the 342 // DefaultDistTag then that takes priority so delete any existing paths. 343 if _, ok := amod.distFiles[DefaultDistTag]; ok { 344 delete(availableTaggedDists, DefaultDistTag) 345 } 346 347 // Finally, merge the distFiles created by GenerateTaggedDistFiles. 348 availableTaggedDists = availableTaggedDists.merge(amod.distFiles) 349 350 if len(availableTaggedDists) == 0 { 351 // Nothing dist-able for this module. 352 return nil 353 } 354 355 // Collate the contributions this module makes to the dist. 356 distContributions := &distContributions{} 357 358 // Iterate over this module's dist structs, merged from the dist and dists properties. 359 for _, dist := range amod.Dists() { 360 // Get the list of goals this dist should be enabled for. e.g. sdk, droidcore 361 goals := strings.Join(dist.Targets, " ") 362 363 // Get the tag representing the output files to be dist'd. e.g. ".jar", ".proguard_map" 364 var tag string 365 if dist.Tag == nil { 366 // If the dist struct does not specify a tag, use the default output files tag. 367 tag = DefaultDistTag 368 } else { 369 tag = *dist.Tag 370 } 371 372 // Get the paths of the output files to be dist'd, represented by the tag. 373 // Can be an empty list. 374 tagPaths := availableTaggedDists[tag] 375 if len(tagPaths) == 0 { 376 // Nothing to dist for this tag, continue to the next dist. 377 continue 378 } 379 380 if len(tagPaths) > 1 && (dist.Dest != nil || dist.Suffix != nil) { 381 errorMessage := "%s: Cannot apply dest/suffix for more than one dist " + 382 "file for %q goals tag %q in module %s. The list of dist files, " + 383 "which should have a single element, is:\n%s" 384 panic(fmt.Errorf(errorMessage, mod, goals, tag, name, tagPaths)) 385 } 386 387 copiesForGoals := distContributions.getCopiesForGoals(goals) 388 389 // Iterate over each path adding a copy instruction to copiesForGoals 390 for _, path := range tagPaths { 391 // It's possible that the Path is nil from errant modules. Be defensive here. 392 if path == nil { 393 tagName := "default" // for error message readability 394 if dist.Tag != nil { 395 tagName = *dist.Tag 396 } 397 panic(fmt.Errorf("Dist file should not be nil for the %s tag in %s", tagName, name)) 398 } 399 400 dest := filepath.Base(path.String()) 401 402 if dist.Dest != nil { 403 var err error 404 if dest, err = validateSafePath(*dist.Dest); err != nil { 405 // This was checked in ModuleBase.GenerateBuildActions 406 panic(err) 407 } 408 } 409 410 if dist.Suffix != nil { 411 ext := filepath.Ext(dest) 412 suffix := *dist.Suffix 413 dest = strings.TrimSuffix(dest, ext) + suffix + ext 414 } 415 416 if dist.Dir != nil { 417 var err error 418 if dest, err = validateSafePath(*dist.Dir, dest); err != nil { 419 // This was checked in ModuleBase.GenerateBuildActions 420 panic(err) 421 } 422 } 423 424 copiesForGoals.addCopyInstruction(path, dest) 425 } 426 } 427 428 return distContributions 429} 430 431// generateDistContributionsForMake generates make rules that will generate the 432// dist according to the instructions in the supplied distContribution. 433func generateDistContributionsForMake(distContributions *distContributions) []string { 434 var ret []string 435 for _, d := range distContributions.copiesForGoals { 436 ret = append(ret, fmt.Sprintf(".PHONY: %s\n", d.goals)) 437 // Create dist-for-goals calls for each of the copy instructions. 438 for _, c := range d.copies { 439 ret = append( 440 ret, 441 fmt.Sprintf("$(call dist-for-goals,%s,%s:%s)\n", d.goals, c.from.String(), c.dest)) 442 } 443 } 444 445 return ret 446} 447 448// Compute the list of Make strings to declare phony goals and dist-for-goals 449// calls from the module's dist and dists properties. 450func (a *AndroidMkEntries) GetDistForGoals(mod blueprint.Module) []string { 451 distContributions := a.getDistContributions(mod) 452 if distContributions == nil { 453 return nil 454 } 455 456 return generateDistContributionsForMake(distContributions) 457} 458 459// Write the license variables to Make for AndroidMkData.Custom(..) methods that do not call WriteAndroidMkData(..) 460// It's required to propagate the license metadata even for module types that have non-standard interfaces to Make. 461func (a *AndroidMkEntries) WriteLicenseVariables(w io.Writer) { 462 fmt.Fprintln(w, "LOCAL_LICENSE_KINDS :=", strings.Join(a.EntryMap["LOCAL_LICENSE_KINDS"], " ")) 463 fmt.Fprintln(w, "LOCAL_LICENSE_CONDITIONS :=", strings.Join(a.EntryMap["LOCAL_LICENSE_CONDITIONS"], " ")) 464 fmt.Fprintln(w, "LOCAL_NOTICE_FILE :=", strings.Join(a.EntryMap["LOCAL_NOTICE_FILE"], " ")) 465 if pn, ok := a.EntryMap["LOCAL_LICENSE_PACKAGE_NAME"]; ok { 466 fmt.Fprintln(w, "LOCAL_LICENSE_PACKAGE_NAME :=", strings.Join(pn, " ")) 467 } 468} 469 470// fillInEntries goes through the common variable processing and calls the extra data funcs to 471// generate and fill in AndroidMkEntries's in-struct data, ready to be flushed to a file. 472type fillInEntriesContext interface { 473 ModuleDir(module blueprint.Module) string 474 Config() Config 475 ModuleProvider(module blueprint.Module, provider blueprint.ProviderKey) interface{} 476} 477 478func (a *AndroidMkEntries) fillInEntries(ctx fillInEntriesContext, mod blueprint.Module) { 479 a.EntryMap = make(map[string][]string) 480 amod := mod.(Module).base() 481 name := amod.BaseModuleName() 482 if a.OverrideName != "" { 483 name = a.OverrideName 484 } 485 486 if a.Include == "" { 487 a.Include = "$(BUILD_PREBUILT)" 488 } 489 a.Required = append(a.Required, amod.commonProperties.Required...) 490 a.Host_required = append(a.Host_required, amod.commonProperties.Host_required...) 491 a.Target_required = append(a.Target_required, amod.commonProperties.Target_required...) 492 493 for _, distString := range a.GetDistForGoals(mod) { 494 fmt.Fprintf(&a.header, distString) 495 } 496 497 fmt.Fprintln(&a.header, "\ninclude $(CLEAR_VARS)") 498 499 // Collect make variable assignment entries. 500 a.SetString("LOCAL_PATH", ctx.ModuleDir(mod)) 501 a.SetString("LOCAL_MODULE", name+a.SubName) 502 a.AddStrings("LOCAL_LICENSE_KINDS", amod.commonProperties.Effective_license_kinds...) 503 a.AddStrings("LOCAL_LICENSE_CONDITIONS", amod.commonProperties.Effective_license_conditions...) 504 a.AddStrings("LOCAL_NOTICE_FILE", amod.commonProperties.Effective_license_text.Strings()...) 505 // TODO(b/151177513): Does this code need to set LOCAL_MODULE_IS_CONTAINER ? 506 if amod.commonProperties.Effective_package_name != nil { 507 a.SetString("LOCAL_LICENSE_PACKAGE_NAME", *amod.commonProperties.Effective_package_name) 508 } else if len(amod.commonProperties.Effective_licenses) > 0 { 509 a.SetString("LOCAL_LICENSE_PACKAGE_NAME", strings.Join(amod.commonProperties.Effective_licenses, " ")) 510 } 511 a.SetString("LOCAL_MODULE_CLASS", a.Class) 512 a.SetString("LOCAL_PREBUILT_MODULE_FILE", a.OutputFile.String()) 513 a.AddStrings("LOCAL_REQUIRED_MODULES", a.Required...) 514 a.AddStrings("LOCAL_HOST_REQUIRED_MODULES", a.Host_required...) 515 a.AddStrings("LOCAL_TARGET_REQUIRED_MODULES", a.Target_required...) 516 517 if am, ok := mod.(ApexModule); ok { 518 a.SetBoolIfTrue("LOCAL_NOT_AVAILABLE_FOR_PLATFORM", am.NotAvailableForPlatform()) 519 } 520 521 archStr := amod.Arch().ArchType.String() 522 host := false 523 switch amod.Os().Class { 524 case Host: 525 if amod.Target().HostCross { 526 // Make cannot identify LOCAL_MODULE_HOST_CROSS_ARCH:= common. 527 if amod.Arch().ArchType != Common { 528 a.SetString("LOCAL_MODULE_HOST_CROSS_ARCH", archStr) 529 } 530 } else { 531 // Make cannot identify LOCAL_MODULE_HOST_ARCH:= common. 532 if amod.Arch().ArchType != Common { 533 a.SetString("LOCAL_MODULE_HOST_ARCH", archStr) 534 } 535 } 536 host = true 537 case Device: 538 // Make cannot identify LOCAL_MODULE_TARGET_ARCH:= common. 539 if amod.Arch().ArchType != Common { 540 if amod.Target().NativeBridge { 541 hostArchStr := amod.Target().NativeBridgeHostArchName 542 if hostArchStr != "" { 543 a.SetString("LOCAL_MODULE_TARGET_ARCH", hostArchStr) 544 } 545 } else { 546 a.SetString("LOCAL_MODULE_TARGET_ARCH", archStr) 547 } 548 } 549 550 if !amod.InRamdisk() && !amod.InVendorRamdisk() { 551 a.AddPaths("LOCAL_FULL_INIT_RC", amod.initRcPaths) 552 } 553 if len(amod.vintfFragmentsPaths) > 0 { 554 a.AddPaths("LOCAL_FULL_VINTF_FRAGMENTS", amod.vintfFragmentsPaths) 555 } 556 a.SetBoolIfTrue("LOCAL_PROPRIETARY_MODULE", Bool(amod.commonProperties.Proprietary)) 557 if Bool(amod.commonProperties.Vendor) || Bool(amod.commonProperties.Soc_specific) { 558 a.SetString("LOCAL_VENDOR_MODULE", "true") 559 } 560 a.SetBoolIfTrue("LOCAL_ODM_MODULE", Bool(amod.commonProperties.Device_specific)) 561 a.SetBoolIfTrue("LOCAL_PRODUCT_MODULE", Bool(amod.commonProperties.Product_specific)) 562 a.SetBoolIfTrue("LOCAL_SYSTEM_EXT_MODULE", Bool(amod.commonProperties.System_ext_specific)) 563 if amod.commonProperties.Owner != nil { 564 a.SetString("LOCAL_MODULE_OWNER", *amod.commonProperties.Owner) 565 } 566 } 567 568 if len(amod.noticeFiles) > 0 { 569 a.SetString("LOCAL_NOTICE_FILE", strings.Join(amod.noticeFiles.Strings(), " ")) 570 } 571 572 if host { 573 makeOs := amod.Os().String() 574 if amod.Os() == Linux || amod.Os() == LinuxBionic { 575 makeOs = "linux" 576 } 577 a.SetString("LOCAL_MODULE_HOST_OS", makeOs) 578 a.SetString("LOCAL_IS_HOST_MODULE", "true") 579 } 580 581 prefix := "" 582 if amod.ArchSpecific() { 583 switch amod.Os().Class { 584 case Host: 585 if amod.Target().HostCross { 586 prefix = "HOST_CROSS_" 587 } else { 588 prefix = "HOST_" 589 } 590 case Device: 591 prefix = "TARGET_" 592 593 } 594 595 if amod.Arch().ArchType != ctx.Config().Targets[amod.Os()][0].Arch.ArchType { 596 prefix = "2ND_" + prefix 597 } 598 } 599 600 extraCtx := &androidMkExtraEntriesContext{ 601 ctx: ctx, 602 mod: mod, 603 } 604 605 for _, extra := range a.ExtraEntries { 606 extra(extraCtx, a) 607 } 608 609 // Write to footer. 610 fmt.Fprintln(&a.footer, "include "+a.Include) 611 blueprintDir := ctx.ModuleDir(mod) 612 for _, footerFunc := range a.ExtraFooters { 613 footerFunc(&a.footer, name, prefix, blueprintDir) 614 } 615} 616 617// write flushes the AndroidMkEntries's in-struct data populated by AndroidMkEntries into the 618// given Writer object. 619func (a *AndroidMkEntries) write(w io.Writer) { 620 if a.Disabled { 621 return 622 } 623 624 if !a.OutputFile.Valid() { 625 return 626 } 627 628 w.Write(a.header.Bytes()) 629 for _, name := range a.entryOrder { 630 fmt.Fprintln(w, name+" := "+strings.Join(a.EntryMap[name], " ")) 631 } 632 w.Write(a.footer.Bytes()) 633} 634 635func (a *AndroidMkEntries) FooterLinesForTests() []string { 636 return strings.Split(string(a.footer.Bytes()), "\n") 637} 638 639// AndroidMkSingleton is a singleton to collect Android.mk data from all modules and dump them into 640// the final Android-<product_name>.mk file output. 641func AndroidMkSingleton() Singleton { 642 return &androidMkSingleton{} 643} 644 645type androidMkSingleton struct{} 646 647func (c *androidMkSingleton) GenerateBuildActions(ctx SingletonContext) { 648 // Skip if Soong wasn't invoked from Make. 649 if !ctx.Config().KatiEnabled() { 650 return 651 } 652 653 var androidMkModulesList []blueprint.Module 654 655 ctx.VisitAllModulesBlueprint(func(module blueprint.Module) { 656 androidMkModulesList = append(androidMkModulesList, module) 657 }) 658 659 // Sort the module list by the module names to eliminate random churns, which may erroneously 660 // invoke additional build processes. 661 sort.SliceStable(androidMkModulesList, func(i, j int) bool { 662 return ctx.ModuleName(androidMkModulesList[i]) < ctx.ModuleName(androidMkModulesList[j]) 663 }) 664 665 transMk := PathForOutput(ctx, "Android"+String(ctx.Config().productVariables.Make_suffix)+".mk") 666 if ctx.Failed() { 667 return 668 } 669 670 err := translateAndroidMk(ctx, absolutePath(transMk.String()), androidMkModulesList) 671 if err != nil { 672 ctx.Errorf(err.Error()) 673 } 674 675 ctx.Build(pctx, BuildParams{ 676 Rule: blueprint.Phony, 677 Output: transMk, 678 }) 679} 680 681func translateAndroidMk(ctx SingletonContext, mkFile string, mods []blueprint.Module) error { 682 buf := &bytes.Buffer{} 683 684 fmt.Fprintln(buf, "LOCAL_MODULE_MAKEFILE := $(lastword $(MAKEFILE_LIST))") 685 686 typeStats := make(map[string]int) 687 for _, mod := range mods { 688 err := translateAndroidMkModule(ctx, buf, mod) 689 if err != nil { 690 os.Remove(mkFile) 691 return err 692 } 693 694 if amod, ok := mod.(Module); ok && ctx.PrimaryModule(amod) == amod { 695 typeStats[ctx.ModuleType(amod)] += 1 696 } 697 } 698 699 keys := []string{} 700 fmt.Fprintln(buf, "\nSTATS.SOONG_MODULE_TYPE :=") 701 for k := range typeStats { 702 keys = append(keys, k) 703 } 704 sort.Strings(keys) 705 for _, mod_type := range keys { 706 fmt.Fprintln(buf, "STATS.SOONG_MODULE_TYPE +=", mod_type) 707 fmt.Fprintf(buf, "STATS.SOONG_MODULE_TYPE.%s := %d\n", mod_type, typeStats[mod_type]) 708 } 709 710 // Don't write to the file if it hasn't changed 711 if _, err := os.Stat(absolutePath(mkFile)); !os.IsNotExist(err) { 712 if data, err := ioutil.ReadFile(absolutePath(mkFile)); err == nil { 713 matches := buf.Len() == len(data) 714 715 if matches { 716 for i, value := range buf.Bytes() { 717 if value != data[i] { 718 matches = false 719 break 720 } 721 } 722 } 723 724 if matches { 725 return nil 726 } 727 } 728 } 729 730 return ioutil.WriteFile(absolutePath(mkFile), buf.Bytes(), 0666) 731} 732 733func translateAndroidMkModule(ctx SingletonContext, w io.Writer, mod blueprint.Module) error { 734 defer func() { 735 if r := recover(); r != nil { 736 panic(fmt.Errorf("%s in translateAndroidMkModule for module %s variant %s", 737 r, ctx.ModuleName(mod), ctx.ModuleSubDir(mod))) 738 } 739 }() 740 741 // Additional cases here require review for correct license propagation to make. 742 switch x := mod.(type) { 743 case AndroidMkDataProvider: 744 return translateAndroidModule(ctx, w, mod, x) 745 case bootstrap.GoBinaryTool: 746 return translateGoBinaryModule(ctx, w, mod, x) 747 case AndroidMkEntriesProvider: 748 return translateAndroidMkEntriesModule(ctx, w, mod, x) 749 default: 750 // Not exported to make so no make variables to set. 751 return nil 752 } 753} 754 755// A simple, special Android.mk entry output func to make it possible to build blueprint tools using 756// m by making them phony targets. 757func translateGoBinaryModule(ctx SingletonContext, w io.Writer, mod blueprint.Module, 758 goBinary bootstrap.GoBinaryTool) error { 759 760 name := ctx.ModuleName(mod) 761 fmt.Fprintln(w, ".PHONY:", name) 762 fmt.Fprintln(w, name+":", goBinary.InstallPath()) 763 fmt.Fprintln(w, "") 764 // Assuming no rules in make include go binaries in distributables. 765 // If the assumption is wrong, make will fail to build without the necessary .meta_lic and .meta_module files. 766 // In that case, add the targets and rules here to build a .meta_lic file for `name` and a .meta_module for 767 // `goBinary.InstallPath()` pointing to the `name`.meta_lic file. 768 769 return nil 770} 771 772func (data *AndroidMkData) fillInData(ctx fillInEntriesContext, mod blueprint.Module) { 773 // Get the preamble content through AndroidMkEntries logic. 774 data.Entries = AndroidMkEntries{ 775 Class: data.Class, 776 SubName: data.SubName, 777 DistFiles: data.DistFiles, 778 OutputFile: data.OutputFile, 779 Disabled: data.Disabled, 780 Include: data.Include, 781 Required: data.Required, 782 Host_required: data.Host_required, 783 Target_required: data.Target_required, 784 } 785 data.Entries.fillInEntries(ctx, mod) 786 787 // copy entries back to data since it is used in Custom 788 data.Required = data.Entries.Required 789 data.Host_required = data.Entries.Host_required 790 data.Target_required = data.Entries.Target_required 791} 792 793// A support func for the deprecated AndroidMkDataProvider interface. Use AndroidMkEntryProvider 794// instead. 795func translateAndroidModule(ctx SingletonContext, w io.Writer, mod blueprint.Module, 796 provider AndroidMkDataProvider) error { 797 798 amod := mod.(Module).base() 799 if shouldSkipAndroidMkProcessing(amod) { 800 return nil 801 } 802 803 data := provider.AndroidMk() 804 if data.Include == "" { 805 data.Include = "$(BUILD_PREBUILT)" 806 } 807 808 data.fillInData(ctx, mod) 809 810 prefix := "" 811 if amod.ArchSpecific() { 812 switch amod.Os().Class { 813 case Host: 814 if amod.Target().HostCross { 815 prefix = "HOST_CROSS_" 816 } else { 817 prefix = "HOST_" 818 } 819 case Device: 820 prefix = "TARGET_" 821 822 } 823 824 if amod.Arch().ArchType != ctx.Config().Targets[amod.Os()][0].Arch.ArchType { 825 prefix = "2ND_" + prefix 826 } 827 } 828 829 name := provider.BaseModuleName() 830 blueprintDir := filepath.Dir(ctx.BlueprintFile(mod)) 831 832 if data.Custom != nil { 833 // List of module types allowed to use .Custom(...) 834 // Additions to the list require careful review for proper license handling. 835 switch reflect.TypeOf(mod).String() { // ctx.ModuleType(mod) doesn't work: aidl_interface creates phony without type 836 case "*aidl.aidlApi": // writes non-custom before adding .phony 837 case "*aidl.aidlMapping": // writes non-custom before adding .phony 838 case "*android.customModule": // appears in tests only 839 case "*apex.apexBundle": // license properties written 840 case "*bpf.bpf": // license properties written (both for module and objs) 841 case "*genrule.Module": // writes non-custom before adding .phony 842 case "*java.SystemModules": // doesn't go through base_rules 843 case "*java.systemModulesImport": // doesn't go through base_rules 844 case "*phony.phony": // license properties written 845 case "*selinux.selinuxContextsModule": // license properties written 846 case "*sysprop.syspropLibrary": // license properties written 847 default: 848 if ctx.Config().IsEnvTrue("ANDROID_REQUIRE_LICENSES") { 849 return fmt.Errorf("custom make rules not allowed for %q (%q) module %q", ctx.ModuleType(mod), reflect.TypeOf(mod), ctx.ModuleName(mod)) 850 } 851 } 852 data.Custom(w, name, prefix, blueprintDir, data) 853 } else { 854 WriteAndroidMkData(w, data) 855 } 856 857 return nil 858} 859 860// A support func for the deprecated AndroidMkDataProvider interface. Use AndroidMkEntryProvider 861// instead. 862func WriteAndroidMkData(w io.Writer, data AndroidMkData) { 863 if data.Disabled { 864 return 865 } 866 867 if !data.OutputFile.Valid() { 868 return 869 } 870 871 // write preamble via Entries 872 data.Entries.footer = bytes.Buffer{} 873 data.Entries.write(w) 874 875 for _, extra := range data.Extra { 876 extra(w, data.OutputFile.Path()) 877 } 878 879 fmt.Fprintln(w, "include "+data.Include) 880} 881 882func translateAndroidMkEntriesModule(ctx SingletonContext, w io.Writer, mod blueprint.Module, 883 provider AndroidMkEntriesProvider) error { 884 if shouldSkipAndroidMkProcessing(mod.(Module).base()) { 885 return nil 886 } 887 888 // Any new or special cases here need review to verify correct propagation of license information. 889 for _, entries := range provider.AndroidMkEntries() { 890 entries.fillInEntries(ctx, mod) 891 entries.write(w) 892 } 893 894 return nil 895} 896 897func shouldSkipAndroidMkProcessing(module *ModuleBase) bool { 898 if !module.commonProperties.NamespaceExportedToMake { 899 // TODO(jeffrygaston) do we want to validate that there are no modules being 900 // exported to Kati that depend on this module? 901 return true 902 } 903 904 return !module.Enabled() || 905 module.commonProperties.HideFromMake || 906 // Make does not understand LinuxBionic 907 module.Os() == LinuxBionic 908} 909 910// A utility func to format LOCAL_TEST_DATA outputs. See the comments on DataPath to understand how 911// to use this func. 912func AndroidMkDataPaths(data []DataPath) []string { 913 var testFiles []string 914 for _, d := range data { 915 rel := d.SrcPath.Rel() 916 path := d.SrcPath.String() 917 // LOCAL_TEST_DATA requires the rel portion of the path to be removed from the path. 918 if !strings.HasSuffix(path, rel) { 919 panic(fmt.Errorf("path %q does not end with %q", path, rel)) 920 } 921 path = strings.TrimSuffix(path, rel) 922 testFileString := path + ":" + rel 923 if len(d.RelativeInstallPath) > 0 { 924 testFileString += ":" + d.RelativeInstallPath 925 } 926 testFiles = append(testFiles, testFileString) 927 } 928 return testFiles 929} 930