Hello GNU make gurus,
Instead of the patch proposed here:
http://lists.gnu.org/archive/html/bug-make/2009-01/msg00007.html
I would like to propose the patch below instead. The difference is that I
renamed keep_going_count to stop_at_err_count which I think is more
descriptive of the intent. I have also added a hunk in job.c which forces
GNU Make to return immediately when the number of errors is reached.
However, there is one problem which manifest itself when using parallel
make, and I need help to solve it (I am not familiar with GNU Make
code). Here is a description of the problem (the patch is further down
below).
Given this makefile:
all: t1 t2
t1:
sleep 30 && echo done || echo failed
t2:
sleep 10 && exit 1
and this command: ../make-3.81/make -j 2 --stop-at-err-count=1
The problem is that --stop-at-err-count=1 forces make to return but
unfinished children are not killed by make, as you can see in this
sample run:
$ ../make-3.81/make -j 2 --stop-at-err-count=1
sleep 30 && echo done || echo failed
sleep 10 && exit 1
make: *** [t2] Error 1
make: *** Waiting for unfinished jobs....
make: *** Aborting after 1 failures
$ done
$ echo $?
2
$
I examined the processes and yes in fact make launches both in parallel:
boo 22255 2955 0 08:42 pts/38 00:00:00 ../make-3.81/make -j 2
--stop-at-err-count=1
boo 22256 22255 0 08:42 pts/38 00:00:00 /bin/sh -c sleep 30 && echo done
|| echo failed
boo 22257 22256 0 08:42 pts/38 00:00:00 sleep 30
boo 22258 22255 0 08:42 pts/38 00:00:00 /bin/sh -c sleep 10 && exit 1
boo 22259 22258 0 08:42 pts/38 00:00:00 sleep 10
and when 22258 exits, GNU Make also exits, but 22256 keeps running. I
want all children to be killed before GNU Make returns. How do I modify
the proposed patch to achieve that?
I would really appreciate feedback on this proposal and on how to fix the
aforementionned problem.
Regards,
Martin d'Anjou
Here is the said patch, it should apply cleanly to 3.81.
----------------------------
diff -u ./job.c /home/boo/local/SRC/make-3.81a/job.c
--- ./job.c 2006-03-19 22:03:04.000000000 -0500
+++ /home/boo/local/SRC/make-3.81a/job.c 2009-01-09 17:31:09.384897000
-0500
@@ -379,9 +379,19 @@
child_error (char *target_name, int exit_code, int exit_sig, int coredump,
int ignored)
{
+ if (max_stop_at_err_count <= stop_at_err_count)
+ {
+ error (NILF, _("*** [%s] Error (aborted after %d failures) %d"),
+ target_name, stop_at_err_count, exit_code);
+ die (2);
+ }
+
if (ignored && silent_flag)
return;
+ /* Only increase STOP_AT_ERR_COUNT if the job _really_ failed. */
+ stop_at_err_count++;
+
#ifdef VMS
if (!(exit_code & 1))
error (NILF,
@@ -485,7 +495,14 @@
Only print this message once no matter how many jobs are left. */
fflush (stdout);
if (!printed)
+ {
error (NILF, _("*** Waiting for unfinished jobs...."));
+ if (max_stop_at_err_count <= stop_at_err_count)
+ {
+ error (NILF, _("*** Aborting after %d
failures"),stop_at_err_count);
+ die (2);
+ }
+ }
printed = 1;
}
diff -u ./main.c /home/boo/local/SRC/make-3.81a/main.c
--- ./main.c 2006-03-19 21:36:37.000000000 -0500
+++ /home/boo/local/SRC/make-3.81a/main.c 2009-01-09 17:31:02.674041000
-0500
@@ -189,9 +189,13 @@
/* Nonzero means keep going even if remaking some file fails (-k). */
-int keep_going_flag;
+int keep_going_flag = 0;
int default_keep_going_flag = 0;
+int stop_at_err_count = 0;
+unsigned int max_stop_at_err_count = -1;
+static unsigned int inf_stop_at_err_count = 0;
+
/* Nonzero means check symlink mtimes. */
int check_symlink_flag = 0;
@@ -342,6 +346,8 @@
-S, --no-keep-going, --stop\n\
Turns off -k.\n"),
N_("\
+ --stop-at-err-count[=N] Stop when N errors are reached. Default 0
(infinite).\n"),
+ N_("\
-t, --touch Touch targets instead of remaking them.\n"),
N_("\
-v, --version Print the version number of make and exit.\n"),
@@ -416,6 +422,14 @@
{ 'W', string, (char *) &new_files, 0, 0, 0, 0, 0, "what-if" },
{ CHAR_MAX+4, flag, (char *) &warn_undefined_variables_flag, 1, 1, 0, 0, 0,
"warn-undefined-variables" },
+ /* BUG: There is a bug in the argument parser where if you have a
+ long-optin, but no corresponding short option in the ASCII
+ range, the output will produce a charachter that can corrupt
+ the terminal.
+ */
+ { CHAR_MAX+5, positive_int, (char *) &max_stop_at_err_count, 1, 1, 0,
+ (char *) &inf_stop_at_err_count,
+ (char *) &max_stop_at_err_count, "stop-at-err-count" },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};
diff -u ./make.h /home/boo/local/SRC/make-3.81a/make.h
--- ./make.h 2006-02-15 18:54:43.000000000 -0500
+++ /home/boo/local/SRC/make-3.81a/make.h 2009-01-09 17:36:55.992563000
-0500
@@ -499,6 +499,9 @@
extern const struct floc *reading_file;
extern const struct floc **expanding_var;
+extern int stop_at_err_count;
+extern unsigned int max_stop_at_err_count;
+
extern char **environ;
extern int just_print_flag, silent_flag, ignore_errors_flag, keep_going_flag;
diff -u ./remake.c /home/boo/local/SRC/make-3.81a/remake.c
--- ./remake.c 2006-03-19 21:36:37.000000000 -0500
+++ /home/boo/local/SRC/make-3.81a/remake.c 2008-09-04 08:12:17.000000000
-0400
@@ -311,7 +311,7 @@
alloca (0);
/* If we got an error, don't bother with double_colon etc. */
- if (status != 0 && !keep_going_flag)
+ if (status != 0 && keep_going_flag == 1)
return status;
if (f->command_state == cs_running
@@ -350,7 +350,7 @@
const char *msg_parent
= _("%sNo rule to make target `%s', needed by `%s'%s");
- if (!keep_going_flag)
+ if (keep_going_flag == 0)
{
if (file->parent == 0)
fatal (NILF, msg_noparent, "", file->name, "");
@@ -529,7 +529,7 @@
while (f != 0);
}
- if (dep_status != 0 && !keep_going_flag)
+ if (dep_status != 0 && keep_going_flag == 0)
break;
if (!running)
@@ -587,7 +587,7 @@
while (f != 0);
}
- if (dep_status != 0 && !keep_going_flag)
+ if (dep_status != 0 && keep_going_flag == 0)
break;
if (!running)
@@ -619,7 +619,7 @@
DBF (DB_VERBOSE, _("Giving up on target file `%s'.\n"));
- if (depth == 0 && keep_going_flag
+ if (depth == 0 && keep_going_flag == 1
&& !just_print_flag && !question_flag)
error (NILF,
_("Target `%s' not remade because of errors."), file->name);
@@ -1017,7 +1017,7 @@
if (! d->ignore_mtime)
*must_make_ptr = maybe_make;
check_renamed (d->file);
- if (dep_status != 0 && !keep_going_flag)
+ if (dep_status != 0 && keep_going_flag == 0)
break;
if (d->file->command_state == cs_running
_______________________________________________
Bug-make mailing list
Bug-make@gnu.org
http://lists.gnu.org/mailman/listinfo/bug-make