rust: Prevent manually defined lib link flags.

Adds a filter to prevent modules from manually defining certain linkage
flags. These flags should only be automatically generated based on
listed dependencies.

Bug: 161942165
Test: Soong tests pass
Change-Id: Ibc014391ef1de10188c2d139d41d0241d6c68b5f
diff --git a/rust/compiler.go b/rust/compiler.go
index df77759..de59f39 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -17,6 +17,7 @@
 import (
 	"fmt"
 	"path/filepath"
+	"strings"
 
 	"github.com/google/blueprint/proptools"
 
@@ -235,6 +236,25 @@
 	if err != nil {
 		ctx.PropertyErrorf("lints", err.Error())
 	}
+
+	// linkage-related flags are disallowed.
+	for _, s := range compiler.Properties.Ld_flags {
+		if strings.HasPrefix(s, "-Wl,-l") || strings.HasPrefix(s, "-Wl,-L") {
+			ctx.PropertyErrorf("ld_flags", "'-Wl,-l' and '-Wl,-L' flags cannot be manually specified")
+		}
+	}
+	for _, s := range compiler.Properties.Flags {
+		if strings.HasPrefix(s, "-l") || strings.HasPrefix(s, "-L") {
+			ctx.PropertyErrorf("flags", "'-l' and '-L' flags cannot be manually specified")
+		}
+		if strings.HasPrefix(s, "--extern") {
+			ctx.PropertyErrorf("flags", "'--extern' flag cannot be manually specified")
+		}
+		if strings.HasPrefix(s, "-Clink-args=") || strings.HasPrefix(s, "-C link-args=") {
+			ctx.PropertyErrorf("flags", "'-C link-args' flag cannot be manually specified")
+		}
+	}
+
 	flags.RustFlags = append(flags.RustFlags, lintFlags)
 	flags.RustFlags = append(flags.RustFlags, compiler.Properties.Flags...)
 	flags.RustFlags = append(flags.RustFlags, compiler.cfgsToFlags()...)
diff --git a/rust/compiler_test.go b/rust/compiler_test.go
index 5ca9e7f..c331b4c 100644
--- a/rust/compiler_test.go
+++ b/rust/compiler_test.go
@@ -208,3 +208,73 @@
 		t.Errorf("libstd is not linked dynamically for dylibs")
 	}
 }
+
+// Ensure that manual link flags are disallowed.
+func TestManualLinkageRejection(t *testing.T) {
+	// rustc flags
+	testRustError(t, ".* cannot be manually specified", `
+		rust_binary {
+			name: "foo",
+			srcs: [
+				"foo.rs",
+			],
+			flags: ["-lbar"],
+		}
+	`)
+	testRustError(t, ".* cannot be manually specified", `
+		rust_binary {
+			name: "foo",
+			srcs: [
+				"foo.rs",
+			],
+			flags: ["--extern=foo"],
+		}
+	`)
+	testRustError(t, ".* cannot be manually specified", `
+		rust_binary {
+			name: "foo",
+			srcs: [
+				"foo.rs",
+			],
+			flags: ["-Clink-args=foo"],
+		}
+	`)
+	testRustError(t, ".* cannot be manually specified", `
+		rust_binary {
+			name: "foo",
+			srcs: [
+				"foo.rs",
+			],
+			flags: ["-C link-args=foo"],
+		}
+	`)
+	testRustError(t, ".* cannot be manually specified", `
+		rust_binary {
+			name: "foo",
+			srcs: [
+				"foo.rs",
+			],
+			flags: ["-L foo/"],
+		}
+	`)
+
+	// lld flags
+	testRustError(t, ".* cannot be manually specified", `
+		rust_binary {
+			name: "foo",
+			srcs: [
+				"foo.rs",
+			],
+			ld_flags: ["-Wl,-L bar/"],
+		}
+	`)
+	testRustError(t, ".* cannot be manually specified", `
+		rust_binary {
+			name: "foo",
+			srcs: [
+				"foo.rs",
+			],
+			ld_flags: ["-Wl,-lbar"],
+		}
+	`)
+}