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/androidmk.go b/cc/androidmk.go
index df44a4c..4986387 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -26,6 +26,23 @@
 
 type AndroidMkContext interface {
 	Target() android.Target
+	subAndroidMk(*android.AndroidMkData, interface{})
+}
+
+type subAndroidMkProvider interface {
+	AndroidMk(AndroidMkContext, *android.AndroidMkData)
+}
+
+func (c *Module) subAndroidMk(data *android.AndroidMkData, obj interface{}) {
+	if c.subAndroidMkOnce == nil {
+		c.subAndroidMkOnce = make(map[subAndroidMkProvider]bool)
+	}
+	if androidmk, ok := obj.(subAndroidMkProvider); ok {
+		if !c.subAndroidMkOnce[androidmk] {
+			c.subAndroidMkOnce[androidmk] = true
+			androidmk.AndroidMk(c, data)
+		}
+	}
 }
 
 func (c *Module) AndroidMk() (ret android.AndroidMkData, err error) {
@@ -50,43 +67,27 @@
 		return nil
 	})
 
-	callSubAndroidMk := func(obj interface{}) {
-		if obj != nil {
-			if androidmk, ok := obj.(interface {
-				AndroidMk(AndroidMkContext, *android.AndroidMkData)
-			}); ok {
-				androidmk.AndroidMk(c, &ret)
-			}
-		}
-	}
-
 	for _, feature := range c.features {
-		callSubAndroidMk(feature)
+		c.subAndroidMk(&ret, feature)
 	}
 
-	callSubAndroidMk(c.compiler)
-	callSubAndroidMk(c.linker)
-	if c.linker.installable() {
-		callSubAndroidMk(c.installer)
-	}
+	c.subAndroidMk(&ret, c.compiler)
+	c.subAndroidMk(&ret, c.linker)
+	c.subAndroidMk(&ret, c.installer)
 
 	return ret, nil
 }
 
-func (library *baseLinker) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
+func (library *libraryDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
+	if !library.static() {
+		ctx.subAndroidMk(ret, &library.stripper)
+	}
+
 	if library.static() {
 		ret.Class = "STATIC_LIBRARIES"
 	} else {
 		ret.Class = "SHARED_LIBRARIES"
 	}
-}
-
-func (library *libraryLinker) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
-	library.baseLinker.AndroidMk(ctx, ret)
-
-	if !library.static() {
-		library.stripper.AndroidMk(ctx, ret)
-	}
 
 	ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) error {
 		var exportedIncludes []string
@@ -106,6 +107,10 @@
 
 		return nil
 	})
+
+	if !library.static() {
+		ctx.subAndroidMk(ret, library.baseInstaller)
+	}
 }
 
 func (object *objectLinker) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
@@ -119,30 +124,39 @@
 	}
 }
 
-func (binary *binaryLinker) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
-	binary.stripper.AndroidMk(ctx, ret)
+func (binary *binaryDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
+	ctx.subAndroidMk(ret, &binary.stripper)
 
 	ret.Class = "EXECUTABLES"
 	ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) error {
 		fmt.Fprintln(w, "LOCAL_CXX_STL := none")
 		fmt.Fprintln(w, "LOCAL_SYSTEM_SHARED_LIBRARIES :=")
-		if binary.static() {
+		if Bool(binary.Properties.Static_executable) {
 			fmt.Fprintln(w, "LOCAL_FORCE_STATIC_EXECUTABLE := true")
 		}
 		return nil
 	})
 }
 
-func (test *testBinaryLinker) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
-	test.binaryLinker.AndroidMk(ctx, ret)
-	if Bool(test.testLinker.Properties.Test_per_src) {
-		ret.SubName = "_" + test.binaryLinker.Properties.Stem
+func (benchmark *benchmarkDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
+	ctx.subAndroidMk(ret, benchmark.binaryDecorator)
+	ctx.subAndroidMk(ret, benchmark.baseInstaller)
+}
+
+func (test *testBinary) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
+	ctx.subAndroidMk(ret, test.binaryDecorator)
+	ctx.subAndroidMk(ret, test.baseInstaller)
+	if Bool(test.Properties.Test_per_src) {
+		ret.SubName = "_" + test.binaryDecorator.Properties.Stem
 	}
 }
 
-func (library *toolchainLibraryLinker) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
-	library.baseLinker.AndroidMk(ctx, ret)
+func (test *testLibrary) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
+	ctx.subAndroidMk(ret, test.libraryDecorator)
+}
 
+func (library *toolchainLibraryDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
+	ret.Class = "STATIC_LIBRARIES"
 	ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) error {
 		fmt.Fprintln(w, "LOCAL_MODULE_SUFFIX := "+outputFile.Ext())
 		fmt.Fprintln(w, "LOCAL_CXX_STL := none")
@@ -185,13 +199,11 @@
 	})
 }
 
-func (c *stubCompiler) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
+func (c *stubDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
 	ret.SubName = "." + strconv.Itoa(c.properties.ApiLevel)
-}
 
-func (installer *stubInstaller) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
 	ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) error {
-		path, file := filepath.Split(installer.installPath)
+		path, file := filepath.Split(c.installPath)
 		stem := strings.TrimSuffix(file, filepath.Ext(file))
 		fmt.Fprintln(w, "LOCAL_MODULE_PATH := "+path)
 		fmt.Fprintln(w, "LOCAL_MODULE_STEM := "+stem)