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 15package main 16 17import ( 18 mkparser "android/soong/androidmk/parser" 19 "fmt" 20 "sort" 21 "strings" 22 23 bpparser "github.com/google/blueprint/parser" 24) 25 26const ( 27 clear_vars = "__android_mk_clear_vars" 28 include_ignored = "__android_mk_include_ignored" 29) 30 31type bpVariable struct { 32 name string 33 variableType bpparser.Type 34} 35 36type variableAssignmentContext struct { 37 file *bpFile 38 prefix string 39 mkvalue *mkparser.MakeString 40 append bool 41} 42 43var rewriteProperties = map[string](func(variableAssignmentContext) error){ 44 // custom functions 45 "LOCAL_AIDL_INCLUDES": localAidlIncludes, 46 "LOCAL_C_INCLUDES": localIncludeDirs, 47 "LOCAL_EXPORT_C_INCLUDE_DIRS": exportIncludeDirs, 48 "LOCAL_LDFLAGS": ldflags, 49 "LOCAL_MODULE_CLASS": prebuiltClass, 50 "LOCAL_MODULE_STEM": stem, 51 "LOCAL_MODULE_HOST_OS": hostOs, 52 "LOCAL_SANITIZE": sanitize(""), 53 "LOCAL_SANITIZE_DIAG": sanitize("diag."), 54 "LOCAL_CFLAGS": cflags, 55 "LOCAL_UNINSTALLABLE_MODULE": invert("installable"), 56 "LOCAL_PROGUARD_ENABLED": proguardEnabled, 57 58 // composite functions 59 "LOCAL_MODULE_TAGS": includeVariableIf(bpVariable{"tags", bpparser.ListType}, not(valueDumpEquals("optional"))), 60 61 // skip functions 62 "LOCAL_ADDITIONAL_DEPENDENCIES": skip, // TODO: check for only .mk files? 63 "LOCAL_CPP_EXTENSION": skip, 64 "LOCAL_MODULE_SUFFIX": skip, // TODO 65 "LOCAL_PATH": skip, // Nothing to do, except maybe avoid the "./" in paths? 66 "LOCAL_PRELINK_MODULE": skip, // Already phased out 67 "LOCAL_BUILT_MODULE_STEM": skip, 68 "LOCAL_USE_AAPT2": skip, // Always enabled in Soong 69 "LOCAL_JAR_EXCLUDE_FILES": skip, // Soong never excludes files from jars 70} 71 72// adds a group of properties all having the same type 73func addStandardProperties(propertyType bpparser.Type, properties map[string]string) { 74 for key, val := range properties { 75 rewriteProperties[key] = includeVariable(bpVariable{val, propertyType}) 76 } 77} 78 79func init() { 80 addStandardProperties(bpparser.StringType, 81 map[string]string{ 82 "LOCAL_MODULE": "name", 83 "LOCAL_CXX_STL": "stl", 84 "LOCAL_STRIP_MODULE": "strip", 85 "LOCAL_MULTILIB": "compile_multilib", 86 "LOCAL_ARM_MODE_HACK": "instruction_set", 87 "LOCAL_SDK_VERSION": "sdk_version", 88 "LOCAL_NDK_STL_VARIANT": "stl", 89 "LOCAL_JAR_MANIFEST": "manifest", 90 "LOCAL_JARJAR_RULES": "jarjar_rules", 91 "LOCAL_CERTIFICATE": "certificate", 92 "LOCAL_PACKAGE_NAME": "name", 93 "LOCAL_MODULE_RELATIVE_PATH": "relative_install_path", 94 "LOCAL_PROTOC_OPTIMIZE_TYPE": "proto.type", 95 "LOCAL_MODULE_OWNER": "owner", 96 "LOCAL_RENDERSCRIPT_TARGET_API": "renderscript.target_api", 97 "LOCAL_NOTICE_FILE": "notice", 98 "LOCAL_JAVA_LANGUAGE_VERSION": "java_version", 99 "LOCAL_INSTRUMENTATION_FOR": "instrumentation_for", 100 "LOCAL_MANIFEST_FILE": "manifest", 101 102 "LOCAL_DEX_PREOPT_PROFILE_CLASS_LISTING": "dex_preopt.profile", 103 }) 104 addStandardProperties(bpparser.ListType, 105 map[string]string{ 106 "LOCAL_SRC_FILES": "srcs", 107 "LOCAL_SRC_FILES_EXCLUDE": "exclude_srcs", 108 "LOCAL_HEADER_LIBRARIES": "header_libs", 109 "LOCAL_SHARED_LIBRARIES": "shared_libs", 110 "LOCAL_STATIC_LIBRARIES": "static_libs", 111 "LOCAL_WHOLE_STATIC_LIBRARIES": "whole_static_libs", 112 "LOCAL_SYSTEM_SHARED_LIBRARIES": "system_shared_libs", 113 "LOCAL_ASFLAGS": "asflags", 114 "LOCAL_CLANG_ASFLAGS": "clang_asflags", 115 "LOCAL_CONLYFLAGS": "conlyflags", 116 "LOCAL_CPPFLAGS": "cppflags", 117 "LOCAL_REQUIRED_MODULES": "required", 118 "LOCAL_OVERRIDES_MODULES": "overrides", 119 "LOCAL_LDLIBS": "host_ldlibs", 120 "LOCAL_CLANG_CFLAGS": "clang_cflags", 121 "LOCAL_YACCFLAGS": "yaccflags", 122 "LOCAL_SANITIZE_RECOVER": "sanitize.recover", 123 "LOCAL_LOGTAGS_FILES": "logtags", 124 "LOCAL_EXPORT_HEADER_LIBRARY_HEADERS": "export_header_lib_headers", 125 "LOCAL_EXPORT_SHARED_LIBRARY_HEADERS": "export_shared_lib_headers", 126 "LOCAL_EXPORT_STATIC_LIBRARY_HEADERS": "export_static_lib_headers", 127 "LOCAL_INIT_RC": "init_rc", 128 "LOCAL_TIDY_FLAGS": "tidy_flags", 129 // TODO: This is comma-separated, not space-separated 130 "LOCAL_TIDY_CHECKS": "tidy_checks", 131 "LOCAL_RENDERSCRIPT_INCLUDES": "renderscript.include_dirs", 132 "LOCAL_RENDERSCRIPT_FLAGS": "renderscript.flags", 133 134 "LOCAL_JAVA_RESOURCE_DIRS": "java_resource_dirs", 135 "LOCAL_RESOURCE_DIR": "resource_dirs", 136 "LOCAL_JAVACFLAGS": "javacflags", 137 "LOCAL_ERROR_PRONE_FLAGS": "errorprone.javacflags", 138 "LOCAL_DX_FLAGS": "dxflags", 139 "LOCAL_JAVA_LIBRARIES": "libs", 140 "LOCAL_STATIC_JAVA_LIBRARIES": "static_libs", 141 "LOCAL_AAPT_FLAGS": "aaptflags", 142 "LOCAL_PACKAGE_SPLITS": "package_splits", 143 "LOCAL_COMPATIBILITY_SUITE": "test_suites", 144 145 "LOCAL_ANNOTATION_PROCESSORS": "annotation_processors", 146 "LOCAL_ANNOTATION_PROCESSOR_CLASSES": "annotation_processor_classes", 147 148 "LOCAL_PROGUARD_FLAGS": "optimize.proguard_flags", 149 "LOCAL_PROGUARD_FLAG_FILES": "optimize.proguard_flag_files", 150 151 // These will be rewritten to libs/static_libs by bpfix, after their presence is used to convert 152 // java_library_static to android_library. 153 "LOCAL_SHARED_ANDROID_LIBRARIES": "android_libs", 154 "LOCAL_STATIC_ANDROID_LIBRARIES": "android_static_libs", 155 }) 156 157 addStandardProperties(bpparser.BoolType, 158 map[string]string{ 159 // Bool properties 160 "LOCAL_IS_HOST_MODULE": "host", 161 "LOCAL_CLANG": "clang", 162 "LOCAL_FORCE_STATIC_EXECUTABLE": "static_executable", 163 "LOCAL_NATIVE_COVERAGE": "native_coverage", 164 "LOCAL_NO_CRT": "nocrt", 165 "LOCAL_ALLOW_UNDEFINED_SYMBOLS": "allow_undefined_symbols", 166 "LOCAL_RTTI_FLAG": "rtti", 167 "LOCAL_NO_STANDARD_LIBRARIES": "no_standard_libs", 168 "LOCAL_PACK_MODULE_RELOCATIONS": "pack_relocations", 169 "LOCAL_TIDY": "tidy", 170 "LOCAL_PROPRIETARY_MODULE": "proprietary", 171 "LOCAL_VENDOR_MODULE": "vendor", 172 "LOCAL_ODM_MODULE": "device_specific", 173 "LOCAL_PRODUCT_MODULE": "product_specific", 174 "LOCAL_EXPORT_PACKAGE_RESOURCES": "export_package_resources", 175 "LOCAL_PRIVILEGED_MODULE": "privileged", 176 177 "LOCAL_DEX_PREOPT": "dex_preopt.enabled", 178 "LOCAL_DEX_PREOPT_APP_IMAGE": "dex_preopt.app_image", 179 "LOCAL_DEX_PREOPT_GENERATE_PROFILE": "dex_preopt.profile_guided", 180 }) 181} 182 183type listSplitFunc func(bpparser.Expression) (string, bpparser.Expression, error) 184 185func emptyList(value bpparser.Expression) bool { 186 if list, ok := value.(*bpparser.List); ok { 187 return len(list.Values) == 0 188 } 189 return false 190} 191 192func splitBpList(val bpparser.Expression, keyFunc listSplitFunc) (lists map[string]bpparser.Expression, err error) { 193 lists = make(map[string]bpparser.Expression) 194 195 switch val := val.(type) { 196 case *bpparser.Operator: 197 listsA, err := splitBpList(val.Args[0], keyFunc) 198 if err != nil { 199 return nil, err 200 } 201 202 listsB, err := splitBpList(val.Args[1], keyFunc) 203 if err != nil { 204 return nil, err 205 } 206 207 for k, v := range listsA { 208 if !emptyList(v) { 209 lists[k] = v 210 } 211 } 212 213 for k, vB := range listsB { 214 if emptyList(vB) { 215 continue 216 } 217 218 if vA, ok := lists[k]; ok { 219 expression := val.Copy().(*bpparser.Operator) 220 expression.Args = [2]bpparser.Expression{vA, vB} 221 lists[k] = expression 222 } else { 223 lists[k] = vB 224 } 225 } 226 case *bpparser.Variable: 227 key, value, err := keyFunc(val) 228 if err != nil { 229 return nil, err 230 } 231 if value.Type() == bpparser.ListType { 232 lists[key] = value 233 } else { 234 lists[key] = &bpparser.List{ 235 Values: []bpparser.Expression{value}, 236 } 237 } 238 case *bpparser.List: 239 for _, v := range val.Values { 240 key, value, err := keyFunc(v) 241 if err != nil { 242 return nil, err 243 } 244 l := lists[key] 245 if l == nil { 246 l = &bpparser.List{} 247 } 248 l.(*bpparser.List).Values = append(l.(*bpparser.List).Values, value) 249 lists[key] = l 250 } 251 default: 252 panic(fmt.Errorf("unexpected type %t", val)) 253 } 254 255 return lists, nil 256} 257 258// classifyLocalOrGlobalPath tells whether a file path should be interpreted relative to the current module (local) 259// or relative to the root of the source checkout (global) 260func classifyLocalOrGlobalPath(value bpparser.Expression) (string, bpparser.Expression, error) { 261 switch v := value.(type) { 262 case *bpparser.Variable: 263 if v.Name == "LOCAL_PATH" { 264 return "local", &bpparser.String{ 265 Value: ".", 266 }, nil 267 } else { 268 // TODO: Should we split variables? 269 return "global", value, nil 270 } 271 case *bpparser.Operator: 272 if v.Type() != bpparser.StringType { 273 return "", nil, fmt.Errorf("classifyLocalOrGlobalPath expected a string, got %s", v.Type()) 274 } 275 276 if v.Operator != '+' { 277 return "global", value, nil 278 } 279 280 firstOperand := v.Args[0] 281 secondOperand := v.Args[1] 282 if firstOperand.Type() != bpparser.StringType { 283 return "global", value, nil 284 } 285 286 if _, ok := firstOperand.(*bpparser.Operator); ok { 287 return "global", value, nil 288 } 289 290 if variable, ok := firstOperand.(*bpparser.Variable); !ok || variable.Name != "LOCAL_PATH" { 291 return "global", value, nil 292 } 293 294 local := secondOperand 295 if s, ok := secondOperand.(*bpparser.String); ok { 296 if strings.HasPrefix(s.Value, "/") { 297 s.Value = s.Value[1:] 298 } 299 } 300 return "local", local, nil 301 case *bpparser.String: 302 return "global", value, nil 303 default: 304 return "", nil, fmt.Errorf("classifyLocalOrGlobalPath expected a string, got %s", v.Type()) 305 306 } 307} 308 309func sortedMapKeys(inputMap map[string]string) (sortedKeys []string) { 310 keys := make([]string, 0, len(inputMap)) 311 for key := range inputMap { 312 keys = append(keys, key) 313 } 314 sort.Strings(keys) 315 return keys 316} 317 318// splitAndAssign splits a Make list into components and then 319// creates the corresponding variable assignments. 320func splitAndAssign(ctx variableAssignmentContext, splitFunc listSplitFunc, namesByClassification map[string]string) error { 321 val, err := makeVariableToBlueprint(ctx.file, ctx.mkvalue, bpparser.ListType) 322 if err != nil { 323 return err 324 } 325 326 lists, err := splitBpList(val, splitFunc) 327 if err != nil { 328 return err 329 } 330 331 for _, nameClassification := range sortedMapKeys(namesByClassification) { 332 name := namesByClassification[nameClassification] 333 if component, ok := lists[nameClassification]; ok && !emptyList(component) { 334 err = setVariable(ctx.file, ctx.append, ctx.prefix, name, component, true) 335 if err != nil { 336 return err 337 } 338 } 339 } 340 return nil 341} 342 343func localIncludeDirs(ctx variableAssignmentContext) error { 344 return splitAndAssign(ctx, classifyLocalOrGlobalPath, map[string]string{"global": "include_dirs", "local": "local_include_dirs"}) 345} 346 347func exportIncludeDirs(ctx variableAssignmentContext) error { 348 // Add any paths that could not be converted to local relative paths to export_include_dirs 349 // anyways, they will cause an error if they don't exist and can be fixed manually. 350 return splitAndAssign(ctx, classifyLocalOrGlobalPath, map[string]string{"global": "export_include_dirs", "local": "export_include_dirs"}) 351} 352 353func localAidlIncludes(ctx variableAssignmentContext) error { 354 return splitAndAssign(ctx, classifyLocalOrGlobalPath, map[string]string{"global": "aidl.include_dirs", "local": "aidl.local_include_dirs"}) 355} 356 357func stem(ctx variableAssignmentContext) error { 358 val, err := makeVariableToBlueprint(ctx.file, ctx.mkvalue, bpparser.StringType) 359 if err != nil { 360 return err 361 } 362 varName := "stem" 363 364 if exp, ok := val.(*bpparser.Operator); ok && exp.Operator == '+' { 365 if variable, ok := exp.Args[0].(*bpparser.Variable); ok && variable.Name == "LOCAL_MODULE" { 366 varName = "suffix" 367 val = exp.Args[1] 368 } 369 } 370 371 return setVariable(ctx.file, ctx.append, ctx.prefix, varName, val, true) 372} 373 374func hostOs(ctx variableAssignmentContext) error { 375 val, err := makeVariableToBlueprint(ctx.file, ctx.mkvalue, bpparser.ListType) 376 if err != nil { 377 return err 378 } 379 380 inList := func(s string) bool { 381 for _, v := range val.(*bpparser.List).Values { 382 if v.(*bpparser.String).Value == s { 383 return true 384 } 385 } 386 return false 387 } 388 389 falseValue := &bpparser.Bool{ 390 Value: false, 391 } 392 393 trueValue := &bpparser.Bool{ 394 Value: true, 395 } 396 397 if inList("windows") { 398 err = setVariable(ctx.file, ctx.append, "target.windows", "enabled", trueValue, true) 399 } 400 401 if !inList("linux") && err == nil { 402 err = setVariable(ctx.file, ctx.append, "target.linux_glibc", "enabled", falseValue, true) 403 } 404 405 if !inList("darwin") && err == nil { 406 err = setVariable(ctx.file, ctx.append, "target.darwin", "enabled", falseValue, true) 407 } 408 409 return err 410} 411 412func sanitize(sub string) func(ctx variableAssignmentContext) error { 413 return func(ctx variableAssignmentContext) error { 414 val, err := makeVariableToBlueprint(ctx.file, ctx.mkvalue, bpparser.ListType) 415 if err != nil { 416 return err 417 } 418 419 if _, ok := val.(*bpparser.List); !ok { 420 return fmt.Errorf("unsupported sanitize expression") 421 } 422 423 misc := &bpparser.List{} 424 425 for _, v := range val.(*bpparser.List).Values { 426 switch v := v.(type) { 427 case *bpparser.Variable, *bpparser.Operator: 428 ctx.file.errorf(ctx.mkvalue, "unsupported sanitize expression") 429 case *bpparser.String: 430 switch v.Value { 431 case "never", "address", "coverage", "thread", "undefined", "cfi": 432 bpTrue := &bpparser.Bool{ 433 Value: true, 434 } 435 err = setVariable(ctx.file, false, ctx.prefix, "sanitize."+sub+v.Value, bpTrue, true) 436 if err != nil { 437 return err 438 } 439 default: 440 misc.Values = append(misc.Values, v) 441 } 442 default: 443 return fmt.Errorf("sanitize expected a string, got %s", v.Type()) 444 } 445 } 446 447 if len(misc.Values) > 0 { 448 err = setVariable(ctx.file, false, ctx.prefix, "sanitize."+sub+"misc_undefined", misc, true) 449 if err != nil { 450 return err 451 } 452 } 453 454 return err 455 } 456} 457 458func prebuiltClass(ctx variableAssignmentContext) error { 459 class := ctx.mkvalue.Value(ctx.file.scope) 460 if v, ok := prebuiltTypes[class]; ok { 461 ctx.file.scope.Set("BUILD_PREBUILT", v) 462 } else { 463 // reset to default 464 ctx.file.scope.Set("BUILD_PREBUILT", "prebuilt") 465 } 466 return nil 467} 468 469func ldflags(ctx variableAssignmentContext) error { 470 val, err := makeVariableToBlueprint(ctx.file, ctx.mkvalue, bpparser.ListType) 471 if err != nil { 472 return err 473 } 474 475 lists, err := splitBpList(val, func(value bpparser.Expression) (string, bpparser.Expression, error) { 476 // Anything other than "-Wl,--version_script," + LOCAL_PATH + "<path>" matches ldflags 477 exp1, ok := value.(*bpparser.Operator) 478 if !ok { 479 return "ldflags", value, nil 480 } 481 482 exp2, ok := exp1.Args[0].(*bpparser.Operator) 483 if !ok { 484 return "ldflags", value, nil 485 } 486 487 if s, ok := exp2.Args[0].(*bpparser.String); !ok || s.Value != "-Wl,--version-script," { 488 return "ldflags", value, nil 489 } 490 491 if v, ok := exp2.Args[1].(*bpparser.Variable); !ok || v.Name != "LOCAL_PATH" { 492 ctx.file.errorf(ctx.mkvalue, "Unrecognized version-script") 493 return "ldflags", value, nil 494 } 495 496 s, ok := exp1.Args[1].(*bpparser.String) 497 if !ok { 498 ctx.file.errorf(ctx.mkvalue, "Unrecognized version-script") 499 return "ldflags", value, nil 500 } 501 502 s.Value = strings.TrimPrefix(s.Value, "/") 503 504 return "version", s, nil 505 }) 506 if err != nil { 507 return err 508 } 509 510 if ldflags, ok := lists["ldflags"]; ok && !emptyList(ldflags) { 511 err = setVariable(ctx.file, ctx.append, ctx.prefix, "ldflags", ldflags, true) 512 if err != nil { 513 return err 514 } 515 } 516 517 if version_script, ok := lists["version"]; ok && !emptyList(version_script) { 518 if len(version_script.(*bpparser.List).Values) > 1 { 519 ctx.file.errorf(ctx.mkvalue, "multiple version scripts found?") 520 } 521 err = setVariable(ctx.file, false, ctx.prefix, "version_script", version_script.(*bpparser.List).Values[0], true) 522 if err != nil { 523 return err 524 } 525 } 526 527 return nil 528} 529 530func cflags(ctx variableAssignmentContext) error { 531 // The Soong replacement for CFLAGS doesn't need the same extra escaped quotes that were present in Make 532 ctx.mkvalue = ctx.mkvalue.Clone() 533 ctx.mkvalue.ReplaceLiteral(`\"`, `"`) 534 return includeVariableNow(bpVariable{"cflags", bpparser.ListType}, ctx) 535} 536 537func proguardEnabled(ctx variableAssignmentContext) error { 538 val, err := makeVariableToBlueprint(ctx.file, ctx.mkvalue, bpparser.ListType) 539 if err != nil { 540 return err 541 } 542 543 list, ok := val.(*bpparser.List) 544 if !ok { 545 return fmt.Errorf("unsupported proguard expression") 546 } 547 548 set := func(prop string, value bool) { 549 bpValue := &bpparser.Bool{ 550 Value: value, 551 } 552 setVariable(ctx.file, false, ctx.prefix, prop, bpValue, true) 553 } 554 555 enable := false 556 557 for _, v := range list.Values { 558 s, ok := v.(*bpparser.String) 559 if !ok { 560 return fmt.Errorf("unsupported proguard expression") 561 } 562 563 switch s.Value { 564 case "disabled": 565 set("optimize.enabled", false) 566 case "obfuscation": 567 enable = true 568 set("optimize.obfuscate", true) 569 case "optimization": 570 enable = true 571 set("optimize.optimize", true) 572 case "full": 573 enable = true 574 case "custom": 575 set("optimize.no_aapt_flags", true) 576 enable = true 577 default: 578 return fmt.Errorf("unsupported proguard value %q", s) 579 } 580 } 581 582 if enable { 583 // This is only necessary for libraries which default to false, but we can't 584 // tell the difference between a library and an app here. 585 set("optimize.enabled", true) 586 } 587 588 return nil 589} 590 591func invert(name string) func(ctx variableAssignmentContext) error { 592 return func(ctx variableAssignmentContext) error { 593 val, err := makeVariableToBlueprint(ctx.file, ctx.mkvalue, bpparser.BoolType) 594 if err != nil { 595 return err 596 } 597 598 val.(*bpparser.Bool).Value = !val.(*bpparser.Bool).Value 599 600 return setVariable(ctx.file, ctx.append, ctx.prefix, name, val, true) 601 } 602} 603 604// given a conditional, returns a function that will insert a variable assignment or not, based on the conditional 605func includeVariableIf(bpVar bpVariable, conditional func(ctx variableAssignmentContext) bool) func(ctx variableAssignmentContext) error { 606 return func(ctx variableAssignmentContext) error { 607 var err error 608 if conditional(ctx) { 609 err = includeVariableNow(bpVar, ctx) 610 } 611 return err 612 } 613} 614 615// given a variable, returns a function that will always insert a variable assignment 616func includeVariable(bpVar bpVariable) func(ctx variableAssignmentContext) error { 617 return includeVariableIf(bpVar, always) 618} 619 620func includeVariableNow(bpVar bpVariable, ctx variableAssignmentContext) error { 621 var val bpparser.Expression 622 var err error 623 val, err = makeVariableToBlueprint(ctx.file, ctx.mkvalue, bpVar.variableType) 624 if err == nil { 625 err = setVariable(ctx.file, ctx.append, ctx.prefix, bpVar.name, val, true) 626 } 627 return err 628} 629 630// given a function that returns a bool, returns a function that returns the opposite 631func not(conditional func(ctx variableAssignmentContext) bool) func(ctx variableAssignmentContext) bool { 632 return func(ctx variableAssignmentContext) bool { 633 return !conditional(ctx) 634 } 635} 636 637// returns a function that tells whether mkvalue.Dump equals the given query string 638func valueDumpEquals(textToMatch string) func(ctx variableAssignmentContext) bool { 639 return func(ctx variableAssignmentContext) bool { 640 return (ctx.mkvalue.Dump() == textToMatch) 641 } 642} 643 644func always(ctx variableAssignmentContext) bool { 645 return true 646} 647 648func skip(ctx variableAssignmentContext) error { 649 return nil 650} 651 652// Shorter suffixes of other suffixes must be at the end of the list 653var propertyPrefixes = []struct{ mk, bp string }{ 654 {"arm", "arch.arm"}, 655 {"arm64", "arch.arm64"}, 656 {"mips", "arch.mips"}, 657 {"mips64", "arch.mips64"}, 658 {"x86", "arch.x86"}, 659 {"x86_64", "arch.x86_64"}, 660 {"32", "multilib.lib32"}, 661 // 64 must be after x86_64 662 {"64", "multilib.lib64"}, 663 {"darwin", "target.darwin"}, 664 {"linux", "target.linux_glibc"}, 665 {"windows", "target.windows"}, 666} 667 668var conditionalTranslations = map[string]map[bool]string{ 669 "($(HOST_OS),darwin)": { 670 true: "target.darwin", 671 false: "target.not_darwin"}, 672 "($(HOST_OS), darwin)": { 673 true: "target.darwin", 674 false: "target.not_darwin"}, 675 "($(HOST_OS),windows)": { 676 true: "target.windows", 677 false: "target.not_windows"}, 678 "($(HOST_OS), windows)": { 679 true: "target.windows", 680 false: "target.not_windows"}, 681 "($(HOST_OS),linux)": { 682 true: "target.linux_glibc", 683 false: "target.not_linux_glibc"}, 684 "($(HOST_OS), linux)": { 685 true: "target.linux_glibc", 686 false: "target.not_linux_glibc"}, 687 "($(BUILD_OS),darwin)": { 688 true: "target.darwin", 689 false: "target.not_darwin"}, 690 "($(BUILD_OS), darwin)": { 691 true: "target.darwin", 692 false: "target.not_darwin"}, 693 "($(BUILD_OS),linux)": { 694 true: "target.linux_glibc", 695 false: "target.not_linux_glibc"}, 696 "($(BUILD_OS), linux)": { 697 true: "target.linux_glibc", 698 false: "target.not_linux_glibc"}, 699 "(,$(TARGET_BUILD_APPS))": { 700 false: "product_variables.unbundled_build"}, 701 "($(TARGET_BUILD_APPS),)": { 702 false: "product_variables.unbundled_build"}, 703 "($(TARGET_BUILD_PDK),true)": { 704 true: "product_variables.pdk"}, 705 "($(TARGET_BUILD_PDK), true)": { 706 true: "product_variables.pdk"}, 707} 708 709func mydir(args []string) string { 710 return "." 711} 712 713func allFilesUnder(wildcard string) func(args []string) string { 714 return func(args []string) string { 715 dir := "" 716 if len(args) > 0 { 717 dir = strings.TrimSpace(args[0]) 718 } 719 720 return fmt.Sprintf("%s/**/"+wildcard, dir) 721 } 722} 723 724func allSubdirJavaFiles(args []string) string { 725 return "**/*.java" 726} 727 728func includeIgnored(args []string) string { 729 return include_ignored 730} 731 732var moduleTypes = map[string]string{ 733 "BUILD_SHARED_LIBRARY": "cc_library_shared", 734 "BUILD_STATIC_LIBRARY": "cc_library_static", 735 "BUILD_HOST_SHARED_LIBRARY": "cc_library_host_shared", 736 "BUILD_HOST_STATIC_LIBRARY": "cc_library_host_static", 737 "BUILD_HEADER_LIBRARY": "cc_library_headers", 738 "BUILD_EXECUTABLE": "cc_binary", 739 "BUILD_HOST_EXECUTABLE": "cc_binary_host", 740 "BUILD_NATIVE_TEST": "cc_test", 741 "BUILD_HOST_NATIVE_TEST": "cc_test_host", 742 "BUILD_NATIVE_BENCHMARK": "cc_benchmark", 743 "BUILD_HOST_NATIVE_BENCHMARK": "cc_benchmark_host", 744 745 "BUILD_JAVA_LIBRARY": "java_library", 746 "BUILD_STATIC_JAVA_LIBRARY": "java_library_static", 747 "BUILD_HOST_JAVA_LIBRARY": "java_library_host", 748 "BUILD_HOST_DALVIK_JAVA_LIBRARY": "java_library_host_dalvik", 749 "BUILD_PACKAGE": "android_app", 750} 751 752var prebuiltTypes = map[string]string{ 753 "SHARED_LIBRARIES": "cc_prebuilt_library_shared", 754 "STATIC_LIBRARIES": "cc_prebuilt_library_static", 755 "EXECUTABLES": "cc_prebuilt_binary", 756 "JAVA_LIBRARIES": "java_import", 757} 758 759var soongModuleTypes = map[string]bool{} 760 761func androidScope() mkparser.Scope { 762 globalScope := mkparser.NewScope(nil) 763 globalScope.Set("CLEAR_VARS", clear_vars) 764 globalScope.SetFunc("my-dir", mydir) 765 globalScope.SetFunc("all-java-files-under", allFilesUnder("*.java")) 766 globalScope.SetFunc("all-proto-files-under", allFilesUnder("*.proto")) 767 globalScope.SetFunc("all-aidl-files-under", allFilesUnder("*.aidl")) 768 globalScope.SetFunc("all-Iaidl-files-under", allFilesUnder("I*.aidl")) 769 globalScope.SetFunc("all-logtags-files-under", allFilesUnder("*.logtags")) 770 globalScope.SetFunc("all-subdir-java-files", allSubdirJavaFiles) 771 globalScope.SetFunc("all-makefiles-under", includeIgnored) 772 globalScope.SetFunc("first-makefiles-under", includeIgnored) 773 globalScope.SetFunc("all-named-subdir-makefiles", includeIgnored) 774 globalScope.SetFunc("all-subdir-makefiles", includeIgnored) 775 776 for k, v := range moduleTypes { 777 globalScope.Set(k, v) 778 soongModuleTypes[v] = true 779 } 780 for _, v := range prebuiltTypes { 781 soongModuleTypes[v] = true 782 } 783 784 return globalScope 785} 786