diff options
author | Ron Yorston <rmy@pobox.com> | 2022-11-16 14:25:16 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2022-11-16 14:25:16 +0000 |
commit | f3f72ac1d2a56b97c6e90aa359ad236f528b5294 (patch) | |
tree | ebca668d6a8a10d81803568410cb44c3ecf606b9 /miscutils | |
parent | fa94c6da0d38929abbd40062448aaf2ba8d846f4 (diff) | |
download | busybox-w32-f3f72ac1d2a56b97c6e90aa359ad236f528b5294.tar.gz busybox-w32-f3f72ac1d2a56b97c6e90aa359ad236f528b5294.tar.bz2 busybox-w32-f3f72ac1d2a56b97c6e90aa359ad236f528b5294.zip |
make: show location of errors during build
Error messages only displayed the location of an error while the
makefile was being parsed.
Store the location (makefile name and line number) of each command
line. This allows location information to be displayed in errors
encountered while targets are being built.
Take this Makefile, for example:
target:
@echo $(hello
Previously this would display:
make: unterminated variable '$(hello'
Now it shows:
make: (Makefile:2): unterminated variable '$(hello'
Diffstat (limited to 'miscutils')
-rw-r--r-- | miscutils/make.c | 56 |
1 files changed, 41 insertions, 15 deletions
diff --git a/miscutils/make.c b/miscutils/make.c index aedb1c74a..1104dfe87 100644 --- a/miscutils/make.c +++ b/miscutils/make.c | |||
@@ -149,6 +149,8 @@ struct cmd { | |||
149 | struct cmd *c_next; // Next command line | 149 | struct cmd *c_next; // Next command line |
150 | char *c_cmd; // Text of command line | 150 | char *c_cmd; // Text of command line |
151 | int c_refcnt; // Reference count | 151 | int c_refcnt; // Reference count |
152 | const char *c_makefile; // Makefile in which command was defined | ||
153 | int c_dispno; // Line number within makefile | ||
152 | }; | 154 | }; |
153 | 155 | ||
154 | // Macro storage | 156 | // Macro storage |
@@ -229,7 +231,23 @@ static int make(struct name *np, int level); | |||
229 | */ | 231 | */ |
230 | 232 | ||
231 | /* | 233 | /* |
232 | * Error handler. Print message, with line number, and exit. | 234 | * Print message, with makefile and line number if possible. |
235 | */ | ||
236 | static void | ||
237 | vwarning(const char *msg, va_list list) | ||
238 | { | ||
239 | const char *old_applet_name = applet_name; | ||
240 | |||
241 | if (makefile) { | ||
242 | fprintf(stderr, "%s: (%s:%d)", applet_name, makefile, dispno); | ||
243 | applet_name = ""; | ||
244 | } | ||
245 | bb_verror_msg(msg, list, NULL); | ||
246 | applet_name = old_applet_name; | ||
247 | } | ||
248 | |||
249 | /* | ||
250 | * Error handler. Print message and exit. | ||
233 | */ | 251 | */ |
234 | static void error(const char *msg, ...) NORETURN; | 252 | static void error(const char *msg, ...) NORETURN; |
235 | static void | 253 | static void |
@@ -237,16 +255,8 @@ error(const char *msg, ...) | |||
237 | { | 255 | { |
238 | va_list list; | 256 | va_list list; |
239 | 257 | ||
240 | if (makefile) { | ||
241 | const char *num = itoa(dispno); | ||
242 | char *s = malloc(strlen(makefile) + strlen(num) + 2); | ||
243 | if (s) { | ||
244 | sprintf(s, "%s:%s", makefile, num); | ||
245 | applet_name = s; | ||
246 | } | ||
247 | } | ||
248 | va_start(list, msg); | 258 | va_start(list, msg); |
249 | bb_verror_msg(msg, list, NULL); | 259 | vwarning(msg, list); |
250 | va_end(list); | 260 | va_end(list); |
251 | exit(2); | 261 | exit(2); |
252 | } | 262 | } |
@@ -265,6 +275,16 @@ error_in_inference_rule(const char *s) | |||
265 | error("%s in inference rule", s); | 275 | error("%s in inference rule", s); |
266 | } | 276 | } |
267 | 277 | ||
278 | static void | ||
279 | warning(const char *msg, ...) | ||
280 | { | ||
281 | va_list list; | ||
282 | |||
283 | va_start(list, msg); | ||
284 | vwarning(msg, list); | ||
285 | va_end(list); | ||
286 | } | ||
287 | |||
268 | static char * | 288 | static char * |
269 | auto_concat(const char *s1, const char *s2) | 289 | auto_concat(const char *s1, const char *s2) |
270 | { | 290 | { |
@@ -334,6 +354,8 @@ newcmd(struct cmd **cphead, char *str) | |||
334 | /*(*cphead)->c_next = NULL; - xzalloc did it */ | 354 | /*(*cphead)->c_next = NULL; - xzalloc did it */ |
335 | (*cphead)->c_cmd = xstrdup(str); | 355 | (*cphead)->c_cmd = xstrdup(str); |
336 | /*(*cphead)->c_refcnt = 0; */ | 356 | /*(*cphead)->c_refcnt = 0; */ |
357 | (*cphead)->c_makefile = makefile; | ||
358 | (*cphead)->c_dispno = dispno; | ||
337 | } | 359 | } |
338 | 360 | ||
339 | static void | 361 | static void |
@@ -1875,7 +1897,7 @@ remove_target(void) | |||
1875 | if (!dryrun && !print && !precious && | 1897 | if (!dryrun && !print && !precious && |
1876 | target && !(target->n_flag & (N_PRECIOUS | N_PHONY)) && | 1898 | target && !(target->n_flag & (N_PRECIOUS | N_PHONY)) && |
1877 | unlink(target->n_name) == 0) { | 1899 | unlink(target->n_name) == 0) { |
1878 | bb_error_msg("'%s' removed", target->n_name); | 1900 | warning("'%s' removed", target->n_name); |
1879 | } | 1901 | } |
1880 | } | 1902 | } |
1881 | 1903 | ||
@@ -1891,6 +1913,9 @@ docmds(struct name *np, struct cmd *cp) | |||
1891 | for (; cp; cp = cp->c_next) { | 1913 | for (; cp; cp = cp->c_next) { |
1892 | uint8_t ssilent, signore, sdomake; | 1914 | uint8_t ssilent, signore, sdomake; |
1893 | 1915 | ||
1916 | // Location of command in makefile (for use in error messages) | ||
1917 | makefile = cp->c_makefile; | ||
1918 | dispno = cp->c_dispno; | ||
1894 | opts &= ~OPT_make; // We want to know if $(MAKE) is expanded | 1919 | opts &= ~OPT_make; // We want to know if $(MAKE) is expanded |
1895 | q = command = expand_macros(cp->c_cmd, FALSE); | 1920 | q = command = expand_macros(cp->c_cmd, FALSE); |
1896 | ssilent = silent || (np->n_flag & N_SILENT) || dotouch; | 1921 | ssilent = silent || (np->n_flag & N_SILENT) || dotouch; |
@@ -1933,7 +1958,7 @@ docmds(struct name *np, struct cmd *cp) | |||
1933 | error("couldn't execute '%s'", q); | 1958 | error("couldn't execute '%s'", q); |
1934 | } else if (status != 0 && !signore) { | 1959 | } else if (status != 0 && !signore) { |
1935 | if (!doinclude) | 1960 | if (!doinclude) |
1936 | bb_error_msg("failed to build '%s'", np->n_name); | 1961 | warning("failed to build '%s'", np->n_name); |
1937 | #if !ENABLE_PLATFORM_MINGW32 | 1962 | #if !ENABLE_PLATFORM_MINGW32 |
1938 | if (status == SIGINT || status == SIGQUIT) | 1963 | if (status == SIGINT || status == SIGQUIT) |
1939 | #endif | 1964 | #endif |
@@ -1946,6 +1971,7 @@ docmds(struct name *np, struct cmd *cp) | |||
1946 | } | 1971 | } |
1947 | free(command); | 1972 | free(command); |
1948 | } | 1973 | } |
1974 | makefile = NULL; | ||
1949 | return estat; | 1975 | return estat; |
1950 | } | 1976 | } |
1951 | 1977 | ||
@@ -1969,7 +1995,7 @@ touch(struct name *np) | |||
1969 | return; | 1995 | return; |
1970 | } | 1996 | } |
1971 | } | 1997 | } |
1972 | bb_perror_msg("touch %s failed", np->n_name); | 1998 | warning("touch %s failed", np->n_name); |
1973 | } | 1999 | } |
1974 | } | 2000 | } |
1975 | } | 2001 | } |
@@ -2185,10 +2211,10 @@ make(struct name *np, int level) | |||
2185 | if (sc_cmd) | 2211 | if (sc_cmd) |
2186 | estat = make1(np, sc_cmd, oodate, allsrc, dedup, impdep); | 2212 | estat = make1(np, sc_cmd, oodate, allsrc, dedup, impdep); |
2187 | else if (!doinclude) | 2213 | else if (!doinclude) |
2188 | bb_error_msg("nothing to be done for %s", np->n_name); | 2214 | warning("nothing to be done for %s", np->n_name); |
2189 | didsomething = 1; | 2215 | didsomething = 1; |
2190 | } else if (!doinclude) { | 2216 | } else if (!doinclude) { |
2191 | bb_error_msg("'%s' not built due to errors", np->n_name); | 2217 | warning("'%s' not built due to errors", np->n_name); |
2192 | } | 2218 | } |
2193 | free(oodate); | 2219 | free(oodate); |
2194 | } | 2220 | } |