+func buildDependants(tgts []string) map[string]struct{} {
+ defer Jobs.Wait()
+ tracef(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, false) {
+ if tgt != tgtInitial {
+ seen[tgt] = struct{}{}
+ }
+ }
+ }
+ if len(seen) == 0 {
+ return seen
+ }
+
+ levelOrig := Level
+ defer func() {
+ Level = levelOrig
+ }()
+ Level = 1
+ tracef(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 {
+ tracef(CErr, "always run error: %s, skipping dependants", err)
+ return nil
+ }
+ }
+ ok := true
+ for i := 0; i < len(seen); i++ {
+ ok = isOkRun(<-errs) && ok
+ }
+ Jobs.Wait()
+ close(errs)
+ if !ok {
+ tracef(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:
+ tracef(CDebug, "checking %d dependant targets: %v", len(queueSrc), queueSrc)
+ queue := map[string]struct{}{}
+ for _, tgt := range queueSrc {
+ for dep := range deps[tgt] {
+ queue[dep] = struct{}{}
+ }
+ }
+
+ tracef(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 {
+ tracef(CErr, "dependant error: %s, skipping dependants", err)
+ return nil
+ }
+ if !ood {
+ continue
+ }
+ if err := runScript(tgt, errs, false); err != nil {
+ tracef(CErr, "dependant error: %s, skipping dependants", err)
+ return nil
+ }
+ queueSrc = append(queueSrc, tgt)
+ seen[tgt] = struct{}{}
+ jobs++
+ }
+ for i := 0; i < jobs; i++ {
+ ok = isOkRun(<-errs) && ok
+ }
+ if !ok {
+ tracef(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) {
+ // only unique elements
+ m := make(map[string]struct{})
+ for _, t := range tgts {
+ m[t] = struct{}{}
+ }
+ tgts = tgts[:0]
+ for t := range m {
+ tgts = append(tgts, t)
+ }
+ m = nil
+