diff --git a/NEWS b/NEWS index 4a38e4fe..2c46e1e1 100644 --- a/NEWS +++ b/NEWS @@ -24,6 +24,10 @@ http://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=106&set The function is expanded to the contents of the file. The contents are expanded verbatim except that the final newline, if any, is stripped. +* The makefile line numbers shown by GNU make now point directly to the + specific line in the recipe where the failure or warning occurred. + Sample changes suggested by Brian Vandenberg + * The interface to GNU make's "jobserver" is stable as documented in the manual, for tools which may want to access it. @@ -32,7 +36,7 @@ http://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=106&set * The amount of parallelism can be determined by querying MAKEFLAGS, even when the job server is enabled (previously MAKEFLAGS would always contain only - "-j" when job server was enabled). + "-j", with no number, when job server was enabled). * VMS-specific changes: diff --git a/function.c b/function.c index 28015981..b8e69b22 100644 --- a/function.c +++ b/function.c @@ -1734,7 +1734,8 @@ func_shell_base (char *o, char **argv, int trim_newlines) if (reading_file && reading_file->filenm) { char *p = alloca (strlen (reading_file->filenm)+11+4); - sprintf (p, "%s:%lu: ", reading_file->filenm, reading_file->lineno); + sprintf (p, "%s:%lu: ", reading_file->filenm, + reading_file->lineno + reading_file->offset); error_prefix = p; } else diff --git a/gnumake.h b/gnumake.h index b508562f..5b441e58 100644 --- a/gnumake.h +++ b/gnumake.h @@ -24,6 +24,7 @@ typedef struct { const char *filenm; unsigned long lineno; + unsigned long offset; } gmk_floc; typedef char *(*gmk_func_ptr)(const char *nm, unsigned int argc, char **argv); diff --git a/job.c b/job.c index 59f51cd2..2d2c8037 100644 --- a/job.c +++ b/job.c @@ -500,7 +500,7 @@ child_error (struct child *child, else { char *a = alloca (strlen (flocp->filenm) + 1 + 11 + 1); - sprintf (a, "%s:%lu", flocp->filenm, flocp->lineno); + sprintf (a, "%s:%lu", flocp->filenm, flocp->lineno + flocp->offset); nm = a; } @@ -1745,10 +1745,12 @@ new_job (struct file *file) memmove (out, in, strlen (in) + 1); /* Finally, expand the line. */ + cmds->fileinfo.offset = i; lines[i] = allocated_variable_expand_for_file (cmds->command_lines[i], file); } + cmds->fileinfo.offset = 0; c->command_lines = lines; /* Fetch the first command line to be run. */ @@ -1873,12 +1875,15 @@ job_next_command (struct child *child) { /* There are no more lines to be expanded. */ child->command_ptr = 0; + child->file->cmds->fileinfo.offset = 0; return 0; } else /* Get the next line to run. */ child->command_ptr = child->command_lines[child->command_line++]; } + + child->file->cmds->fileinfo.offset = child->command_line - 1; return 1; } diff --git a/output.c b/output.c index 7e905cc3..475862f0 100644 --- a/output.c +++ b/output.c @@ -651,7 +651,7 @@ error (const gmk_floc *flocp, size_t len, const char *fmt, ...) p = get_buffer (len); if (flocp && flocp->filenm) - sprintf (p, "%s:%lu: ", flocp->filenm, flocp->lineno); + sprintf (p, "%s:%lu: ", flocp->filenm, flocp->lineno + flocp->offset); else if (makelevel == 0) sprintf (p, "%s: ", program); else @@ -683,7 +683,7 @@ fatal (const gmk_floc *flocp, size_t len, const char *fmt, ...) p = get_buffer (len); if (flocp && flocp->filenm) - sprintf (p, "%s:%lu: *** ", flocp->filenm, flocp->lineno); + sprintf (p, "%s:%lu: *** ", flocp->filenm, flocp->lineno + flocp->offset); else if (makelevel == 0) sprintf (p, "%s: *** ", program); else diff --git a/read.c b/read.c index 10b250e7..a71eaebe 100644 --- a/read.c +++ b/read.c @@ -324,6 +324,7 @@ eval_makefile (const char *filename, int flags) ebuf.floc.filenm = filename; /* Use the original file name. */ ebuf.floc.lineno = 1; + ebuf.floc.offset = 0; if (ISDB (DB_VERBOSE)) { @@ -470,6 +471,7 @@ eval_buffer (char *buffer, const gmk_floc *floc) { ebuf.floc.filenm = NULL; ebuf.floc.lineno = 1; + ebuf.floc.offset = 0; } curfile = reading_file; @@ -592,6 +594,7 @@ eval (struct ebuffer *ebuf, int set_default) if (filenames != 0) \ { \ fi.lineno = tgts_started; \ + fi.offset = 0; \ record_files (filenames, pattern, pattern_percent, depstr, \ cmds_started, commands, commands_idx, two_colon, \ prefix, &fi); \ @@ -1958,6 +1961,7 @@ record_files (struct nameseq *filenames, const char *pattern, cmds = xmalloc (sizeof (struct commands)); cmds->fileinfo.filenm = flocp->filenm; cmds->fileinfo.lineno = cmds_started; + cmds->fileinfo.offset = 0; cmds->commands = xstrndup (commands, commands_idx); cmds->command_lines = 0; cmds->recipe_prefix = prefix; diff --git a/rule.c b/rule.c index fce8372c..de8b3046 100644 --- a/rule.c +++ b/rule.c @@ -380,6 +380,7 @@ install_pattern_rule (struct pspec *p, int terminal) r->cmds = xmalloc (sizeof (struct commands)); r->cmds->fileinfo.filenm = 0; r->cmds->fileinfo.lineno = 0; + r->cmds->fileinfo.offset = 0; /* These will all be string literals, but we malloc space for them anyway because somebody might want to free them later. */ r->cmds->commands = xstrdup (p->commands); diff --git a/tests/scripts/features/errors b/tests/scripts/features/errors index 43b81d4d..ebd43831 100644 --- a/tests/scripts/features/errors +++ b/tests/scripts/features/errors @@ -90,4 +90,18 @@ if (!$vos) { &compare_output($answer,&get_logfile(1)); } +# Test that error line offset works + +run_make_test(q! +all: + @echo hi + @echo there + @exit 1 +!, + '', "hi\nthere\n#MAKE#: *** [#MAKEFILE#:5: all] Error 1", 512); + 1; + +### Local Variables: +### eval: (setq whitespace-action (delq 'auto-cleanup whitespace-action)) +### End: diff --git a/tests/scripts/features/output-sync b/tests/scripts/features/output-sync index 64d6fe08..7139e002 100644 --- a/tests/scripts/features/output-sync +++ b/tests/scripts/features/output-sync @@ -204,7 +204,7 @@ bar: end #MAKE#[1]: Entering directory '#PWD#/foo' foo-fail: start foo-fail: end -#MAKE#[1]: *** [Makefile:20: foo-fail] Error 1 +#MAKE#[1]: *** [Makefile:23: foo-fail] Error 1 #MAKE#[1]: Leaving directory '#PWD#/foo' #MAKE#: *** [#MAKEFILE#:4: make-foo-fail] Error 2\n", 512); diff --git a/tests/scripts/features/parallelism b/tests/scripts/features/parallelism index 6b9efe1b..fabe5485 100644 --- a/tests/scripts/features/parallelism +++ b/tests/scripts/features/parallelism @@ -99,12 +99,12 @@ ok: \@$sleep_command 4 \@echo Ok done", '-rR -j5', "Fail -#MAKE#: *** [#MAKEFILE#:6: fail.1] Error 1 +#MAKE#: *** [#MAKEFILE#:8: fail.1] Error 1 #MAKE#: *** Waiting for unfinished jobs.... Fail -#MAKE#: *** [#MAKEFILE#:6: fail.2] Error 1 +#MAKE#: *** [#MAKEFILE#:8: fail.2] Error 1 Fail -#MAKE#: *** [#MAKEFILE#:6: fail.3] Error 1 +#MAKE#: *** [#MAKEFILE#:8: fail.3] Error 1 Ok done", 512); diff --git a/tests/scripts/functions/error b/tests/scripts/functions/error index 0d61177f..998afe48 100644 --- a/tests/scripts/functions/error +++ b/tests/scripts/functions/error @@ -54,7 +54,7 @@ $answer = "Some stuff\n$makefile:12: *** error is maybe. Stop.\n"; # Test #4 &run_make_with_options($makefile, "ERROR4=definitely", &get_logfile, 512); -$answer = "Some stuff\n$makefile:16: *** error is definitely. Stop.\n"; +$answer = "Some stuff\n$makefile:17: *** error is definitely. Stop.\n"; &compare_output($answer,&get_logfile(1)); # Test #5 @@ -66,8 +66,6 @@ $answer = "$makefile:22: *** Error found!. Stop.\n"; # This tells the test driver that the perl test script executed properly. 1; - - - - - +### Local Variables: +### eval: (setq whitespace-action (delq 'auto-cleanup whitespace-action)) +### End: diff --git a/tests/scripts/functions/shell b/tests/scripts/functions/shell index 4702b096..809c77fa 100644 --- a/tests/scripts/functions/shell +++ b/tests/scripts/functions/shell @@ -44,4 +44,17 @@ export HI = $(shell echo hi) all: ; @echo $$HI ','','hi'); +# Test shell errors in recipes including offset +run_make_test(' +all: + @echo hi + $(shell ./basdfdfsed there) + @echo there +', + '', "#MAKE#: ./basdfdfsed: Command not found\nhi\nthere\n"); + 1; + +### Local Variables: +### eval: (setq whitespace-action (delq 'auto-cleanup whitespace-action)) +### End: diff --git a/tests/scripts/functions/warning b/tests/scripts/functions/warning index cd452d41..16eb83bb 100644 --- a/tests/scripts/functions/warning +++ b/tests/scripts/functions/warning @@ -52,14 +52,32 @@ $answer = "Some stuff\n$makefile:10: warning is maybe\nhi\n"; # Test #4 &run_make_with_options($makefile, "WARNING4=definitely", &get_logfile, 0); -$answer = "Some stuff\n$makefile:14: warning is definitely\nhi\nthere\n"; +$answer = "Some stuff\n$makefile:15: warning is definitely\nhi\nthere\n"; &compare_output($answer,&get_logfile(1)); +# Test linenumber offset + +run_make_test(q! +all: one two + $(warning in $@ line 3) + @true + $(warning in $@ line 5) + +one two: + $(warning in $@ line 8) + @true + $(warning in $@ line 10) +!, + '', "#MAKEFILE#:8: in one line 8 +#MAKEFILE#:10: in one line 10 +#MAKEFILE#:8: in two line 8 +#MAKEFILE#:10: in two line 10 +#MAKEFILE#:3: in all line 3 +#MAKEFILE#:5: in all line 5\n"); + # This tells the test driver that the perl test script executed properly. 1; - - - - - +### Local Variables: +### eval: (setq whitespace-action (delq 'auto-cleanup whitespace-action)) +### End: diff --git a/variable.c b/variable.c index edbe5945..b0d8d69c 100644 --- a/variable.c +++ b/variable.c @@ -1657,7 +1657,7 @@ print_variable (const void *item, void *arg) fputs (" private", stdout); if (v->fileinfo.filenm) printf (_(" (from '%s', line %lu)"), - v->fileinfo.filenm, v->fileinfo.lineno); + v->fileinfo.filenm, v->fileinfo.lineno + v->fileinfo.offset); putchar ('\n'); fputs (prefix, stdout);