Implement plugins for bootstrap go modules

Now that we have multi-stage bootstrapping, we can make the primary
builder build more dynamic. Add the concept of plugins that will be
linked and loaded into bootstrap_go_binary or bootstrap_go_package
modules. It's expected that the plugin's init() functions will do
whatever registration is necessary.

Example Blueprint definition:

    bootstrap_go_binary {
      name: "builder",
      ...
    }

    bootstrap_go_package {
      name: "plugin1",
      pluginFor: ["builder"],
    }

A package may specify more than one plugin if it will be inserted into
more than one go module.

Change-Id: I109835f444196b66fc4018c3fa36ba0875823184
diff --git a/context.go b/context.go
index c5e8b15..3892f4e 100644
--- a/context.go
+++ b/context.go
@@ -1077,6 +1077,11 @@
 		return errs
 	}
 
+	errs = c.runMutators(config)
+	if len(errs) > 0 {
+		return errs
+	}
+
 	c.dependenciesReady = true
 	return nil
 }
@@ -1151,6 +1156,22 @@
 	return
 }
 
+// findMatchingVariant searches the moduleGroup for a module with the same variant as module,
+// and returns the matching module, or nil if one is not found.
+func (c *Context) findMatchingVariant(module *moduleInfo, group *moduleGroup) *moduleInfo {
+	if len(group.modules) == 1 {
+		return group.modules[0]
+	} else {
+		for _, m := range group.modules {
+			if m.variant.equal(module.dependencyVariant) {
+				return m
+			}
+		}
+	}
+
+	return nil
+}
+
 func (c *Context) addDependency(module *moduleInfo, depName string) []error {
 	depsPos := module.propertyPos["deps"]
 
@@ -1176,16 +1197,9 @@
 		}
 	}
 
-	if len(depInfo.modules) == 1 {
-		module.directDeps = append(module.directDeps, depInfo.modules[0])
+	if m := c.findMatchingVariant(module, depInfo); m != nil {
+		module.directDeps = append(module.directDeps, m)
 		return nil
-	} else {
-		for _, m := range depInfo.modules {
-			if m.variant.equal(module.dependencyVariant) {
-				module.directDeps = append(module.directDeps, m)
-				return nil
-			}
-		}
 	}
 
 	return []error{&Error{
@@ -1196,6 +1210,36 @@
 	}}
 }
 
+func (c *Context) addReverseDependency(module *moduleInfo, destName string) []error {
+	if destName == module.properties.Name {
+		return []error{&Error{
+			Err: fmt.Errorf("%q depends on itself", destName),
+			Pos: module.pos,
+		}}
+	}
+
+	destInfo, ok := c.moduleGroups[destName]
+	if !ok {
+		return []error{&Error{
+			Err: fmt.Errorf("%q has a reverse dependency on undefined module %q",
+				module.properties.Name, destName),
+			Pos: module.pos,
+		}}
+	}
+
+	if m := c.findMatchingVariant(module, destInfo); m != nil {
+		m.directDeps = append(m.directDeps, module)
+		return nil
+	}
+
+	return []error{&Error{
+		Err: fmt.Errorf("reverse dependency %q of %q missing variant %q",
+			destName, module.properties.Name,
+			c.prettyPrintVariant(module.dependencyVariant)),
+		Pos: module.pos,
+	}}
+}
+
 func (c *Context) addVariationDependency(module *moduleInfo, variations []Variation,
 	depName string, far bool) []error {
 
@@ -1435,11 +1479,6 @@
 		}
 	}
 
-	errs = c.runMutators(config)
-	if len(errs) > 0 {
-		return nil, errs
-	}
-
 	liveGlobals := newLiveTracker(config)
 
 	c.initSpecialVariables()