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// LOCAL_SRC_FILES := $(LOCAL_MODULE) 557// which occurs often. 558func resolveLocalModule(mod *parser.Module, val parser.Expression) parser.Expression { 559 if varLocalName, ok := val.(*parser.Variable); ok { 560 if varLocalName.Name == "LOCAL_MODULE" { 561 if v, ok := getLiteralStringProperty(mod, "name"); ok { 562 return v 563 } 564 } 565 } 566 return val 567} 568 569// etcPrebuiltModuleUpdate contains information on updating certain parts of a defined module such as: 570// * changing the module type from prebuilt_etc to a different one 571// * stripping the prefix of the install path based on the module type 572// * appending additional boolean properties to the prebuilt module 573type etcPrebuiltModuleUpdate struct { 574 // The prefix of the install path defined in local_module_path. The prefix is removed from local_module_path 575 // before setting the 'filename' attribute. 576 prefix string 577 578 // There is only one prebuilt module type in makefiles. In Soong, there are multiple versions of 579 // prebuilts based on local_module_path. By default, it is "prebuilt_etc" if modType is blank. An 580 // example is if the local_module_path contains $(TARGET_OUT)/usr/share, the module type is 581 // considered as prebuilt_usr_share. 582 modType string 583 584 // Additional boolean attributes to be added in the prebuilt module. Each added boolean attribute 585 // has a value of true. 586 flags []string 587} 588 589func (f etcPrebuiltModuleUpdate) update(m *parser.Module, path string) bool { 590 updated := false 591 if path == f.prefix { 592 updated = true 593 } else if trimmedPath := strings.TrimPrefix(path, f.prefix+"/"); trimmedPath != path { 594 m.Properties = append(m.Properties, &parser.Property{ 595 Name: "relative_install_path", 596 Value: &parser.String{Value: trimmedPath}, 597 }) 598 updated = true 599 } 600 if updated { 601 for _, flag := range f.flags { 602 m.Properties = append(m.Properties, &parser.Property{Name: flag, Value: &parser.Bool{Value: true, Token: "true"}}) 603 } 604 if f.modType != "" { 605 m.Type = f.modType 606 } 607 } 608 return updated 609} 610 611var localModuleUpdate = map[string][]etcPrebuiltModuleUpdate{ 612 "HOST_OUT": { 613 {prefix: "/etc", modType: "prebuilt_etc_host"}, 614 {prefix: "/usr/share", modType: "prebuilt_usr_share_host"}, 615 {prefix: "", modType: "prebuilt_root_host"}, 616 }, 617 "PRODUCT_OUT": {{prefix: "/system/etc"}, {prefix: "/vendor/etc", flags: []string{"proprietary"}}}, 618 "TARGET_OUT": {{prefix: "/usr/share", modType: "prebuilt_usr_share"}, {prefix: "/fonts", modType: "prebuilt_font"}, 619 {prefix: "/etc/firmware", modType: "prebuilt_firmware"}, {prefix: "/vendor/firmware", modType: "prebuilt_firmware", flags: []string{"proprietary"}}, 620 {prefix: "/etc"}}, 621 "TARGET_OUT_ETC": {{prefix: "/firmware", modType: "prebuilt_firmware"}, {prefix: ""}}, 622 "TARGET_OUT_PRODUCT": {{prefix: "/etc", flags: []string{"product_specific"}}, {prefix: "/fonts", modType: "prebuilt_font", flags: []string{"product_specific"}}}, 623 "TARGET_OUT_PRODUCT_ETC": {{prefix: "", flags: []string{"product_specific"}}}, 624 "TARGET_OUT_ODM": {{prefix: "/etc", flags: []string{"device_specific"}}}, 625 "TARGET_OUT_SYSTEM_EXT": {{prefix: "/etc", flags: []string{"system_ext_specific"}}}, 626 "TARGET_OUT_SYSTEM_EXT_ETC": {{prefix: "", flags: []string{"system_ext_specific"}}}, 627 "TARGET_OUT_VENDOR": {{prefix: "/etc", flags: []string{"proprietary"}}, {prefix: "/firmware", modType: "prebuilt_firmware", flags: []string{"proprietary"}}}, 628 "TARGET_OUT_VENDOR_ETC": {{prefix: "", flags: []string{"proprietary"}}}, 629 "TARGET_RECOVERY_ROOT_OUT": {{prefix: "/system/etc", flags: []string{"recovery"}}}, 630} 631 632// rewriteAndroidPrebuiltEtc fixes prebuilt_etc rule 633func rewriteAndroidmkPrebuiltEtc(f *Fixer) error { 634 for _, def := range f.tree.Defs { 635 mod, ok := def.(*parser.Module) 636 if !ok { 637 continue 638 } 639 640 if mod.Type != "prebuilt_etc" && mod.Type != "prebuilt_etc_host" { 641 continue 642 } 643 644 // 'srcs' --> 'src' conversion 645 convertToSingleSource(mod, "src") 646 647 renameProperty(mod, "sub_dir", "relative_install_path") 648 649 // The rewriter converts LOCAL_MODULE_PATH attribute into a struct attribute 650 // 'local_module_path'. Analyze its contents and create the correct sub_dir:, 651 // filename: and boolean attributes combination 652 const local_module_path = "local_module_path" 653 if prop_local_module_path, ok := mod.GetProperty(local_module_path); ok { 654 removeProperty(mod, local_module_path) 655 prefixVariableName := getStringProperty(prop_local_module_path, "var") 656 if moduleUpdates, ok := localModuleUpdate[prefixVariableName]; ok { 657 path := getStringProperty(prop_local_module_path, "fixed") 658 updated := false 659 for i := 0; i < len(moduleUpdates) && !updated; i++ { 660 updated = moduleUpdates[i].update(mod, path) 661 } 662 if !updated { 663 expectedPrefices := "" 664 sep := "" 665 for _, moduleUpdate := range moduleUpdates { 666 expectedPrefices += sep 667 sep = ", " 668 expectedPrefices += moduleUpdate.prefix 669 } 670 return indicateAttributeError(mod, "filename", 671 "LOCAL_MODULE_PATH value under $(%s) should start with %s", prefixVariableName, expectedPrefices) 672 } 673 } else { 674 return indicateAttributeError(mod, "filename", "Cannot handle $(%s) for the prebuilt_etc", prefixVariableName) 675 } 676 } 677 } 678 return nil 679} 680 681func rewriteAndroidTest(f *Fixer) error { 682 for _, def := range f.tree.Defs { 683 mod, ok := def.(*parser.Module) 684 if !ok { 685 // The definition is not a module. 686 continue 687 } 688 if mod.Type != "android_test" && mod.Type != "android_test_helper_app" { 689 // The module is not an android_test or android_test_helper_app. 690 continue 691 } 692 // The rewriter converts LOCAL_MODULE_PATH attribute into a struct attribute 693 // 'local_module_path'. For the android_test module, it should be $(TARGET_OUT_DATA_APPS), 694 // that is, `local_module_path: { var: "TARGET_OUT_DATA_APPS"}` 695 // 1. if the `key: val` pair matches, (key is `local_module_path`, 696 // and val is `{ var: "TARGET_OUT_DATA_APPS"}`), this property is removed; 697 // 2. o/w, an error msg is thrown. 698 const local_module_path = "local_module_path" 699 if prop_local_module_path, ok := mod.GetProperty(local_module_path); ok { 700 removeProperty(mod, local_module_path) 701 prefixVariableName := getStringProperty(prop_local_module_path, "var") 702 path := getStringProperty(prop_local_module_path, "fixed") 703 if prefixVariableName == "TARGET_OUT_DATA_APPS" && path == "" { 704 continue 705 } 706 return indicateAttributeError(mod, "filename", 707 "Only LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS) is allowed for the %s", mod.Type) 708 } 709 } 710 return nil 711} 712 713func rewriteAndroidAppImport(f *Fixer) error { 714 for _, def := range f.tree.Defs { 715 mod, ok := def.(*parser.Module) 716 if !(ok && mod.Type == "android_app_import") { 717 continue 718 } 719 // 'srcs' --> 'apk' conversion 720 convertToSingleSource(mod, "apk") 721 // Handle special certificate value, "PRESIGNED". 722 if cert, ok := mod.GetProperty("certificate"); ok { 723 if certStr, ok := cert.Value.(*parser.String); ok { 724 if certStr.Value == "PRESIGNED" { 725 removeProperty(mod, "certificate") 726 prop := &parser.Property{ 727 Name: "presigned", 728 Value: &parser.Bool{ 729 Value: true, 730 }, 731 } 732 mod.Properties = append(mod.Properties, prop) 733 } 734 } 735 } 736 } 737 return nil 738} 739 740func RewriteRuntimeResourceOverlay(f *Fixer) error { 741 for _, def := range f.tree.Defs { 742 mod, ok := def.(*parser.Module) 743 if !(ok && mod.Type == "runtime_resource_overlay") { 744 continue 745 } 746 // runtime_resource_overlays are always product specific in Make. 747 if _, ok := mod.GetProperty("product_specific"); !ok { 748 prop := &parser.Property{ 749 Name: "product_specific", 750 Value: &parser.Bool{ 751 Value: true, 752 }, 753 } 754 mod.Properties = append(mod.Properties, prop) 755 } 756 } 757 return nil 758} 759 760// Removes library dependencies which are empty (and restricted from usage in Soong) 761func removeEmptyLibDependencies(f *Fixer) error { 762 emptyLibraries := []string{ 763 "libhidltransport", 764 "libhwbinder", 765 } 766 relevantFields := []string{ 767 "export_shared_lib_headers", 768 "export_static_lib_headers", 769 "static_libs", 770 "whole_static_libs", 771 "shared_libs", 772 } 773 for _, def := range f.tree.Defs { 774 mod, ok := def.(*parser.Module) 775 if !ok { 776 continue 777 } 778 for _, field := range relevantFields { 779 listValue, ok := getLiteralListProperty(mod, field) 780 if !ok { 781 continue 782 } 783 newValues := []parser.Expression{} 784 for _, v := range listValue.Values { 785 stringValue, ok := v.(*parser.String) 786 if !ok { 787 return fmt.Errorf("Expecting string for %s.%s fields", mod.Type, field) 788 } 789 if inList(stringValue.Value, emptyLibraries) { 790 continue 791 } 792 newValues = append(newValues, stringValue) 793 } 794 if len(newValues) == 0 && len(listValue.Values) != 0 { 795 removeProperty(mod, field) 796 } else { 797 listValue.Values = newValues 798 } 799 } 800 } 801 return nil 802} 803 804// Removes hidl_interface 'types' which are no longer needed 805func removeHidlInterfaceTypes(f *Fixer) error { 806 for _, def := range f.tree.Defs { 807 mod, ok := def.(*parser.Module) 808 if !(ok && mod.Type == "hidl_interface") { 809 continue 810 } 811 removeProperty(mod, "types") 812 } 813 return nil 814} 815 816func removeSoongConfigBoolVariable(f *Fixer) error { 817 found := map[string]bool{} 818 newDefs := make([]parser.Definition, 0, len(f.tree.Defs)) 819 for _, def := range f.tree.Defs { 820 if mod, ok := def.(*parser.Module); ok && mod.Type == "soong_config_bool_variable" { 821 if name, ok := getLiteralStringPropertyValue(mod, "name"); ok { 822 found[name] = true 823 } else { 824 return fmt.Errorf("Found soong_config_bool_variable without a name") 825 } 826 } else { 827 newDefs = append(newDefs, def) 828 } 829 } 830 f.tree.Defs = newDefs 831 832 if len(found) == 0 { 833 return nil 834 } 835 836 return runPatchListMod(func(mod *parser.Module, buf []byte, patchList *parser.PatchList) error { 837 if mod.Type != "soong_config_module_type" { 838 return nil 839 } 840 841 variables, ok := getLiteralListProperty(mod, "variables") 842 if !ok { 843 return nil 844 } 845 846 boolValues := strings.Builder{} 847 empty := true 848 for _, item := range variables.Values { 849 nameValue, ok := item.(*parser.String) 850 if !ok { 851 empty = false 852 continue 853 } 854 if found[nameValue.Value] { 855 patchList.Add(item.Pos().Offset, item.End().Offset+2, "") 856 857 boolValues.WriteString(`"`) 858 boolValues.WriteString(nameValue.Value) 859 boolValues.WriteString(`",`) 860 } else { 861 empty = false 862 } 863 } 864 if empty { 865 *patchList = parser.PatchList{} 866 867 prop, _ := mod.GetProperty("variables") 868 patchList.Add(prop.Pos().Offset, prop.End().Offset+2, "") 869 } 870 if boolValues.Len() == 0 { 871 return nil 872 } 873 874 boolVariables, ok := getLiteralListProperty(mod, "bool_variables") 875 if ok { 876 patchList.Add(boolVariables.RBracePos.Offset, boolVariables.RBracePos.Offset, ","+boolValues.String()) 877 } else { 878 patchList.Add(variables.RBracePos.Offset+2, variables.RBracePos.Offset+2, 879 fmt.Sprintf(`bool_variables: [%s],`, boolValues.String())) 880 } 881 882 return nil 883 })(f) 884 885 return nil 886} 887 888func removeResourceAndAssetsIfDefault(f *Fixer) error { 889 for _, def := range f.tree.Defs { 890 mod, ok := def.(*parser.Module) 891 if !ok { 892 continue 893 } 894 resourceDirList, resourceDirFound := getLiteralListPropertyValue(mod, "resource_dirs") 895 if resourceDirFound && len(resourceDirList) == 1 && resourceDirList[0] == "res" { 896 removeProperty(mod, "resource_dirs") 897 } 898 assetDirList, assetDirFound := getLiteralListPropertyValue(mod, "asset_dirs") 899 if assetDirFound && len(assetDirList) == 1 && assetDirList[0] == "assets" { 900 removeProperty(mod, "asset_dirs") 901 } 902 } 903 return nil 904} 905 906// Converts the default source list property, 'srcs', to a single source property with a given name. 907// "LOCAL_MODULE" reference is also resolved during the conversion process. 908func convertToSingleSource(mod *parser.Module, srcPropertyName string) { 909 if srcs, ok := mod.GetProperty("srcs"); ok { 910 if srcList, ok := srcs.Value.(*parser.List); ok { 911 removeProperty(mod, "srcs") 912 if len(srcList.Values) == 1 { 913 mod.Properties = append(mod.Properties, 914 &parser.Property{ 915 Name: srcPropertyName, 916 NamePos: srcs.NamePos, 917 ColonPos: srcs.ColonPos, 918 Value: resolveLocalModule(mod, srcList.Values[0])}) 919 } else if len(srcList.Values) > 1 { 920 indicateAttributeError(mod, srcPropertyName, "LOCAL_SRC_FILES should contain at most one item") 921 } 922 } else if _, ok = srcs.Value.(*parser.Variable); ok { 923 removeProperty(mod, "srcs") 924 mod.Properties = append(mod.Properties, 925 &parser.Property{Name: srcPropertyName, 926 NamePos: srcs.NamePos, 927 ColonPos: srcs.ColonPos, 928 Value: resolveLocalModule(mod, srcs.Value)}) 929 } else { 930 renameProperty(mod, "srcs", "apk") 931 } 932 } 933} 934 935type patchListModFunction func(*parser.Module, []byte, *parser.PatchList) error 936 937func runPatchListMod(modFunc patchListModFunction) func(*Fixer) error { 938 return func(f *Fixer) error { 939 // Make sure all the offsets are accurate 940 buf, err := f.reparse() 941 if err != nil { 942 return err 943 } 944 945 var patchlist parser.PatchList 946 for _, def := range f.tree.Defs { 947 mod, ok := def.(*parser.Module) 948 if !ok { 949 continue 950 } 951 952 err := modFunc(mod, buf, &patchlist) 953 if err != nil { 954 return err 955 } 956 } 957 958 newBuf := new(bytes.Buffer) 959 err = patchlist.Apply(bytes.NewReader(buf), newBuf) 960 if err != nil { 961 return err 962 } 963 964 // Save a copy of the buffer to print for errors below 965 bufCopy := append([]byte(nil), newBuf.Bytes()...) 966 967 newTree, err := parse(f.tree.Name, newBuf) 968 if err != nil { 969 return fmt.Errorf("Failed to parse: %v\nBuffer:\n%s", err, string(bufCopy)) 970 } 971 972 f.tree = newTree 973 974 return nil 975 } 976} 977 978var commonPropertyPriorities = []string{ 979 "name", 980 "defaults", 981 "device_supported", 982 "host_supported", 983 "installable", 984} 985 986func reorderCommonProperties(mod *parser.Module, buf []byte, patchlist *parser.PatchList) error { 987 if len(mod.Properties) == 0 { 988 return nil 989 } 990 991 pos := mod.LBracePos.Offset + 1 992 stage := "" 993 994 for _, name := range commonPropertyPriorities { 995 idx := propertyIndex(mod.Properties, name) 996 if idx == -1 { 997 continue 998 } 999 if idx == 0 { 1000 err := patchlist.Add(pos, pos, stage) 1001 if err != nil { 1002 return err 1003 } 1004 stage = "" 1005 1006 pos = mod.Properties[0].End().Offset + 1 1007 mod.Properties = mod.Properties[1:] 1008 continue 1009 } 1010 1011 prop := mod.Properties[idx] 1012 mod.Properties = append(mod.Properties[:idx], mod.Properties[idx+1:]...) 1013 1014 stage += string(buf[prop.Pos().Offset : prop.End().Offset+1]) 1015 1016 err := patchlist.Add(prop.Pos().Offset, prop.End().Offset+2, "") 1017 if err != nil { 1018 return err 1019 } 1020 } 1021 1022 if stage != "" { 1023 err := patchlist.Add(pos, pos, stage) 1024 if err != nil { 1025 return err 1026 } 1027 } 1028 1029 return nil 1030} 1031 1032func removeTags(mod *parser.Module, buf []byte, patchlist *parser.PatchList) error { 1033 prop, ok := mod.GetProperty("tags") 1034 if !ok { 1035 return nil 1036 } 1037 list, ok := prop.Value.(*parser.List) 1038 if !ok { 1039 return nil 1040 } 1041 1042 replaceStr := "" 1043 1044 for _, item := range list.Values { 1045 str, ok := item.(*parser.String) 1046 if !ok { 1047 replaceStr += fmt.Sprintf("// ERROR: Unable to parse tag %q\n", item) 1048 continue 1049 } 1050 1051 switch str.Value { 1052 case "optional": 1053 continue 1054 case "debug": 1055 replaceStr += `// WARNING: Module tags are not supported in Soong. 1056 // Add this module to PRODUCT_PACKAGES_DEBUG in your product file if you want to 1057 // force installation for -userdebug and -eng builds. 1058 ` 1059 case "eng": 1060 replaceStr += `// WARNING: Module tags are not supported in Soong. 1061 // Add this module to PRODUCT_PACKAGES_ENG in your product file if you want to 1062 // force installation for -eng builds. 1063 ` 1064 case "tests": 1065 switch { 1066 case strings.Contains(mod.Type, "cc_test"), 1067 strings.Contains(mod.Type, "cc_library_static"), 1068 strings.Contains(mod.Type, "java_test"), 1069 mod.Type == "android_test", 1070 mod.Type == "android_test_import": 1071 continue 1072 case strings.Contains(mod.Type, "cc_lib"): 1073 replaceStr += `// WARNING: Module tags are not supported in Soong. 1074 // To make a shared library only for tests, use the "cc_test_library" module 1075 // type. If you don't use gtest, set "gtest: false". 1076 ` 1077 case strings.Contains(mod.Type, "cc_bin"): 1078 replaceStr += `// WARNING: Module tags are not supported in Soong. 1079 // For native test binaries, use the "cc_test" module type. Some differences: 1080 // - If you don't use gtest, set "gtest: false" 1081 // - Binaries will be installed into /data/nativetest[64]/<name>/<name> 1082 // - Both 32 & 64 bit versions will be built (as appropriate) 1083 ` 1084 case strings.Contains(mod.Type, "java_lib"): 1085 replaceStr += `// WARNING: Module tags are not supported in Soong. 1086 // For JUnit or similar tests, use the "java_test" module type. A dependency on 1087 // Junit will be added by default, if it is using some other runner, set "junit: false". 1088 ` 1089 case mod.Type == "android_app": 1090 replaceStr += `// WARNING: Module tags are not supported in Soong. 1091 // For JUnit or instrumentataion app tests, use the "android_test" module type. 1092 ` 1093 default: 1094 replaceStr += `// WARNING: Module tags are not supported in Soong. 1095 // In most cases, tests are now identified by their module type: 1096 // cc_test, java_test, python_test 1097 ` 1098 } 1099 default: 1100 replaceStr += fmt.Sprintf("// WARNING: Unknown module tag %q\n", str.Value) 1101 } 1102 } 1103 1104 return patchlist.Add(prop.Pos().Offset, prop.End().Offset+2, replaceStr) 1105} 1106 1107type propertyProvider interface { 1108 GetProperty(string) (*parser.Property, bool) 1109 RemoveProperty(string) bool 1110} 1111 1112func removeNestedProperty(mod *parser.Module, patchList *parser.PatchList, propName string) error { 1113 propNames := strings.Split(propName, ".") 1114 1115 var propProvider, toRemoveFrom propertyProvider 1116 propProvider = mod 1117 1118 var propToRemove *parser.Property 1119 for i, name := range propNames { 1120 p, ok := propProvider.GetProperty(name) 1121 if !ok { 1122 return nil 1123 } 1124 // if this is the inner most element, it's time to delete 1125 if i == len(propNames)-1 { 1126 if propToRemove == nil { 1127 // if we cannot remove the properties that the current property is nested in, 1128 // remove only the current property 1129 propToRemove = p 1130 toRemoveFrom = propProvider 1131 } 1132 1133 // remove the property from the list, in case we remove other properties in this list 1134 toRemoveFrom.RemoveProperty(propToRemove.Name) 1135 // only removing the property would leave blank line(s), remove with a patch 1136 if err := patchList.Add(propToRemove.Pos().Offset, propToRemove.End().Offset+2, ""); err != nil { 1137 return err 1138 } 1139 } else { 1140 propMap, ok := p.Value.(*parser.Map) 1141 if !ok { 1142 return nil 1143 } 1144 if len(propMap.Properties) > 1 { 1145 // if there are other properties in this struct, we need to keep this struct 1146 toRemoveFrom = nil 1147 propToRemove = nil 1148 } else if propToRemove == nil { 1149 // otherwise, we can remove the empty struct entirely 1150 toRemoveFrom = propProvider 1151 propToRemove = p 1152 } 1153 propProvider = propMap 1154 } 1155 } 1156 1157 return nil 1158} 1159 1160func removeObsoleteProperty(propName string) patchListModFunction { 1161 return func(mod *parser.Module, buf []byte, patchList *parser.PatchList) error { 1162 return removeNestedProperty(mod, patchList, propName) 1163 } 1164} 1165 1166func mergeMatchingModuleProperties(mod *parser.Module, buf []byte, patchlist *parser.PatchList) error { 1167 return mergeMatchingProperties(&mod.Properties, buf, patchlist) 1168} 1169 1170func mergeMatchingProperties(properties *[]*parser.Property, buf []byte, patchlist *parser.PatchList) error { 1171 seen := make(map[string]*parser.Property) 1172 for i := 0; i < len(*properties); i++ { 1173 property := (*properties)[i] 1174 if prev, exists := seen[property.Name]; exists { 1175 err := mergeProperties(prev, property, buf, patchlist) 1176 if err != nil { 1177 return err 1178 } 1179 *properties = append((*properties)[:i], (*properties)[i+1:]...) 1180 } else { 1181 seen[property.Name] = property 1182 if mapProperty, ok := property.Value.(*parser.Map); ok { 1183 err := mergeMatchingProperties(&mapProperty.Properties, buf, patchlist) 1184 if err != nil { 1185 return err 1186 } 1187 } 1188 } 1189 } 1190 return nil 1191} 1192 1193func mergeProperties(a, b *parser.Property, buf []byte, patchlist *parser.PatchList) error { 1194 // The value of one of the properties may be a variable reference with no type assigned 1195 // Bail out in this case. Soong will notice duplicate entries and will tell to merge them. 1196 if _, isVar := a.Value.(*parser.Variable); isVar { 1197 return nil 1198 } 1199 if _, isVar := b.Value.(*parser.Variable); isVar { 1200 return nil 1201 } 1202 if a.Value.Type() != b.Value.Type() { 1203 return fmt.Errorf("type mismatch when merging properties %q: %s and %s", a.Name, a.Value.Type(), b.Value.Type()) 1204 } 1205 1206 switch a.Value.Type() { 1207 case parser.StringType: 1208 return fmt.Errorf("conflicting definitions of string property %q", a.Name) 1209 case parser.ListType: 1210 return mergeListProperties(a, b, buf, patchlist) 1211 } 1212 1213 return nil 1214} 1215 1216func mergeListProperties(a, b *parser.Property, buf []byte, patchlist *parser.PatchList) error { 1217 aval, oka := a.Value.(*parser.List) 1218 bval, okb := b.Value.(*parser.List) 1219 if !oka || !okb { 1220 // Merging expressions not supported yet 1221 return nil 1222 } 1223 1224 s := string(buf[bval.LBracePos.Offset+1 : bval.RBracePos.Offset]) 1225 if bval.LBracePos.Line != bval.RBracePos.Line { 1226 if s[0] != '\n' { 1227 panic("expected \n") 1228 } 1229 // If B is a multi line list, skip the first "\n" in case A already has a trailing "\n" 1230 s = s[1:] 1231 } 1232 if aval.LBracePos.Line == aval.RBracePos.Line { 1233 // A is a single line list with no trailing comma 1234 if len(aval.Values) > 0 { 1235 s = "," + s 1236 } 1237 } 1238 1239 err := patchlist.Add(aval.RBracePos.Offset, aval.RBracePos.Offset, s) 1240 if err != nil { 1241 return err 1242 } 1243 err = patchlist.Add(b.NamePos.Offset, b.End().Offset+2, "") 1244 if err != nil { 1245 return err 1246 } 1247 1248 return nil 1249} 1250 1251// removes from <items> every item present in <removals> 1252func filterExpressionList(patchList *parser.PatchList, items *parser.List, removals *parser.List) { 1253 writeIndex := 0 1254 for _, item := range items.Values { 1255 included := true 1256 for _, removal := range removals.Values { 1257 equal, err := parser.ExpressionsAreSame(item, removal) 1258 if err != nil { 1259 continue 1260 } 1261 if equal { 1262 included = false 1263 break 1264 } 1265 } 1266 if included { 1267 items.Values[writeIndex] = item 1268 writeIndex++ 1269 } else { 1270 patchList.Add(item.Pos().Offset, item.End().Offset+2, "") 1271 } 1272 } 1273 items.Values = items.Values[:writeIndex] 1274} 1275 1276// Remove each modules[i].Properties[<legacyName>][j] that matches a modules[i].Properties[<canonicalName>][k] 1277func removeMatchingModuleListProperties(mod *parser.Module, patchList *parser.PatchList, canonicalName string, legacyName string) error { 1278 legacyProp, ok := mod.GetProperty(legacyName) 1279 if !ok { 1280 return nil 1281 } 1282 legacyList, ok := legacyProp.Value.(*parser.List) 1283 if !ok || len(legacyList.Values) == 0 { 1284 return nil 1285 } 1286 canonicalList, ok := getLiteralListProperty(mod, canonicalName) 1287 if !ok { 1288 return nil 1289 } 1290 1291 localPatches := parser.PatchList{} 1292 filterExpressionList(&localPatches, legacyList, canonicalList) 1293 1294 if len(legacyList.Values) == 0 { 1295 patchList.Add(legacyProp.Pos().Offset, legacyProp.End().Offset+2, "") 1296 } else { 1297 for _, p := range localPatches { 1298 patchList.Add(p.Start, p.End, p.Replacement) 1299 } 1300 } 1301 1302 return nil 1303} 1304 1305func hasNonEmptyLiteralListProperty(mod *parser.Module, name string) bool { 1306 list, found := getLiteralListProperty(mod, name) 1307 return found && len(list.Values) > 0 1308} 1309 1310func hasNonEmptyLiteralStringProperty(mod *parser.Module, name string) bool { 1311 s, found := getLiteralStringPropertyValue(mod, name) 1312 return found && len(s) > 0 1313} 1314 1315func getLiteralListProperty(mod *parser.Module, name string) (list *parser.List, found bool) { 1316 prop, ok := mod.GetProperty(name) 1317 if !ok { 1318 return nil, false 1319 } 1320 list, ok = prop.Value.(*parser.List) 1321 return list, ok 1322} 1323 1324func getLiteralListPropertyValue(mod *parser.Module, name string) (list []string, found bool) { 1325 listValue, ok := getLiteralListProperty(mod, name) 1326 if !ok { 1327 return nil, false 1328 } 1329 for _, v := range listValue.Values { 1330 stringValue, ok := v.(*parser.String) 1331 if !ok { 1332 return nil, false 1333 } 1334 list = append(list, stringValue.Value) 1335 } 1336 1337 return list, true 1338} 1339 1340func getLiteralStringProperty(mod *parser.Module, name string) (s *parser.String, found bool) { 1341 prop, ok := mod.GetProperty(name) 1342 if !ok { 1343 return nil, false 1344 } 1345 s, ok = prop.Value.(*parser.String) 1346 return s, ok 1347} 1348 1349func getLiteralStringPropertyValue(mod *parser.Module, name string) (s string, found bool) { 1350 stringValue, ok := getLiteralStringProperty(mod, name) 1351 if !ok { 1352 return "", false 1353 } 1354 1355 return stringValue.Value, true 1356} 1357 1358func getLiteralBoolProperty(mod *parser.Module, name string) (b *parser.Bool, found bool) { 1359 prop, ok := mod.GetProperty(name) 1360 if !ok { 1361 return nil, false 1362 } 1363 b, ok = prop.Value.(*parser.Bool) 1364 return b, ok 1365} 1366 1367func getLiteralBoolPropertyValue(mod *parser.Module, name string) (s bool, found bool) { 1368 boolValue, ok := getLiteralBoolProperty(mod, name) 1369 if !ok { 1370 return false, false 1371 } 1372 1373 return boolValue.Value, true 1374} 1375 1376func propertyIndex(props []*parser.Property, propertyName string) int { 1377 for i, prop := range props { 1378 if prop.Name == propertyName { 1379 return i 1380 } 1381 } 1382 return -1 1383} 1384 1385func renameProperty(mod *parser.Module, from, to string) { 1386 for _, prop := range mod.Properties { 1387 if prop.Name == from { 1388 prop.Name = to 1389 } 1390 } 1391} 1392 1393func removeProperty(mod *parser.Module, propertyName string) { 1394 newList := make([]*parser.Property, 0, len(mod.Properties)) 1395 for _, prop := range mod.Properties { 1396 if prop.Name != propertyName { 1397 newList = append(newList, prop) 1398 } 1399 } 1400 mod.Properties = newList 1401} 1402 1403func inList(s string, list []string) bool { 1404 for _, v := range list { 1405 if s == v { 1406 return true 1407 } 1408 } 1409 return false 1410} 1411 1412func formatFlagProperty(mod *parser.Module, field string, buf []byte, patchlist *parser.PatchList) error { 1413 // the comment or empty lines in the value of the field are skipped 1414 listValue, ok := getLiteralListProperty(mod, field) 1415 if !ok { 1416 // if do not find 1417 return nil 1418 } 1419 for i := 0; i < len(listValue.Values); i++ { 1420 curValue, ok := listValue.Values[i].(*parser.String) 1421 if !ok { 1422 return fmt.Errorf("Expecting string for %s.%s fields", mod.Type, field) 1423 } 1424 if !strings.HasPrefix(curValue.Value, "-") { 1425 return fmt.Errorf("Expecting the string `%s` starting with '-'", curValue.Value) 1426 } 1427 if i+1 < len(listValue.Values) { 1428 nextValue, ok := listValue.Values[i+1].(*parser.String) 1429 if !ok { 1430 return fmt.Errorf("Expecting string for %s.%s fields", mod.Type, field) 1431 } 1432 if !strings.HasPrefix(nextValue.Value, "-") { 1433 // delete the line 1434 err := patchlist.Add(curValue.Pos().Offset, curValue.End().Offset+2, "") 1435 if err != nil { 1436 return err 1437 } 1438 // replace the line 1439 value := "\"" + curValue.Value + " " + nextValue.Value + "\"," 1440 err = patchlist.Add(nextValue.Pos().Offset, nextValue.End().Offset+1, value) 1441 if err != nil { 1442 return err 1443 } 1444 // combined two lines to one 1445 i++ 1446 } 1447 } 1448 } 1449 return nil 1450} 1451 1452func formatFlagProperties(mod *parser.Module, buf []byte, patchlist *parser.PatchList) error { 1453 relevantFields := []string{ 1454 // cc flags 1455 "asflags", 1456 "cflags", 1457 "clang_asflags", 1458 "clang_cflags", 1459 "conlyflags", 1460 "cppflags", 1461 "ldflags", 1462 "tidy_flags", 1463 // java flags 1464 "aaptflags", 1465 "dxflags", 1466 "javacflags", 1467 "kotlincflags", 1468 } 1469 for _, field := range relevantFields { 1470 err := formatFlagProperty(mod, field, buf, patchlist) 1471 if err != nil { 1472 return err 1473 } 1474 } 1475 return nil 1476} 1477 1478func rewriteLicenseProperty(fs pathtools.FileSystem, relativePath string) patchListModFunction { 1479 return func(mod *parser.Module, buf []byte, patchList *parser.PatchList) error { 1480 return rewriteLicenseProperties(mod, patchList, fs, relativePath) 1481 } 1482} 1483 1484// rewrite the "android_license_kinds" and "android_license_files" properties to a package module 1485// (and a license module when needed). 1486func rewriteLicenseProperties(mod *parser.Module, patchList *parser.PatchList, fs pathtools.FileSystem, 1487 relativePath string) error { 1488 // if a package module has been added, no more action is needed. 1489 for _, patch := range *patchList { 1490 if strings.Contains(patch.Replacement, "package {") { 1491 return nil 1492 } 1493 } 1494 1495 // initial the fs 1496 if fs == nil { 1497 fs = pathtools.NewOsFs(os.Getenv("ANDROID_BUILD_TOP")) 1498 } 1499 1500 // initial the relativePath 1501 if len(relativePath) == 0 { 1502 relativePath = getModuleRelativePath() 1503 } 1504 // validate the relativePath 1505 ok := hasFile(relativePath+"/Android.mk", fs) 1506 // some modules in the existing test cases in the androidmk_test.go do not have a valid path 1507 if !ok && len(relativePath) > 0 { 1508 return fmt.Errorf("Cannot find an Android.mk file at path %q", relativePath) 1509 } 1510 1511 licenseKindsPropertyName := "android_license_kinds" 1512 licenseFilesPropertyName := "android_license_files" 1513 1514 androidBpFileErr := "// Error: No Android.bp file is found at path\n" + 1515 "// %s\n" + 1516 "// Please add one there with the needed license module first.\n" + 1517 "// Then reset the default_applicable_licenses property below with the license module name.\n" 1518 licenseModuleErr := "// Error: Cannot get the name of the license module in the\n" + 1519 "// %s file.\n" + 1520 "// If no such license module exists, please add one there first.\n" + 1521 "// Then reset the default_applicable_licenses property below with the license module name.\n" 1522 1523 defaultApplicableLicense := "Android-Apache-2.0" 1524 var licenseModuleName, licensePatch string 1525 var hasFileInParentDir bool 1526 1527 // when LOCAL_NOTICE_FILE is not empty 1528 if hasNonEmptyLiteralListProperty(mod, licenseFilesPropertyName) { 1529 hasFileInParentDir = hasValueStartWithTwoDotsLiteralList(mod, licenseFilesPropertyName) 1530 // if have LOCAL_NOTICE_FILE outside the current directory, need to find and refer to the license 1531 // module in the LOCAL_NOTICE_FILE location directly and no new license module needs to be created 1532 if hasFileInParentDir { 1533 bpPath, ok := getPathFromProperty(mod, licenseFilesPropertyName, fs, relativePath) 1534 if !ok { 1535 bpDir, err := getDirFromProperty(mod, licenseFilesPropertyName, fs, relativePath) 1536 if err != nil { 1537 return err 1538 } 1539 licensePatch += fmt.Sprintf(androidBpFileErr, bpDir) 1540 defaultApplicableLicense = "" 1541 } else { 1542 licenseModuleName, _ = getModuleName(bpPath, "license", fs) 1543 if len(licenseModuleName) == 0 { 1544 licensePatch += fmt.Sprintf(licenseModuleErr, bpPath) 1545 } 1546 defaultApplicableLicense = licenseModuleName 1547 } 1548 } else { 1549 // if have LOCAL_NOTICE_FILE in the current directory, need to create a new license module 1550 if len(relativePath) == 0 { 1551 return fmt.Errorf("Cannot obtain the relative path of the Android.mk file") 1552 } 1553 licenseModuleName = strings.Replace(relativePath, "/", "_", -1) + "_license" 1554 defaultApplicableLicense = licenseModuleName 1555 } 1556 } 1557 1558 //add the package module 1559 if hasNonEmptyLiteralListProperty(mod, licenseKindsPropertyName) { 1560 licensePatch += "package {\n" + 1561 " // See: http://go/android-license-faq\n" + 1562 " default_applicable_licenses: [\n" + 1563 " \"" + defaultApplicableLicense + "\",\n" + 1564 " ],\n" + 1565 "}\n" + 1566 "\n" 1567 } 1568 1569 // append the license module when necessary 1570 // when LOCAL_NOTICE_FILE is not empty and in the current directory, create a new license module 1571 // otherwise, use the above default license directly 1572 if hasNonEmptyLiteralListProperty(mod, licenseFilesPropertyName) && !hasFileInParentDir { 1573 licenseKinds, err := mergeLiteralListPropertyValue(mod, licenseKindsPropertyName) 1574 if err != nil { 1575 return err 1576 } 1577 licenseFiles, err := mergeLiteralListPropertyValue(mod, licenseFilesPropertyName) 1578 if err != nil { 1579 return err 1580 } 1581 licensePatch += "license {\n" + 1582 " name: \"" + licenseModuleName + "\",\n" + 1583 " visibility: [\":__subpackages__\"],\n" + 1584 " license_kinds: [\n" + 1585 licenseKinds + 1586 " ],\n" + 1587 " license_text: [\n" + 1588 licenseFiles + 1589 " ],\n" + 1590 "}\n" + 1591 "\n" 1592 } 1593 1594 // add to the patchList 1595 pos := mod.Pos().Offset 1596 err := patchList.Add(pos, pos, licensePatch) 1597 if err != nil { 1598 return err 1599 } 1600 return nil 1601} 1602 1603// merge the string vaules in a list property of a module into one string with expected format 1604func mergeLiteralListPropertyValue(mod *parser.Module, property string) (s string, err error) { 1605 listValue, ok := getLiteralListPropertyValue(mod, property) 1606 if !ok { 1607 // if do not find 1608 return "", fmt.Errorf("Cannot retrieve the %s.%s field", mod.Type, property) 1609 } 1610 for i := 0; i < len(listValue); i++ { 1611 s += " \"" + listValue[i] + "\",\n" 1612 } 1613 return s, nil 1614} 1615 1616// check whether a string list property has any value starting with `../` 1617func hasValueStartWithTwoDotsLiteralList(mod *parser.Module, property string) bool { 1618 listValue, ok := getLiteralListPropertyValue(mod, property) 1619 if ok { 1620 for i := 0; i < len(listValue); i++ { 1621 if strings.HasPrefix(listValue[i], "../") { 1622 return true 1623 } 1624 } 1625 } 1626 return false 1627} 1628 1629// get the relative path from ANDROID_BUILD_TOP to the Android.mk file to be converted 1630func getModuleRelativePath() string { 1631 // get the absolute path of the top of the tree 1632 rootPath := os.Getenv("ANDROID_BUILD_TOP") 1633 // get the absolute path of the `Android.mk` file to be converted 1634 absPath := getModuleAbsolutePath() 1635 // get the relative path of the `Android.mk` file to top of the tree 1636 relModulePath, err := filepath.Rel(rootPath, absPath) 1637 if err != nil { 1638 return "" 1639 } 1640 return relModulePath 1641} 1642 1643// get the absolute path of the Android.mk file to be converted 1644func getModuleAbsolutePath() string { 1645 // get the absolute path at where the `androidmk` commend is executed 1646 curAbsPath, err := filepath.Abs(".") 1647 if err != nil { 1648 return "" 1649 } 1650 // the argument for the `androidmk` command could be 1651 // 1. "./a/b/c/Android.mk"; 2. "a/b/c/Android.mk"; 3. "Android.mk" 1652 argPath := flag.Arg(0) 1653 if strings.HasPrefix(argPath, "./") { 1654 argPath = strings.TrimPrefix(argPath, ".") 1655 } 1656 argPath = strings.TrimSuffix(argPath, "Android.mk") 1657 if strings.HasSuffix(argPath, "/") { 1658 argPath = strings.TrimSuffix(argPath, "/") 1659 } 1660 if len(argPath) > 0 && !strings.HasPrefix(argPath, "/") { 1661 argPath = "/" + argPath 1662 } 1663 // get the absolute path of the `Android.mk` file to be converted 1664 absPath := curAbsPath + argPath 1665 return absPath 1666} 1667 1668// check whether a file exists in a filesystem 1669func hasFile(path string, fs pathtools.FileSystem) bool { 1670 ok, _, _ := fs.Exists(path) 1671 return ok 1672} 1673 1674// get the directory where an `Android.bp` file and the property files are expected to locate 1675func getDirFromProperty(mod *parser.Module, property string, fs pathtools.FileSystem, relativePath string) (string, error) { 1676 listValue, ok := getLiteralListPropertyValue(mod, property) 1677 if !ok { 1678 // if do not find 1679 return "", fmt.Errorf("Cannot retrieve the %s.%s property", mod.Type, property) 1680 } 1681 if len(listValue) == 0 { 1682 // if empty 1683 return "", fmt.Errorf("Cannot find the value of the %s.%s property", mod.Type, property) 1684 } 1685 if relativePath == "" { 1686 relativePath = "." 1687 } 1688 _, isDir, _ := fs.Exists(relativePath) 1689 if !isDir { 1690 return "", fmt.Errorf("Cannot find the path %q", relativePath) 1691 } 1692 path := relativePath 1693 for { 1694 if !strings.HasPrefix(listValue[0], "../") { 1695 break 1696 } 1697 path = filepath.Dir(path) 1698 listValue[0] = strings.TrimPrefix(listValue[0], "../") 1699 } 1700 _, isDir, _ = fs.Exists(path) 1701 if !isDir { 1702 return "", fmt.Errorf("Cannot find the path %q", path) 1703 } 1704 return path, nil 1705} 1706 1707// get the path of the `Android.bp` file at the expected location where the property files locate 1708func getPathFromProperty(mod *parser.Module, property string, fs pathtools.FileSystem, relativePath string) (string, bool) { 1709 dir, err := getDirFromProperty(mod, property, fs, relativePath) 1710 if err != nil { 1711 return "", false 1712 } 1713 ok := hasFile(dir+"/Android.bp", fs) 1714 if !ok { 1715 return "", false 1716 } 1717 return dir + "/Android.bp", true 1718} 1719 1720// parse an Android.bp file to get the name of the first module with type of moduleType 1721func getModuleName(path string, moduleType string, fs pathtools.FileSystem) (string, error) { 1722 tree, err := parserPath(path, fs) 1723 if err != nil { 1724 return "", err 1725 } 1726 for _, def := range tree.Defs { 1727 mod, ok := def.(*parser.Module) 1728 if !ok || mod.Type != moduleType { 1729 continue 1730 } 1731 prop, ok := mod.GetProperty("name") 1732 if !ok { 1733 return "", fmt.Errorf("Cannot get the %s."+"name property", mod.Type) 1734 } 1735 propVal, ok := prop.Value.(*parser.String) 1736 if ok { 1737 return propVal.Value, nil 1738 } 1739 } 1740 return "", fmt.Errorf("Cannot find the value of the %s."+"name property", moduleType) 1741} 1742 1743// parse an Android.bp file with the specific path 1744func parserPath(path string, fs pathtools.FileSystem) (tree *parser.File, err error) { 1745 f, err := fs.Open(path) 1746 if err != nil { 1747 return tree, err 1748 } 1749 defer f.Close() 1750 fileContent, _ := ioutil.ReadAll(f) 1751 tree, err = parse(path, bytes.NewBufferString(string(fileContent))) 1752 if err != nil { 1753 return tree, err 1754 } 1755 return tree, nil 1756} 1757 1758// remove the incorrect property that Soong does not support 1759func removeIncorrectProperties(propName string) patchListModFunction { 1760 return removeObsoleteProperty(propName) 1761} 1762 1763// the modules on the same Android.mk file are expected to have the same license 1764func haveSameLicense(f *Fixer) error { 1765 androidLicenseProperties := []string{ 1766 "android_license_kinds", 1767 "android_license_conditions", 1768 "android_license_files", 1769 } 1770 1771 var prevModuleName string 1772 var prevLicenseKindsVals, prevLicenseConditionsVals, prevLicenseFilesVals []string 1773 prevLicenseVals := [][]string{ 1774 prevLicenseKindsVals, 1775 prevLicenseConditionsVals, 1776 prevLicenseFilesVals, 1777 } 1778 1779 for _, def := range f.tree.Defs { 1780 mod, ok := def.(*parser.Module) 1781 if !ok { 1782 continue 1783 } 1784 for idx, property := range androidLicenseProperties { 1785 curModuleName, ok := getLiteralStringPropertyValue(mod, "name") 1786 // some modules in the existing test cases in the androidmk_test.go do not have name property 1787 hasNameProperty := hasProperty(mod, "name") 1788 if hasNameProperty && (!ok || len(curModuleName) == 0) { 1789 return fmt.Errorf("Cannot retrieve the name property of a module of %s type.", mod.Type) 1790 } 1791 curVals, ok := getLiteralListPropertyValue(mod, property) 1792 // some modules in the existing test cases in the androidmk_test.go do not have license-related property 1793 hasLicenseProperty := hasProperty(mod, property) 1794 if hasLicenseProperty && (!ok || len(curVals) == 0) { 1795 // if do not find the property, or no value is found for the property 1796 return fmt.Errorf("Cannot retrieve the %s.%s property", mod.Type, property) 1797 } 1798 if len(prevLicenseVals[idx]) > 0 { 1799 if !reflect.DeepEqual(prevLicenseVals[idx], curVals) { 1800 return fmt.Errorf("Modules %s and %s are expected to have the same %s property.", 1801 prevModuleName, curModuleName, property) 1802 } 1803 } 1804 sort.Strings(curVals) 1805 prevLicenseVals[idx] = curVals 1806 prevModuleName = curModuleName 1807 } 1808 } 1809 return nil 1810} 1811 1812func hasProperty(mod *parser.Module, propName string) bool { 1813 _, ok := mod.GetProperty(propName) 1814 return ok 1815} 1816