Add support for Rust C libraries.

Adds the ability for rust modules to be compiled as C libraries, and
allows cc modules to depend on these rust-generated modules. This also
means that soong-rust should not have any dependencies on soong-cc aside
from what's required for testing.

There's a couple small fixes included as well:

 - A bug in libNameFromFilePath that caused issues when library's had
 "lib" in their name.
 - VariantName is removed from rust library MutatedProperties since this
 was unused.

Bug: 140726209
Test: Soong tests pass.
Test: Example cc_binary can include a rust shared library as a dep.
Test: m crosvm.experimental
Change-Id: Ia7deed1345d2423001089014cc65ce7934123da4
diff --git a/rust/rust.go b/rust/rust.go
index a9321be..ce81b91 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -75,6 +75,85 @@
 	outputFile       android.OptionalPath
 }
 
+func (mod *Module) BuildStubs() bool {
+	return false
+}
+
+func (mod *Module) HasStubsVariants() bool {
+	return false
+}
+
+func (mod *Module) SelectedStl() string {
+	return ""
+}
+
+func (mod *Module) ApiLevel() string {
+	panic(fmt.Errorf("Called ApiLevel on Rust module %q; stubs libraries are not yet supported.", mod.BaseModuleName()))
+}
+
+func (mod *Module) Static() bool {
+	if mod.compiler != nil {
+		if library, ok := mod.compiler.(libraryInterface); ok {
+			return library.static()
+		}
+	}
+	panic(fmt.Errorf("Static called on non-library module: %q", mod.BaseModuleName()))
+}
+
+func (mod *Module) Shared() bool {
+	if mod.compiler != nil {
+		if library, ok := mod.compiler.(libraryInterface); ok {
+			return library.static()
+		}
+	}
+	panic(fmt.Errorf("Shared called on non-library module: %q", mod.BaseModuleName()))
+}
+
+func (mod *Module) Toc() android.OptionalPath {
+	if mod.compiler != nil {
+		if _, ok := mod.compiler.(libraryInterface); ok {
+			return android.OptionalPath{}
+		}
+	}
+	panic(fmt.Errorf("Toc() called on non-library module: %q", mod.BaseModuleName()))
+}
+
+func (mod *Module) OnlyInRecovery() bool {
+	return false
+}
+
+func (mod *Module) UseVndk() bool {
+	return false
+}
+
+func (mod *Module) MustUseVendorVariant() bool {
+	return false
+}
+
+func (mod *Module) IsVndk() bool {
+	return false
+}
+
+func (mod *Module) HasVendorVariant() bool {
+	return false
+}
+
+func (mod *Module) SdkVersion() string {
+	return ""
+}
+
+func (mod *Module) ToolchainLibrary() bool {
+	return false
+}
+
+func (mod *Module) NdkPrebuiltStl() bool {
+	return false
+}
+
+func (mod *Module) StubDecorator() bool {
+	return false
+}
+
 type Deps struct {
 	Dylibs     []string
 	Rlibs      []string
@@ -169,11 +248,10 @@
 	return false
 }
 
-func (mod *Module) IncludeDirs() android.Paths {
+func (mod *Module) IncludeDirs(ctx android.BaseModuleContext) android.Paths {
 	if mod.compiler != nil {
-		if _, ok := mod.compiler.(*libraryDecorator); ok {
-			//TODO add Include_dirs to libraryDecorator for C libraries.
-			return android.Paths{}
+		if library, ok := mod.compiler.(*libraryDecorator); ok {
+			return android.PathsForSource(ctx, library.Properties.Include_dirs)
 		}
 	}
 	panic(fmt.Errorf("IncludeDirs called on non-library module: %q", mod.BaseModuleName()))
@@ -181,8 +259,8 @@
 
 func (mod *Module) SetStatic() {
 	if mod.compiler != nil {
-		if _, ok := mod.compiler.(*libraryDecorator); ok {
-			//TODO add support for static variants.
+		if library, ok := mod.compiler.(libraryInterface); ok {
+			library.setStatic()
 			return
 		}
 	}
@@ -191,8 +269,8 @@
 
 func (mod *Module) SetShared() {
 	if mod.compiler != nil {
-		if _, ok := mod.compiler.(*libraryDecorator); ok {
-			//TODO add support for shared variants.
+		if library, ok := mod.compiler.(libraryInterface); ok {
+			library.setShared()
 			return
 		}
 	}
@@ -209,9 +287,8 @@
 
 func (mod *Module) BuildStaticVariant() bool {
 	if mod.compiler != nil {
-		if _, ok := mod.compiler.(*libraryDecorator); ok {
-			//TODO add support for static variants.
-			return false
+		if library, ok := mod.compiler.(libraryInterface); ok {
+			return library.buildStatic()
 		}
 	}
 	panic(fmt.Errorf("BuildStaticVariant called on non-library module: %q", mod.BaseModuleName()))
@@ -219,9 +296,8 @@
 
 func (mod *Module) BuildSharedVariant() bool {
 	if mod.compiler != nil {
-		if _, ok := mod.compiler.(*libraryDecorator); ok {
-			//TODO add support for shared variants.
-			return false
+		if library, ok := mod.compiler.(libraryInterface); ok {
+			return library.buildShared()
 		}
 	}
 	panic(fmt.Errorf("BuildSharedVariant called on non-library module: %q", mod.BaseModuleName()))
@@ -430,13 +506,12 @@
 	directRlibDeps := []*Module{}
 	directDylibDeps := []*Module{}
 	directProcMacroDeps := []*Module{}
-	directSharedLibDeps := []*(cc.Module){}
-	directStaticLibDeps := []*(cc.Module){}
+	directSharedLibDeps := [](cc.LinkableInterface){}
+	directStaticLibDeps := [](cc.LinkableInterface){}
 
 	ctx.VisitDirectDeps(func(dep android.Module) {
 		depName := ctx.OtherModuleName(dep)
 		depTag := ctx.OtherModuleDependencyTag(dep)
-
 		if rustDep, ok := dep.(*Module); ok {
 			//Handle Rust Modules
 
@@ -484,16 +559,19 @@
 				}
 			}
 
-		} else if ccDep, ok := dep.(*cc.Module); ok {
-			//Handle C dependencies
+		}
 
-			if ccDep.Target().Os != ctx.Os() {
-				ctx.ModuleErrorf("OS mismatch between %q and %q", ctx.ModuleName(), depName)
-				return
-			}
-			if ccDep.Target().Arch.ArchType != ctx.Arch().ArchType {
-				ctx.ModuleErrorf("Arch mismatch between %q and %q", ctx.ModuleName(), depName)
-				return
+		if ccDep, ok := dep.(cc.LinkableInterface); ok {
+			//Handle C dependencies
+			if _, ok := ccDep.(*Module); !ok {
+				if ccDep.Module().Target().Os != ctx.Os() {
+					ctx.ModuleErrorf("OS mismatch between %q and %q", ctx.ModuleName(), depName)
+					return
+				}
+				if ccDep.Module().Target().Arch.ArchType != ctx.Arch().ArchType {
+					ctx.ModuleErrorf("Arch mismatch between %q and %q", ctx.ModuleName(), depName)
+					return
+				}
 			}
 
 			linkFile := ccDep.OutputFile()
@@ -524,7 +602,7 @@
 			}
 
 			// Make sure these dependencies are propagated
-			if lib, ok := mod.compiler.(*libraryDecorator); ok && (exportDep || lib.rlib()) {
+			if lib, ok := mod.compiler.(*libraryDecorator); ok && exportDep {
 				lib.linkDirs = append(lib.linkDirs, linkPath)
 				lib.depFlags = append(lib.depFlags, "-l"+libName)
 			} else if procMacro, ok := mod.compiler.(*procMacroDecorator); ok && exportDep {
@@ -576,8 +654,8 @@
 }
 func libNameFromFilePath(filepath android.Path) string {
 	libName := strings.Split(filepath.Base(), filepath.Ext())[0]
-	if strings.Contains(libName, "lib") {
-		libName = strings.Split(libName, "lib")[1]
+	if strings.HasPrefix(libName, "lib") {
+		libName = libName[3:]
 	}
 	return libName
 }
@@ -591,23 +669,37 @@
 	ctx.ctx = ctx
 
 	deps := mod.deps(ctx)
-
-	actx.AddVariationDependencies([]blueprint.Variation{{Mutator: "rust_libraries", Variation: "rlib"}}, rlibDepTag, deps.Rlibs...)
-	actx.AddVariationDependencies([]blueprint.Variation{{Mutator: "rust_libraries", Variation: "dylib"}}, dylibDepTag, deps.Dylibs...)
-
-	ccDepVariations := []blueprint.Variation{}
-	ccDepVariations = append(ccDepVariations, blueprint.Variation{Mutator: "version", Variation: ""})
+	commonDepVariations := []blueprint.Variation{}
+	commonDepVariations = append(commonDepVariations,
+		blueprint.Variation{Mutator: "version", Variation: ""})
 	if !mod.Host() {
-		ccDepVariations = append(ccDepVariations, blueprint.Variation{Mutator: "image", Variation: "core"})
+		commonDepVariations = append(commonDepVariations,
+			blueprint.Variation{Mutator: "image", Variation: "core"})
 	}
-	actx.AddVariationDependencies(append(ccDepVariations, blueprint.Variation{Mutator: "link", Variation: "shared"}), cc.SharedDepTag, deps.SharedLibs...)
-	actx.AddVariationDependencies(append(ccDepVariations, blueprint.Variation{Mutator: "link", Variation: "static"}), cc.StaticDepTag, deps.StaticLibs...)
+
+	actx.AddVariationDependencies(
+		append(commonDepVariations, []blueprint.Variation{
+			{Mutator: "rust_libraries", Variation: "rlib"},
+			{Mutator: "link", Variation: ""}}...),
+		rlibDepTag, deps.Rlibs...)
+	actx.AddVariationDependencies(
+		append(commonDepVariations, []blueprint.Variation{
+			{Mutator: "rust_libraries", Variation: "dylib"},
+			{Mutator: "link", Variation: ""}}...),
+		dylibDepTag, deps.Dylibs...)
+
+	actx.AddVariationDependencies(append(commonDepVariations,
+		blueprint.Variation{Mutator: "link", Variation: "shared"}),
+		cc.SharedDepTag, deps.SharedLibs...)
+	actx.AddVariationDependencies(append(commonDepVariations,
+		blueprint.Variation{Mutator: "link", Variation: "static"}),
+		cc.StaticDepTag, deps.StaticLibs...)
 
 	if deps.CrtBegin != "" {
-		actx.AddVariationDependencies(ccDepVariations, cc.CrtBeginDepTag, deps.CrtBegin)
+		actx.AddVariationDependencies(commonDepVariations, cc.CrtBeginDepTag, deps.CrtBegin)
 	}
 	if deps.CrtEnd != "" {
-		actx.AddVariationDependencies(ccDepVariations, cc.CrtEndDepTag, deps.CrtEnd)
+		actx.AddVariationDependencies(commonDepVariations, cc.CrtEndDepTag, deps.CrtEnd)
 	}
 
 	// proc_macros are compiler plugins, and so we need the host arch variant as a dependendcy.