From: Paul Smith Date: Mon, 31 May 2021 18:37:09 +0000 (-0400) Subject: [SV 60595] Restart whenever any makefile is rebuilt X-Git-Tag: 4.3.90~164 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=7c4e6b0299774280e3a93060c70c661f459aaf40;p=thirdparty%2Fmake.git [SV 60595] Restart whenever any makefile is rebuilt Previously if an included makefile was rebuilt as a prerequisite of another included makefile which didn't need to be rebuilt, make would not realize that it needed to re-exec itself. Ensure that if any included makefile target is rebuilt we re-exec. Also ensure that if an included makefile is not readable, and our rule for rebuilding it doesn't actually change it, we will still fail. * src/remake.c (update_goal_chain): If a goal's update was successful then check its status, even if no actual commands were run because it was already up to date. (show_goal_error): Remove superfluous cast. * src/main.c (main): If the makefile remake did nothing, check that we were able to successfully include all the makefiles we care about; if not fail. When generating error messages about included makefiles be sure to show the filename/linenumber information. * test/scripts/features/reinvoke: Add tests for this behavior. * test/scripts/options/dash-k: Update error messages. --- diff --git a/src/main.c b/src/main.c index 54060f2f..629f1665 100644 --- a/src/main.c +++ b/src/main.c @@ -2295,10 +2295,28 @@ main (int argc, char **argv, char **envp) for one of the makefiles to be remade as a target on the command line. Since we're not actually updating anything with -q we can treat this as "did nothing". */ + break; case us_none: - /* Did nothing. */ - break; + /* No makefiles needed to be updated. If we couldn't read some + included file that we care about, fail. */ + { + int any_failed = 0; + struct goaldep *d; + + for (d = read_files; d != 0; d = d->next) + if (d->error && ! (d->flags & RM_DONTCARE)) + { + /* This makefile couldn't be loaded, and we care. */ + OSS (error, &d->floc, + _("%s: %s"), dep_name (d), strerror (d->error)); + any_failed = 1; + } + + if (any_failed) + die (MAKE_FAILURE); + break; + } case us_failed: /* Failed to update. Figure out if we care. */ @@ -2327,7 +2345,8 @@ main (int argc, char **argv, char **envp) FILE_TIMESTAMP mtime; /* The update failed and this makefile was not from the MAKEFILES variable, so we care. */ - OS (error, NILF, _("Failed to remake makefile '%s'."), + OS (error, &d->floc, + _("Failed to remake makefile '%s'."), d->file->name); mtime = file_mtime_no_search (d->file); any_remade |= (mtime != NONEXISTENT_MTIME @@ -2346,7 +2365,7 @@ main (int argc, char **argv, char **envp) if (d->flags & RM_INCLUDED) /* An included makefile. We don't need to die, but we do want to complain. */ - error (NILF, l, + error (&d->floc, l, _("Included makefile '%s' was not found."), dnm); else { diff --git a/src/remake.c b/src/remake.c index f7605fc0..b20d37c7 100644 --- a/src/remake.c +++ b/src/remake.c @@ -78,8 +78,8 @@ static FILE_TIMESTAMP name_mtime (const char *name); static const char *library_search (const char *lib, FILE_TIMESTAMP *mtime_ptr); -/* Remake all the goals in the 'struct dep' chain GOALS. Return -1 if nothing - was done, 0 if all goals were updated successfully, or 1 if a goal failed. +/* Remake all the goals in the 'struct dep' chain GOALS. Return update_status + representing the totality of the status of the goals. If rebuilding_makefiles is nonzero, these goals are makefiles, so -t, -q, and -n should be disabled for them unless they were also command-line @@ -185,8 +185,7 @@ update_goal_chain (struct goaldep *goaldeps) FILE_TIMESTAMP mtime = MTIME (file); check_renamed (file); - if (file->updated && g->changed && - mtime != file->mtime_before_update) + if (file->updated && mtime != file->mtime_before_update) { /* Updating was done. If this is a makefile and just_print_flag or question_flag is set (meaning @@ -288,7 +287,7 @@ show_goal_error (void) if (goal->error) { OSS (error, &goal->floc, "%s: %s", - goal->file->name, strerror ((int)goal->error)); + goal->file->name, strerror (goal->error)); goal->error = 0; } return; @@ -1421,7 +1420,7 @@ f_mtime (struct file *file, int search) / 1e9)); char from_now_string[100]; - if (from_now >= 99 && from_now <= ULONG_MAX) + if (from_now >= 100.0 && from_now < (double) ULONG_MAX) sprintf (from_now_string, "%lu", (unsigned long) from_now); else sprintf (from_now_string, "%.2g", from_now); diff --git a/tests/scripts/features/reinvoke b/tests/scripts/features/reinvoke index 657f6c9b..237c8385 100644 --- a/tests/scripts/features/reinvoke +++ b/tests/scripts/features/reinvoke @@ -17,9 +17,7 @@ $omkfile = $makefile; run_make_test(' all: ; @echo running rules. -#MAKEFILE# incl.mk: incl-1.mk - @echo rebuilding $@ - @echo >> $@ +#MAKEFILE# incl.mk: incl-1.mk ; @echo rebuilding $@; echo >> $@ include incl.mk', '', "rebuilding incl.mk\nrunning rules.\n"); @@ -74,9 +72,36 @@ foo30723: ; @touch $@ unlink('foo30723'); +# If ANY makefile is rebuilt then we should re-exec + +run_make_test(' +all: ; @echo RESTARTS=$(MAKE_RESTARTS) + +m1.d: ; @echo $@; touch $@ + +m2.d: m1.d ; @test -f $< || { echo $@; touch $@; } + +include m1.d +-include m2.d +', + '', "m1.d\nRESTARTS=1\n"); + +unlink('m1.d', 'm2.d'); + +# Same as before but be sure we get error messages for un-created makefiles + +run_make_test(' +all: ; @echo RESTARTS=$(MAKE_RESTARTS) + +m1.d: ; @echo $@; touch $@ + +m2.d: m1.d ; @test -f $< || { echo $@; touch $@; } + +include m1.d m2.d +', + '', "m1.d\n#MAKEFILE#:8: m2.d: $ERR_no_such_file\n", 512); + +unlink('m1.d', 'm2.d'); + # 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/options/dash-k b/tests/scripts/options/dash-k index cd78e7f0..323dff60 100644 --- a/tests/scripts/options/dash-k +++ b/tests/scripts/options/dash-k @@ -108,7 +108,7 @@ ifile: no-such-file; @false '-k', "#MAKEFILE#:2: ifile: $ERR_no_such_file #MAKE#: *** No rule to make target 'no-such-file', needed by 'ifile'. -#MAKE#: Failed to remake makefile 'ifile'. +#MAKEFILE#:2: Failed to remake makefile 'ifile'. hi\n", 512); }