+func buildDependants(tgts []string) map[string]struct{} {
+ defer Jobs.Wait()
+ trace(CDebug, "collecting deps")
+ seen := map[string]struct{}{}
+ deps := map[string]map[string]struct{}{}
+ for _, tgtInitial := range tgts {
+ for _, tgt := range collectDeps(Cwd, tgtInitial, 0, deps) {
+ if tgt != tgtInitial {
+ seen[tgt] = struct{}{}
+ }
+ }
+ }
+ if len(seen) == 0 {
+ return nil
+ }
+
+ levelOrig := Level
+ defer func() {
+ Level = levelOrig
+ }()
+ Level = 1
+ trace(CDebug, "building %d alwayses: %v", len(seen), seen)
+ errs := make(chan error, len(seen))
+ for tgt := range seen {
+ if err := runScript(tgt, errs, false); err != nil {
+ trace(CErr, "always run error: %s, skipping dependants", err)
+ return nil
+ }
+ }
+ ok := true
+ for i := 0; i < len(seen); i++ {
+ ok = ok && isOkRun(<-errs)
+ }
+ Jobs.Wait()
+ close(errs)
+ if !ok {
+ trace(CDebug, "alwayses failed, skipping dependants")
+ return nil
+ }
+
+ queueSrc := make([]string, 0, len(seen))
+ for tgt := range seen {
+ queueSrc = append(queueSrc, tgt)
+ }
+ if len(queueSrc) == 0 {
+ return seen
+ }
+
+RebuildDeps:
+ trace(CDebug, "checking %d dependant targets: %v", len(queueSrc), queueSrc)
+ queue := []string{}
+ for _, tgt := range queueSrc {
+ for dep := range deps[tgt] {
+ queue = append(queue, dep)
+ }
+ }
+ trace(CDebug, "building %d dependant targets: %v", len(queue), queue)
+ errs = make(chan error, len(queue))
+ jobs := 0
+ queueSrc = []string{}
+ for _, tgt := range queue {
+ ood, err := isOODWithTrace(Cwd, tgt, 0, seen)
+ if err != nil {
+ trace(CErr, "dependant error: %s, skipping dependants", err)
+ return nil
+ }
+ if !ood {
+ continue
+ }
+ if err := runScript(tgt, errs, false); err != nil {
+ trace(CErr, "dependant error: %s, skipping dependants", err)
+ return nil
+ }
+ queueSrc = append(queueSrc, tgt)
+ seen[tgt] = struct{}{}
+ jobs++
+ }
+ for i := 0; i < jobs; i++ {
+ ok = ok && isOkRun(<-errs)
+ }
+ if !ok {
+ trace(CDebug, "dependants failed, skipping them")
+ return nil
+ }
+ Jobs.Wait()
+ close(errs)
+ if jobs == 0 {
+ return seen
+ }
+ Level++
+ goto RebuildDeps
+}
+
+func ifchange(tgts []string, forced, traced bool) (bool, error) {