Refactor cc modules to use decorators instead of inheritance

For example , instead of trying to have libraryLinker inherit from
baseLinker and libraryCompiler inherit from baseCompiler, create a
single decorator object that wraps both baseLinker and baseCompiler.

Test: Builds, no unexpected changes to build.ninja
Change-Id: I2468adaea8466c203a240259ba5694b8b1df7a52
diff --git a/cc/cc.go b/cc/cc.go
index 8af2b8c..b381897 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -35,8 +35,6 @@
 func init() {
 	soong.RegisterModuleType("cc_defaults", defaultsFactory)
 
-	soong.RegisterModuleType("toolchain_library", toolchainLibraryFactory)
-
 	// LinkageMutator must be registered after common.ArchMutator, but that is guaranteed by
 	// the Go initialization order because this package depends on common, so common's init
 	// functions will run first.
@@ -189,7 +187,6 @@
 
 	link(ctx ModuleContext, flags Flags, deps PathDeps, objFiles android.Paths) android.Path
 	appendLdflags([]string)
-	installable() bool
 }
 
 type installer interface {
@@ -252,6 +249,8 @@
 	outputFile android.OptionalPath
 
 	cachedToolchain config.Toolchain
+
+	subAndroidMkOnce map[subAndroidMkProvider]bool
 }
 
 func (c *Module) Init() (blueprint.Module, []interface{}) {
@@ -283,6 +282,17 @@
 	return android.InitDefaultableModule(c, c, props...)
 }
 
+// Returns true for dependency roots (binaries)
+// TODO(ccross): also handle dlopenable libraries
+func (c *Module) isDependencyRoot() bool {
+	if root, ok := c.linker.(interface {
+		isDependencyRoot() bool
+	}); ok {
+		return root.isDependencyRoot()
+	}
+	return false
+}
+
 type baseModuleContext struct {
 	android.BaseContext
 	moduleContextImpl
@@ -322,25 +332,21 @@
 }
 
 func (ctx *moduleContextImpl) static() bool {
-	if ctx.mod.linker == nil {
-		panic(fmt.Errorf("static called on module %q with no linker", ctx.ctx.ModuleName()))
+	if static, ok := ctx.mod.linker.(interface {
+		static() bool
+	}); ok {
+		return static.static()
 	}
-	if linker, ok := ctx.mod.linker.(baseLinkerInterface); ok {
-		return linker.static()
-	} else {
-		panic(fmt.Errorf("static called on module %q that doesn't use base linker", ctx.ctx.ModuleName()))
-	}
+	return false
 }
 
 func (ctx *moduleContextImpl) staticBinary() bool {
-	if ctx.mod.linker == nil {
-		panic(fmt.Errorf("staticBinary called on module %q with no linker", ctx.ctx.ModuleName()))
+	if static, ok := ctx.mod.linker.(interface {
+		staticBinary() bool
+	}); ok {
+		return static.staticBinary()
 	}
-	if linker, ok := ctx.mod.linker.(baseLinkerInterface); ok {
-		return linker.staticBinary()
-	} else {
-		panic(fmt.Errorf("staticBinary called on module %q that doesn't use base linker", ctx.ctx.ModuleName()))
-	}
+	return false
 }
 
 func (ctx *moduleContextImpl) noDefaultCompilerFlags() bool {
@@ -453,7 +459,7 @@
 		}
 		c.outputFile = android.OptionalPathForPath(outputFile)
 
-		if c.installer != nil && c.linker.installable() {
+		if c.installer != nil {
 			c.installer.install(ctx, outputFile)
 			if ctx.Failed() {
 				return
@@ -680,7 +686,7 @@
 			// Platform code can link to anything
 			return
 		}
-		if _, ok := to.linker.(*toolchainLibraryLinker); ok {
+		if _, ok := to.linker.(*toolchainLibraryDecorator); ok {
 			// These are always allowed
 			return
 		}
@@ -692,7 +698,7 @@
 			// These are allowed, but don't set sdk_version
 			return
 		}
-		if _, ok := to.linker.(*stubLinker); ok {
+		if _, ok := to.linker.(*stubDecorator); ok {
 			// These aren't real libraries, but are the stub shared libraries that are included in
 			// the NDK.
 			return
@@ -794,7 +800,7 @@
 
 		if tag == reuseObjTag {
 			depPaths.ObjFiles = append(depPaths.ObjFiles,
-				cc.compiler.(*libraryCompiler).reuseObjFiles...)
+				cc.compiler.(libraryInterface).reuseObjs()...)
 			return
 		}
 
@@ -824,8 +830,8 @@
 			depPtr = &depPaths.LateStaticLibs
 		case wholeStaticDepTag:
 			depPtr = &depPaths.WholeStaticLibs
-			staticLib, _ := cc.linker.(libraryInterface)
-			if staticLib == nil || !staticLib.static() {
+			staticLib, ok := cc.linker.(libraryInterface)
+			if !ok || !staticLib.static() {
 				ctx.ModuleErrorf("module %q not a static library", name)
 				return
 			}
@@ -882,11 +888,11 @@
 		&BaseProperties{},
 		&BaseCompilerProperties{},
 		&BaseLinkerProperties{},
-		&LibraryCompilerProperties{},
+		&LibraryProperties{},
 		&FlagExporterProperties{},
-		&LibraryLinkerProperties{},
 		&BinaryLinkerProperties{},
-		&TestLinkerProperties{},
+		&TestProperties{},
+		&TestBinaryProperties{},
 		&UnusedProperties{},
 		&StlProperties{},
 		&SanitizeProperties{},
@@ -899,58 +905,6 @@
 	return android.InitDefaultsModule(module, module, propertyStructs...)
 }
 
-//
-// Device libraries shipped with gcc
-//
-
-type toolchainLibraryLinker struct {
-	baseLinker
-}
-
-var _ baseLinkerInterface = (*toolchainLibraryLinker)(nil)
-
-func (*toolchainLibraryLinker) linkerDeps(ctx BaseModuleContext, deps Deps) Deps {
-	// toolchain libraries can't have any dependencies
-	return deps
-}
-
-func (*toolchainLibraryLinker) buildStatic() bool {
-	return true
-}
-
-func (*toolchainLibraryLinker) buildShared() bool {
-	return false
-}
-
-func toolchainLibraryFactory() (blueprint.Module, []interface{}) {
-	module := newBaseModule(android.DeviceSupported, android.MultilibBoth)
-	module.compiler = &baseCompiler{}
-	module.linker = &toolchainLibraryLinker{}
-	module.Properties.Clang = proptools.BoolPtr(false)
-	return module.Init()
-}
-
-func (library *toolchainLibraryLinker) link(ctx ModuleContext,
-	flags Flags, deps PathDeps, objFiles android.Paths) android.Path {
-
-	libName := ctx.ModuleName() + staticLibraryExtension
-	outputFile := android.PathForModuleOut(ctx, libName)
-
-	if flags.Clang {
-		ctx.ModuleErrorf("toolchain_library must use GCC, not Clang")
-	}
-
-	CopyGccLib(ctx, libName, flagsToBuilderFlags(flags), outputFile)
-
-	ctx.CheckbuildFile(outputFile)
-
-	return outputFile
-}
-
-func (*toolchainLibraryLinker) installable() bool {
-	return false
-}
-
 // lastUniqueElements returns all unique elements of a slice, keeping the last copy of each
 // modifies the slice contents in place, and returns a subslice of the original slice
 func lastUniqueElements(list []string) []string {