Add support to extend commands bpfix and androidmk
Allows our partners to maintain partner-specific fixes in their repos. Converts most of androidmk into a library similar to bpfix. Makes some methods and types public for use by extended versions.
Bug:140727544
Test: Ran unit test cases &&
ran test conversions with sample
Change-Id: I7e1fbf3a6a7a8bd47334f43fe3eb68cbbd3426c1
diff --git a/androidmk/cmd/androidmk.go b/androidmk/cmd/androidmk.go
new file mode 100644
index 0000000..00488eb
--- /dev/null
+++ b/androidmk/cmd/androidmk.go
@@ -0,0 +1,56 @@
+// Copyright 2017 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+ "bytes"
+ "flag"
+ "fmt"
+ "io/ioutil"
+ "os"
+
+ "android/soong/androidmk/androidmk"
+)
+
+var usage = func() {
+ fmt.Fprintf(os.Stderr, "usage: androidmk [flags] <inputFile>\n"+
+ "\nandroidmk parses <inputFile> as an Android.mk file and attempts to output an analogous Android.bp file (to standard out)\n")
+ flag.PrintDefaults()
+ os.Exit(1)
+}
+
+func main() {
+ flag.Usage = usage
+ flag.Parse()
+ if len(flag.Args()) != 1 {
+ usage()
+ }
+ filePathToRead := flag.Arg(0)
+ b, err := ioutil.ReadFile(filePathToRead)
+ if err != nil {
+ fmt.Println(err.Error())
+ return
+ }
+
+ output, errs := androidmk.ConvertFile(os.Args[1], bytes.NewBuffer(b))
+ if len(errs) > 0 {
+ for _, err := range errs {
+ fmt.Fprintln(os.Stderr, "ERROR: ", err)
+ }
+ os.Exit(1)
+ }
+
+ fmt.Print(output)
+}
diff --git a/androidmk/cmd/androidmk/android.go b/androidmk/cmd/androidmk/android.go
deleted file mode 100644
index fcadd03..0000000
--- a/androidmk/cmd/androidmk/android.go
+++ /dev/null
@@ -1,979 +0,0 @@
-// Copyright 2017 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package main
-
-import (
- "android/soong/android"
- mkparser "android/soong/androidmk/parser"
- "fmt"
- "strings"
-
- bpparser "github.com/google/blueprint/parser"
-)
-
-const (
- clear_vars = "__android_mk_clear_vars"
- include_ignored = "__android_mk_include_ignored"
-)
-
-type bpVariable struct {
- name string
- variableType bpparser.Type
-}
-
-type variableAssignmentContext struct {
- file *bpFile
- prefix string
- mkvalue *mkparser.MakeString
- append bool
-}
-
-var rewriteProperties = map[string](func(variableAssignmentContext) error){
- // custom functions
- "LOCAL_32_BIT_ONLY": local32BitOnly,
- "LOCAL_AIDL_INCLUDES": localAidlIncludes,
- "LOCAL_ASSET_DIR": localizePathList("asset_dirs"),
- "LOCAL_C_INCLUDES": localIncludeDirs,
- "LOCAL_EXPORT_C_INCLUDE_DIRS": exportIncludeDirs,
- "LOCAL_JARJAR_RULES": localizePath("jarjar_rules"),
- "LOCAL_LDFLAGS": ldflags,
- "LOCAL_MODULE_CLASS": prebuiltClass,
- "LOCAL_MODULE_STEM": stem,
- "LOCAL_MODULE_HOST_OS": hostOs,
- "LOCAL_RESOURCE_DIR": localizePathList("resource_dirs"),
- "LOCAL_SANITIZE": sanitize(""),
- "LOCAL_SANITIZE_DIAG": sanitize("diag."),
- "LOCAL_STRIP_MODULE": strip(),
- "LOCAL_CFLAGS": cflags,
- "LOCAL_UNINSTALLABLE_MODULE": invert("installable"),
- "LOCAL_PROGUARD_ENABLED": proguardEnabled,
- "LOCAL_MODULE_PATH": prebuiltModulePath,
-
- // composite functions
- "LOCAL_MODULE_TAGS": includeVariableIf(bpVariable{"tags", bpparser.ListType}, not(valueDumpEquals("optional"))),
-
- // skip functions
- "LOCAL_ADDITIONAL_DEPENDENCIES": skip, // TODO: check for only .mk files?
- "LOCAL_CPP_EXTENSION": skip,
- "LOCAL_MODULE_SUFFIX": skip, // TODO
- "LOCAL_PATH": skip, // Nothing to do, except maybe avoid the "./" in paths?
- "LOCAL_PRELINK_MODULE": skip, // Already phased out
- "LOCAL_BUILT_MODULE_STEM": skip,
- "LOCAL_USE_AAPT2": skip, // Always enabled in Soong
- "LOCAL_JAR_EXCLUDE_FILES": skip, // Soong never excludes files from jars
-
- "LOCAL_ANNOTATION_PROCESSOR_CLASSES": skip, // Soong gets the processor classes from the plugin
- "LOCAL_CTS_TEST_PACKAGE": skip, // Obsolete
- "LOCAL_JACK_ENABLED": skip, // Obselete
- "LOCAL_JACK_FLAGS": skip, // Obselete
-}
-
-// adds a group of properties all having the same type
-func addStandardProperties(propertyType bpparser.Type, properties map[string]string) {
- for key, val := range properties {
- rewriteProperties[key] = includeVariable(bpVariable{val, propertyType})
- }
-}
-
-func init() {
- addStandardProperties(bpparser.StringType,
- map[string]string{
- "LOCAL_MODULE": "name",
- "LOCAL_CXX_STL": "stl",
- "LOCAL_MULTILIB": "compile_multilib",
- "LOCAL_ARM_MODE_HACK": "instruction_set",
- "LOCAL_SDK_VERSION": "sdk_version",
- "LOCAL_MIN_SDK_VERSION": "min_sdk_version",
- "LOCAL_NDK_STL_VARIANT": "stl",
- "LOCAL_JAR_MANIFEST": "manifest",
- "LOCAL_CERTIFICATE": "certificate",
- "LOCAL_PACKAGE_NAME": "name",
- "LOCAL_MODULE_RELATIVE_PATH": "relative_install_path",
- "LOCAL_PROTOC_OPTIMIZE_TYPE": "proto.type",
- "LOCAL_MODULE_OWNER": "owner",
- "LOCAL_RENDERSCRIPT_TARGET_API": "renderscript.target_api",
- "LOCAL_NOTICE_FILE": "notice",
- "LOCAL_JAVA_LANGUAGE_VERSION": "java_version",
- "LOCAL_INSTRUMENTATION_FOR": "instrumentation_for",
- "LOCAL_MANIFEST_FILE": "manifest",
-
- "LOCAL_DEX_PREOPT_PROFILE_CLASS_LISTING": "dex_preopt.profile",
- "LOCAL_TEST_CONFIG": "test_config",
- })
- addStandardProperties(bpparser.ListType,
- map[string]string{
- "LOCAL_SRC_FILES": "srcs",
- "LOCAL_SRC_FILES_EXCLUDE": "exclude_srcs",
- "LOCAL_HEADER_LIBRARIES": "header_libs",
- "LOCAL_SHARED_LIBRARIES": "shared_libs",
- "LOCAL_STATIC_LIBRARIES": "static_libs",
- "LOCAL_WHOLE_STATIC_LIBRARIES": "whole_static_libs",
- "LOCAL_SYSTEM_SHARED_LIBRARIES": "system_shared_libs",
- "LOCAL_ASFLAGS": "asflags",
- "LOCAL_CLANG_ASFLAGS": "clang_asflags",
- "LOCAL_COMPATIBILITY_SUPPORT_FILES": "data",
- "LOCAL_CONLYFLAGS": "conlyflags",
- "LOCAL_CPPFLAGS": "cppflags",
- "LOCAL_REQUIRED_MODULES": "required",
- "LOCAL_HOST_REQUIRED_MODULES": "host_required",
- "LOCAL_TARGET_REQUIRED_MODULES": "target_required",
- "LOCAL_OVERRIDES_MODULES": "overrides",
- "LOCAL_LDLIBS": "host_ldlibs",
- "LOCAL_CLANG_CFLAGS": "clang_cflags",
- "LOCAL_YACCFLAGS": "yacc.flags",
- "LOCAL_SANITIZE_RECOVER": "sanitize.recover",
- "LOCAL_LOGTAGS_FILES": "logtags",
- "LOCAL_EXPORT_HEADER_LIBRARY_HEADERS": "export_header_lib_headers",
- "LOCAL_EXPORT_SHARED_LIBRARY_HEADERS": "export_shared_lib_headers",
- "LOCAL_EXPORT_STATIC_LIBRARY_HEADERS": "export_static_lib_headers",
- "LOCAL_INIT_RC": "init_rc",
- "LOCAL_VINTF_FRAGMENTS": "vintf_fragments",
- "LOCAL_TIDY_FLAGS": "tidy_flags",
- // TODO: This is comma-separated, not space-separated
- "LOCAL_TIDY_CHECKS": "tidy_checks",
- "LOCAL_RENDERSCRIPT_INCLUDES": "renderscript.include_dirs",
- "LOCAL_RENDERSCRIPT_FLAGS": "renderscript.flags",
-
- "LOCAL_JAVA_RESOURCE_DIRS": "java_resource_dirs",
- "LOCAL_JAVA_RESOURCE_FILES": "java_resources",
- "LOCAL_JAVACFLAGS": "javacflags",
- "LOCAL_ERROR_PRONE_FLAGS": "errorprone.javacflags",
- "LOCAL_DX_FLAGS": "dxflags",
- "LOCAL_JAVA_LIBRARIES": "libs",
- "LOCAL_STATIC_JAVA_LIBRARIES": "static_libs",
- "LOCAL_JNI_SHARED_LIBRARIES": "jni_libs",
- "LOCAL_AAPT_FLAGS": "aaptflags",
- "LOCAL_PACKAGE_SPLITS": "package_splits",
- "LOCAL_COMPATIBILITY_SUITE": "test_suites",
- "LOCAL_OVERRIDES_PACKAGES": "overrides",
-
- "LOCAL_ANNOTATION_PROCESSORS": "plugins",
-
- "LOCAL_PROGUARD_FLAGS": "optimize.proguard_flags",
- "LOCAL_PROGUARD_FLAG_FILES": "optimize.proguard_flags_files",
-
- // These will be rewritten to libs/static_libs by bpfix, after their presence is used to convert
- // java_library_static to android_library.
- "LOCAL_SHARED_ANDROID_LIBRARIES": "android_libs",
- "LOCAL_STATIC_ANDROID_LIBRARIES": "android_static_libs",
- "LOCAL_ADDITIONAL_CERTIFICATES": "additional_certificates",
-
- // Jacoco filters:
- "LOCAL_JACK_COVERAGE_INCLUDE_FILTER": "jacoco.include_filter",
- "LOCAL_JACK_COVERAGE_EXCLUDE_FILTER": "jacoco.exclude_filter",
-
- "LOCAL_FULL_LIBS_MANIFEST_FILES": "additional_manifests",
- })
-
- addStandardProperties(bpparser.BoolType,
- map[string]string{
- // Bool properties
- "LOCAL_IS_HOST_MODULE": "host",
- "LOCAL_CLANG": "clang",
- "LOCAL_FORCE_STATIC_EXECUTABLE": "static_executable",
- "LOCAL_NATIVE_COVERAGE": "native_coverage",
- "LOCAL_NO_CRT": "nocrt",
- "LOCAL_ALLOW_UNDEFINED_SYMBOLS": "allow_undefined_symbols",
- "LOCAL_RTTI_FLAG": "rtti",
- "LOCAL_PACK_MODULE_RELOCATIONS": "pack_relocations",
- "LOCAL_TIDY": "tidy",
- "LOCAL_USE_CLANG_LLD": "use_clang_lld",
- "LOCAL_PROPRIETARY_MODULE": "proprietary",
- "LOCAL_VENDOR_MODULE": "vendor",
- "LOCAL_ODM_MODULE": "device_specific",
- "LOCAL_PRODUCT_MODULE": "product_specific",
- "LOCAL_SYSTEM_EXT_MODULE": "system_ext_specific",
- "LOCAL_EXPORT_PACKAGE_RESOURCES": "export_package_resources",
- "LOCAL_PRIVILEGED_MODULE": "privileged",
- "LOCAL_AAPT_INCLUDE_ALL_RESOURCES": "aapt_include_all_resources",
- "LOCAL_USE_EMBEDDED_NATIVE_LIBS": "use_embedded_native_libs",
- "LOCAL_USE_EMBEDDED_DEX": "use_embedded_dex",
-
- "LOCAL_DEX_PREOPT": "dex_preopt.enabled",
- "LOCAL_DEX_PREOPT_APP_IMAGE": "dex_preopt.app_image",
- "LOCAL_DEX_PREOPT_GENERATE_PROFILE": "dex_preopt.profile_guided",
-
- "LOCAL_PRIVATE_PLATFORM_APIS": "platform_apis",
- "LOCAL_JETIFIER_ENABLED": "jetifier",
- })
-}
-
-type listSplitFunc func(bpparser.Expression) (string, bpparser.Expression, error)
-
-func emptyList(value bpparser.Expression) bool {
- if list, ok := value.(*bpparser.List); ok {
- return len(list.Values) == 0
- }
- return false
-}
-
-func splitBpList(val bpparser.Expression, keyFunc listSplitFunc) (lists map[string]bpparser.Expression, err error) {
- lists = make(map[string]bpparser.Expression)
-
- switch val := val.(type) {
- case *bpparser.Operator:
- listsA, err := splitBpList(val.Args[0], keyFunc)
- if err != nil {
- return nil, err
- }
-
- listsB, err := splitBpList(val.Args[1], keyFunc)
- if err != nil {
- return nil, err
- }
-
- for k, v := range listsA {
- if !emptyList(v) {
- lists[k] = v
- }
- }
-
- for k, vB := range listsB {
- if emptyList(vB) {
- continue
- }
-
- if vA, ok := lists[k]; ok {
- expression := val.Copy().(*bpparser.Operator)
- expression.Args = [2]bpparser.Expression{vA, vB}
- lists[k] = expression
- } else {
- lists[k] = vB
- }
- }
- case *bpparser.Variable:
- key, value, err := keyFunc(val)
- if err != nil {
- return nil, err
- }
- if value.Type() == bpparser.ListType {
- lists[key] = value
- } else {
- lists[key] = &bpparser.List{
- Values: []bpparser.Expression{value},
- }
- }
- case *bpparser.List:
- for _, v := range val.Values {
- key, value, err := keyFunc(v)
- if err != nil {
- return nil, err
- }
- l := lists[key]
- if l == nil {
- l = &bpparser.List{}
- }
- l.(*bpparser.List).Values = append(l.(*bpparser.List).Values, value)
- lists[key] = l
- }
- default:
- panic(fmt.Errorf("unexpected type %t", val))
- }
-
- return lists, nil
-}
-
-// classifyLocalOrGlobalPath tells whether a file path should be interpreted relative to the current module (local)
-// or relative to the root of the source checkout (global)
-func classifyLocalOrGlobalPath(value bpparser.Expression) (string, bpparser.Expression, error) {
- switch v := value.(type) {
- case *bpparser.Variable:
- if v.Name == "LOCAL_PATH" {
- return "local", &bpparser.String{
- Value: ".",
- }, nil
- } else {
- // TODO: Should we split variables?
- return "global", value, nil
- }
- case *bpparser.Operator:
- if v.Type() != bpparser.StringType {
- return "", nil, fmt.Errorf("classifyLocalOrGlobalPath expected a string, got %s", v.Type())
- }
-
- if v.Operator != '+' {
- return "global", value, nil
- }
-
- firstOperand := v.Args[0]
- secondOperand := v.Args[1]
- if firstOperand.Type() != bpparser.StringType {
- return "global", value, nil
- }
-
- if _, ok := firstOperand.(*bpparser.Operator); ok {
- return "global", value, nil
- }
-
- if variable, ok := firstOperand.(*bpparser.Variable); !ok || variable.Name != "LOCAL_PATH" {
- return "global", value, nil
- }
-
- local := secondOperand
- if s, ok := secondOperand.(*bpparser.String); ok {
- if strings.HasPrefix(s.Value, "/") {
- s.Value = s.Value[1:]
- }
- }
- return "local", local, nil
- case *bpparser.String:
- return "global", value, nil
- default:
- return "", nil, fmt.Errorf("classifyLocalOrGlobalPath expected a string, got %s", v.Type())
-
- }
-}
-
-// splitAndAssign splits a Make list into components and then
-// creates the corresponding variable assignments.
-func splitAndAssign(ctx variableAssignmentContext, splitFunc listSplitFunc, namesByClassification map[string]string) error {
- val, err := makeVariableToBlueprint(ctx.file, ctx.mkvalue, bpparser.ListType)
- if err != nil {
- return err
- }
-
- lists, err := splitBpList(val, splitFunc)
- if err != nil {
- return err
- }
-
- for _, nameClassification := range android.SortedStringKeys(namesByClassification) {
- name := namesByClassification[nameClassification]
- if component, ok := lists[nameClassification]; ok && !emptyList(component) {
- err = setVariable(ctx.file, ctx.append, ctx.prefix, name, component, true)
- if err != nil {
- return err
- }
- }
- }
- return nil
-}
-
-func localIncludeDirs(ctx variableAssignmentContext) error {
- return splitAndAssign(ctx, classifyLocalOrGlobalPath, map[string]string{"global": "include_dirs", "local": "local_include_dirs"})
-}
-
-func exportIncludeDirs(ctx variableAssignmentContext) error {
- // Add any paths that could not be converted to local relative paths to export_include_dirs
- // anyways, they will cause an error if they don't exist and can be fixed manually.
- return splitAndAssign(ctx, classifyLocalOrGlobalPath, map[string]string{"global": "export_include_dirs", "local": "export_include_dirs"})
-}
-
-func local32BitOnly(ctx variableAssignmentContext) error {
- val, err := makeVariableToBlueprint(ctx.file, ctx.mkvalue, bpparser.BoolType)
- if err != nil {
- return err
- }
- if val.(*bpparser.Bool).Value {
- thirtyTwo := &bpparser.String{
- Value: "32",
- }
- setVariable(ctx.file, false, ctx.prefix, "compile_multilib", thirtyTwo, true)
- }
- return nil
-}
-
-func localAidlIncludes(ctx variableAssignmentContext) error {
- return splitAndAssign(ctx, classifyLocalOrGlobalPath, map[string]string{"global": "aidl.include_dirs", "local": "aidl.local_include_dirs"})
-}
-
-func localizePathList(attribute string) func(ctx variableAssignmentContext) error {
- return func(ctx variableAssignmentContext) error {
- paths, err := localizePaths(ctx)
- if err == nil {
- err = setVariable(ctx.file, ctx.append, ctx.prefix, attribute, paths, true)
- }
- return err
- }
-}
-
-func localizePath(attribute string) func(ctx variableAssignmentContext) error {
- return func(ctx variableAssignmentContext) error {
- paths, err := localizePaths(ctx)
- if err == nil {
- pathList, ok := paths.(*bpparser.List)
- if !ok {
- panic("Expected list")
- }
- switch len(pathList.Values) {
- case 0:
- err = setVariable(ctx.file, ctx.append, ctx.prefix, attribute, &bpparser.List{}, true)
- case 1:
- err = setVariable(ctx.file, ctx.append, ctx.prefix, attribute, pathList.Values[0], true)
- default:
- err = fmt.Errorf("Expected single value for %s", attribute)
- }
- }
- return err
- }
-}
-
-// Convert the "full" paths (that is, from the top of the source tree) to the relative one
-// (from the directory containing the blueprint file) and set given attribute to it.
-// This is needed for some of makefile variables (e.g., LOCAL_RESOURCE_DIR).
-// At the moment only the paths of the `$(LOCAL_PATH)/foo/bar` format can be converted
-// (to `foo/bar` in this case) as we cannot convert a literal path without
-// knowing makefiles's location in the source tree. We just issue a warning in the latter case.
-func localizePaths(ctx variableAssignmentContext) (bpparser.Expression, error) {
- bpvalue, err := makeVariableToBlueprint(ctx.file, ctx.mkvalue, bpparser.ListType)
- var result bpparser.Expression
- if err != nil {
- return result, err
- }
- classifiedPaths, err := splitBpList(bpvalue, classifyLocalOrGlobalPath)
- if err != nil {
- return result, err
- }
- for pathClass, path := range classifiedPaths {
- switch pathClass {
- case "local":
- result = path
- default:
- err = fmt.Errorf("Only $(LOCAL_PATH)/.. values are allowed")
- }
- }
- return result, err
-}
-
-func stem(ctx variableAssignmentContext) error {
- val, err := makeVariableToBlueprint(ctx.file, ctx.mkvalue, bpparser.StringType)
- if err != nil {
- return err
- }
- varName := "stem"
-
- if exp, ok := val.(*bpparser.Operator); ok && exp.Operator == '+' {
- if variable, ok := exp.Args[0].(*bpparser.Variable); ok && variable.Name == "LOCAL_MODULE" {
- varName = "suffix"
- val = exp.Args[1]
- }
- }
-
- return setVariable(ctx.file, ctx.append, ctx.prefix, varName, val, true)
-}
-
-func hostOs(ctx variableAssignmentContext) error {
- val, err := makeVariableToBlueprint(ctx.file, ctx.mkvalue, bpparser.ListType)
- if err != nil {
- return err
- }
-
- inList := func(s string) bool {
- for _, v := range val.(*bpparser.List).Values {
- if v.(*bpparser.String).Value == s {
- return true
- }
- }
- return false
- }
-
- falseValue := &bpparser.Bool{
- Value: false,
- }
-
- trueValue := &bpparser.Bool{
- Value: true,
- }
-
- if inList("windows") {
- err = setVariable(ctx.file, ctx.append, "target.windows", "enabled", trueValue, true)
- }
-
- if !inList("linux") && err == nil {
- err = setVariable(ctx.file, ctx.append, "target.linux_glibc", "enabled", falseValue, true)
- }
-
- if !inList("darwin") && err == nil {
- err = setVariable(ctx.file, ctx.append, "target.darwin", "enabled", falseValue, true)
- }
-
- return err
-}
-
-func sanitize(sub string) func(ctx variableAssignmentContext) error {
- return func(ctx variableAssignmentContext) error {
- val, err := makeVariableToBlueprint(ctx.file, ctx.mkvalue, bpparser.ListType)
- if err != nil {
- return err
- }
-
- if _, ok := val.(*bpparser.List); !ok {
- return fmt.Errorf("unsupported sanitize expression")
- }
-
- misc := &bpparser.List{}
-
- for _, v := range val.(*bpparser.List).Values {
- switch v := v.(type) {
- case *bpparser.Variable, *bpparser.Operator:
- ctx.file.errorf(ctx.mkvalue, "unsupported sanitize expression")
- case *bpparser.String:
- switch v.Value {
- case "never", "address", "fuzzer", "thread", "undefined", "cfi":
- bpTrue := &bpparser.Bool{
- Value: true,
- }
- err = setVariable(ctx.file, false, ctx.prefix, "sanitize."+sub+v.Value, bpTrue, true)
- if err != nil {
- return err
- }
- default:
- misc.Values = append(misc.Values, v)
- }
- default:
- return fmt.Errorf("sanitize expected a string, got %s", v.Type())
- }
- }
-
- if len(misc.Values) > 0 {
- err = setVariable(ctx.file, false, ctx.prefix, "sanitize."+sub+"misc_undefined", misc, true)
- if err != nil {
- return err
- }
- }
-
- return err
- }
-}
-
-func strip() func(ctx variableAssignmentContext) error {
- return func(ctx variableAssignmentContext) error {
- val, err := makeVariableToBlueprint(ctx.file, ctx.mkvalue, bpparser.StringType)
- if err != nil {
- return err
- }
-
- if _, ok := val.(*bpparser.String); !ok {
- return fmt.Errorf("unsupported strip expression")
- }
-
- bpTrue := &bpparser.Bool{
- Value: true,
- }
- v := val.(*bpparser.String).Value
- sub := (map[string]string{"false": "none", "true": "all", "keep_symbols": "keep_symbols"})[v]
- if sub == "" {
- return fmt.Errorf("unexpected strip option: %s", v)
- }
- return setVariable(ctx.file, false, ctx.prefix, "strip."+sub, bpTrue, true)
- }
-}
-
-func prebuiltClass(ctx variableAssignmentContext) error {
- class := ctx.mkvalue.Value(ctx.file.scope)
- if _, ok := prebuiltTypes[class]; ok {
- ctx.file.scope.Set("BUILD_PREBUILT", class)
- } else {
- // reset to default
- ctx.file.scope.Set("BUILD_PREBUILT", "prebuilt")
- }
- return nil
-}
-
-func makeBlueprintStringAssignment(file *bpFile, prefix string, suffix string, value string) error {
- val, err := makeVariableToBlueprint(file, mkparser.SimpleMakeString(value, mkparser.NoPos), bpparser.StringType)
- if err == nil {
- err = setVariable(file, false, prefix, suffix, val, true)
- }
- return err
-}
-
-// If variable is a literal variable name, return the name, otherwise return ""
-func varLiteralName(variable mkparser.Variable) string {
- if len(variable.Name.Variables) == 0 {
- return variable.Name.Strings[0]
- }
- return ""
-}
-
-func prebuiltModulePath(ctx variableAssignmentContext) error {
- // Cannot handle appending
- if ctx.append {
- return fmt.Errorf("Cannot handle appending to LOCAL_MODULE_PATH")
- }
- // Analyze value in order to set the correct values for the 'device_specific',
- // 'product_specific', 'system_ext_specific' 'vendor'/'soc_specific',
- // 'system_ext_specific' attribute. Two cases are allowed:
- // $(VAR)/<literal-value>
- // $(PRODUCT_OUT)/$(TARGET_COPY_OUT_VENDOR)/<literal-value>
- // The last case is equivalent to $(TARGET_OUT_VENDOR)/<literal-value>
- // Map the variable name if present to `local_module_path_var`
- // Map literal-path to local_module_path_fixed
- varname := ""
- fixed := ""
- val := ctx.mkvalue
- if len(val.Variables) == 1 && varLiteralName(val.Variables[0]) != "" && len(val.Strings) == 2 && val.Strings[0] == "" {
- fixed = val.Strings[1]
- varname = val.Variables[0].Name.Strings[0]
- } else if len(val.Variables) == 2 && varLiteralName(val.Variables[0]) == "PRODUCT_OUT" && varLiteralName(val.Variables[1]) == "TARGET_COPY_OUT_VENDOR" &&
- len(val.Strings) == 3 && val.Strings[0] == "" && val.Strings[1] == "/" {
- fixed = val.Strings[2]
- varname = "TARGET_OUT_VENDOR"
- } else {
- return fmt.Errorf("LOCAL_MODULE_PATH value should start with $(<some-varaible>)/ or $(PRODUCT_OUT)/$(TARGET_COPY_VENDOR)/")
- }
- err := makeBlueprintStringAssignment(ctx.file, "local_module_path", "var", varname)
- if err == nil && fixed != "" {
- err = makeBlueprintStringAssignment(ctx.file, "local_module_path", "fixed", fixed)
- }
- return err
-}
-
-func ldflags(ctx variableAssignmentContext) error {
- val, err := makeVariableToBlueprint(ctx.file, ctx.mkvalue, bpparser.ListType)
- if err != nil {
- return err
- }
-
- lists, err := splitBpList(val, func(value bpparser.Expression) (string, bpparser.Expression, error) {
- // Anything other than "-Wl,--version_script," + LOCAL_PATH + "<path>" matches ldflags
- exp1, ok := value.(*bpparser.Operator)
- if !ok {
- return "ldflags", value, nil
- }
-
- exp2, ok := exp1.Args[0].(*bpparser.Operator)
- if !ok {
- return "ldflags", value, nil
- }
-
- if s, ok := exp2.Args[0].(*bpparser.String); !ok || s.Value != "-Wl,--version-script," {
- return "ldflags", value, nil
- }
-
- if v, ok := exp2.Args[1].(*bpparser.Variable); !ok || v.Name != "LOCAL_PATH" {
- ctx.file.errorf(ctx.mkvalue, "Unrecognized version-script")
- return "ldflags", value, nil
- }
-
- s, ok := exp1.Args[1].(*bpparser.String)
- if !ok {
- ctx.file.errorf(ctx.mkvalue, "Unrecognized version-script")
- return "ldflags", value, nil
- }
-
- s.Value = strings.TrimPrefix(s.Value, "/")
-
- return "version", s, nil
- })
- if err != nil {
- return err
- }
-
- if ldflags, ok := lists["ldflags"]; ok && !emptyList(ldflags) {
- err = setVariable(ctx.file, ctx.append, ctx.prefix, "ldflags", ldflags, true)
- if err != nil {
- return err
- }
- }
-
- if version_script, ok := lists["version"]; ok && !emptyList(version_script) {
- if len(version_script.(*bpparser.List).Values) > 1 {
- ctx.file.errorf(ctx.mkvalue, "multiple version scripts found?")
- }
- err = setVariable(ctx.file, false, ctx.prefix, "version_script", version_script.(*bpparser.List).Values[0], true)
- if err != nil {
- return err
- }
- }
-
- return nil
-}
-
-func cflags(ctx variableAssignmentContext) error {
- // The Soong replacement for CFLAGS doesn't need the same extra escaped quotes that were present in Make
- ctx.mkvalue = ctx.mkvalue.Clone()
- ctx.mkvalue.ReplaceLiteral(`\"`, `"`)
- return includeVariableNow(bpVariable{"cflags", bpparser.ListType}, ctx)
-}
-
-func proguardEnabled(ctx variableAssignmentContext) error {
- val, err := makeVariableToBlueprint(ctx.file, ctx.mkvalue, bpparser.ListType)
- if err != nil {
- return err
- }
-
- list, ok := val.(*bpparser.List)
- if !ok {
- return fmt.Errorf("unsupported proguard expression")
- }
-
- set := func(prop string, value bool) {
- bpValue := &bpparser.Bool{
- Value: value,
- }
- setVariable(ctx.file, false, ctx.prefix, prop, bpValue, true)
- }
-
- enable := false
-
- for _, v := range list.Values {
- s, ok := v.(*bpparser.String)
- if !ok {
- return fmt.Errorf("unsupported proguard expression")
- }
-
- switch s.Value {
- case "disabled":
- set("optimize.enabled", false)
- case "obfuscation":
- enable = true
- set("optimize.obfuscate", true)
- case "optimization":
- enable = true
- set("optimize.optimize", true)
- case "full":
- enable = true
- case "custom":
- set("optimize.no_aapt_flags", true)
- enable = true
- default:
- return fmt.Errorf("unsupported proguard value %q", s)
- }
- }
-
- if enable {
- // This is only necessary for libraries which default to false, but we can't
- // tell the difference between a library and an app here.
- set("optimize.enabled", true)
- }
-
- return nil
-}
-
-func invert(name string) func(ctx variableAssignmentContext) error {
- return func(ctx variableAssignmentContext) error {
- val, err := makeVariableToBlueprint(ctx.file, ctx.mkvalue, bpparser.BoolType)
- if err != nil {
- return err
- }
-
- val.(*bpparser.Bool).Value = !val.(*bpparser.Bool).Value
-
- return setVariable(ctx.file, ctx.append, ctx.prefix, name, val, true)
- }
-}
-
-// given a conditional, returns a function that will insert a variable assignment or not, based on the conditional
-func includeVariableIf(bpVar bpVariable, conditional func(ctx variableAssignmentContext) bool) func(ctx variableAssignmentContext) error {
- return func(ctx variableAssignmentContext) error {
- var err error
- if conditional(ctx) {
- err = includeVariableNow(bpVar, ctx)
- }
- return err
- }
-}
-
-// given a variable, returns a function that will always insert a variable assignment
-func includeVariable(bpVar bpVariable) func(ctx variableAssignmentContext) error {
- return includeVariableIf(bpVar, always)
-}
-
-func includeVariableNow(bpVar bpVariable, ctx variableAssignmentContext) error {
- var val bpparser.Expression
- var err error
- val, err = makeVariableToBlueprint(ctx.file, ctx.mkvalue, bpVar.variableType)
- if err == nil {
- err = setVariable(ctx.file, ctx.append, ctx.prefix, bpVar.name, val, true)
- }
- return err
-}
-
-// given a function that returns a bool, returns a function that returns the opposite
-func not(conditional func(ctx variableAssignmentContext) bool) func(ctx variableAssignmentContext) bool {
- return func(ctx variableAssignmentContext) bool {
- return !conditional(ctx)
- }
-}
-
-// returns a function that tells whether mkvalue.Dump equals the given query string
-func valueDumpEquals(textToMatch string) func(ctx variableAssignmentContext) bool {
- return func(ctx variableAssignmentContext) bool {
- return (ctx.mkvalue.Dump() == textToMatch)
- }
-}
-
-func always(ctx variableAssignmentContext) bool {
- return true
-}
-
-func skip(ctx variableAssignmentContext) error {
- return nil
-}
-
-// Shorter suffixes of other suffixes must be at the end of the list
-var propertyPrefixes = []struct{ mk, bp string }{
- {"arm", "arch.arm"},
- {"arm64", "arch.arm64"},
- {"mips", "arch.mips"},
- {"mips64", "arch.mips64"},
- {"x86", "arch.x86"},
- {"x86_64", "arch.x86_64"},
- {"32", "multilib.lib32"},
- // 64 must be after x86_64
- {"64", "multilib.lib64"},
- {"darwin", "target.darwin"},
- {"linux", "target.linux_glibc"},
- {"windows", "target.windows"},
-}
-
-var conditionalTranslations = map[string]map[bool]string{
- "($(HOST_OS),darwin)": {
- true: "target.darwin",
- false: "target.not_darwin"},
- "($(HOST_OS), darwin)": {
- true: "target.darwin",
- false: "target.not_darwin"},
- "($(HOST_OS),windows)": {
- true: "target.windows",
- false: "target.not_windows"},
- "($(HOST_OS), windows)": {
- true: "target.windows",
- false: "target.not_windows"},
- "($(HOST_OS),linux)": {
- true: "target.linux_glibc",
- false: "target.not_linux_glibc"},
- "($(HOST_OS), linux)": {
- true: "target.linux_glibc",
- false: "target.not_linux_glibc"},
- "($(BUILD_OS),darwin)": {
- true: "target.darwin",
- false: "target.not_darwin"},
- "($(BUILD_OS), darwin)": {
- true: "target.darwin",
- false: "target.not_darwin"},
- "($(BUILD_OS),linux)": {
- true: "target.linux_glibc",
- false: "target.not_linux_glibc"},
- "($(BUILD_OS), linux)": {
- true: "target.linux_glibc",
- false: "target.not_linux_glibc"},
- "(,$(TARGET_BUILD_APPS))": {
- false: "product_variables.unbundled_build"},
- "($(TARGET_BUILD_APPS),)": {
- false: "product_variables.unbundled_build"},
- "($(TARGET_BUILD_PDK),true)": {
- true: "product_variables.pdk"},
- "($(TARGET_BUILD_PDK), true)": {
- true: "product_variables.pdk"},
-}
-
-func mydir(args []string) []string {
- return []string{"."}
-}
-
-func allFilesUnder(wildcard string) func(args []string) []string {
- return func(args []string) []string {
- dirs := []string{""}
- if len(args) > 0 {
- dirs = strings.Fields(args[0])
- }
-
- paths := make([]string, len(dirs))
- for i := range paths {
- paths[i] = fmt.Sprintf("%s/**/"+wildcard, dirs[i])
- }
- return paths
- }
-}
-
-func allSubdirJavaFiles(args []string) []string {
- return []string{"**/*.java"}
-}
-
-func includeIgnored(args []string) []string {
- return []string{include_ignored}
-}
-
-var moduleTypes = map[string]string{
- "BUILD_SHARED_LIBRARY": "cc_library_shared",
- "BUILD_STATIC_LIBRARY": "cc_library_static",
- "BUILD_HOST_SHARED_LIBRARY": "cc_library_host_shared",
- "BUILD_HOST_STATIC_LIBRARY": "cc_library_host_static",
- "BUILD_HEADER_LIBRARY": "cc_library_headers",
- "BUILD_EXECUTABLE": "cc_binary",
- "BUILD_HOST_EXECUTABLE": "cc_binary_host",
- "BUILD_NATIVE_TEST": "cc_test",
- "BUILD_HOST_NATIVE_TEST": "cc_test_host",
- "BUILD_NATIVE_BENCHMARK": "cc_benchmark",
- "BUILD_HOST_NATIVE_BENCHMARK": "cc_benchmark_host",
-
- "BUILD_JAVA_LIBRARY": "java_library_installable", // will be rewritten to java_library by bpfix
- "BUILD_STATIC_JAVA_LIBRARY": "java_library",
- "BUILD_HOST_JAVA_LIBRARY": "java_library_host",
- "BUILD_HOST_DALVIK_JAVA_LIBRARY": "java_library_host_dalvik",
- "BUILD_PACKAGE": "android_app",
-
- "BUILD_CTS_EXECUTABLE": "cc_binary", // will be further massaged by bpfix depending on the output path
- "BUILD_CTS_SUPPORT_PACKAGE": "cts_support_package", // will be rewritten to android_test by bpfix
- "BUILD_CTS_PACKAGE": "cts_package", // will be rewritten to android_test by bpfix
- "BUILD_CTS_TARGET_JAVA_LIBRARY": "cts_target_java_library", // will be rewritten to java_library by bpfix
- "BUILD_CTS_HOST_JAVA_LIBRARY": "cts_host_java_library", // will be rewritten to java_library_host by bpfix
-}
-
-var prebuiltTypes = map[string]string{
- "SHARED_LIBRARIES": "cc_prebuilt_library_shared",
- "STATIC_LIBRARIES": "cc_prebuilt_library_static",
- "EXECUTABLES": "cc_prebuilt_binary",
- "JAVA_LIBRARIES": "java_import",
- "APPS": "android_app_import",
- "ETC": "prebuilt_etc",
-}
-
-var soongModuleTypes = map[string]bool{}
-
-var includePathToModule = map[string]string{
- "test/vts/tools/build/Android.host_config.mk": "vts_config",
- // The rest will be populated dynamically in androidScope below
-}
-
-func mapIncludePath(path string) (string, bool) {
- if path == clear_vars || path == include_ignored {
- return path, true
- }
- module, ok := includePathToModule[path]
- return module, ok
-}
-
-func androidScope() mkparser.Scope {
- globalScope := mkparser.NewScope(nil)
- globalScope.Set("CLEAR_VARS", clear_vars)
- globalScope.SetFunc("my-dir", mydir)
- globalScope.SetFunc("all-java-files-under", allFilesUnder("*.java"))
- globalScope.SetFunc("all-proto-files-under", allFilesUnder("*.proto"))
- globalScope.SetFunc("all-aidl-files-under", allFilesUnder("*.aidl"))
- globalScope.SetFunc("all-Iaidl-files-under", allFilesUnder("I*.aidl"))
- globalScope.SetFunc("all-logtags-files-under", allFilesUnder("*.logtags"))
- globalScope.SetFunc("all-subdir-java-files", allSubdirJavaFiles)
- globalScope.SetFunc("all-makefiles-under", includeIgnored)
- globalScope.SetFunc("first-makefiles-under", includeIgnored)
- globalScope.SetFunc("all-named-subdir-makefiles", includeIgnored)
- globalScope.SetFunc("all-subdir-makefiles", includeIgnored)
-
- // The scope maps each known variable to a path, and then includePathToModule maps a path
- // to a module. We don't care what the actual path value is so long as the value in scope
- // is mapped, so we might as well use variable name as key, too.
- for varName, moduleName := range moduleTypes {
- path := varName
- globalScope.Set(varName, path)
- includePathToModule[path] = moduleName
- }
- for varName, moduleName := range prebuiltTypes {
- includePathToModule[varName] = moduleName
- }
-
- return globalScope
-}
diff --git a/androidmk/cmd/androidmk/androidmk.go b/androidmk/cmd/androidmk/androidmk.go
deleted file mode 100644
index d2a84d1..0000000
--- a/androidmk/cmd/androidmk/androidmk.go
+++ /dev/null
@@ -1,474 +0,0 @@
-// Copyright 2017 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package main
-
-import (
- "bytes"
- "flag"
- "fmt"
- "io/ioutil"
- "os"
- "strings"
- "text/scanner"
-
- "android/soong/bpfix/bpfix"
-
- mkparser "android/soong/androidmk/parser"
-
- bpparser "github.com/google/blueprint/parser"
-)
-
-var usage = func() {
- fmt.Fprintf(os.Stderr, "usage: androidmk [flags] <inputFile>\n"+
- "\nandroidmk parses <inputFile> as an Android.mk file and attempts to output an analogous Android.bp file (to standard out)\n")
- flag.PrintDefaults()
- os.Exit(1)
-}
-
-// TODO: non-expanded variables with expressions
-
-type bpFile struct {
- comments []*bpparser.CommentGroup
- defs []bpparser.Definition
- localAssignments map[string]*bpparser.Property
- globalAssignments map[string]*bpparser.Expression
- scope mkparser.Scope
- module *bpparser.Module
-
- mkPos scanner.Position // Position of the last handled line in the makefile
- bpPos scanner.Position // Position of the last emitted line to the blueprint file
-
- inModule bool
-}
-
-func (f *bpFile) insertComment(s string) {
- f.comments = append(f.comments, &bpparser.CommentGroup{
- Comments: []*bpparser.Comment{
- &bpparser.Comment{
- Comment: []string{s},
- Slash: f.bpPos,
- },
- },
- })
- f.bpPos.Offset += len(s)
-}
-
-func (f *bpFile) insertExtraComment(s string) {
- f.insertComment(s)
- f.bpPos.Line++
-}
-
-// records that the given node failed to be converted and includes an explanatory message
-func (f *bpFile) errorf(failedNode mkparser.Node, message string, args ...interface{}) {
- orig := failedNode.Dump()
- message = fmt.Sprintf(message, args...)
- f.addErrorText(fmt.Sprintf("// ANDROIDMK TRANSLATION ERROR: %s", message))
-
- lines := strings.Split(orig, "\n")
- for _, l := range lines {
- f.insertExtraComment("// " + l)
- }
-}
-
-// records that something unexpected occurred
-func (f *bpFile) warnf(message string, args ...interface{}) {
- message = fmt.Sprintf(message, args...)
- f.addErrorText(fmt.Sprintf("// ANDROIDMK TRANSLATION WARNING: %s", message))
-}
-
-// adds the given error message as-is to the bottom of the (in-progress) file
-func (f *bpFile) addErrorText(message string) {
- f.insertExtraComment(message)
-}
-
-func (f *bpFile) setMkPos(pos, end scanner.Position) {
- // It is unusual but not forbidden for pos.Line to be smaller than f.mkPos.Line
- // For example:
- //
- // if true # this line is emitted 1st
- // if true # this line is emitted 2nd
- // some-target: some-file # this line is emitted 3rd
- // echo doing something # this recipe is emitted 6th
- // endif #some comment # this endif is emitted 4th; this comment is part of the recipe
- // echo doing more stuff # this is part of the recipe
- // endif # this endif is emitted 5th
- //
- // However, if pos.Line < f.mkPos.Line, we treat it as though it were equal
- if pos.Line >= f.mkPos.Line {
- f.bpPos.Line += (pos.Line - f.mkPos.Line)
- f.mkPos = end
- }
-
-}
-
-type conditional struct {
- cond string
- eq bool
-}
-
-func main() {
- flag.Usage = usage
- flag.Parse()
- if len(flag.Args()) != 1 {
- usage()
- }
- filePathToRead := flag.Arg(0)
- b, err := ioutil.ReadFile(filePathToRead)
- if err != nil {
- fmt.Println(err.Error())
- return
- }
-
- output, errs := convertFile(os.Args[1], bytes.NewBuffer(b))
- if len(errs) > 0 {
- for _, err := range errs {
- fmt.Fprintln(os.Stderr, "ERROR: ", err)
- }
- os.Exit(1)
- }
-
- fmt.Print(output)
-}
-
-func convertFile(filename string, buffer *bytes.Buffer) (string, []error) {
- p := mkparser.NewParser(filename, buffer)
-
- nodes, errs := p.Parse()
- if len(errs) > 0 {
- return "", errs
- }
-
- file := &bpFile{
- scope: androidScope(),
- localAssignments: make(map[string]*bpparser.Property),
- globalAssignments: make(map[string]*bpparser.Expression),
- }
-
- var conds []*conditional
- var assignmentCond *conditional
-
- for _, node := range nodes {
- file.setMkPos(p.Unpack(node.Pos()), p.Unpack(node.End()))
-
- switch x := node.(type) {
- case *mkparser.Comment:
- file.insertComment("//" + x.Comment)
- case *mkparser.Assignment:
- handleAssignment(file, x, assignmentCond)
- case *mkparser.Directive:
- switch x.Name {
- case "include", "-include":
- module, ok := mapIncludePath(x.Args.Value(file.scope))
- if !ok {
- file.errorf(x, "unsupported include")
- continue
- }
- switch module {
- case clear_vars:
- resetModule(file)
- case include_ignored:
- // subdirs are already automatically included in Soong
- continue
- default:
- handleModuleConditionals(file, x, conds)
- makeModule(file, module)
- }
- case "ifeq", "ifneq", "ifdef", "ifndef":
- args := x.Args.Dump()
- eq := x.Name == "ifeq" || x.Name == "ifdef"
- if _, ok := conditionalTranslations[args]; ok {
- newCond := conditional{args, eq}
- conds = append(conds, &newCond)
- if file.inModule {
- if assignmentCond == nil {
- assignmentCond = &newCond
- } else {
- file.errorf(x, "unsupported nested conditional in module")
- }
- }
- } else {
- file.errorf(x, "unsupported conditional")
- conds = append(conds, nil)
- continue
- }
- case "else":
- if len(conds) == 0 {
- file.errorf(x, "missing if before else")
- continue
- } else if conds[len(conds)-1] == nil {
- file.errorf(x, "else from unsupported conditional")
- continue
- }
- conds[len(conds)-1].eq = !conds[len(conds)-1].eq
- case "endif":
- if len(conds) == 0 {
- file.errorf(x, "missing if before endif")
- continue
- } else if conds[len(conds)-1] == nil {
- file.errorf(x, "endif from unsupported conditional")
- conds = conds[:len(conds)-1]
- } else {
- if assignmentCond == conds[len(conds)-1] {
- assignmentCond = nil
- }
- conds = conds[:len(conds)-1]
- }
- default:
- file.errorf(x, "unsupported directive")
- continue
- }
- default:
- file.errorf(x, "unsupported line")
- }
- }
-
- tree := &bpparser.File{
- Defs: file.defs,
- Comments: file.comments,
- }
-
- // check for common supported but undesirable structures and clean them up
- fixer := bpfix.NewFixer(tree)
- tree, err := fixer.Fix(bpfix.NewFixRequest().AddAll())
- if err != nil {
- return "", []error{err}
- }
-
- out, err := bpparser.Print(tree)
- if err != nil {
- return "", []error{err}
- }
-
- return string(out), nil
-}
-
-func handleAssignment(file *bpFile, assignment *mkparser.Assignment, c *conditional) {
- if !assignment.Name.Const() {
- file.errorf(assignment, "unsupported non-const variable name")
- return
- }
-
- if assignment.Target != nil {
- file.errorf(assignment, "unsupported target assignment")
- return
- }
-
- name := assignment.Name.Value(nil)
- prefix := ""
-
- if strings.HasPrefix(name, "LOCAL_") {
- for _, x := range propertyPrefixes {
- if strings.HasSuffix(name, "_"+x.mk) {
- name = strings.TrimSuffix(name, "_"+x.mk)
- prefix = x.bp
- break
- }
- }
-
- if c != nil {
- if prefix != "" {
- file.errorf(assignment, "prefix assignment inside conditional, skipping conditional")
- } else {
- var ok bool
- if prefix, ok = conditionalTranslations[c.cond][c.eq]; !ok {
- panic("unknown conditional")
- }
- }
- }
- } else {
- if c != nil {
- eq := "eq"
- if !c.eq {
- eq = "neq"
- }
- file.errorf(assignment, "conditional %s %s on global assignment", eq, c.cond)
- }
- }
-
- appendVariable := assignment.Type == "+="
-
- var err error
- if prop, ok := rewriteProperties[name]; ok {
- err = prop(variableAssignmentContext{file, prefix, assignment.Value, appendVariable})
- } else {
- switch {
- case name == "LOCAL_ARM_MODE":
- // This is a hack to get the LOCAL_ARM_MODE value inside
- // of an arch: { arm: {} } block.
- armModeAssign := assignment
- armModeAssign.Name = mkparser.SimpleMakeString("LOCAL_ARM_MODE_HACK_arm", assignment.Name.Pos())
- handleAssignment(file, armModeAssign, c)
- case strings.HasPrefix(name, "LOCAL_"):
- file.errorf(assignment, "unsupported assignment to %s", name)
- return
- default:
- var val bpparser.Expression
- val, err = makeVariableToBlueprint(file, assignment.Value, bpparser.ListType)
- if err == nil {
- err = setVariable(file, appendVariable, prefix, name, val, false)
- }
- }
- }
- if err != nil {
- file.errorf(assignment, err.Error())
- }
-}
-
-func handleModuleConditionals(file *bpFile, directive *mkparser.Directive, conds []*conditional) {
- for _, c := range conds {
- if c == nil {
- continue
- }
-
- if _, ok := conditionalTranslations[c.cond]; !ok {
- panic("unknown conditional " + c.cond)
- }
-
- disabledPrefix := conditionalTranslations[c.cond][!c.eq]
-
- // Create a fake assignment with enabled = false
- val, err := makeVariableToBlueprint(file, mkparser.SimpleMakeString("false", mkparser.NoPos), bpparser.BoolType)
- if err == nil {
- err = setVariable(file, false, disabledPrefix, "enabled", val, true)
- }
- if err != nil {
- file.errorf(directive, err.Error())
- }
- }
-}
-
-func makeModule(file *bpFile, t string) {
- file.module.Type = t
- file.module.TypePos = file.module.LBracePos
- file.module.RBracePos = file.bpPos
- file.defs = append(file.defs, file.module)
- file.inModule = false
-}
-
-func resetModule(file *bpFile) {
- file.module = &bpparser.Module{}
- file.module.LBracePos = file.bpPos
- file.localAssignments = make(map[string]*bpparser.Property)
- file.inModule = true
-}
-
-func makeVariableToBlueprint(file *bpFile, val *mkparser.MakeString,
- typ bpparser.Type) (bpparser.Expression, error) {
-
- var exp bpparser.Expression
- var err error
- switch typ {
- case bpparser.ListType:
- exp, err = makeToListExpression(val, file.scope)
- case bpparser.StringType:
- exp, err = makeToStringExpression(val, file.scope)
- case bpparser.BoolType:
- exp, err = makeToBoolExpression(val)
- default:
- panic("unknown type")
- }
-
- if err != nil {
- return nil, err
- }
-
- return exp, nil
-}
-
-func setVariable(file *bpFile, plusequals bool, prefix, name string, value bpparser.Expression, local bool) error {
-
- if prefix != "" {
- name = prefix + "." + name
- }
-
- pos := file.bpPos
-
- var oldValue *bpparser.Expression
- if local {
- oldProp := file.localAssignments[name]
- if oldProp != nil {
- oldValue = &oldProp.Value
- }
- } else {
- oldValue = file.globalAssignments[name]
- }
-
- if local {
- if oldValue != nil && plusequals {
- val, err := addValues(*oldValue, value)
- if err != nil {
- return fmt.Errorf("unsupported addition: %s", err.Error())
- }
- val.(*bpparser.Operator).OperatorPos = pos
- *oldValue = val
- } else {
- names := strings.Split(name, ".")
- if file.module == nil {
- file.warnf("No 'include $(CLEAR_VARS)' detected before first assignment; clearing vars now")
- resetModule(file)
- }
- container := &file.module.Properties
-
- for i, n := range names[:len(names)-1] {
- fqn := strings.Join(names[0:i+1], ".")
- prop := file.localAssignments[fqn]
- if prop == nil {
- prop = &bpparser.Property{
- Name: n,
- NamePos: pos,
- Value: &bpparser.Map{
- Properties: []*bpparser.Property{},
- },
- }
- file.localAssignments[fqn] = prop
- *container = append(*container, prop)
- }
- container = &prop.Value.(*bpparser.Map).Properties
- }
-
- prop := &bpparser.Property{
- Name: names[len(names)-1],
- NamePos: pos,
- Value: value,
- }
- file.localAssignments[name] = prop
- *container = append(*container, prop)
- }
- } else {
- if oldValue != nil && plusequals {
- a := &bpparser.Assignment{
- Name: name,
- NamePos: pos,
- Value: value,
- OrigValue: value,
- EqualsPos: pos,
- Assigner: "+=",
- }
- file.defs = append(file.defs, a)
- } else {
- a := &bpparser.Assignment{
- Name: name,
- NamePos: pos,
- Value: value,
- OrigValue: value,
- EqualsPos: pos,
- Assigner: "=",
- }
- file.globalAssignments[name] = &a.Value
- file.defs = append(file.defs, a)
- }
- }
- return nil
-}
diff --git a/androidmk/cmd/androidmk/androidmk_test.go b/androidmk/cmd/androidmk/androidmk_test.go
deleted file mode 100644
index dbb7fde..0000000
--- a/androidmk/cmd/androidmk/androidmk_test.go
+++ /dev/null
@@ -1,1363 +0,0 @@
-// Copyright 2016 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package main
-
-import (
- "bytes"
- "fmt"
- "strings"
- "testing"
-
- "android/soong/bpfix/bpfix"
-)
-
-var testCases = []struct {
- desc string
- in string
- expected string
-}{
- {
- desc: "basic cc_library_shared with comments",
- in: `
-#
-# Copyright
-#
-
-# Module Comment
-include $(CLEAR_VARS)
-# Name Comment
-LOCAL_MODULE := test
-# Source comment
-LOCAL_SRC_FILES_EXCLUDE := a.c
-# Second source comment
-LOCAL_SRC_FILES_EXCLUDE += b.c
-include $(BUILD_SHARED_LIBRARY)`,
- expected: `
-//
-// Copyright
-//
-
-// Module Comment
-cc_library_shared {
- // Name Comment
- name: "test",
- // Source comment
- exclude_srcs: ["a.c"] + ["b.c"], // Second source comment
-
-}`,
- },
- {
- desc: "split local/global include_dirs (1)",
- in: `
-include $(CLEAR_VARS)
-LOCAL_C_INCLUDES := $(LOCAL_PATH)
-include $(BUILD_SHARED_LIBRARY)`,
- expected: `
-cc_library_shared {
- local_include_dirs: ["."],
-}`,
- },
- {
- desc: "split local/global include_dirs (2)",
- in: `
-include $(CLEAR_VARS)
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-include $(BUILD_SHARED_LIBRARY)`,
- expected: `
-cc_library_shared {
- local_include_dirs: ["include"],
-}`,
- },
- {
- desc: "split local/global include_dirs (3)",
- in: `
-include $(CLEAR_VARS)
-LOCAL_C_INCLUDES := system/core/include
-include $(BUILD_SHARED_LIBRARY)`,
- expected: `
-cc_library_shared {
- include_dirs: ["system/core/include"],
-}`,
- },
- {
- desc: "split local/global include_dirs (4)",
- in: `
-input := testing/include
-include $(CLEAR_VARS)
-# Comment 1
-LOCAL_C_INCLUDES := $(LOCAL_PATH) $(LOCAL_PATH)/include system/core/include $(input)
-# Comment 2
-LOCAL_C_INCLUDES += $(TOP)/system/core/include $(LOCAL_PATH)/test/include
-# Comment 3
-include $(BUILD_SHARED_LIBRARY)`,
- expected: `
-input = ["testing/include"]
-cc_library_shared {
- // Comment 1
- include_dirs: ["system/core/include"] + input + ["system/core/include"], // Comment 2
- local_include_dirs: ["."] + ["include"] + ["test/include"],
- // Comment 3
-}`,
- },
- {
- desc: "Convert to local path",
- in: `
-include $(CLEAR_VARS)
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res $(LOCAL_PATH)/res2
-LOCAL_ASSET_DIR := $(LOCAL_PATH)/asset
-LOCAL_JARJAR_RULES := $(LOCAL_PATH)/jarjar-rules.txt
-include $(BUILD_PACKAGE)
- `,
- expected: `
-android_app {
- resource_dirs: [
- "res",
- "res2",
- ],
- asset_dirs: ["asset"],
- jarjar_rules: "jarjar-rules.txt",
-}`,
- },
- {
- desc: "LOCAL_MODULE_STEM",
- in: `
-include $(CLEAR_VARS)
-LOCAL_MODULE := libtest
-LOCAL_MODULE_STEM := $(LOCAL_MODULE).so
-include $(BUILD_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := libtest2
-LOCAL_MODULE_STEM := testing.so
-include $(BUILD_SHARED_LIBRARY)
-`,
- expected: `
-cc_library_shared {
- name: "libtest",
- suffix: ".so",
-}
-
-cc_library_shared {
- name: "libtest2",
- stem: "testing.so",
-}
-`,
- },
- {
- desc: "LOCAL_MODULE_HOST_OS",
- in: `
-include $(CLEAR_VARS)
-LOCAL_MODULE := libtest
-LOCAL_MODULE_HOST_OS := linux darwin windows
-include $(BUILD_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := libtest2
-LOCAL_MODULE_HOST_OS := linux
-include $(BUILD_SHARED_LIBRARY)
-`,
- expected: `
-cc_library_shared {
- name: "libtest",
- target: {
- windows: {
- enabled: true,
- }
- }
-}
-
-cc_library_shared {
- name: "libtest2",
- target: {
- darwin: {
- enabled: false,
- }
- }
-}
-`,
- },
- {
- desc: "LOCAL_RTTI_VALUE",
- in: `
-include $(CLEAR_VARS)
-LOCAL_MODULE := libtest
-LOCAL_RTTI_FLAG := # Empty flag
-include $(BUILD_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := libtest2
-LOCAL_RTTI_FLAG := -frtti
-include $(BUILD_SHARED_LIBRARY)
-`,
- expected: `
-cc_library_shared {
- name: "libtest",
- rtti: false, // Empty flag
-}
-
-cc_library_shared {
- name: "libtest2",
- rtti: true,
-}
-`,
- },
- {
- desc: "LOCAL_ARM_MODE",
- in: `
-include $(CLEAR_VARS)
-LOCAL_ARM_MODE := arm
-include $(BUILD_SHARED_LIBRARY)
-`,
- expected: `
-cc_library_shared {
- arch: {
- arm: {
- instruction_set: "arm",
- },
- },
-}
-`,
- },
- {
- desc: "_<OS> suffixes",
- in: `
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES_darwin := darwin.c
-LOCAL_SRC_FILES_linux := linux.c
-LOCAL_SRC_FILES_windows := windows.c
-include $(BUILD_SHARED_LIBRARY)
-`,
- expected: `
-cc_library_shared {
- target: {
- darwin: {
- srcs: ["darwin.c"],
- },
- linux_glibc: {
- srcs: ["linux.c"],
- },
- windows: {
- srcs: ["windows.c"],
- },
- },
-}
-`,
- },
- {
- desc: "LOCAL_SANITIZE := never",
- in: `
-include $(CLEAR_VARS)
-LOCAL_SANITIZE := never
-include $(BUILD_SHARED_LIBRARY)
-`,
- expected: `
-cc_library_shared {
- sanitize: {
- never: true,
- },
-}
-`,
- },
- {
- desc: "LOCAL_SANITIZE unknown parameter",
- in: `
-include $(CLEAR_VARS)
-LOCAL_SANITIZE := thread cfi asdf
-LOCAL_SANITIZE_DIAG := cfi
-LOCAL_SANITIZE_RECOVER := qwert
-include $(BUILD_SHARED_LIBRARY)
-`,
- expected: `
-cc_library_shared {
- sanitize: {
- thread: true,
- cfi: true,
- misc_undefined: ["asdf"],
- diag: {
- cfi: true,
- },
- recover: ["qwert"],
- },
-}
-`,
- },
- {
- desc: "LOCAL_SANITIZE_RECOVER",
- in: `
-include $(CLEAR_VARS)
-LOCAL_SANITIZE_RECOVER := shift-exponent
-include $(BUILD_SHARED_LIBRARY)
-`,
- expected: `
-cc_library_shared {
- sanitize: {
- recover: ["shift-exponent"],
- },
-}
-`,
- },
- {
- desc: "version_script in LOCAL_LDFLAGS",
- in: `
-include $(CLEAR_VARS)
-LOCAL_LDFLAGS := -Wl,--link-opt -Wl,--version-script,$(LOCAL_PATH)/exported32.map
-include $(BUILD_SHARED_LIBRARY)
-`,
- expected: `
-cc_library_shared {
- ldflags: ["-Wl,--link-opt"],
- version_script: "exported32.map",
-}
-`,
- },
- {
- desc: "Handle TOP",
- in: `
-include $(CLEAR_VARS)
-LOCAL_C_INCLUDES := $(TOP)/system/core/include $(TOP)
-include $(BUILD_SHARED_LIBRARY)
-`,
- expected: `
-cc_library_shared {
- include_dirs: ["system/core/include", "."],
-}
-`,
- },
- {
- desc: "Remove LOCAL_MODULE_TAGS optional",
- in: `
-include $(CLEAR_VARS)
-LOCAL_MODULE_TAGS := optional
-include $(BUILD_SHARED_LIBRARY)
-`,
-
- expected: `
-cc_library_shared {
-
-}
-`,
- },
- {
- desc: "Warn for LOCAL_MODULE_TAGS non-optional",
- in: `
-include $(CLEAR_VARS)
-LOCAL_MODULE_TAGS := debug
-include $(BUILD_SHARED_LIBRARY)
-`,
-
- expected: `
-cc_library_shared {
- // WARNING: Module tags are not supported in Soong.
- // Add this module to PRODUCT_PACKAGES_DEBUG in your product file if you want to
- // force installation for -userdebug and -eng builds.
-}
-`,
- },
- {
- desc: "Custom warning for LOCAL_MODULE_TAGS tests",
- in: `
-include $(CLEAR_VARS)
-LOCAL_MODULE_TAGS := debug tests
-include $(BUILD_SHARED_LIBRARY)
-`,
-
- expected: `
-cc_library_shared {
- // WARNING: Module tags are not supported in Soong.
- // Add this module to PRODUCT_PACKAGES_DEBUG in your product file if you want to
- // force installation for -userdebug and -eng builds.
- // WARNING: Module tags are not supported in Soong.
- // To make a shared library only for tests, use the "cc_test_library" module
- // type. If you don't use gtest, set "gtest: false".
-}
-`,
- },
- {
- desc: "Ignore LOCAL_MODULE_TAGS tests for cc_test",
- in: `
-include $(CLEAR_VARS)
-LOCAL_MODULE_TAGS := tests
-include $(BUILD_NATIVE_TEST)
-`,
-
- expected: `
-cc_test {
-}
-`,
- },
- {
- desc: "Convert LOCAL_MODULE_TAGS tests to java_test",
- in: `
-include $(CLEAR_VARS)
-LOCAL_MODULE_TAGS := tests
-include $(BUILD_JAVA_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE_TAGS := tests
-include $(BUILD_PACKAGE)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE_TAGS := tests
-include $(BUILD_HOST_JAVA_LIBRARY)
-`,
-
- expected: `
-java_test {
-}
-
-android_test {
-}
-
-java_test_host {
-}
-`,
- },
-
- {
- desc: "Input containing escaped quotes",
- in: `
-include $(CLEAR_VARS)
-LOCAL_MODULE:= libsensorservice
-LOCAL_CFLAGS:= -DLOG_TAG=\"-DDontEscapeMe\"
-LOCAL_SRC_FILES := \"EscapeMe.cc\"
-include $(BUILD_SHARED_LIBRARY)
-`,
-
- expected: `
-cc_library_shared {
- name: "libsensorservice",
- cflags: ["-DLOG_TAG=\"-DDontEscapeMe\""],
- srcs: ["\\\"EscapeMe.cc\\\""],
-}
-`,
- },
- {
-
- desc: "Don't fail on missing CLEAR_VARS",
- in: `
-LOCAL_MODULE := iAmAModule
-include $(BUILD_SHARED_LIBRARY)`,
-
- expected: `
-// ANDROIDMK TRANSLATION WARNING: No 'include $(CLEAR_VARS)' detected before first assignment; clearing vars now
-cc_library_shared {
- name: "iAmAModule",
-
-}`,
- },
- {
-
- desc: "LOCAL_AIDL_INCLUDES",
- in: `
-include $(CLEAR_VARS)
-LOCAL_MODULE := iAmAModule
-LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/src/main/java system/core
-include $(BUILD_SHARED_LIBRARY)`,
-
- expected: `
-cc_library_shared {
- name: "iAmAModule",
- aidl: {
- include_dirs: ["system/core"],
- local_include_dirs: ["src/main/java"],
- }
-}`,
- },
- {
- // the important part of this test case is that it confirms that androidmk doesn't
- // panic in this case
- desc: "multiple directives inside recipe",
- in: `
-ifeq ($(a),true)
-ifeq ($(b),false)
-imABuildStatement: somefile
- echo begin
-endif # a==true
- echo middle
-endif # b==false
- echo end
-`,
- expected: `
-// ANDROIDMK TRANSLATION ERROR: unsupported conditional
-// ifeq ($(a),true)
-
-// ANDROIDMK TRANSLATION ERROR: unsupported conditional
-// ifeq ($(b),false)
-
-// ANDROIDMK TRANSLATION ERROR: unsupported line
-// rule: imABuildStatement: somefile
-// echo begin
-// # a==true
-// echo middle
-// # b==false
-// echo end
-//
-// ANDROIDMK TRANSLATION ERROR: endif from unsupported conditional
-// endif
-// ANDROIDMK TRANSLATION ERROR: endif from unsupported conditional
-// endif
- `,
- },
- {
- desc: "ignore all-makefiles-under",
- in: `
-include $(call all-makefiles-under,$(LOCAL_PATH))
-`,
- expected: ``,
- },
- {
- desc: "proguard options for java library",
- in: `
- include $(CLEAR_VARS)
- # Empty
- LOCAL_PROGUARD_ENABLED :=
- # Disabled
- LOCAL_PROGUARD_ENABLED := disabled
- # Full
- LOCAL_PROGUARD_ENABLED := full
- # Obfuscation and optimization
- LOCAL_PROGUARD_ENABLED := obfuscation optimization
- # Custom
- LOCAL_PROGUARD_ENABLED := custom
- include $(BUILD_STATIC_JAVA_LIBRARY)
- `,
- expected: `
- java_library {
- // Empty
-
- // Disabled
- optimize: {
- enabled: false,
- // Full
- enabled: true,
- // Obfuscation and optimization
- obfuscate: true,
- optimize: true,
- enabled: true,
- // Custom
- no_aapt_flags: true,
- enabled: true,
- },
- }
- `,
- },
- {
- desc: "java library",
- in: `
- include $(CLEAR_VARS)
- LOCAL_SRC_FILES := a.java
- include $(BUILD_STATIC_JAVA_LIBRARY)
-
- include $(CLEAR_VARS)
- LOCAL_SRC_FILES := b.java
- include $(BUILD_JAVA_LIBRARY)
-
- include $(CLEAR_VARS)
- LOCAL_SRC_FILES := c.java
- LOCAL_UNINSTALLABLE_MODULE := true
- include $(BUILD_JAVA_LIBRARY)
-
- include $(CLEAR_VARS)
- LOCAL_SRC_FILES := d.java
- LOCAL_UNINSTALLABLE_MODULE := false
- include $(BUILD_JAVA_LIBRARY)
-
- include $(CLEAR_VARS)
- LOCAL_SRC_FILES := $(call all-java-files-under, src gen)
- include $(BUILD_STATIC_JAVA_LIBRARY)
-
- include $(CLEAR_VARS)
- LOCAL_JAVA_RESOURCE_FILES := foo bar
- include $(BUILD_STATIC_JAVA_LIBRARY)
- `,
- expected: `
- java_library {
- srcs: ["a.java"],
- }
-
- java_library {
- installable: true,
- srcs: ["b.java"],
- }
-
- java_library {
- installable: false,
- srcs: ["c.java"],
- }
-
- java_library {
- installable: true,
- srcs: ["d.java"],
- }
-
- java_library {
- srcs: [
- "src/**/*.java",
- "gen/**/*.java",
- ],
- }
-
- java_library {
- java_resources: [
- "foo",
- "bar",
- ],
- }
- `,
- },
- {
- desc: "errorprone options for java library",
- in: `
- include $(CLEAR_VARS)
- LOCAL_ERROR_PRONE_FLAGS := -Xep:AsyncCallableReturnsNull:ERROR -Xep:AsyncFunctionReturnsNull:ERROR
- include $(BUILD_STATIC_JAVA_LIBRARY)
- `,
- expected: `
- java_library {
- errorprone: {
- javacflags: [
- "-Xep:AsyncCallableReturnsNull:ERROR",
- "-Xep:AsyncFunctionReturnsNull:ERROR",
- ],
- },
- }
- `,
- },
- {
- desc: "java prebuilt",
- in: `
- include $(CLEAR_VARS)
- LOCAL_SRC_FILES := test.jar
- LOCAL_MODULE_CLASS := JAVA_LIBRARIES
- LOCAL_STATIC_ANDROID_LIBRARIES :=
- LOCAL_JETIFIER_ENABLED := true
- include $(BUILD_PREBUILT)
- `,
- expected: `
- java_import {
- jars: ["test.jar"],
-
- jetifier: true,
- }
- `,
- },
- {
- desc: "aar prebuilt",
- in: `
- include $(CLEAR_VARS)
- LOCAL_SRC_FILES := test.aar
- LOCAL_MODULE_CLASS := JAVA_LIBRARIES
- include $(BUILD_PREBUILT)
- `,
- expected: `
- android_library_import {
- aars: ["test.aar"],
-
- }
- `,
- },
-
- {
- desc: "aar",
- in: `
- include $(CLEAR_VARS)
- LOCAL_SRC_FILES := test.java
- LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
- LOCAL_JACK_COVERAGE_INCLUDE_FILTER := foo.*
- include $(BUILD_STATIC_JAVA_LIBRARY)
-
- include $(CLEAR_VARS)
- LOCAL_SRC_FILES := test.java
- LOCAL_STATIC_LIBRARIES := foo
- LOCAL_STATIC_ANDROID_LIBRARIES := bar
- LOCAL_JACK_COVERAGE_EXCLUDE_FILTER := bar.*
- include $(BUILD_STATIC_JAVA_LIBRARY)
-
- include $(CLEAR_VARS)
- LOCAL_SRC_FILES := test.java
- LOCAL_SHARED_LIBRARIES := foo
- LOCAL_SHARED_ANDROID_LIBRARIES := bar
- include $(BUILD_STATIC_JAVA_LIBRARY)
-
- include $(CLEAR_VARS)
- LOCAL_SRC_FILES := test.java
- LOCAL_STATIC_ANDROID_LIBRARIES :=
- include $(BUILD_STATIC_JAVA_LIBRARY)
- `,
- expected: `
- android_library {
- srcs: ["test.java"],
- resource_dirs: ["res"],
- jacoco: {
- include_filter: ["foo.*"],
- },
- }
-
- android_library {
- srcs: ["test.java"],
- static_libs: [
- "foo",
- "bar",
- ],
- jacoco: {
- exclude_filter: ["bar.*"],
- },
- }
-
- android_library {
- srcs: ["test.java"],
- libs: [
- "foo",
- "bar",
- ],
- }
-
- java_library {
- srcs: ["test.java"],
- static_libs: [],
- }
- `,
- },
- {
- desc: "cc_library shared_libs",
- in: `
- include $(CLEAR_VARS)
- LOCAL_SHARED_LIBRARIES := libfoo
- include $(BUILD_SHARED_LIBRARY)
- `,
- expected: `
- cc_library_shared {
- shared_libs: ["libfoo"],
- }
- `,
- },
- {
- desc: "LOCAL_STRIP_MODULE",
- in: `
-include $(CLEAR_VARS)
-LOCAL_MODULE := libtest
-LOCAL_STRIP_MODULE := false
-include $(BUILD_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := libtest2
-LOCAL_STRIP_MODULE := true
-include $(BUILD_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := libtest3
-LOCAL_STRIP_MODULE := keep_symbols
-include $(BUILD_SHARED_LIBRARY)
-`,
- expected: `
-cc_library_shared {
- name: "libtest",
- strip: {
- none: true,
- }
-}
-
-cc_library_shared {
- name: "libtest2",
- strip: {
- all: true,
- }
-}
-
-cc_library_shared {
- name: "libtest3",
- strip: {
- keep_symbols: true,
- }
-}
-`,
- },
- {
- desc: "BUILD_CTS_SUPPORT_PACKAGE",
- in: `
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := FooTest
-LOCAL_COMPATIBILITY_SUITE := cts
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-include $(BUILD_CTS_SUPPORT_PACKAGE)
-`,
- expected: `
-android_test {
- name: "FooTest",
- defaults: ["cts_support_defaults"],
- test_suites: ["cts"],
-
-}
-`,
- },
- {
- desc: "BUILD_CTS_PACKAGE",
- in: `
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := FooTest
-LOCAL_COMPATIBILITY_SUITE := cts
-LOCAL_CTS_TEST_PACKAGE := foo.bar
-LOCAL_COMPATIBILITY_SUPPORT_FILES := file1
-include $(BUILD_CTS_PACKAGE)
-`,
- expected: `
-android_test {
- name: "FooTest",
- defaults: ["cts_defaults"],
- test_suites: ["cts"],
-
- data: ["file1"],
-}
-`,
- },
- {
- desc: "BUILD_CTS_*_JAVA_LIBRARY",
- in: `
-include $(CLEAR_VARS)
-LOCAL_MODULE := foolib
-include $(BUILD_CTS_TARGET_JAVA_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := foolib-host
-include $(BUILD_CTS_HOST_JAVA_LIBRARY)
-`,
- expected: `
-java_library {
- name: "foolib",
- defaults: ["cts_defaults"],
-}
-
-java_library_host {
- name: "foolib-host",
- defaults: ["cts_defaults"],
-}
-`,
- },
- {
- desc: "LOCAL_ANNOTATION_PROCESSORS",
- in: `
-include $(CLEAR_VARS)
-LOCAL_MODULE := foolib
-LOCAL_ANNOTATION_PROCESSORS := bar
-LOCAL_ANNOTATION_PROCESSOR_CLASSES := com.bar
-include $(BUILD_STATIC_JAVA_LIBRARY)
-`,
- expected: `
-java_library {
- name: "foolib",
- plugins: ["bar"],
-
-}
-`,
- },
- {
- desc: "prebuilt_etc_TARGET_OUT_ETC",
- in: `
-include $(CLEAR_VARS)
-LOCAL_MODULE := etc.test1
-LOCAL_SRC_FILES := mymod
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/foo/bar
-include $(BUILD_PREBUILT)
-`,
- expected: `
-prebuilt_etc {
- name: "etc.test1",
- src: "mymod",
- sub_dir: "foo/bar",
-
-}
-`,
- },
- {
- desc: "prebuilt_etc_PRODUCT_OUT/system/etc",
- in: `
-include $(CLEAR_VARS)
-LOCAL_MODULE := etc.test1
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(PRODUCT_OUT)/system/etc/foo/bar
-LOCAL_SRC_FILES := $(LOCAL_MODULE)
-include $(BUILD_PREBUILT)
-`,
- expected: `
-prebuilt_etc {
- name: "etc.test1",
-
- src: "etc.test1",
- sub_dir: "foo/bar",
-
-}
-`,
- },
- {
- desc: "prebuilt_etc_TARGET_OUT_ODM/etc",
- in: `
-include $(CLEAR_VARS)
-LOCAL_MODULE := etc.test1
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_ODM)/etc/foo/bar
-include $(BUILD_PREBUILT)
-`,
- expected: `
-prebuilt_etc {
- name: "etc.test1",
- sub_dir: "foo/bar",
- device_specific: true,
-
-}
-`,
- },
- {
- desc: "prebuilt_etc_TARGET_OUT_PRODUCT/etc",
- in: `
-include $(CLEAR_VARS)
-LOCAL_MODULE := etc.test1
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT)/etc/foo/bar
-include $(BUILD_PREBUILT)
-`,
- expected: `
-prebuilt_etc {
- name: "etc.test1",
- sub_dir: "foo/bar",
- product_specific: true,
-
-
-}
-`,
- },
- {
- desc: "prebuilt_etc_TARGET_OUT_PRODUCT_ETC",
- in: `
-include $(CLEAR_VARS)
-LOCAL_MODULE := etc.test1
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_ETC)/foo/bar
-include $(BUILD_PREBUILT)
-`,
- expected: `
-prebuilt_etc {
- name: "etc.test1",
- sub_dir: "foo/bar",
- product_specific: true,
-
-}
-`,
- },
- {
- desc: "prebuilt_etc_TARGET_OUT_SYSTEM_EXT/etc",
- in: `
-include $(CLEAR_VARS)
-LOCAL_MODULE := etc.test1
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_SYSTEM_EXT)/etc/foo/bar
-include $(BUILD_PREBUILT)
-`,
- expected: `
-prebuilt_etc {
- name: "etc.test1",
- sub_dir: "foo/bar",
- system_ext_specific: true,
-
-}
-`,
- },
- {
- desc: "prebuilt_etc_TARGET_OUT_SYSTEM_EXT_ETC",
- in: `
-include $(CLEAR_VARS)
-LOCAL_MODULE := etc.test1
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_SYSTEM_EXT_ETC)/foo/bar
-include $(BUILD_PREBUILT)
-`,
- expected: `
-prebuilt_etc {
- name: "etc.test1",
- sub_dir: "foo/bar",
- system_ext_specific: true,
-
-
-}
-`,
- },
- {
- desc: "prebuilt_etc_TARGET_OUT_VENDOR/etc",
- in: `
-include $(CLEAR_VARS)
-LOCAL_MODULE := etc.test1
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/etc/foo/bar
-include $(BUILD_PREBUILT)
-`,
- expected: `
-prebuilt_etc {
- name: "etc.test1",
- sub_dir: "foo/bar",
- proprietary: true,
-
-}
-`,
- },
- {
- desc: "prebuilt_etc_PRODUCT_OUT/TARGET_COPY_OUT_VENDOR/etc",
- in: `
-include $(CLEAR_VARS)
-LOCAL_MODULE := etc.test1
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_VENDOR)/etc/foo/bar
-include $(BUILD_PREBUILT)
-`,
- expected: `
-prebuilt_etc {
- name: "etc.test1",
- sub_dir: "foo/bar",
- proprietary: true,
-
-}
-`,
- },
- {
- desc: "prebuilt_etc_TARGET_OUT_VENDOR_ETC",
- in: `
-include $(CLEAR_VARS)
-LOCAL_MODULE := etc.test1
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_ETC)/foo/bar
-include $(BUILD_PREBUILT)
-`,
- expected: `
-prebuilt_etc {
- name: "etc.test1",
- sub_dir: "foo/bar",
- proprietary: true,
-
-}
-`,
- },
- {
- desc: "prebuilt_etc_TARGET_RECOVERY_ROOT_OUT/system/etc",
- in: `
-include $(CLEAR_VARS)
-LOCAL_MODULE := etc.test1
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/system/etc/foo/bar
-include $(BUILD_PREBUILT)
-`,
- expected: `
-prebuilt_etc {
- name: "etc.test1",
- sub_dir: "foo/bar",
- recovery: true,
-
-}
-`,
- },
- {
- desc: "prebuilt_usr_share",
- in: `
-include $(CLEAR_VARS)
-LOCAL_MODULE := foo
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT)/usr/share
-LOCAL_SRC_FILES := foo.txt
-include $(BUILD_PREBUILT)
-`,
- expected: `
-prebuilt_usr_share {
- name: "foo",
-
- src: "foo.txt",
-}
-`,
- },
- {
- desc: "prebuilt_usr_share subdir_bar",
- in: `
-include $(CLEAR_VARS)
-LOCAL_MODULE := foo
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT)/usr/share/bar
-LOCAL_SRC_FILES := foo.txt
-include $(BUILD_PREBUILT)
-`,
- expected: `
-prebuilt_usr_share {
- name: "foo",
-
- src: "foo.txt",
- sub_dir: "bar",
-}
-`,
- },
- {
- desc: "prebuilt_usr_share_host",
- in: `
-include $(CLEAR_VARS)
-LOCAL_MODULE := foo
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(HOST_OUT)/usr/share
-LOCAL_SRC_FILES := foo.txt
-include $(BUILD_PREBUILT)
-`,
- expected: `
-prebuilt_usr_share_host {
- name: "foo",
-
- src: "foo.txt",
-}
-`,
- },
- {
- desc: "prebuilt_font",
- in: `
-include $(CLEAR_VARS)
-LOCAL_MODULE := font.ttf
-LOCAL_SRC_FILES := $(LOCAL_MODULE)
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_PATH := $(TARGET_OUT)/fonts
-include $(BUILD_PREBUILT)
-`,
- expected: `
-prebuilt_font {
- name: "font.ttf",
- src: "font.ttf",
-
-}
-`,
- },
- {
- desc: "prebuilt_font",
- in: `
-include $(CLEAR_VARS)
-LOCAL_MODULE := font.ttf
-LOCAL_SRC_FILES := $(LOCAL_MODULE)
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT)/fonts
-include $(BUILD_PREBUILT)
-`,
- expected: `
-prebuilt_font {
- name: "font.ttf",
- src: "font.ttf",
- product_specific: true,
-
-}
-`,
- },
- {
- desc: "prebuilt_usr_share_host subdir_bar",
- in: `
-include $(CLEAR_VARS)
-LOCAL_MODULE := foo
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(HOST_OUT)/usr/share/bar
-LOCAL_SRC_FILES := foo.txt
-include $(BUILD_PREBUILT)
-`,
- expected: `
-prebuilt_usr_share_host {
- name: "foo",
-
- src: "foo.txt",
- sub_dir: "bar",
-}
-`,
- },
- {
- desc: "prebuilt_firmware subdir_bar in $(TARGET_OUT_ETC)",
- in: `
-include $(CLEAR_VARS)
-LOCAL_MODULE := foo
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/firmware/bar
-LOCAL_SRC_FILES := foo.fw
-include $(BUILD_PREBUILT)
-`,
- expected: `
-prebuilt_firmware {
- name: "foo",
-
- src: "foo.fw",
- sub_dir: "bar",
-}
-`,
- },
- {
- desc: "prebuilt_firmware subdir_bar in $(TARGET_OUT)",
- in: `
-include $(CLEAR_VARS)
-LOCAL_MODULE := foo
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT)/etc/firmware/bar
-LOCAL_SRC_FILES := foo.fw
-include $(BUILD_PREBUILT)
-`,
- expected: `
-prebuilt_firmware {
- name: "foo",
-
- src: "foo.fw",
- sub_dir: "bar",
-}
-`,
- },
- {
- desc: "prebuilt_firmware subdir_bar in $(TARGET_OUT_VENDOR)",
- in: `
-include $(CLEAR_VARS)
-LOCAL_MODULE := foo
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/firmware/bar
-LOCAL_SRC_FILES := foo.fw
-include $(BUILD_PREBUILT)
-`,
- expected: `
-prebuilt_firmware {
- name: "foo",
-
- src: "foo.fw",
- sub_dir: "bar",
- proprietary: true,
-}
-`,
- },
- {
- desc: "prebuilt_firmware subdir_bar in $(TARGET_OUT)/vendor",
- in: `
-include $(CLEAR_VARS)
-LOCAL_MODULE := foo
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT)/vendor/firmware/bar
-LOCAL_SRC_FILES := foo.fw
-include $(BUILD_PREBUILT)
-`,
- expected: `
-prebuilt_firmware {
- name: "foo",
-
- src: "foo.fw",
- sub_dir: "bar",
- proprietary: true,
-}
-`,
- },
- {
- desc: "vts_config",
- in: `
-include $(CLEAR_VARS)
-LOCAL_MODULE := vtsconf
-include test/vts/tools/build/Android.host_config.mk
-`,
- expected: `
-vts_config {
- name: "vtsconf",
-}
-`,
- },
- {
- desc: "comment with ESC",
- in: `
-# Comment line 1 \
-# Comment line 2
-`,
- expected: `
-// Comment line 1 \
-// Comment line 2
-`,
- },
- {
- desc: "Merge with variable reference",
- in: `
-include $(CLEAR_VARS)
-LOCAL_MODULE := foo
-LOCAL_STATIC_ANDROID_LIBRARIES := $(FOO)
-LOCAL_STATIC_JAVA_LIBRARIES := javalib
-LOCAL_JAVA_RESOURCE_DIRS := $(FOO)
-include $(BUILD_PACKAGE)
-`,
- expected: `
-android_app {
- name: "foo",
- static_libs: FOO,
- static_libs: ["javalib"],
- java_resource_dirs: FOO,
-}
-`,
- },
- {
- desc: "LOCAL_JACK_ENABLED and LOCAL_JACK_FLAGS skipped",
- in: `
-include $(CLEAR_VARS)
-LOCAL_MODULE := foo
-LOCAL_JACK_ENABLED := incremental
-LOCAL_JACK_FLAGS := --multi-dex native
-include $(BUILD_PACKAGE)
- `,
- expected: `
-android_app {
- name: "foo",
-
-}
- `,
- },
- {
- desc: "android_app_import",
- in: `
-include $(CLEAR_VARS)
-LOCAL_MODULE := foo
-LOCAL_SRC_FILES := foo.apk
-LOCAL_PRIVILEGED_MODULE := true
-LOCAL_MODULE_CLASS := APPS
-LOCAL_MODULE_TAGS := optional
-LOCAL_DEX_PREOPT := false
-include $(BUILD_PREBUILT)
-`,
- expected: `
-android_app_import {
- name: "foo",
-
- privileged: true,
-
- dex_preopt: {
- enabled: false,
- },
- apk: "foo.apk",
-
-}
-`,
- },
-}
-
-func TestEndToEnd(t *testing.T) {
- for i, test := range testCases {
- expected, err := bpfix.Reformat(test.expected)
- if err != nil {
- t.Error(err)
- }
-
- got, errs := convertFile(fmt.Sprintf("<testcase %d>", i), bytes.NewBufferString(test.in))
- if len(errs) > 0 {
- t.Errorf("Unexpected errors: %q", errs)
- continue
- }
-
- if got != expected {
- t.Errorf("failed testcase '%s'\ninput:\n%s\n\nexpected:\n%s\ngot:\n%s\n", test.desc, strings.TrimSpace(test.in), expected, got)
- }
- }
-}
diff --git a/androidmk/cmd/androidmk/values.go b/androidmk/cmd/androidmk/values.go
deleted file mode 100644
index 90f2e74..0000000
--- a/androidmk/cmd/androidmk/values.go
+++ /dev/null
@@ -1,228 +0,0 @@
-// Copyright 2017 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package main
-
-import (
- "fmt"
- "strings"
-
- mkparser "android/soong/androidmk/parser"
-
- bpparser "github.com/google/blueprint/parser"
-)
-
-func stringToStringValue(s string) bpparser.Expression {
- return &bpparser.String{
- Value: s,
- }
-}
-
-func stringListToStringValueList(list []string) []bpparser.Expression {
- valList := make([]bpparser.Expression, len(list))
- for i, l := range list {
- valList[i] = stringToStringValue(l)
- }
- return valList
-}
-
-func addValues(val1, val2 bpparser.Expression) (bpparser.Expression, error) {
- if val1 == nil {
- return val2, nil
- }
-
- if val1.Type() == bpparser.StringType && val2.Type() == bpparser.ListType {
- val1 = &bpparser.List{
- Values: []bpparser.Expression{val1},
- }
- } else if val2.Type() == bpparser.StringType && val1.Type() == bpparser.ListType {
- val2 = &bpparser.List{
- Values: []bpparser.Expression{val1},
- }
- } else if val1.Type() != val2.Type() {
- return nil, fmt.Errorf("cannot add mismatched types")
- }
-
- return &bpparser.Operator{
- Operator: '+',
- Args: [2]bpparser.Expression{val1, val2},
- }, nil
-}
-
-func makeToStringExpression(ms *mkparser.MakeString, scope mkparser.Scope) (bpparser.Expression, error) {
-
- var val bpparser.Expression
- var err error
-
- if ms.Strings[0] != "" {
- val = stringToStringValue(ms.Strings[0])
- }
-
- for i, s := range ms.Strings[1:] {
- if ret, ok := ms.Variables[i].EvalFunction(scope); ok {
- if len(ret) > 1 {
- return nil, fmt.Errorf("Unexpected list value %s", ms.Dump())
- }
- val, err = addValues(val, stringToStringValue(ret[0]))
- } else {
- name := ms.Variables[i].Name
- if !name.Const() {
- return nil, fmt.Errorf("Unsupported non-const variable name %s", name.Dump())
- }
- tmp := &bpparser.Variable{
- Name: name.Value(nil),
- Value: &bpparser.String{},
- }
-
- if tmp.Name == "TOP" {
- if s[0] == '/' {
- s = s[1:]
- } else {
- s = "." + s
- }
- } else {
- val, err = addValues(val, tmp)
- if err != nil {
- return nil, err
- }
- }
- }
-
- if s != "" {
- tmp := stringToStringValue(s)
- val, err = addValues(val, tmp)
- if err != nil {
- return nil, err
- }
- }
- }
-
- return val, nil
-}
-
-func stringToListValue(s string) bpparser.Expression {
- list := strings.Fields(s)
- valList := make([]bpparser.Expression, len(list))
- for i, l := range list {
- valList[i] = &bpparser.String{
- Value: l,
- }
- }
- return &bpparser.List{
- Values: valList,
- }
-
-}
-
-func makeToListExpression(ms *mkparser.MakeString, scope mkparser.Scope) (bpparser.Expression, error) {
-
- fields := ms.Split(" \t")
-
- var listOfListValues []bpparser.Expression
-
- listValue := &bpparser.List{}
-
- for _, f := range fields {
- if len(f.Variables) == 1 && f.Strings[0] == "" && f.Strings[1] == "" {
- if ret, ok := f.Variables[0].EvalFunction(scope); ok {
- listValue.Values = append(listValue.Values, stringListToStringValueList(ret)...)
- } else {
- // Variable by itself, variable is probably a list
- if !f.Variables[0].Name.Const() {
- return nil, fmt.Errorf("unsupported non-const variable name")
- }
- if f.Variables[0].Name.Value(nil) == "TOP" {
- listValue.Values = append(listValue.Values, &bpparser.String{
- Value: ".",
- })
- } else {
- if len(listValue.Values) > 0 {
- listOfListValues = append(listOfListValues, listValue)
- }
- listOfListValues = append(listOfListValues, &bpparser.Variable{
- Name: f.Variables[0].Name.Value(nil),
- Value: &bpparser.List{},
- })
- listValue = &bpparser.List{}
- }
- }
- } else {
- s, err := makeToStringExpression(f, scope)
- if err != nil {
- return nil, err
- }
- if s == nil {
- continue
- }
-
- listValue.Values = append(listValue.Values, s)
- }
- }
-
- if len(listValue.Values) > 0 {
- listOfListValues = append(listOfListValues, listValue)
- }
-
- if len(listOfListValues) == 0 {
- return listValue, nil
- }
-
- val := listOfListValues[0]
- for _, tmp := range listOfListValues[1:] {
- var err error
- val, err = addValues(val, tmp)
- if err != nil {
- return nil, err
- }
- }
-
- return val, nil
-}
-
-func stringToBoolValue(s string) (bpparser.Expression, error) {
- var b bool
- s = strings.TrimSpace(s)
- switch s {
- case "true":
- b = true
- case "false", "":
- b = false
- case "-frtti": // HACK for LOCAL_RTTI_VALUE
- b = true
- default:
- return nil, fmt.Errorf("unexpected bool value %s", s)
- }
- return &bpparser.Bool{
- Value: b,
- }, nil
-}
-
-func makeToBoolExpression(ms *mkparser.MakeString) (bpparser.Expression, error) {
- if !ms.Const() {
- if len(ms.Variables) == 1 && ms.Strings[0] == "" && ms.Strings[1] == "" {
- name := ms.Variables[0].Name
- if !name.Const() {
- return nil, fmt.Errorf("unsupported non-const variable name")
- }
- return &bpparser.Variable{
- Name: name.Value(nil),
- Value: &bpparser.Bool{},
- }, nil
- } else {
- return nil, fmt.Errorf("non-const bool expression %s", ms.Dump())
- }
- }
-
- return stringToBoolValue(ms.Value(nil))
-}