diff options
Diffstat (limited to 'src/remake.c')
-rw-r--r-- | src/remake.c | 40 |
1 files changed, 30 insertions, 10 deletions
diff --git a/src/remake.c b/src/remake.c index 04daf49c..dec4667c 100644 --- a/src/remake.c +++ b/src/remake.c @@ -119,6 +119,7 @@ update_goal_chain (struct goaldep *goaldeps) unsigned long last_cmd_count = 0; int t = touch_flag, q = question_flag, n = just_print_flag; enum update_status status = us_none; + const unsigned int depth = rebuilding_makefiles ? 1 : 0; /* Duplicate the chain so we can remove things from it. */ struct dep *goals_orig = copy_dep_chain ((struct dep *)goaldeps); @@ -137,6 +138,7 @@ update_goal_chain (struct goaldep *goaldeps) while (goals != 0) { struct dep *gu, *g, *lastgoal; + int running = 0, wait = 0; /* Start jobs that are waiting for the load to go down. */ @@ -154,16 +156,14 @@ update_goal_chain (struct goaldep *goaldeps) while (gu != 0) { /* Iterate over all double-colon entries for this file. */ - struct file *file; + struct file *file, *dchead; int stop = 0, any_not_updated = 0; g = gu->shuf ? gu->shuf : gu; goal_dep = g; - - for (file = g->file->double_colon ? g->file->double_colon : g->file; - file != NULL; - file = file->prev) + dchead = g->file->double_colon ? g->file->double_colon : g->file; + for (file = dchead; file != NULL; file = file->prev) { unsigned int ocommands_started; enum update_status fail; @@ -188,8 +188,24 @@ update_goal_chain (struct goaldep *goaldeps) actually run. */ ocommands_started = commands_started; - fail = update_file (file, rebuilding_makefiles ? 1 : 0); + stop = 0; + + /* In the case of double colon rules, only the recipe of the 1st + rule should be blocked by .WAIT. The recipes of all subsequent + rules for the same file will execute sequentially in order + after the 1st. */ + wait = file == dchead && g->wait_here && running; + if (wait) + { + DBF (DB_VERBOSE, _(".WAIT is blocking '%s'.\n")); + break; + } + + fail = update_file (file, depth); check_renamed (file); + running |= (file->command_state == cs_running + || file->command_state == cs_deps_running); + /* Set the goal's 'changed' flag if any commands were started by calling update_file above. We check this flag below to @@ -197,7 +213,6 @@ update_goal_chain (struct goaldep *goaldeps) if (commands_started > ocommands_started) g->changed = 1; - stop = 0; if ((fail || file->updated) && status < us_question) { /* We updated this goal. Update STATUS and decide whether @@ -249,6 +264,9 @@ update_goal_chain (struct goaldep *goaldeps) /* Reset FILE since it is null at the end of the loop. */ file = g->file; + if (wait) + break; + if (stop || !any_not_updated) { /* If we have found nothing whatever to do for the goal, @@ -285,8 +303,9 @@ update_goal_chain (struct goaldep *goaldeps) } /* If we reached the end of the dependency graph update CONSIDERED - for the next pass. */ - if (gu == 0) + for the next pass. In the case of waiting, increment CONSIDERED to + prevent the same file from getting pruned over and over again. */ + if (gu == 0 || wait) ++considered; } @@ -384,7 +403,8 @@ update_file (struct file *file, unsigned int depth) if (f->command_state == cs_running || f->command_state == cs_deps_running) /* Don't run other :: rules for this target until - this rule is finished. */ + this rule is finished. Multiple recipes running in parallel and + updating the same target will corrupt the target. */ return us_success; if (new > status) |