1// Copyright 2017 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 implements the logic of bpfix and also provides a programmatic interface 16 17package bpfix 18 19import ( 20 "bytes" 21 "errors" 22 "flag" 23 "fmt" 24 "io" 25 "io/ioutil" 26 "os" 27 "path/filepath" 28 "reflect" 29 "sort" 30 "strings" 31 32 "github.com/google/blueprint/parser" 33 "github.com/google/blueprint/pathtools" 34) 35 36// Reformat takes a blueprint file as a string and returns a formatted version 37func Reformat(input string) (string, error) { 38 tree, err := parse("<string>", bytes.NewBufferString(input)) 39 if err != nil { 40 return "", err 41 } 42 43 res, err := parser.Print(tree) 44 if err != nil { 45 return "", err 46 } 47 48 return string(res), nil 49} 50 51// A FixRequest specifies the details of which fixes to apply to an individual file 52// A FixRequest doesn't specify whether to do a dry run or where to write the results; that's in cmd/bpfix.go 53type FixRequest struct { 54 steps []FixStep 55} 56type FixStepsExtension struct { 57 Name string 58 Steps []FixStep 59} 60 61type FixStep struct { 62 Name string 63 Fix func(f *Fixer) error 64} 65 66var fixStepsExtensions = []*FixStepsExtension(nil) 67 68func RegisterFixStepExtension(extension *FixStepsExtension) { 69 fixStepsExtensions = append(fixStepsExtensions, extension) 70} 71 72var fixSteps = []FixStep{ 73 { 74 Name: "simplifyKnownRedundantVariables", 75 Fix: runPatchListMod(simplifyKnownPropertiesDuplicatingEachOther), 76 }, 77 { 78 Name: "rewriteIncorrectAndroidmkPrebuilts", 79 Fix: rewriteIncorrectAndroidmkPrebuilts, 80 }, 81 { 82 Name: "rewriteCtsModuleTypes", 83 Fix: rewriteCtsModuleTypes, 84 }, 85 { 86 Name: "rewriteIncorrectAndroidmkAndroidLibraries", 87 Fix: rewriteIncorrectAndroidmkAndroidLibraries, 88 }, 89 { 90 Name: "rewriteTestModuleTypes", 91 Fix: rewriteTestModuleTypes, 92 }, 93 { 94 Name: "rewriteAndroidmkJavaLibs", 95 Fix: rewriteAndroidmkJavaLibs, 96 }, 97 { 98 Name: "rewriteJavaStaticLibs", 99 Fix: rewriteJavaStaticLibs, 100 }, 101 { 102 Name: "rewritePrebuiltEtc", 103 Fix: rewriteAndroidmkPrebuiltEtc, 104 }, 105 { 106 Name: "mergeMatchingModuleProperties", 107 Fix: runPatchListMod(mergeMatchingModuleProperties), 108 }, 109 { 110 Name: "reorderCommonProperties", 111 Fix: runPatchListMod(reorderCommonProperties), 112 }, 113 { 114 Name: "removeTags", 115 Fix: runPatchListMod(removeTags), 116 }, 117 { 118 Name: "rewriteAndroidTest", 119 Fix: rewriteAndroidTest, 120 }, 121 { 122 Name: "rewriteAndroidAppImport", 123 Fix: rewriteAndroidAppImport, 124 }, 125 { 126 Name: "removeEmptyLibDependencies", 127 Fix: removeEmptyLibDependencies, 128 }, 129 { 130 Name: "removeHidlInterfaceTypes", 131 Fix: removeHidlInterfaceTypes, 132 }, 133 { 134 Name: "removeSoongConfigBoolVariable", 135 Fix: removeSoongConfigBoolVariable, 136 }, 137 { 138 Name: "removePdkProperty", 139 Fix: runPatchListMod(removeObsoleteProperty("product_variables.pdk")), 140 }, 141 { 142 Name: "removeScudoProperty", 143 Fix: runPatchListMod(removeObsoleteProperty("sanitize.scudo")), 144 }, 145 { 146 Name: "removeAndroidLicenseKinds", 147 Fix: runPatchListMod(removeIncorrectProperties("android_license_kinds")), 148 }, 149 { 150 Name: "removeAndroidLicenseConditions", 151 Fix: runPatchListMod(removeIncorrectProperties("android_license_conditions")), 152 }, 153 { 154 Name: "removeAndroidLicenseFiles", 155 Fix: runPatchListMod(removeIncorrectProperties("android_license_files")), 156 }, 157 { 158 Name: "formatFlagProperties", 159 Fix: runPatchListMod(formatFlagProperties), 160 }, 161 { 162 Name: "removeResourcesAndAssetsIfDefault", 163 Fix: removeResourceAndAssetsIfDefault, 164 }, 165} 166 167// for fix that only need to run once 168var fixStepsOnce = []FixStep{ 169 { 170 Name: "haveSameLicense", 171 Fix: haveSameLicense, 172 }, 173 { 174 Name: "rewriteLicenseProperties", 175 Fix: runPatchListMod(rewriteLicenseProperty(nil, "")), 176 }, 177} 178 179func NewFixRequest() FixRequest { 180 return FixRequest{} 181} 182 183func (r FixRequest) AddAll() (result FixRequest) { 184 result.steps = append([]FixStep(nil), r.steps...) 185 result.steps = append(result.steps, fixSteps...) 186 for _, extension := range fixStepsExtensions { 187 result.steps = append(result.steps, extension.Steps...) 188 } 189 return result 190} 191 192func (r FixRequest) AddBase() (result FixRequest) { 193 result.steps = append([]FixStep(nil), r.steps...) 194 result.steps = append(result.steps, fixSteps...) 195 return result 196} 197 198func (r FixRequest) AddMatchingExtensions(pattern string) (result FixRequest) { 199 result.steps = append([]FixStep(nil), r.steps...) 200 for _, extension := range fixStepsExtensions { 201 if match, _ := filepath.Match(pattern, extension.Name); match { 202 result.steps = append(result.steps, extension.Steps...) 203 } 204 } 205 return result 206} 207 208type Fixer struct { 209 tree *parser.File 210} 211 212func (f Fixer) Tree() *parser.File { 213 return f.tree 214} 215 216func NewFixer(tree *parser.File) *Fixer { 217 fixer := &Fixer{tree} 218 219 // make a copy of the tree 220 fixer.reparse() 221 222 return fixer 223} 224 225// Fix repeatedly applies the fixes listed in the given FixRequest to the given File 226// until there is no fix that affects the tree 227func (f *Fixer) Fix(config FixRequest) (*parser.File, error) { 228 prevIdentifier, err := f.fingerprint() 229 if err != nil { 230 return nil, err 231 } 232 233 // run fix that is expected to run once first 234 configOnce := NewFixRequest() 235 configOnce.steps = append(configOnce.steps, fixStepsOnce...) 236 if len(configOnce.steps) > 0 { 237 err = f.fixTreeOnce(configOnce) 238 if err != nil { 239 return nil, err 240 } 241 } 242 243 maxNumIterations := 20 244 i := 0 245 for { 246 err = f.fixTreeOnce(config) 247 newIdentifier, err := f.fingerprint() 248 if err != nil { 249 return nil, err 250 } 251 if bytes.Equal(newIdentifier, prevIdentifier) { 252 break 253 } 254 prevIdentifier = newIdentifier 255 // any errors from a previous iteration generally get thrown away and overwritten by errors on the next iteration 256 257 // detect infinite loop 258 i++ 259 if i >= maxNumIterations { 260 return nil, fmt.Errorf("Applied fixes %d times and yet the tree continued to change. Is there an infinite loop?", i) 261 } 262 } 263 return f.tree, err 264} 265 266// returns a unique identifier for the given tree that can be used to determine whether the tree changed 267func (f *Fixer) fingerprint() (fingerprint []byte, err error) { 268 bytes, err := parser.Print(f.tree) 269 if err != nil { 270 return nil, err 271 } 272 return bytes, nil 273} 274 275func (f *Fixer) reparse() ([]byte, error) { 276 buf, err := parser.Print(f.tree) 277 if err != nil { 278 return nil, err 279 } 280 newTree, err := parse(f.tree.Name, bytes.NewReader(buf)) 281 if err != nil { 282 return nil, err 283 } 284 f.tree = newTree 285 return buf, nil 286} 287 288func parse(name string, r io.Reader) (*parser.File, error) { 289 tree, errs := parser.Parse(name, r, parser.NewScope(nil)) 290 if errs != nil { 291 s := "parse error: " 292 for _, err := range errs { 293 s += "\n" + err.Error() 294 } 295 return nil, errors.New(s) 296 } 297 return tree, nil 298} 299 300func (f *Fixer) fixTreeOnce(config FixRequest) error { 301 for _, fix := range config.steps { 302 err := fix.Fix(f) 303 if err != nil { 304 return err 305 } 306 } 307 return nil 308} 309 310func simplifyKnownPropertiesDuplicatingEachOther(mod *parser.Module, buf []byte, patchList *parser.PatchList) error { 311 // remove from local_include_dirs anything in export_include_dirs 312 return removeMatchingModuleListProperties(mod, patchList, 313 "export_include_dirs", "local_include_dirs") 314} 315 316func rewriteIncorrectAndroidmkPrebuilts(f *Fixer) error { 317 for _, def := range f.tree.Defs { 318 mod, ok := def.(*parser.Module) 319 if !ok { 320 continue 321 } 322 if mod.Type != "java_import" { 323 continue 324 } 325 host, _ := getLiteralBoolPropertyValue(mod, "host") 326 if host { 327 mod.Type = "java_import_host" 328 removeProperty(mod, "host") 329 } 330 srcs, ok := getLiteralListProperty(mod, "srcs") 331 if !ok { 332 continue 333 } 334 if len(srcs.Values) == 0 { 335 continue 336 } 337 src, ok := srcs.Values[0].(*parser.String) 338 if !ok { 339 continue 340 } 341 switch filepath.Ext(src.Value) { 342 case ".jar": 343 renameProperty(mod, "srcs", "jars") 344 345 case ".aar": 346 renameProperty(mod, "srcs", "aars") 347 mod.Type = "android_library_import" 348 349 // An android_library_import doesn't get installed, so setting "installable = false" isn't supported 350 removeProperty(mod, "installable") 351 } 352 } 353 354 return nil 355} 356 357func rewriteCtsModuleTypes(f *Fixer) error { 358 for _, def := range f.tree.Defs { 359 mod, ok := def.(*parser.Module) 360 if !ok { 361 continue 362 } 363 364 if mod.Type != "cts_support_package" && mod.Type != "cts_package" && 365 mod.Type != "cts_target_java_library" && 366 mod.Type != "cts_host_java_library" { 367 368 continue 369 } 370 371 var defStr string 372 switch mod.Type { 373 case "cts_support_package": 374 mod.Type = "android_test_helper_app" 375 defStr = "cts_support_defaults" 376 case "cts_package": 377 mod.Type = "android_test" 378 defStr = "cts_defaults" 379 case "cts_target_java_library": 380 mod.Type = "java_library" 381 defStr = "cts_defaults" 382 case "cts_host_java_library": 383 mod.Type = "java_library_host" 384 defStr = "cts_defaults" 385 } 386 387 defaults := &parser.Property{ 388 Name: "defaults", 389 Value: &parser.List{ 390 Values: []parser.Expression{ 391 &parser.String{ 392 Value: defStr, 393 }, 394 }, 395 }, 396 } 397 mod.Properties = append(mod.Properties, defaults) 398 } 399 400 return nil 401} 402 403func rewriteIncorrectAndroidmkAndroidLibraries(f *Fixer) error { 404 for _, def := range f.tree.Defs { 405 mod, ok := def.(*parser.Module) 406 if !ok { 407 continue 408 } 409 410 if !strings.HasPrefix(mod.Type, "java_") && !strings.HasPrefix(mod.Type, "android_") { 411 continue 412 } 413 414 hasAndroidLibraries := hasNonEmptyLiteralListProperty(mod, "android_libs") 415 hasStaticAndroidLibraries := hasNonEmptyLiteralListProperty(mod, "android_static_libs") 416 hasResourceDirs := hasNonEmptyLiteralListProperty(mod, "resource_dirs") 417 418 if hasAndroidLibraries || hasStaticAndroidLibraries || hasResourceDirs { 419 if mod.Type == "java_library_static" || mod.Type == "java_library" { 420 mod.Type = "android_library" 421 } 422 } 423 424 if mod.Type == "java_import" && !hasStaticAndroidLibraries { 425 removeProperty(mod, "android_static_libs") 426 } 427 428 // These may conflict with existing libs and static_libs properties, but the 429 // mergeMatchingModuleProperties pass will fix it. 430 renameProperty(mod, "shared_libs", "libs") 431 renameProperty(mod, "android_libs", "libs") 432 renameProperty(mod, "android_static_libs", "static_libs") 433 } 434 435 return nil 436} 437 438// rewriteTestModuleTypes looks for modules that are identifiable as tests but for which Make doesn't have a separate 439// module class, and moves them to the appropriate Soong module type. 440func rewriteTestModuleTypes(f *Fixer) error { 441 for _, def := range f.tree.Defs { 442 mod, ok := def.(*parser.Module) 443 if !ok { 444 continue 445 } 446 447 if !strings.HasPrefix(mod.Type, "java_") && !strings.HasPrefix(mod.Type, "android_") && mod.Type != "cc_binary" { 448 continue 449 } 450 451 hasInstrumentationFor := hasNonEmptyLiteralStringProperty(mod, "instrumentation_for") 452 hasTestSuites := hasNonEmptyLiteralListProperty(mod, "test_suites") 453 tags, _ := getLiteralListPropertyValue(mod, "tags") 454 455 var hasTestsTag bool 456 for _, tag := range tags { 457 if tag == "tests" { 458 hasTestsTag = true 459 } 460 } 461 462 isTest := hasInstrumentationFor || hasTestsTag || hasTestSuites 463 464 if isTest { 465 switch mod.Type { 466 case "android_app": 467 mod.Type = "android_test" 468 case "android_app_import": 469 mod.Type = "android_test_import" 470 case "java_library", "java_library_installable": 471 mod.Type = "java_test" 472 case "java_library_host": 473 mod.Type = "java_test_host" 474 case "cc_binary": 475 mod.Type = "cc_test" 476 } 477 } 478 } 479 480 return nil 481} 482 483// rewriteJavaStaticLibs rewrites java_library_static into java_library 484func rewriteJavaStaticLibs(f *Fixer) error { 485 for _, def := range f.tree.Defs { 486 mod, ok := def.(*parser.Module) 487 if !ok { 488 continue 489 } 490 491 if mod.Type == "java_library_static" { 492 mod.Type = "java_library" 493 } 494 } 495 496 return nil 497} 498 499// rewriteAndroidmkJavaLibs rewrites java_library_installable into java_library plus installable: true 500func rewriteAndroidmkJavaLibs(f *Fixer) error { 501 for _, def := range f.tree.Defs { 502 mod, ok := def.(*parser.Module) 503 if !ok { 504 continue 505 } 506 507 if mod.Type != "java_library_installable" { 508 continue 509 } 510 511 mod.Type = "java_library" 512 513 _, hasInstallable := mod.GetProperty("installable") 514 if !hasInstallable { 515 prop := &parser.Property{ 516 Name: "installable", 517 Value: &parser.Bool{ 518 Value: true, 519 }, 520 } 521 mod.Properties = append(mod.Properties, prop) 522 } 523 } 524 525 return nil 526} 527 528// Helper function to get the value of a string-valued property in a given compound property. 529func getStringProperty(prop *parser.Property, fieldName string) string { 530 if propsAsMap, ok := prop.Value.(*parser.Map); ok { 531 for _, propField := range propsAsMap.Properties { 532 if fieldName == propField.Name { 533 if propFieldAsString, ok := propField.Value.(*parser.String); ok { 534 return propFieldAsString.Value 535 } else { 536 return "" 537 } 538 } 539 } 540 } 541 return "" 542} 543 544// Set the value of the given attribute to the error message 545func indicateAttributeError(mod *parser.Module, attributeName string, format string, a ...interface{}) error { 546 msg := fmt.Sprintf(format, a...) 547 mod.Properties = append(mod.Properties, &parser.Property{ 548 Name: attributeName, 549 Value: &parser.String{Value: "ERROR: " + msg}, 550 }) 551 return errors.New(msg) 552} 553 554// If a variable is LOCAL_MODULE, get its value from the 'name' attribute. 555// This handles the statement 556// 557// LOCAL_SRC_FILES := $(LOCAL_MODULE) 558// 559// which occurs often. 560func resolveLocalModule(mod *parser.Module, val parser.Expression) parser.Expression { 561 if varLocalName, ok := val.(*parser.Variable); ok { 562 if varLocalName.Name == "LOCAL_MODULE" { 563 if v, ok := getLiteralStringProperty(mod, "name"); ok { 564 return v 565 } 566 } 567 } 568 return val 569} 570 571// etcPrebuiltModuleUpdate contains information on updating certain parts of a defined module such as: 572// - changing the module type from prebuilt_etc to a different one 573// - stripping the prefix of the install path based on the module type 574// - appending additional boolean properties to the prebuilt module 575type etcPrebuiltModuleUpdate struct { 576 // The prefix of the install path defined in local_module_path. The prefix is removed from local_module_path 577 // before setting the 'filename' attribute. 578 prefix string 579 580 // There is only one prebuilt module type in makefiles. In Soong, there are multiple versions of 581 // prebuilts based on local_module_path. By default, it is "prebuilt_etc" if modType is blank. An 582 // example is if the local_module_path contains $(TARGET_OUT)/usr/share, the module type is 583 // considered as prebuilt_usr_share. 584 modType string 585 586 // Additional boolean attributes to be added in the prebuilt module. Each added boolean attribute 587 // has a value of true. 588 flags []string 589} 590 591func (f etcPrebuiltModuleUpdate) update(m *parser.Module, path string) bool { 592 updated := false 593 if path == f.prefix { 594 updated = true 595 } else if trimmedPath := strings.TrimPrefix(path, f.prefix+"/"); trimmedPath != path { 596 m.Properties = append(m.Properties, &parser.Property{ 597 Name: "relative_install_path", 598 Value: &parser.String{Value: trimmedPath}, 599 }) 600 updated = true 601 } 602 if updated { 603 for _, flag := range f.flags { 604 m.Properties = append(m.Properties, &parser.Property{Name: flag, Value: &parser.Bool{Value: true, Token: "true"}}) 605 } 606 if f.modType != "" { 607 m.Type = f.modType 608 } 609 } 610 return updated 611} 612 613var localModuleUpdate = map[string][]etcPrebuiltModuleUpdate{ 614 "HOST_OUT": { 615 {prefix: "/etc", modType: "prebuilt_etc_host"}, 616 {prefix: "/usr/share", modType: "prebuilt_usr_share_host"}, 617 {prefix: "", modType: "prebuilt_root_host"}, 618 }, 619 "PRODUCT_OUT": {{prefix: "/system/etc"}, {prefix: "/vendor/etc", flags: []string{"proprietary"}}}, 620 "TARGET_OUT": {{prefix: "/usr/share", modType: "prebuilt_usr_share"}, {prefix: "/fonts", modType: "prebuilt_font"}, 621 {prefix: "/etc/firmware", modType: "prebuilt_firmware"}, {prefix: "/vendor/firmware", modType: "prebuilt_firmware", flags: []string{"proprietary"}}, 622 {prefix: "/etc"}}, 623 "TARGET_OUT_ETC": {{prefix: "/firmware", modType: "prebuilt_firmware"}, {prefix: ""}}, 624 "TARGET_OUT_PRODUCT": {{prefix: "/etc", flags: []string{"product_specific"}}, {prefix: "/fonts", modType: "prebuilt_font", flags: []string{"product_specific"}}}, 625 "TARGET_OUT_PRODUCT_ETC": {{prefix: "", flags: []string{"product_specific"}}}, 626 "TARGET_OUT_ODM": {{prefix: "/etc", flags: []string{"device_specific"}}}, 627 "TARGET_OUT_SYSTEM_EXT": {{prefix: "/etc", flags: []string{"system_ext_specific"}}}, 628 "TARGET_OUT_SYSTEM_EXT_ETC": {{prefix: "", flags: []string{"system_ext_specific"}}}, 629 "TARGET_OUT_VENDOR": {{prefix: "/etc", flags: []string{"proprietary"}}, {prefix: "/firmware", modType: "prebuilt_firmware", flags: []string{"proprietary"}}}, 630 "TARGET_OUT_VENDOR_ETC": {{prefix: "", flags: []string{"proprietary"}}}, 631 "TARGET_RECOVERY_ROOT_OUT": {{prefix: "/system/etc", flags: []string{"recovery"}}}, 632} 633 634// rewriteAndroidPrebuiltEtc fixes prebuilt_etc rule 635func rewriteAndroidmkPrebuiltEtc(f *Fixer) error { 636 for _, def := range f.tree.Defs { 637 mod, ok := def.(*parser.Module) 638 if !ok { 639 continue 640 } 641 642 if mod.Type != "prebuilt_etc" && mod.Type != "prebuilt_etc_host" { 643 continue 644 } 645 646 // 'srcs' --> 'src' conversion 647 convertToSingleSource(mod, "src") 648 649 renameProperty(mod, "sub_dir", "relative_install_path") 650 651 // The rewriter converts LOCAL_MODULE_PATH attribute into a struct attribute 652 // 'local_module_path'. Analyze its contents and create the correct sub_dir:, 653 // filename: and boolean attributes combination 654 const local_module_path = "local_module_path" 655 if prop_local_module_path, ok := mod.GetProperty(local_module_path); ok { 656 removeProperty(mod, local_module_path) 657 prefixVariableName := getStringProperty(prop_local_module_path, "var") 658 if moduleUpdates, ok := localModuleUpdate[prefixVariableName]; ok { 659 path := getStringProperty(prop_local_module_path, "fixed") 660 updated := false 661 for i := 0; i < len(moduleUpdates) && !updated; i++ { 662 updated = moduleUpdates[i].update(mod, path) 663 } 664 if !updated { 665 expectedPrefices := "" 666 sep := "" 667 for _, moduleUpdate := range moduleUpdates { 668 expectedPrefices += sep 669 sep = ", " 670 expectedPrefices += moduleUpdate.prefix 671 } 672 return indicateAttributeError(mod, "filename", 673 "LOCAL_MODULE_PATH value under $(%s) should start with %s", prefixVariableName, expectedPrefices) 674 } 675 } else { 676 return indicateAttributeError(mod, "filename", "Cannot handle $(%s) for the prebuilt_etc", prefixVariableName) 677 } 678 } 679 } 680 return nil 681} 682 683func rewriteAndroidTest(f *Fixer) error { 684 for _, def := range f.tree.Defs { 685 mod, ok := def.(*parser.Module) 686 if !ok { 687 // The definition is not a module. 688 continue 689 } 690 if mod.Type != "android_test" && mod.Type != "android_test_helper_app" { 691 // The module is not an android_test or android_test_helper_app. 692 continue 693 } 694 // The rewriter converts LOCAL_MODULE_PATH attribute into a struct attribute 695 // 'local_module_path'. For the android_test module, it should be $(TARGET_OUT_DATA_APPS), 696 // that is, `local_module_path: { var: "TARGET_OUT_DATA_APPS"}` 697 // 1. if the `key: val` pair matches, (key is `local_module_path`, 698 // and val is `{ var: "TARGET_OUT_DATA_APPS"}`), this property is removed; 699 // 2. o/w, an error msg is thrown. 700 const local_module_path = "local_module_path" 701 if prop_local_module_path, ok := mod.GetProperty(local_module_path); ok { 702 removeProperty(mod, local_module_path) 703 prefixVariableName := getStringProperty(prop_local_module_path, "var") 704 path := getStringProperty(prop_local_module_path, "fixed") 705 if prefixVariableName == "TARGET_OUT_DATA_APPS" && path == "" { 706 continue 707 } 708 return indicateAttributeError(mod, "filename", 709 "Only LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS) is allowed for the %s", mod.Type) 710 } 711 } 712 return nil 713} 714 715func rewriteAndroidAppImport(f *Fixer) error { 716 for _, def := range f.tree.Defs { 717 mod, ok := def.(*parser.Module) 718 if !(ok && mod.Type == "android_app_import") { 719 continue 720 } 721 // 'srcs' --> 'apk' conversion 722 convertToSingleSource(mod, "apk") 723 // Handle special certificate value, "PRESIGNED". 724 if cert, ok := mod.GetProperty("certificate"); ok { 725 if certStr, ok := cert.Value.(*parser.String); ok { 726 if certStr.Value == "PRESIGNED" { 727 removeProperty(mod, "certificate") 728 prop := &parser.Property{ 729 Name: "presigned", 730 Value: &parser.Bool{ 731 Value: true, 732 }, 733 } 734 mod.Properties = append(mod.Properties, prop) 735 } 736 } 737 } 738 } 739 return nil 740} 741 742func RewriteRuntimeResourceOverlay(f *Fixer) error { 743 for _, def := range f.tree.Defs { 744 mod, ok := def.(*parser.Module) 745 if !(ok && mod.Type == "runtime_resource_overlay") { 746 continue 747 } 748 // runtime_resource_overlays are always product specific in Make. 749 if _, ok := mod.GetProperty("product_specific"); !ok { 750 prop := &parser.Property{ 751 Name: "product_specific", 752 Value: &parser.Bool{ 753 Value: true, 754 }, 755 } 756 mod.Properties = append(mod.Properties, prop) 757 } 758 } 759 return nil 760} 761 762// Removes library dependencies which are empty (and restricted from usage in Soong) 763func removeEmptyLibDependencies(f *Fixer) error { 764 emptyLibraries := []string{ 765 "libhidltransport", 766 "libhwbinder", 767 } 768 relevantFields := []string{ 769 "export_shared_lib_headers", 770 "export_static_lib_headers", 771 "static_libs", 772 "whole_static_libs", 773 "shared_libs", 774 } 775 for _, def := range f.tree.Defs { 776 mod, ok := def.(*parser.Module) 777 if !ok { 778 continue 779 } 780 for _, field := range relevantFields { 781 listValue, ok := getLiteralListProperty(mod, field) 782 if !ok { 783 continue 784 } 785 newValues := []parser.Expression{} 786 for _, v := range listValue.Values { 787 stringValue, ok := v.(*parser.String) 788 if !ok { 789 return fmt.Errorf("Expecting string for %s.%s fields", mod.Type, field) 790 } 791 if inList(stringValue.Value, emptyLibraries) { 792 continue 793 } 794 newValues = append(newValues, stringValue) 795 } 796 if len(newValues) == 0 && len(listValue.Values) != 0 { 797 removeProperty(mod, field) 798 } else { 799 listValue.Values = newValues 800 } 801 } 802 } 803 return nil 804} 805 806// Removes hidl_interface 'types' which are no longer needed 807func removeHidlInterfaceTypes(f *Fixer) error { 808 for _, def := range f.tree.Defs { 809 mod, ok := def.(*parser.Module) 810 if !(ok && mod.Type == "hidl_interface") { 811 continue 812 } 813 removeProperty(mod, "types") 814 } 815 return nil 816} 817 818func removeSoongConfigBoolVariable(f *Fixer) error { 819 found := map[string]bool{} 820 newDefs := make([]parser.Definition, 0, len(f.tree.Defs)) 821 for _, def := range f.tree.Defs { 822 if mod, ok := def.(*parser.Module); ok && mod.Type == "soong_config_bool_variable" { 823 if name, ok := getLiteralStringPropertyValue(mod, "name"); ok { 824 found[name] = true 825 } else { 826 return fmt.Errorf("Found soong_config_bool_variable without a name") 827 } 828 } else { 829 newDefs = append(newDefs, def) 830 } 831 } 832 f.tree.Defs = newDefs 833 834 if len(found) == 0 { 835 return nil 836 } 837 838 return runPatchListMod(func(mod *parser.Module, buf []byte, patchList *parser.PatchList) error { 839 if mod.Type != "soong_config_module_type" { 840 return nil 841 } 842 843 variables, ok := getLiteralListProperty(mod, "variables") 844 if !ok { 845 return nil 846 } 847 848 boolValues := strings.Builder{} 849 empty := true 850 for _, item := range variables.Values { 851 nameValue, ok := item.(*parser.String) 852 if !ok { 853 empty = false 854 continue 855 } 856 if found[nameValue.Value] { 857 patchList.Add(item.Pos().Offset, item.End().Offset+2, "") 858 859 boolValues.WriteString(`"`) 860 boolValues.WriteString(nameValue.Value) 861 boolValues.WriteString(`",`) 862 } else { 863 empty = false 864 } 865 } 866 if empty { 867 *patchList = parser.PatchList{} 868 869 prop, _ := mod.GetProperty("variables") 870 patchList.Add(prop.Pos().Offset, prop.End().Offset+2, "") 871 } 872 if boolValues.Len() == 0 { 873 return nil 874 } 875 876 boolVariables, ok := getLiteralListProperty(mod, "bool_variables") 877 if ok { 878 patchList.Add(boolVariables.RBracePos.Offset, boolVariables.RBracePos.Offset, ","+boolValues.String()) 879 } else { 880 patchList.Add(variables.RBracePos.Offset+2, variables.RBracePos.Offset+2, 881 fmt.Sprintf(`bool_variables: [%s],`, boolValues.String())) 882 } 883 884 return nil 885 })(f) 886 887 return nil 888} 889 890func removeResourceAndAssetsIfDefault(f *Fixer) error { 891 for _, def := range f.tree.Defs { 892 mod, ok := def.(*parser.Module) 893 if !ok { 894 continue 895 } 896 resourceDirList, resourceDirFound := getLiteralListPropertyValue(mod, "resource_dirs") 897 if resourceDirFound && len(resourceDirList) == 1 && resourceDirList[0] == "res" { 898 removeProperty(mod, "resource_dirs") 899 } 900 assetDirList, assetDirFound := getLiteralListPropertyValue(mod, "asset_dirs") 901 if assetDirFound && len(assetDirList) == 1 && assetDirList[0] == "assets" { 902 removeProperty(mod, "asset_dirs") 903 } 904 } 905 return nil 906} 907 908// Converts the default source list property, 'srcs', to a single source property with a given name. 909// "LOCAL_MODULE" reference is also resolved during the conversion process. 910func convertToSingleSource(mod *parser.Module, srcPropertyName string) { 911 if srcs, ok := mod.GetProperty("srcs"); ok { 912 if srcList, ok := srcs.Value.(*parser.List); ok { 913 removeProperty(mod, "srcs") 914 if len(srcList.Values) == 1 { 915 mod.Properties = append(mod.Properties, 916 &parser.Property{ 917 Name: srcPropertyName, 918 NamePos: srcs.NamePos, 919 ColonPos: srcs.ColonPos, 920 Value: resolveLocalModule(mod, srcList.Values[0])}) 921 } else if len(srcList.Values) > 1 { 922 indicateAttributeError(mod, srcPropertyName, "LOCAL_SRC_FILES should contain at most one item") 923 } 924 } else if _, ok = srcs.Value.(*parser.Variable); ok { 925 removeProperty(mod, "srcs") 926 mod.Properties = append(mod.Properties, 927 &parser.Property{Name: srcPropertyName, 928 NamePos: srcs.NamePos, 929 ColonPos: srcs.ColonPos, 930 Value: resolveLocalModule(mod, srcs.Value)}) 931 } else { 932 renameProperty(mod, "srcs", "apk") 933 } 934 } 935} 936 937type patchListModFunction func(*parser.Module, []byte, *parser.PatchList) error 938 939func runPatchListMod(modFunc patchListModFunction) func(*Fixer) error { 940 return func(f *Fixer) error { 941 // Make sure all the offsets are accurate 942 buf, err := f.reparse() 943 if err != nil { 944 return err 945 } 946 947 var patchlist parser.PatchList 948 for _, def := range f.tree.Defs { 949 mod, ok := def.(*parser.Module) 950 if !ok { 951 continue 952 } 953 954 err := modFunc(mod, buf, &patchlist) 955 if err != nil { 956 return err 957 } 958 } 959 960 newBuf := new(bytes.Buffer) 961 err = patchlist.Apply(bytes.NewReader(buf), newBuf) 962 if err != nil { 963 return err 964 } 965 966 // Save a copy of the buffer to print for errors below 967 bufCopy := append([]byte(nil), newBuf.Bytes()...) 968 969 newTree, err := parse(f.tree.Name, newBuf) 970 if err != nil { 971 return fmt.Errorf("Failed to parse: %v\nBuffer:\n%s", err, string(bufCopy)) 972 } 973 974 f.tree = newTree 975 976 return nil 977 } 978} 979 980var commonPropertyPriorities = []string{ 981 "name", 982 "defaults", 983 "device_supported", 984 "host_supported", 985 "installable", 986} 987 988func reorderCommonProperties(mod *parser.Module, buf []byte, patchlist *parser.PatchList) error { 989 if len(mod.Properties) == 0 { 990 return nil 991 } 992 993 pos := mod.LBracePos.Offset + 1 994 stage := "" 995 996 for _, name := range commonPropertyPriorities { 997 idx := propertyIndex(mod.Properties, name) 998 if idx == -1 { 999 continue 1000 } 1001 if idx == 0 { 1002 err := patchlist.Add(pos, pos, stage) 1003 if err != nil { 1004 return err 1005 } 1006 stage = "" 1007 1008 pos = mod.Properties[0].End().Offset + 1 1009 mod.Properties = mod.Properties[1:] 1010 continue 1011 } 1012 1013 prop := mod.Properties[idx] 1014 mod.Properties = append(mod.Properties[:idx], mod.Properties[idx+1:]...) 1015 1016 stage += string(buf[prop.Pos().Offset : prop.End().Offset+1]) 1017 1018 err := patchlist.Add(prop.Pos().Offset, prop.End().Offset+2, "") 1019 if err != nil { 1020 return err 1021 } 1022 } 1023 1024 if stage != "" { 1025 err := patchlist.Add(pos, pos, stage) 1026 if err != nil { 1027 return err 1028 } 1029 } 1030 1031 return nil 1032} 1033 1034func removeTags(mod *parser.Module, buf []byte, patchlist *parser.PatchList) error { 1035 prop, ok := mod.GetProperty("tags") 1036 if !ok { 1037 return nil 1038 } 1039 list, ok := prop.Value.(*parser.List) 1040 if !ok { 1041 return nil 1042 } 1043 1044 replaceStr := "" 1045 1046 for _, item := range list.Values { 1047 str, ok := item.(*parser.String) 1048 if !ok { 1049 replaceStr += fmt.Sprintf("// ERROR: Unable to parse tag %q\n", item) 1050 continue 1051 } 1052 1053 switch str.Value { 1054 case "optional": 1055 continue 1056 case "debug": 1057 replaceStr += `// WARNING: Module tags are not supported in Soong. 1058 // Add this module to PRODUCT_PACKAGES_DEBUG in your product file if you want to 1059 // force installation for -userdebug and -eng builds. 1060 ` 1061 case "eng": 1062 replaceStr += `// WARNING: Module tags are not supported in Soong. 1063 // Add this module to PRODUCT_PACKAGES_ENG in your product file if you want to 1064 // force installation for -eng builds. 1065 ` 1066 case "tests": 1067 switch { 1068 case strings.Contains(mod.Type, "cc_test"), 1069 strings.Contains(mod.Type, "cc_library_static"), 1070 strings.Contains(mod.Type, "java_test"), 1071 mod.Type == "android_test", 1072 mod.Type == "android_test_import": 1073 continue 1074 case strings.Contains(mod.Type, "cc_lib"): 1075 replaceStr += `// WARNING: Module tags are not supported in Soong. 1076 // To make a shared library only for tests, use the "cc_test_library" module 1077 // type. If you don't use gtest, set "gtest: false". 1078 ` 1079 case strings.Contains(mod.Type, "cc_bin"): 1080 replaceStr += `// WARNING: Module tags are not supported in Soong. 1081 // For native test binaries, use the "cc_test" module type. Some differences: 1082 // - If you don't use gtest, set "gtest: false" 1083 // - Binaries will be installed into /data/nativetest[64]/<name>/<name> 1084 // - Both 32 & 64 bit versions will be built (as appropriate) 1085 ` 1086 case strings.Contains(mod.Type, "java_lib"): 1087 replaceStr += `// WARNING: Module tags are not supported in Soong. 1088 // For JUnit or similar tests, use the "java_test" module type. A dependency on 1089 // Junit will be added by default, if it is using some other runner, set "junit: false". 1090 ` 1091 case mod.Type == "android_app": 1092 replaceStr += `// WARNING: Module tags are not supported in Soong. 1093 // For JUnit or instrumentataion app tests, use the "android_test" module type. 1094 ` 1095 default: 1096 replaceStr += `// WARNING: Module tags are not supported in Soong. 1097 // In most cases, tests are now identified by their module type: 1098 // cc_test, java_test, python_test 1099 ` 1100 } 1101 default: 1102 replaceStr += fmt.Sprintf("// WARNING: Unknown module tag %q\n", str.Value) 1103 } 1104 } 1105 1106 return patchlist.Add(prop.Pos().Offset, prop.End().Offset+2, replaceStr) 1107} 1108 1109type propertyProvider interface { 1110 GetProperty(string) (*parser.Property, bool) 1111 RemoveProperty(string) bool 1112} 1113 1114func removeNestedProperty(mod *parser.Module, patchList *parser.PatchList, propName string) error { 1115 propNames := strings.Split(propName, ".") 1116 1117 var propProvider, toRemoveFrom propertyProvider 1118 propProvider = mod 1119 1120 var propToRemove *parser.Property 1121 for i, name := range propNames { 1122 p, ok := propProvider.GetProperty(name) 1123 if !ok { 1124 return nil 1125 } 1126 // if this is the inner most element, it's time to delete 1127 if i == len(propNames)-1 { 1128 if propToRemove == nil { 1129 // if we cannot remove the properties that the current property is nested in, 1130 // remove only the current property 1131 propToRemove = p 1132 toRemoveFrom = propProvider 1133 } 1134 1135 // remove the property from the list, in case we remove other properties in this list 1136 toRemoveFrom.RemoveProperty(propToRemove.Name) 1137 // only removing the property would leave blank line(s), remove with a patch 1138 if err := patchList.Add(propToRemove.Pos().Offset, propToRemove.End().Offset+2, ""); err != nil { 1139 return err 1140 } 1141 } else { 1142 propMap, ok := p.Value.(*parser.Map) 1143 if !ok { 1144 return nil 1145 } 1146 if len(propMap.Properties) > 1 { 1147 // if there are other properties in this struct, we need to keep this struct 1148 toRemoveFrom = nil 1149 propToRemove = nil 1150 } else if propToRemove == nil { 1151 // otherwise, we can remove the empty struct entirely 1152 toRemoveFrom = propProvider 1153 propToRemove = p 1154 } 1155 propProvider = propMap 1156 } 1157 } 1158 1159 return nil 1160} 1161 1162func removeObsoleteProperty(propName string) patchListModFunction { 1163 return func(mod *parser.Module, buf []byte, patchList *parser.PatchList) error { 1164 return removeNestedProperty(mod, patchList, propName) 1165 } 1166} 1167 1168func mergeMatchingModuleProperties(mod *parser.Module, buf []byte, patchlist *parser.PatchList) error { 1169 return mergeMatchingProperties(&mod.Properties, buf, patchlist) 1170} 1171 1172func mergeMatchingProperties(properties *[]*parser.Property, buf []byte, patchlist *parser.PatchList) error { 1173 seen := make(map[string]*parser.Property) 1174 for i := 0; i < len(*properties); i++ { 1175 property := (*properties)[i] 1176 if prev, exists := seen[property.Name]; exists { 1177 err := mergeProperties(prev, property, buf, patchlist) 1178 if err != nil { 1179 return err 1180 } 1181 *properties = append((*properties)[:i], (*properties)[i+1:]...) 1182 } else { 1183 seen[property.Name] = property 1184 if mapProperty, ok := property.Value.(*parser.Map); ok { 1185 err := mergeMatchingProperties(&mapProperty.Properties, buf, patchlist) 1186 if err != nil { 1187 return err 1188 } 1189 } 1190 } 1191 } 1192 return nil 1193} 1194 1195func mergeProperties(a, b *parser.Property, buf []byte, patchlist *parser.PatchList) error { 1196 // The value of one of the properties may be a variable reference with no type assigned 1197 // Bail out in this case. Soong will notice duplicate entries and will tell to merge them. 1198 if _, isVar := a.Value.(*parser.Variable); isVar { 1199 return nil 1200 } 1201 if _, isVar := b.Value.(*parser.Variable); isVar { 1202 return nil 1203 } 1204 if a.Value.Type() != b.Value.Type() { 1205 return fmt.Errorf("type mismatch when merging properties %q: %s and %s", a.Name, a.Value.Type(), b.Value.Type()) 1206 } 1207 1208 switch a.Value.Type() { 1209 case parser.StringType: 1210 return fmt.Errorf("conflicting definitions of string property %q", a.Name) 1211 case parser.ListType: 1212 return mergeListProperties(a, b, buf, patchlist) 1213 } 1214 1215 return nil 1216} 1217 1218func mergeListProperties(a, b *parser.Property, buf []byte, patchlist *parser.PatchList) error { 1219 aval, oka := a.Value.(*parser.List) 1220 bval, okb := b.Value.(*parser.List) 1221 if !oka || !okb { 1222 // Merging expressions not supported yet 1223 return nil 1224 } 1225 1226 s := string(buf[bval.LBracePos.Offset+1 : bval.RBracePos.Offset]) 1227 if bval.LBracePos.Line != bval.RBracePos.Line { 1228 if s[0] != '\n' { 1229 panic("expected \n") 1230 } 1231 // If B is a multi line list, skip the first "\n" in case A already has a trailing "\n" 1232 s = s[1:] 1233 } 1234 if aval.LBracePos.Line == aval.RBracePos.Line { 1235 // A is a single line list with no trailing comma 1236 if len(aval.Values) > 0 { 1237 s = "," + s 1238 } 1239 } 1240 1241 err := patchlist.Add(aval.RBracePos.Offset, aval.RBracePos.Offset, s) 1242 if err != nil { 1243 return err 1244 } 1245 err = patchlist.Add(b.NamePos.Offset, b.End().Offset+2, "") 1246 if err != nil { 1247 return err 1248 } 1249 1250 return nil 1251} 1252 1253// removes from <items> every item present in <removals> 1254func filterExpressionList(patchList *parser.PatchList, items *parser.List, removals *parser.List) { 1255 writeIndex := 0 1256 for _, item := range items.Values { 1257 included := true 1258 for _, removal := range removals.Values { 1259 equal, err := parser.ExpressionsAreSame(item, removal) 1260 if err != nil { 1261 continue 1262 } 1263 if equal { 1264 included = false 1265 break 1266 } 1267 } 1268 if included { 1269 items.Values[writeIndex] = item 1270 writeIndex++ 1271 } else { 1272 patchList.Add(item.Pos().Offset, item.End().Offset+2, "") 1273 } 1274 } 1275 items.Values = items.Values[:writeIndex] 1276} 1277 1278// Remove each modules[i].Properties[<legacyName>][j] that matches a modules[i].Properties[<canonicalName>][k] 1279func removeMatchingModuleListProperties(mod *parser.Module, patchList *parser.PatchList, canonicalName string, legacyName string) error { 1280 legacyProp, ok := mod.GetProperty(legacyName) 1281 if !ok { 1282 return nil 1283 } 1284 legacyList, ok := legacyProp.Value.(*parser.List) 1285 if !ok || len(legacyList.Values) == 0 { 1286 return nil 1287 } 1288 canonicalList, ok := getLiteralListProperty(mod, canonicalName) 1289 if !ok { 1290 return nil 1291 } 1292 1293 localPatches := parser.PatchList{} 1294 filterExpressionList(&localPatches, legacyList, canonicalList) 1295 1296 if len(legacyList.Values) == 0 { 1297 patchList.Add(legacyProp.Pos().Offset, legacyProp.End().Offset+2, "") 1298 } else { 1299 for _, p := range localPatches { 1300 patchList.Add(p.Start, p.End, p.Replacement) 1301 } 1302 } 1303 1304 return nil 1305} 1306 1307func hasNonEmptyLiteralListProperty(mod *parser.Module, name string) bool { 1308 list, found := getLiteralListProperty(mod, name) 1309 return found && len(list.Values) > 0 1310} 1311 1312func hasNonEmptyLiteralStringProperty(mod *parser.Module, name string) bool { 1313 s, found := getLiteralStringPropertyValue(mod, name) 1314 return found && len(s) > 0 1315} 1316 1317func getLiteralListProperty(mod *parser.Module, name string) (list *parser.List, found bool) { 1318 prop, ok := mod.GetProperty(name) 1319 if !ok { 1320 return nil, false 1321 } 1322 list, ok = prop.Value.(*parser.List) 1323 return list, ok 1324} 1325 1326func getLiteralListPropertyValue(mod *parser.Module, name string) (list []string, found bool) { 1327 listValue, ok := getLiteralListProperty(mod, name) 1328 if !ok { 1329 return nil, false 1330 } 1331 for _, v := range listValue.Values { 1332 stringValue, ok := v.(*parser.String) 1333 if !ok { 1334 return nil, false 1335 } 1336 list = append(list, stringValue.Value) 1337 } 1338 1339 return list, true 1340} 1341 1342func getLiteralStringProperty(mod *parser.Module, name string) (s *parser.String, found bool) { 1343 prop, ok := mod.GetProperty(name) 1344 if !ok { 1345 return nil, false 1346 } 1347 s, ok = prop.Value.(*parser.String) 1348 return s, ok 1349} 1350 1351func getLiteralStringPropertyValue(mod *parser.Module, name string) (s string, found bool) { 1352 stringValue, ok := getLiteralStringProperty(mod, name) 1353 if !ok { 1354 return "", false 1355 } 1356 1357 return stringValue.Value, true 1358} 1359 1360func getLiteralBoolProperty(mod *parser.Module, name string) (b *parser.Bool, found bool) { 1361 prop, ok := mod.GetProperty(name) 1362 if !ok { 1363 return nil, false 1364 } 1365 b, ok = prop.Value.(*parser.Bool) 1366 return b, ok 1367} 1368 1369func getLiteralBoolPropertyValue(mod *parser.Module, name string) (s bool, found bool) { 1370 boolValue, ok := getLiteralBoolProperty(mod, name) 1371 if !ok { 1372 return false, false 1373 } 1374 1375 return boolValue.Value, true 1376} 1377 1378func propertyIndex(props []*parser.Property, propertyName string) int { 1379 for i, prop := range props { 1380 if prop.Name == propertyName { 1381 return i 1382 } 1383 } 1384 return -1 1385} 1386 1387func renameProperty(mod *parser.Module, from, to string) { 1388 for _, prop := range mod.Properties { 1389 if prop.Name == from { 1390 prop.Name = to 1391 } 1392 } 1393} 1394 1395func removeProperty(mod *parser.Module, propertyName string) { 1396 newList := make([]*parser.Property, 0, len(mod.Properties)) 1397 for _, prop := range mod.Properties { 1398 if prop.Name != propertyName { 1399 newList = append(newList, prop) 1400 } 1401 } 1402 mod.Properties = newList 1403} 1404 1405func inList(s string, list []string) bool { 1406 for _, v := range list { 1407 if s == v { 1408 return true 1409 } 1410 } 1411 return false 1412} 1413 1414func formatFlagProperty(mod *parser.Module, field string, buf []byte, patchlist *parser.PatchList) error { 1415 // the comment or empty lines in the value of the field are skipped 1416 listValue, ok := getLiteralListProperty(mod, field) 1417 if !ok { 1418 // if do not find 1419 return nil 1420 } 1421 for i := 0; i < len(listValue.Values); i++ { 1422 curValue, ok := listValue.Values[i].(*parser.String) 1423 if !ok { 1424 return fmt.Errorf("Expecting string for %s.%s fields", mod.Type, field) 1425 } 1426 if !strings.HasPrefix(curValue.Value, "-") { 1427 return fmt.Errorf("Expecting the string `%s` starting with '-'", curValue.Value) 1428 } 1429 if i+1 < len(listValue.Values) { 1430 nextValue, ok := listValue.Values[i+1].(*parser.String) 1431 if !ok { 1432 return fmt.Errorf("Expecting string for %s.%s fields", mod.Type, field) 1433 } 1434 if !strings.HasPrefix(nextValue.Value, "-") { 1435 // delete the line 1436 err := patchlist.Add(curValue.Pos().Offset, curValue.End().Offset+2, "") 1437 if err != nil { 1438 return err 1439 } 1440 // replace the line 1441 value := "\"" + curValue.Value + " " + nextValue.Value + "\"," 1442 err = patchlist.Add(nextValue.Pos().Offset, nextValue.End().Offset+1, value) 1443 if err != nil { 1444 return err 1445 } 1446 // combined two lines to one 1447 i++ 1448 } 1449 } 1450 } 1451 return nil 1452} 1453 1454func formatFlagProperties(mod *parser.Module, buf []byte, patchlist *parser.PatchList) error { 1455 relevantFields := []string{ 1456 // cc flags 1457 "asflags", 1458 "cflags", 1459 "clang_asflags", 1460 "clang_cflags", 1461 "conlyflags", 1462 "cppflags", 1463 "ldflags", 1464 "tidy_flags", 1465 // java flags 1466 "aaptflags", 1467 "dxflags", 1468 "javacflags", 1469 "kotlincflags", 1470 } 1471 for _, field := range relevantFields { 1472 err := formatFlagProperty(mod, field, buf, patchlist) 1473 if err != nil { 1474 return err 1475 } 1476 } 1477 return nil 1478} 1479 1480func rewriteLicenseProperty(fs pathtools.FileSystem, relativePath string) patchListModFunction { 1481 return func(mod *parser.Module, buf []byte, patchList *parser.PatchList) error { 1482 return rewriteLicenseProperties(mod, patchList, fs, relativePath) 1483 } 1484} 1485 1486// rewrite the "android_license_kinds" and "android_license_files" properties to a package module 1487// (and a license module when needed). 1488func rewriteLicenseProperties(mod *parser.Module, patchList *parser.PatchList, fs pathtools.FileSystem, 1489 relativePath string) error { 1490 // if a package module has been added, no more action is needed. 1491 for _, patch := range *patchList { 1492 if strings.Contains(patch.Replacement, "package {") { 1493 return nil 1494 } 1495 } 1496 1497 // initial the fs 1498 if fs == nil { 1499 fs = pathtools.NewOsFs(os.Getenv("ANDROID_BUILD_TOP")) 1500 } 1501 1502 // initial the relativePath 1503 if len(relativePath) == 0 { 1504 relativePath = getModuleRelativePath() 1505 } 1506 // validate the relativePath 1507 ok := hasFile(relativePath+"/Android.mk", fs) 1508 // some modules in the existing test cases in the androidmk_test.go do not have a valid path 1509 if !ok && len(relativePath) > 0 { 1510 return fmt.Errorf("Cannot find an Android.mk file at path %q", relativePath) 1511 } 1512 1513 licenseKindsPropertyName := "android_license_kinds" 1514 licenseFilesPropertyName := "android_license_files" 1515 1516 androidBpFileErr := "// Error: No Android.bp file is found at path\n" + 1517 "// %s\n" + 1518 "// Please add one there with the needed license module first.\n" + 1519 "// Then reset the default_applicable_licenses property below with the license module name.\n" 1520 licenseModuleErr := "// Error: Cannot get the name of the license module in the\n" + 1521 "// %s file.\n" + 1522 "// If no such license module exists, please add one there first.\n" + 1523 "// Then reset the default_applicable_licenses property below with the license module name.\n" 1524 1525 defaultApplicableLicense := "Android-Apache-2.0" 1526 var licenseModuleName, licensePatch string 1527 var hasFileInParentDir bool 1528 1529 // when LOCAL_NOTICE_FILE is not empty 1530 if hasNonEmptyLiteralListProperty(mod, licenseFilesPropertyName) { 1531 hasFileInParentDir = hasValueStartWithTwoDotsLiteralList(mod, licenseFilesPropertyName) 1532 // if have LOCAL_NOTICE_FILE outside the current directory, need to find and refer to the license 1533 // module in the LOCAL_NOTICE_FILE location directly and no new license module needs to be created 1534 if hasFileInParentDir { 1535 bpPath, ok := getPathFromProperty(mod, licenseFilesPropertyName, fs, relativePath) 1536 if !ok { 1537 bpDir, err := getDirFromProperty(mod, licenseFilesPropertyName, fs, relativePath) 1538 if err != nil { 1539 return err 1540 } 1541 licensePatch += fmt.Sprintf(androidBpFileErr, bpDir) 1542 defaultApplicableLicense = "" 1543 } else { 1544 licenseModuleName, _ = getModuleName(bpPath, "license", fs) 1545 if len(licenseModuleName) == 0 { 1546 licensePatch += fmt.Sprintf(licenseModuleErr, bpPath) 1547 } 1548 defaultApplicableLicense = licenseModuleName 1549 } 1550 } else { 1551 // if have LOCAL_NOTICE_FILE in the current directory, need to create a new license module 1552 if len(relativePath) == 0 { 1553 return fmt.Errorf("Cannot obtain the relative path of the Android.mk file") 1554 } 1555 licenseModuleName = strings.Replace(relativePath, "/", "_", -1) + "_license" 1556 defaultApplicableLicense = licenseModuleName 1557 } 1558 } 1559 1560 //add the package module 1561 if hasNonEmptyLiteralListProperty(mod, licenseKindsPropertyName) { 1562 licensePatch += "package {\n" + 1563 " // See: http://go/android-license-faq\n" + 1564 " default_applicable_licenses: [\n" + 1565 " \"" + defaultApplicableLicense + "\",\n" + 1566 " ],\n" + 1567 "}\n" + 1568 "\n" 1569 } 1570 1571 // append the license module when necessary 1572 // when LOCAL_NOTICE_FILE is not empty and in the current directory, create a new license module 1573 // otherwise, use the above default license directly 1574 if hasNonEmptyLiteralListProperty(mod, licenseFilesPropertyName) && !hasFileInParentDir { 1575 licenseKinds, err := mergeLiteralListPropertyValue(mod, licenseKindsPropertyName) 1576 if err != nil { 1577 return err 1578 } 1579 licenseFiles, err := mergeLiteralListPropertyValue(mod, licenseFilesPropertyName) 1580 if err != nil { 1581 return err 1582 } 1583 licensePatch += "license {\n" + 1584 " name: \"" + licenseModuleName + "\",\n" + 1585 " visibility: [\":__subpackages__\"],\n" + 1586 " license_kinds: [\n" + 1587 licenseKinds + 1588 " ],\n" + 1589 " license_text: [\n" + 1590 licenseFiles + 1591 " ],\n" + 1592 "}\n" + 1593 "\n" 1594 } 1595 1596 // add to the patchList 1597 pos := mod.Pos().Offset 1598 err := patchList.Add(pos, pos, licensePatch) 1599 if err != nil { 1600 return err 1601 } 1602 return nil 1603} 1604 1605// merge the string vaules in a list property of a module into one string with expected format 1606func mergeLiteralListPropertyValue(mod *parser.Module, property string) (s string, err error) { 1607 listValue, ok := getLiteralListPropertyValue(mod, property) 1608 if !ok { 1609 // if do not find 1610 return "", fmt.Errorf("Cannot retrieve the %s.%s field", mod.Type, property) 1611 } 1612 for i := 0; i < len(listValue); i++ { 1613 s += " \"" + listValue[i] + "\",\n" 1614 } 1615 return s, nil 1616} 1617 1618// check whether a string list property has any value starting with `../` 1619func hasValueStartWithTwoDotsLiteralList(mod *parser.Module, property string) bool { 1620 listValue, ok := getLiteralListPropertyValue(mod, property) 1621 if ok { 1622 for i := 0; i < len(listValue); i++ { 1623 if strings.HasPrefix(listValue[i], "../") { 1624 return true 1625 } 1626 } 1627 } 1628 return false 1629} 1630 1631// get the relative path from ANDROID_BUILD_TOP to the Android.mk file to be converted 1632func getModuleRelativePath() string { 1633 // get the absolute path of the top of the tree 1634 rootPath := os.Getenv("ANDROID_BUILD_TOP") 1635 // get the absolute path of the `Android.mk` file to be converted 1636 absPath := getModuleAbsolutePath() 1637 // get the relative path of the `Android.mk` file to top of the tree 1638 relModulePath, err := filepath.Rel(rootPath, absPath) 1639 if err != nil { 1640 return "" 1641 } 1642 return relModulePath 1643} 1644 1645// get the absolute path of the Android.mk file to be converted 1646func getModuleAbsolutePath() string { 1647 // get the absolute path at where the `androidmk` commend is executed 1648 curAbsPath, err := filepath.Abs(".") 1649 if err != nil { 1650 return "" 1651 } 1652 // the argument for the `androidmk` command could be 1653 // 1. "./a/b/c/Android.mk"; 2. "a/b/c/Android.mk"; 3. "Android.mk" 1654 argPath := flag.Arg(0) 1655 if strings.HasPrefix(argPath, "./") { 1656 argPath = strings.TrimPrefix(argPath, ".") 1657 } 1658 argPath = strings.TrimSuffix(argPath, "Android.mk") 1659 if strings.HasSuffix(argPath, "/") { 1660 argPath = strings.TrimSuffix(argPath, "/") 1661 } 1662 if len(argPath) > 0 && !strings.HasPrefix(argPath, "/") { 1663 argPath = "/" + argPath 1664 } 1665 // get the absolute path of the `Android.mk` file to be converted 1666 absPath := curAbsPath + argPath 1667 return absPath 1668} 1669 1670// check whether a file exists in a filesystem 1671func hasFile(path string, fs pathtools.FileSystem) bool { 1672 ok, _, _ := fs.Exists(path) 1673 return ok 1674} 1675 1676// get the directory where an `Android.bp` file and the property files are expected to locate 1677func getDirFromProperty(mod *parser.Module, property string, fs pathtools.FileSystem, relativePath string) (string, error) { 1678 listValue, ok := getLiteralListPropertyValue(mod, property) 1679 if !ok { 1680 // if do not find 1681 return "", fmt.Errorf("Cannot retrieve the %s.%s property", mod.Type, property) 1682 } 1683 if len(listValue) == 0 { 1684 // if empty 1685 return "", fmt.Errorf("Cannot find the value of the %s.%s property", mod.Type, property) 1686 } 1687 if relativePath == "" { 1688 relativePath = "." 1689 } 1690 _, isDir, _ := fs.Exists(relativePath) 1691 if !isDir { 1692 return "", fmt.Errorf("Cannot find the path %q", relativePath) 1693 } 1694 path := relativePath 1695 for { 1696 if !strings.HasPrefix(listValue[0], "../") { 1697 break 1698 } 1699 path = filepath.Dir(path) 1700 listValue[0] = strings.TrimPrefix(listValue[0], "../") 1701 } 1702 _, isDir, _ = fs.Exists(path) 1703 if !isDir { 1704 return "", fmt.Errorf("Cannot find the path %q", path) 1705 } 1706 return path, nil 1707} 1708 1709// get the path of the `Android.bp` file at the expected location where the property files locate 1710func getPathFromProperty(mod *parser.Module, property string, fs pathtools.FileSystem, relativePath string) (string, bool) { 1711 dir, err := getDirFromProperty(mod, property, fs, relativePath) 1712 if err != nil { 1713 return "", false 1714 } 1715 ok := hasFile(dir+"/Android.bp", fs) 1716 if !ok { 1717 return "", false 1718 } 1719 return dir + "/Android.bp", true 1720} 1721 1722// parse an Android.bp file to get the name of the first module with type of moduleType 1723func getModuleName(path string, moduleType string, fs pathtools.FileSystem) (string, error) { 1724 tree, err := parserPath(path, fs) 1725 if err != nil { 1726 return "", err 1727 } 1728 for _, def := range tree.Defs { 1729 mod, ok := def.(*parser.Module) 1730 if !ok || mod.Type != moduleType { 1731 continue 1732 } 1733 prop, ok := mod.GetProperty("name") 1734 if !ok { 1735 return "", fmt.Errorf("Cannot get the %s."+"name property", mod.Type) 1736 } 1737 propVal, ok := prop.Value.(*parser.String) 1738 if ok { 1739 return propVal.Value, nil 1740 } 1741 } 1742 return "", fmt.Errorf("Cannot find the value of the %s."+"name property", moduleType) 1743} 1744 1745// parse an Android.bp file with the specific path 1746func parserPath(path string, fs pathtools.FileSystem) (tree *parser.File, err error) { 1747 f, err := fs.Open(path) 1748 if err != nil { 1749 return tree, err 1750 } 1751 defer f.Close() 1752 fileContent, _ := ioutil.ReadAll(f) 1753 tree, err = parse(path, bytes.NewBufferString(string(fileContent))) 1754 if err != nil { 1755 return tree, err 1756 } 1757 return tree, nil 1758} 1759 1760// remove the incorrect property that Soong does not support 1761func removeIncorrectProperties(propName string) patchListModFunction { 1762 return removeObsoleteProperty(propName) 1763} 1764 1765// the modules on the same Android.mk file are expected to have the same license 1766func haveSameLicense(f *Fixer) error { 1767 androidLicenseProperties := []string{ 1768 "android_license_kinds", 1769 "android_license_conditions", 1770 "android_license_files", 1771 } 1772 1773 var prevModuleName string 1774 var prevLicenseKindsVals, prevLicenseConditionsVals, prevLicenseFilesVals []string 1775 prevLicenseVals := [][]string{ 1776 prevLicenseKindsVals, 1777 prevLicenseConditionsVals, 1778 prevLicenseFilesVals, 1779 } 1780 1781 for _, def := range f.tree.Defs { 1782 mod, ok := def.(*parser.Module) 1783 if !ok { 1784 continue 1785 } 1786 for idx, property := range androidLicenseProperties { 1787 curModuleName, ok := getLiteralStringPropertyValue(mod, "name") 1788 // some modules in the existing test cases in the androidmk_test.go do not have name property 1789 hasNameProperty := hasProperty(mod, "name") 1790 if hasNameProperty && (!ok || len(curModuleName) == 0) { 1791 return fmt.Errorf("Cannot retrieve the name property of a module of %s type.", mod.Type) 1792 } 1793 curVals, ok := getLiteralListPropertyValue(mod, property) 1794 // some modules in the existing test cases in the androidmk_test.go do not have license-related property 1795 hasLicenseProperty := hasProperty(mod, property) 1796 if hasLicenseProperty && (!ok || len(curVals) == 0) { 1797 // if do not find the property, or no value is found for the property 1798 return fmt.Errorf("Cannot retrieve the %s.%s property", mod.Type, property) 1799 } 1800 if len(prevLicenseVals[idx]) > 0 { 1801 if !reflect.DeepEqual(prevLicenseVals[idx], curVals) { 1802 return fmt.Errorf("Modules %s and %s are expected to have the same %s property.", 1803 prevModuleName, curModuleName, property) 1804 } 1805 } 1806 sort.Strings(curVals) 1807 prevLicenseVals[idx] = curVals 1808 prevModuleName = curModuleName 1809 } 1810 } 1811 return nil 1812} 1813 1814func hasProperty(mod *parser.Module, propName string) bool { 1815 _, ok := mod.GetProperty(propName) 1816 return ok 1817} 1818