Allow primary builder to handle missing dependencies

In some cases the primary builder may need to handle missing
dependencies.  Add Context.SetAllowMissingDependencies to cause
Blueprint to store the list of missing dependencies without immediately
emitting an error, and ModuleContext.GetMissingDependencies to return
the missing dependencies to the primary builder.  If the primary builder
does not call ModuleContext.GetMissingDependencies Blueprint will emit
dependency errors.
diff --git a/context.go b/context.go
index c8bc1f9..dd2666a 100644
--- a/context.go
+++ b/context.go
@@ -81,6 +81,9 @@
 	// set by SetIgnoreUnknownModuleTypes
 	ignoreUnknownModuleTypes bool
 
+	// set by SetAllowMissingDependencies
+	allowMissingDependencies bool
+
 	// set during PrepareBuildActions
 	pkgNames        map[*packageContext]string
 	globalVariables map[Variable]*ninjaString
@@ -137,7 +140,8 @@
 	moduleProperties []interface{}
 
 	// set during ResolveDependencies
-	directDeps []*moduleInfo
+	directDeps  []*moduleInfo
+	missingDeps []string
 
 	// set during updateDependencies
 	reverseDeps []*moduleInfo
@@ -437,6 +441,14 @@
 	c.ignoreUnknownModuleTypes = ignoreUnknownModuleTypes
 }
 
+// SetAllowMissingDependencies changes the behavior of Blueprint to ignore
+// unresolved dependencies.  If the module's GenerateBuildActions calls
+// ModuleContext.GetMissingDependencies Blueprint will not emit any errors
+// for missing dependencies.
+func (c *Context) SetAllowMissingDependencies(allowMissingDependencies bool) {
+	c.allowMissingDependencies = allowMissingDependencies
+}
+
 // Parse parses a single Blueprints file from r, creating Module objects for
 // each of the module definitions encountered.  If the Blueprints file contains
 // an assignment to the "subdirs" variable, then the subdirectories listed are
@@ -1121,6 +1133,10 @@
 
 	depInfo, ok := c.moduleGroups[depName]
 	if !ok {
+		if c.allowMissingDependencies {
+			module.missingDeps = append(module.missingDeps, depName)
+			return nil
+		}
 		return []error{&Error{
 			Err: fmt.Errorf("%q depends on undefined module %q",
 				module.properties.Name, depName),
@@ -1181,6 +1197,10 @@
 
 	depInfo, ok := c.moduleGroups[depName]
 	if !ok {
+		if c.allowMissingDependencies {
+			module.missingDeps = append(module.missingDeps, depName)
+			return nil
+		}
 		return []error{&Error{
 			Err: fmt.Errorf("%q depends on undefined module %q",
 				module.properties.Name, depName),
@@ -1674,7 +1694,8 @@
 				config:  config,
 				module:  module,
 			},
-			scope: scope,
+			scope:              scope,
+			handledMissingDeps: module.missingDeps == nil,
 		}
 
 		mctx.module.logicModule.GenerateBuildActions(mctx)
@@ -1684,6 +1705,19 @@
 			return true
 		}
 
+		if module.missingDeps != nil && !mctx.handledMissingDeps {
+			var errs []error
+			for _, depName := range module.missingDeps {
+				errs = append(errs, &Error{
+					Err: fmt.Errorf("%q depends on undefined module %q",
+						module.properties.Name, depName),
+					Pos: module.pos,
+				})
+			}
+			errsCh <- errs
+			return true
+		}
+
 		depsCh <- mctx.ninjaFileDeps
 
 		newErrs := c.processLocalBuildActions(&module.actionDefs,