androidmk: Support version_script

This only translates the common case using $(LOCAL_PATH). If it doesn't
match here, Soong will throw an error with a suggested fix.

Change-Id: If64c8fca008a1a414fc12389e6b1bb40af0df899
diff --git a/androidmk/cmd/androidmk/android.go b/androidmk/cmd/androidmk/android.go
index eb89f19..d480274 100644
--- a/androidmk/cmd/androidmk/android.go
+++ b/androidmk/cmd/androidmk/android.go
@@ -42,7 +42,6 @@
 	"LOCAL_CFLAGS":                  {"cflags", bpparser.List},
 	"LOCAL_CONLYFLAGS":              {"conlyflags", bpparser.List},
 	"LOCAL_CPPFLAGS":                {"cppflags", bpparser.List},
-	"LOCAL_LDFLAGS":                 {"ldflags", bpparser.List},
 	"LOCAL_REQUIRED_MODULES":        {"required", bpparser.List},
 	"LOCAL_MODULE_TAGS":             {"tags", bpparser.List},
 	"LOCAL_LDLIBS":                  {"host_ldlibs", bpparser.List},
@@ -83,6 +82,7 @@
 	"LOCAL_MODULE_HOST_OS":        {hostOs},
 	"LOCAL_SRC_FILES":             {srcFiles},
 	"LOCAL_SANITIZE":              {sanitize},
+	"LOCAL_LDFLAGS":               {ldflags},
 }
 
 type listSplitFunc func(bpparser.Value) (string, *bpparser.Value, error)
@@ -422,6 +422,56 @@
 	return err
 }
 
+func ldflags(file *bpFile, prefix string, mkvalue *mkparser.MakeString, appendVariable bool) error {
+	val, err := makeVariableToBlueprint(file, mkvalue, bpparser.List)
+	if err != nil {
+		return err
+	}
+
+	lists, err := splitBpList(val, func(value bpparser.Value) (string, *bpparser.Value, error) {
+		// Anything other than "-Wl,--version_script," + LOCAL_PATH + "<path>" matches ldflags
+		if value.Variable != "" || value.Expression == nil {
+			return "ldflags", &value, nil
+		}
+
+		exp := value.Expression.Args[0]
+		if exp.Variable != "" || exp.Expression == nil || exp.Expression.Args[0].StringValue != "-Wl,--version-script," {
+			return "ldflags", &value, nil
+		}
+
+		if exp.Expression.Args[1].Variable != "LOCAL_PATH" {
+			file.errorf(mkvalue, "Unrecognized version-script")
+			return "ldflags", &value, nil
+		}
+
+		value.Expression.Args[1].StringValue = strings.TrimPrefix(value.Expression.Args[1].StringValue, "/")
+
+		return "version", &value.Expression.Args[1], nil
+	})
+	if err != nil {
+		return err
+	}
+
+	if ldflags, ok := lists["ldflags"]; ok && !emptyList(ldflags) {
+		err = setVariable(file, appendVariable, prefix, "ldflags", ldflags, true)
+		if err != nil {
+			return err
+		}
+	}
+
+	if version_script, ok := lists["version"]; ok && !emptyList(version_script) {
+		if len(version_script.ListValue) > 1 {
+			file.errorf(mkvalue, "multiple version scripts found?")
+		}
+		err = setVariable(file, false, prefix, "version_script", &version_script.ListValue[0], true)
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
 var deleteProperties = map[string]struct{}{
 	"LOCAL_CPP_EXTENSION": struct{}{},
 }
diff --git a/androidmk/cmd/androidmk/test.go b/androidmk/cmd/androidmk/test.go
index 579578e..b3ce5d0 100644
--- a/androidmk/cmd/androidmk/test.go
+++ b/androidmk/cmd/androidmk/test.go
@@ -331,6 +331,20 @@
 }
 `,
 	},
+	{
+		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",
+}
+`,
+	},
 }
 
 func reformatBlueprint(input string) string {
diff --git a/cc/check.go b/cc/check.go
index e6a8036..38a64a0 100644
--- a/cc/check.go
+++ b/cc/check.go
@@ -69,6 +69,8 @@
 			}
 		} else if strings.HasPrefix(flag, "-L") {
 			ctx.PropertyErrorf(prop, "Bad flag: `%s` is not allowed", flag)
+		} else if strings.HasPrefix(flag, "-Wl,--version-script") {
+			ctx.PropertyErrorf(prop, "Bad flag: `%s`, use version_script instead", flag)
 		} else if strings.Contains(flag, " ") {
 			ctx.PropertyErrorf(prop, "Bad flag: `%s` is not an allowed multi-word flag. Should it be split into multiple flags?", flag)
 		}