[SV 63856] Implement .WAIT on the command line

* src/main.c (handle_non_switch_argument): Return 1 if arg is .WAIT.
(decode_switches): Set wait_here for a goal that follows .WAIT.
* src/remake.c (update_goal_chain): Honor wait_here for a command
line goal.  Don't allow double-colon targets to continue if .WAIT is
given for one of them.
* tests/scripts/targets/WAIT: Add .WAIT tests.
This commit is contained in:
Dmitry Goncharov
2023-04-02 10:50:17 -04:00
committed by Paul Smith
parent 54b3202f8d
commit cd46baab90
3 changed files with 168 additions and 18 deletions

View File

@@ -2975,15 +2975,17 @@ init_switches (void)
}
/* Non-option argument. It might be a variable definition. */
static void
/* Non-option argument. It might be a variable definition.
Returns 1 if the argument we read was .WAIT, else 0.
*/
static unsigned int
handle_non_switch_argument (const char *arg, enum variable_origin origin)
{
struct variable *v;
if (arg[0] == '-' && arg[1] == '\0')
/* Ignore plain '-' for compatibility. */
return;
return 0;
#if MK_OS_VMS
{
@@ -3036,7 +3038,12 @@ handle_non_switch_argument (const char *arg, enum variable_origin origin)
Enter it as a file and add it to the dep chain of goals.
Check ARG[0] because if the top makefile resets MAKEOVERRIDES
then ARG points to an empty string in the submake. */
struct file *f = enter_file (strcache_add (expand_command_line_file (arg)));
struct file *f;
if (strcmp (arg, ".WAIT") == 0)
return 1;
f = enter_file (strcache_add (expand_command_line_file (arg)));
f->cmd_target = 1;
if (goals == 0)
@@ -3077,6 +3084,7 @@ handle_non_switch_argument (const char *arg, enum variable_origin origin)
define_variable_cname ("MAKECMDGOALS", value, o_default, 0);
}
}
return 0;
}
/* Called if the makefile resets the MAKEFLAGS variable. */
@@ -3098,6 +3106,7 @@ decode_switches (int argc, const char **argv, enum variable_origin origin)
struct command_switch *cs;
struct stringlist *sl;
int c;
unsigned int found_wait = 0;
/* getopt does most of the parsing for us.
First, get its vectors set up. */
@@ -3120,15 +3129,22 @@ decode_switches (int argc, const char **argv, enum variable_origin origin)
if (c == EOF)
/* End of arguments, or "--" marker seen. */
break;
else if (c == 1)
/* An argument not starting with a dash. */
handle_non_switch_argument (coptarg, origin);
else if (c == '?')
/* Bad option. We will print a usage message and die later.
But continue to parse the other options so the user can
see all he did wrong. */
bad = 1;
else if (c == 1)
{
/* An argument not starting with a dash. */
const unsigned int prior_found_wait = found_wait;
found_wait = handle_non_switch_argument (coptarg, origin);
if (prior_found_wait && lastgoal)
/* If the argument before this was .WAIT, wait here. */
lastgoal->wait_here = 1;
}
else
/* An option starting with a dash. */
for (cs = switches; cs->c != '\0'; ++cs)
if (cs->c == c)
{
@@ -3320,7 +3336,12 @@ decode_switches (int argc, const char **argv, enum variable_origin origin)
to be returned in order, this only happens when there is a "--"
argument to prevent later arguments from being options. */
while (optind < argc)
handle_non_switch_argument (argv[optind++], origin);
{
const int prior_found_wait = found_wait;
found_wait = handle_non_switch_argument (argv[optind++], origin);
if (prior_found_wait && lastgoal)
lastgoal->wait_here = 1;
}
if (bad && origin == o_command)
print_usage (bad);

View File

@@ -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)