Enforce correct rust library file names.

rustc expects libraries and proc_macro filenames to conform to
a particular format, alphanumeric with underscores and lib${crate_name}.*.
Enforce this with a check when getStem() is called.

This makes the crate_name property required for proc_macros and
libraries. This also removes the notion of a default crate name derived
from the module name. It's not needed for binaries, so this won't impact
them.

Bug: 143579265
Test: m -j crosvm.experimental
Change-Id: I2770cf7d02dd4291c3d240d58d242b940098dcee
diff --git a/rust/library.go b/rust/library.go
index 273a3ce..adf6e95 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -15,6 +15,9 @@
 package rust
 
 import (
+	"regexp"
+	"strings"
+
 	"android/soong/android"
 )
 
@@ -354,6 +357,33 @@
 	return outputFile
 }
 
+func (library *libraryDecorator) getStem(ctx ModuleContext) string {
+	stem := library.baseCompiler.getStemWithoutSuffix(ctx)
+	validateLibraryStem(ctx, stem, library.crateName())
+
+	return stem + String(library.baseCompiler.Properties.Suffix)
+}
+
+var validCrateName = regexp.MustCompile("[^a-zA-Z0-9_]+")
+
+func validateLibraryStem(ctx BaseModuleContext, filename string, crate_name string) {
+	if crate_name == "" {
+		ctx.PropertyErrorf("crate_name", "crate_name must be defined.")
+	}
+
+	// crate_names are used for the library output file, and rustc expects these
+	// to be alphanumeric with underscores allowed.
+	if validCrateName.MatchString(crate_name) {
+		ctx.PropertyErrorf("crate_name",
+			"library crate_names must be alphanumeric with underscores allowed")
+	}
+
+	// Libraries are expected to begin with "lib" followed by the crate_name
+	if !strings.HasPrefix(filename, "lib"+crate_name) {
+		ctx.ModuleErrorf("Invalid name or stem property; library filenames must start with lib<crate_name>")
+	}
+}
+
 func LibraryMutator(mctx android.BottomUpMutatorContext) {
 	if m, ok := mctx.Module().(*Module); ok && m.compiler != nil {
 		switch library := m.compiler.(type) {