diff options
Diffstat (limited to 'src/kmk/remake.c')
-rw-r--r-- | src/kmk/remake.c | 421 |
1 files changed, 250 insertions, 171 deletions
diff --git a/src/kmk/remake.c b/src/kmk/remake.c index c465f0b..8855a2f 100644 --- a/src/kmk/remake.c +++ b/src/kmk/remake.c @@ -1,7 +1,7 @@ /* Basic dependency engine for GNU Make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software -Foundation, Inc. +1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the @@ -88,7 +88,6 @@ int update_goal_chain (struct dep *goals) { int t = touch_flag, q = question_flag, n = just_print_flag; - unsigned int j = job_slots; int status = -1; #define MTIME(file) (rebuilding_makefiles ? file_mtime_no_search (file) \ @@ -140,6 +139,9 @@ update_goal_chain (struct dep *goals) { unsigned int ocommands_started; int x; + + file->dontcare = g->dontcare; + check_renamed (file); if (rebuilding_makefiles) { @@ -213,6 +215,8 @@ update_goal_chain (struct dep *goals) When they are all finished, the goal is finished. */ any_not_updated |= !file->updated; + file->dontcare = 0; + if (stop) break; } @@ -273,7 +277,6 @@ update_goal_chain (struct dep *goals) touch_flag = t; question_flag = q; just_print_flag = n; - job_slots = j; } return status; @@ -305,8 +308,14 @@ update_file (struct file *file, unsigned int depth) change is possible below here until then. */ if (f->considered == considered) { - DBF (DB_VERBOSE, _("Pruning file `%s'.\n")); - return f->command_state == cs_finished ? f->update_status : 0; + /* Check for the case where a target has been tried and failed but + the diagnostics hasn't been issued. If we need the diagnostics + then we will have to continue. */ + if (!(f->updated && f->update_status > 0 && !f->dontcare && f->no_diag)) + { + DBF (DB_VERBOSE, _("Pruning file `%s'.\n")); + return f->command_state == cs_finished ? f->update_status : 0; + } } /* This loop runs until we start commands for a double colon rule, or until @@ -323,7 +332,7 @@ update_file (struct file *file, unsigned int depth) /* If we got an error, don't bother with double_colon etc. */ if (status != 0 && !keep_going_flag) - return status; + return status; if (f->command_state == cs_running || f->command_state == cs_deps_running) @@ -354,65 +363,89 @@ update_file (struct file *file, unsigned int depth) /* Show a message stating the target failed to build. */ static void -complain (const struct file *file) +complain (struct file *file) { const char *msg_noparent = _("%sNo rule to make target `%s'%s"); const char *msg_parent = _("%sNo rule to make target `%s', needed by `%s'%s"); -#ifdef KMK - /* jokes */ - if (!keep_going_flag && file->parent == 0) + /* If this file has no_diag set then it means we tried to update it + before in the dontcare mode and failed. The target that actually + failed is not necessarily this file but could be one of its direct + or indirect dependencies. So traverse this file's dependencies and + find the one that actually caused the failure. */ + + struct dep *d; + + for (d = file->deps; d != 0; d = d->next) { - const char *msg_joke = 0; - extern struct dep *goals; - - /* classics */ - if (!strcmp (file->name, "fire") - || !strcmp (file->name, "Fire")) - msg_joke = "No matches.\n"; - else if (!strcmp (file->name, "love") - || !strcmp (file->name, "Love") - || !strcmp (file->name, "peace") - || !strcmp (file->name, "Peace")) - msg_joke = "Not war.\n"; - else if (!strcmp (file->name, "war")) - msg_joke = "Don't know how to make war.\n"; - - /* http://xkcd.com/149/ - GNU Make bug #23273. */ - else if (( !strcmp (file->name, "me") - && goals != 0 - && !strcmp (dep_name(goals), "me") - && goals->next != 0 - && !strcmp (dep_name(goals->next), "a") - && goals->next->next != 0) - || !strncmp (file->name, "me a ", 5)) - msg_joke = + if (d->file->updated && d->file->update_status > 0 && file->no_diag) + { + complain (d->file); + break; + } + } + + if (d == 0) + { + /* Didn't find any dependencies to complain about. */ + +#ifdef KMK + /* jokes */ + if (!keep_going_flag && file->parent == 0) + { + const char *msg_joke = 0; + extern struct dep *goals; + + /* classics */ + if (!strcmp (file->name, "fire") + || !strcmp (file->name, "Fire")) + msg_joke = "No matches.\n"; + else if (!strcmp (file->name, "love") + || !strcmp (file->name, "Love") + || !strcmp (file->name, "peace") + || !strcmp (file->name, "Peace")) + msg_joke = "Not war.\n"; + else if (!strcmp (file->name, "war")) + msg_joke = "Don't know how to make war.\n"; + + /* http://xkcd.com/149/ - GNU Make bug #23273. */ + else if (( !strcmp (file->name, "me") + && goals != 0 + && !strcmp (dep_name(goals), "me") + && goals->next != 0 + && !strcmp (dep_name(goals->next), "a") + && goals->next->next != 0) + || !strncmp (file->name, "me a ", 5)) + msg_joke = # ifdef HAVE_UNISTD_H getuid () == 0 ? "Okay.\n" : # endif - "What? Make it yourself!\n"; - if (msg_joke) - { - fputs (msg_joke, stderr); - die (2); + "What? Make it yourself!\n"; + if (msg_joke) + { + fputs (msg_joke, stderr); + die (2); + } } - } #endif /* KMK */ - if (!keep_going_flag) - { + if (!keep_going_flag) + { + if (file->parent == 0) + fatal (NILF, msg_noparent, "", file->name, ""); + + fatal (NILF, msg_parent, "", file->name, file->parent->name, ""); + } + if (file->parent == 0) - fatal (NILF, msg_noparent, "", file->name, ""); + error (NILF, msg_noparent, "*** ", file->name, "."); + else + error (NILF, msg_parent, "*** ", file->name, file->parent->name, "."); - fatal (NILF, msg_parent, "", file->name, file->parent->name, ""); + file->no_diag = 0; } - - if (file->parent == 0) - error (NILF, msg_noparent, "*** ", file->name, "."); - else - error (NILF, msg_parent, "*** ", file->name, file->parent->name, "."); } /* Consider a single `struct file' and update it as appropriate. */ @@ -420,12 +453,16 @@ complain (const struct file *file) static int update_file_1 (struct file *file, unsigned int depth) { - register FILE_TIMESTAMP this_mtime; + FILE_TIMESTAMP this_mtime; int noexist, must_make, deps_changed; int dep_status = 0; - register struct dep *d, *lastd; + struct file *ofile; + struct dep *d, *ad; + struct dep amake; int running = 0; #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET + struct file *req_file = file; + struct file *org_file = file; struct file *f2, *f3; /* Always work on the primary multi target file. */ @@ -434,7 +471,7 @@ update_file_1 (struct file *file, unsigned int depth) { DBS (DB_VERBOSE, (_("Considering target file `%s' -> multi head `%s'.\n"), file->name, file->multi_head->name)); - file = file->multi_head; + org_file = file = file->multi_head; } else #endif /* CONFIG_WITH_EXPLICIT_MULTITARGET */ @@ -447,15 +484,12 @@ update_file_1 (struct file *file, unsigned int depth) DBF (DB_VERBOSE, _("Recently tried and failed to update file `%s'.\n")); - /* If the file we tried to make is marked dontcare then no message + /* If the file we tried to make is marked no_diag then no message was printed about it when it failed during the makefile rebuild. If we're trying to build it again in the normal rebuild, print a message now. */ - if (file->dontcare && !rebuilding_makefiles) - { - file->dontcare = 0; + if (file->no_diag && !file->dontcare) complain (file); - } return file->update_status; } @@ -479,11 +513,19 @@ update_file_1 (struct file *file, unsigned int depth) abort (); } + /* Determine whether the diagnostics will be issued should this update + fail. */ + file->no_diag = file->dontcare; + ++depth; /* Notice recursive update of the same file. */ start_updating (file); + /* We might change file if we find a different one via vpath; + remember this one to turn off updating. */ + ofile = file; + /* Looking at the file's modtime beforehand allows the possibility that its name may be changed by a VPATH search, and thus it may not need an implicit rule. If this were not done, the file @@ -508,6 +550,16 @@ update_file_1 (struct file *file, unsigned int depth) f3 = f2; } } + /** @todo this isn't sufficient, need to introduce a truly optional type and + * make |+ ignore mtime. let's hope that doesn't break too much... */ + /* If the requested file doesn't exist, always do a remake in the + hope that it is recreated even if it's "maybe" target. */ + else if (f2 == req_file && file_mtime (f2) == NONEXISTENT_MTIME) + { + this_mtime = NONEXISTENT_MTIME; + f3 = f2; + break; + } check_renamed (file); noexist = this_mtime == NONEXISTENT_MTIME; if (noexist) @@ -550,22 +602,32 @@ update_file_1 (struct file *file, unsigned int depth) file->cmds = default_file->cmds; } - /* Update all non-intermediate files we depend on, if necessary, - and see whether any of them is more recent than this file. - For explicit multitarget rules we must iterate all the output + /* Update all non-intermediate files we depend on, if necessary, and see + whether any of them is more recent than this file. We need to walk our + deps, AND the deps of any also_make targets to ensure everything happens + in the correct order. + + bird: For explicit multitarget rules we must iterate all the output files to get the correct picture. The special .MUST_MAKE - target variable call is also done from this context. */ + target variable call is also done from this context. */ #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET - for (f2 = file; f2; f2 = f2->multi_next) - { - lastd = 0; - d = f2->deps; -#else - lastd = 0; - d = file->deps; + assert (file == org_file); + for (f2 = file; f2; file = f2 = f2->multi_next) + { #endif - while (d != 0) + amake.file = file; + amake.next = file->also_make; + ad = &amake; + while (ad) + { + struct dep *lastd = 0; + + /* Find the deps we're scanning */ + d = ad->file->deps; + ad = ad->next; + + while (d) { FILE_TIMESTAMP mtime; int maybe_make; @@ -580,7 +642,7 @@ update_file_1 (struct file *file, unsigned int depth) { #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET /* silently ignore the order-only dep hack. */ - if (f2->multi_maybe && d->file == file) + if (file->multi_maybe && d->file == org_file) { lastd = d; d = d->next; @@ -589,31 +651,19 @@ update_file_1 (struct file *file, unsigned int depth) #endif error (NILF, _("Circular %s <- %s dependency dropped."), -#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET - f2->name, d->file->name); -#else file->name, d->file->name); -#endif /* We cannot free D here because our the caller will still have a reference to it when we were called recursively via check_dep below. */ if (lastd == 0) -#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET - f2->deps = d->next; -#else file->deps = d->next; -#endif else lastd->next = d->next; d = d->next; continue; } -#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET - d->file->parent = f2; -#else d->file->parent = file; -#endif maybe_make = must_make; /* Inherit dontcare flag from our parent. */ @@ -623,7 +673,6 @@ update_file_1 (struct file *file, unsigned int depth) d->file->dontcare = file->dontcare; } - dep_status |= check_dep (d->file, depth, this_mtime, &maybe_make); /* Restore original dontcare flag. */ @@ -660,11 +709,13 @@ update_file_1 (struct file *file, unsigned int depth) lastd = d; d = d->next; } + } #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET - if (dep_status != 0 && !keep_going_flag) - break; - } + if (dep_status != 0 && !keep_going_flag) + break; + } + file = org_file; #endif #ifdef CONFIG_WITH_DOT_MUST_MAKE @@ -673,7 +724,7 @@ update_file_1 (struct file *file, unsigned int depth) # ifdef CONFIG_WITH_EXPLICIT_MULTITARGET if (!must_make) - for (f2 = file; f2 && !must_make; f2 = f2->multi_next) + for (f2 = org_file; f2 && !must_make; f2 = f2->multi_next) must_make = call_must_make_target_var (f2, depth); # else if (!must_make) @@ -687,22 +738,16 @@ update_file_1 (struct file *file, unsigned int depth) if (must_make || always_make_flag) { #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET - for (f2 = file; f2; f2 = f2->multi_next) - for (d = f2->deps; d != 0; d = d->next) -#else - for (d = file->deps; d != 0; d = d->next) + for (file = f2 = org_file; f2; file = f2 = f2->multi_next) #endif + for (d = file->deps; d != 0; d = d->next) if (d->file->intermediate) { int dontcare = 0; FILE_TIMESTAMP mtime = file_mtime (d->file); check_renamed (d->file); -#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET - d->file->parent = f2; -#else d->file->parent = file; -#endif /* Inherit dontcare flag from our parent. */ if (rebuilding_makefiles) @@ -737,16 +782,16 @@ update_file_1 (struct file *file, unsigned int depth) break; if (!running) -#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET - d->changed = ((f2->phony && f2->cmds != 0) -#else d->changed = ((file->phony && file->cmds != 0) -#endif || file_mtime (d->file) != mtime); } +#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET + file = org_file; +#endif } finish_updating (file); + finish_updating (ofile); DBF (DB_VERBOSE, _("Finished prerequisites of target file `%s'.\n")); @@ -793,13 +838,13 @@ update_file_1 (struct file *file, unsigned int depth) deps_changed = 0; #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET - for (f2 = file; f2; f2 = f2->multi_next) + for (file = f2 = org_file; f2; file = f2 = f2->multi_next) #endif for (d = file->deps; d != 0; d = d->next) { FILE_TIMESTAMP d_mtime = file_mtime (d->file); #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET - if (d->file == file && f2->multi_maybe) + if (d->file == file && file->multi_maybe) continue; #endif check_renamed (d->file); @@ -854,6 +899,9 @@ update_file_1 (struct file *file, unsigned int depth) } } } +#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET + file = org_file; +#endif /* Here depth returns to the value it had when we were called. */ depth--; @@ -1163,7 +1211,7 @@ notice_finished_file (struct file *file) really check the target's mtime again. Otherwise, assume the target would have been updated. */ - if (question_flag || just_print_flag || touch_flag) + if ((question_flag || just_print_flag || touch_flag) && file->cmds) { for (i = file->cmds->ncommand_lines; i > 0; --i) if (! (file->cmds->lines_flags[i-1] & COMMANDS_RECURSE)) @@ -1270,12 +1318,17 @@ static int check_dep (struct file *file, unsigned int depth, FILE_TIMESTAMP this_mtime, int *must_make_ptr) { + struct file *ofile; struct dep *d; int dep_status = 0; ++depth; start_updating (file); + /* We might change file if we find a different one via vpath; + remember this one to turn off updating. */ + ofile = file; + if (file->phony || !file->intermediate) { /* If this is a non-intermediate file, update it and record whether it @@ -1325,23 +1378,16 @@ check_dep (struct file *file, unsigned int depth, /* Otherwise, update all non-intermediate files we depend on, if necessary, and see whether any of them is more recent than the file on whose behalf we are checking. */ - struct dep *lastd; + struct dep *ld; int deps_running = 0; - /* Reset this target's state so that we check it fresh. It could be - that it's already been checked as part of an order-only - prerequisite and so wasn't rebuilt then, but should be now. - - bird: What if we're already running the recipe? We don't wish - it to be started once again do we? This happens with the - SECONDARY Test #9 here now... If the idea is to re-evaluate - the target regardless of whether it's running or no, then - perhaps saving and restoring is a better idea? - See bug #15919. */ - if (file->command_state != cs_running) /* bird */ + /* If this target is not running, set it's state so that we check it + fresh. It could be it was checked as part of an order-only + prerequisite and so wasn't rebuilt then, but should be now. */ + if (file->command_state != cs_running) set_command_state (file, cs_not_started); - lastd = 0; + ld = 0; d = file->deps; while (d != 0) { @@ -1351,7 +1397,7 @@ check_dep (struct file *file, unsigned int depth, { error (NILF, _("Circular %s <- %s dependency dropped."), file->name, d->file->name); - if (lastd == 0) + if (ld == 0) { file->deps = d->next; free_dep (d); @@ -1359,9 +1405,9 @@ check_dep (struct file *file, unsigned int depth, } else { - lastd->next = d->next; + ld->next = d->next; free_dep (d); - d = lastd->next; + d = ld->next; } continue; } @@ -1380,7 +1426,7 @@ check_dep (struct file *file, unsigned int depth, || d->file->command_state == cs_deps_running) deps_running = 1; - lastd = d; + ld = d; d = d->next; } @@ -1393,6 +1439,8 @@ check_dep (struct file *file, unsigned int depth, } finish_updating (file); + finish_updating (ofile); + return dep_status; } @@ -1577,7 +1625,7 @@ f_mtime (struct file *file, int search) if (mtime == NONEXISTENT_MTIME && search && !file->ignore_vpath) { /* If name_mtime failed, search VPATH. */ - const char *name = vpath_search (file->name, &mtime); + const char *name = vpath_search (file->name, &mtime, NULL, NULL); if (name /* Last resort, is it a library (-lxxx)? */ || (file->name[0] == '-' && file->name[1] == 'l' @@ -1828,30 +1876,31 @@ library_search (const char *lib, FILE_TIMESTAMP *mtime_ptr) 0 }; - static char *libpatterns = NULL; - - const char *libname = lib+2; /* Name without the '-l'. */ + const char *file = 0; + char *libpatterns; FILE_TIMESTAMP mtime; /* Loop variables for the libpatterns value. */ char *p; const char *p2; unsigned int len; + unsigned int liblen; - char **dp; + /* Information about the earliest (in the vpath sequence) match. */ + unsigned int best_vpath = 0, best_path = 0; /* bird: gcc maybe used uninitialized (both) */ + unsigned int std_dirs = 0; - /* If we don't have libpatterns, get it. */ - if (!libpatterns) - { - int save = warn_undefined_variables_flag; - warn_undefined_variables_flag = 0; + char **dp; - libpatterns = xstrdup (variable_expand ("$(strip $(.LIBPATTERNS))")); + libpatterns = xstrdup (variable_expand ("$(.LIBPATTERNS)")); - warn_undefined_variables_flag = save; - } + /* Skip the '-l'. */ + lib += 2; + liblen = strlen (lib); - /* Loop through all the patterns in .LIBPATTERNS, and search on each one. */ + /* Loop through all the patterns in .LIBPATTERNS, and search on each one. + To implement the linker-compatible behavior we have to search through + all entries in .LIBPATTERNS and choose the "earliest" one. */ p2 = libpatterns; while ((p = find_next_token (&p2, &len)) != 0) { @@ -1861,7 +1910,7 @@ library_search (const char *lib, FILE_TIMESTAMP *mtime_ptr) char *libbuf = variable_expand (""); const size_t libbuf_offset = libbuf - variable_buffer; /* bird */ - /* Expand the pattern using LIBNAME as a replacement. */ + /* Expand the pattern using LIB as a replacement. */ { char c = p[len]; char *p3, *p4; @@ -1870,16 +1919,13 @@ library_search (const char *lib, FILE_TIMESTAMP *mtime_ptr) p3 = find_percent (p); if (!p3) { - /* Give a warning if there is no pattern, then remove the - pattern so it's ignored next time. */ + /* Give a warning if there is no pattern. */ error (NILF, _(".LIBPATTERNS element `%s' is not a pattern"), p); - for (; len; --len, ++p) - *p = ' '; - *p = c; + p[len] = c; continue; } p4 = variable_buffer_output (libbuf, p, p3-p); - p4 = variable_buffer_output (p4, libname, strlen (libname)); + p4 = variable_buffer_output (p4, lib, liblen); p4 = variable_buffer_output (p4, p3+1, len - (p3-p)); p[len] = c; libbuf = variable_buffer + libbuf_offset; /* bird - variable_buffer may have been reallocated. */ @@ -1891,48 +1937,81 @@ library_search (const char *lib, FILE_TIMESTAMP *mtime_ptr) { if (mtime_ptr != 0) *mtime_ptr = mtime; - return strcache_add (libbuf); + file = strcache_add (libbuf); + /* This by definition will have the best index, so stop now. */ + break; } /* Now try VPATH search on that. */ { - const char *file = vpath_search (libbuf, mtime_ptr); - if (file) - return file; + unsigned int vpath_index, path_index; + const char* f = vpath_search (libbuf, mtime_ptr ? &mtime : NULL, + &vpath_index, &path_index); + if (f) + { + /* If we have a better match, record it. */ + if (file == 0 || + vpath_index < best_vpath || + (vpath_index == best_vpath && path_index < best_path)) + { + file = f; + best_vpath = vpath_index; + best_path = path_index; + + if (mtime_ptr != 0) + *mtime_ptr = mtime; + } + } } /* Now try the standard set of directories. */ if (!buflen) - { - for (dp = dirs; *dp != 0; ++dp) - { - int l = strlen (*dp); - if (l > libdir_maxlen) - libdir_maxlen = l; - } - buflen = strlen (libbuf); - buf = xmalloc(libdir_maxlen + buflen + 2); - } + { + for (dp = dirs; *dp != 0; ++dp) + { + int l = strlen (*dp); + if (l > libdir_maxlen) + libdir_maxlen = l; + std_dirs++; + } + buflen = strlen (libbuf); + buf = xmalloc(libdir_maxlen + buflen + 2); + } else if (buflen < strlen (libbuf)) - { - buflen = strlen (libbuf); - buf = xrealloc (buf, libdir_maxlen + buflen + 2); - } + { + buflen = strlen (libbuf); + buf = xrealloc (buf, libdir_maxlen + buflen + 2); + } + + { + /* Use the last std_dirs index for standard directories. This + was it will always be greater than the VPATH index. */ + unsigned int vpath_index = ~((unsigned int)0) - std_dirs; + + for (dp = dirs; *dp != 0; ++dp) + { + sprintf (buf, "%s/%s", *dp, libbuf); + mtime = name_mtime (buf); + if (mtime != NONEXISTENT_MTIME) + { + if (file == 0 || vpath_index < best_vpath) + { + file = strcache_add (buf); + best_vpath = vpath_index; + + if (mtime_ptr != 0) + *mtime_ptr = mtime; + } + } + + vpath_index++; + } + } - for (dp = dirs; *dp != 0; ++dp) - { - sprintf (buf, "%s/%s", *dp, libbuf); - mtime = name_mtime (buf); - if (mtime != NONEXISTENT_MTIME) - { - if (mtime_ptr != 0) - *mtime_ptr = mtime; - return strcache_add (buf); - } - } } - return 0; + free (libpatterns); + return file; } |