From 62e8f029e9bd0a2418409f6d6902824c3110515e Mon Sep 17 00:00:00 2001 From: Paul Smith Date: Sun, 19 Jul 2020 13:56:23 -0400 Subject: [PATCH] [SV 58735] Define the order that makefiles are rebuilt. Ensure that makefiles are rebuilt in the order in which make first considered them, and document this behavior in the manual. * NEWS: Add a note about the new behavior * doc/make.text (How make Processes a Makefile): Document it. * main.c (main): Inverse the list of makefile goals. * read.c (read_all_makefiles): Add default makefiles to the list at the front in reverse order, the same way other makefiles are added. * tests/scripts/features/include: Add tests to verify rebuild order. --- NEWS | 9 ++++++++- doc/make.texi | 36 +++++++++++++++++++--------------- src/main.c | 15 +++++++++++--- src/read.c | 13 ++---------- tests/scripts/features/include | 25 +++++++++++++++++++++-- 5 files changed, 65 insertions(+), 33 deletions(-) diff --git a/NEWS b/NEWS index 6a04680e..81b5726a 100644 --- a/NEWS +++ b/NEWS @@ -17,10 +17,17 @@ https://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=109&se * WARNING: Backward-incompatibility! Previously if --no-print-directory was seen anywhere in the environment or - command line it would take precedence over --print-directory. Now, the + command line it would take precedence over any --print-directory. Now, the last setting of directory printing options seen will be used, so a command line such as "--no-print-directory -w" _will_ show directory entry/exits. +* WARNING: Backward-incompatibility! + Previously the order in which makefiles were remade was not explicitly + stated, but it was (roughly) the inverse of the order in which they were + processed by make. In this release, the order in which makefiles are + rebuilt is the same order in which make processed them, and this is defined + to be true in the GNU make manual. + * GNU Make can now be built for MS-Windows using the Tiny C tcc compiler. diff --git a/doc/make.texi b/doc/make.texi index 733c0b96..21573c00 100644 --- a/doc/make.texi +++ b/doc/make.texi @@ -1346,16 +1346,21 @@ files. If a makefile can be remade from other files, you probably want @code{make} to get an up-to-date version of the makefile to read in. To this end, after reading in all makefiles @code{make} will consider -each as a goal target and attempt to update it. If a makefile has a -rule which says how to update it (found either in that very makefile or -in another one) or if an implicit rule applies to it (@pxref{Implicit -Rules, ,Using Implicit Rules}), it will be updated if necessary. After -all makefiles have been checked, if any have actually been changed, -@code{make} starts with a clean slate and reads all the makefiles over -again. (It will also attempt to update each of them over again, but -normally this will not change them again, since they are already up to -date.) Each restart will cause the special variable -@code{MAKE_RESTARTS} to be updated (@pxref{Special Variables}).@refill +each as a goal target, in the order in which they were processed, and +attempt to update it. If parallel builds (@pxref{Parallel, ,Parallel +Execution}) are enabled then makefiles will be rebuilt in parallel as +well. + +If a makefile has a rule which says how to update it (found either in +that very makefile or in another one) or if an implicit rule applies +to it (@pxref{Implicit Rules, ,Using Implicit Rules}), it will be +updated if necessary. After all makefiles have been checked, if any +have actually been changed, @code{make} starts with a clean slate and +reads all the makefiles over again. (It will also attempt to update +each of them over again, but normally this will not change them again, +since they are already up to date.) Each restart will cause the +special variable @code{MAKE_RESTARTS} to be updated (@pxref{Special +Variables}).@refill If you know that one or more of your makefiles cannot be remade and you want to keep @code{make} from performing an implicit rule search @@ -1384,12 +1389,11 @@ if a default makefile does not exist but can be created by running @code{make} rules, you probably want the rules to be run so that the makefile can be used. -Therefore, if none of the default makefiles exists, @code{make} will try -to make each of them in the same order in which they are searched for -(@pxref{Makefile Names, ,What Name to Give Your Makefile}) -until it succeeds in making one, or it runs out of names to try. Note -that it is not an error if @code{make} cannot find or make any makefile; -a makefile is not always necessary.@refill +Therefore, if none of the default makefiles exists, @code{make} will +try to make each of them until it succeeds in making one, or it runs +out of names to try. Note that it is not an error if @code{make} +cannot find or make any makefile; a makefile is not always +necessary.@refill When you use the @samp{-t} or @samp{--touch} option (@pxref{Instead of Execution, ,Instead of Executing Recipes}), diff --git a/src/main.c b/src/main.c index bcba2d18..c79a9f64 100644 --- a/src/main.c +++ b/src/main.c @@ -2188,11 +2188,20 @@ main (int argc, char **argv, char **envp) DB (DB_BASIC, (_("Updating makefiles....\n"))); + /* Count the makefiles, and reverse the order so that we attempt to + rebuild them in the order they were read. */ { - struct goaldep *d; unsigned int num_mkfiles = 0; - for (d = read_files; d != NULL; d = d->next) - ++num_mkfiles; + struct goaldep *d = read_files; + read_files = NULL; + while (d != NULL) + { + struct goaldep *t = d; + d = d->next; + t->next = read_files; + read_files = t; + ++num_mkfiles; + } makefile_mtimes = alloca (num_mkfiles * sizeof (FILE_TIMESTAMP)); } diff --git a/src/read.c b/src/read.c index db52a55b..c55998c3 100644 --- a/src/read.c +++ b/src/read.c @@ -263,10 +263,6 @@ read_all_makefiles (const char **makefiles) { /* No default makefile was found. Add the default makefiles to the 'read_files' chain so they will be updated if possible. */ - struct goaldep *tail = read_files; - /* Add them to the tail, after any MAKEFILES variable makefiles. */ - while (tail != 0 && tail->next != 0) - tail = tail->next; for (p = default_makefiles; *p != 0; ++p) { struct goaldep *d = alloc_goaldep (); @@ -274,14 +270,9 @@ read_all_makefiles (const char **makefiles) /* Tell update_goal_chain to bail out as soon as this file is made, and main not to die if we can't make this file. */ d->flags = RM_DONTCARE; - if (tail == 0) - read_files = d; - else - tail->next = d; - tail = d; + d->next = read_files; + read_files = d; } - if (tail != 0) - tail->next = 0; } } diff --git a/tests/scripts/features/include b/tests/scripts/features/include index 0c63c067..7dd17b5b 100644 --- a/tests/scripts/features/include +++ b/tests/scripts/features/include @@ -157,7 +157,7 @@ include inc1 include inc2 inc2:; echo > $@ !, - '', "echo > inc2\necho > inc1\nDONE\n"); + '', "echo > inc1\necho > inc2\nDONE\n"); rmfiles('inc1', 'inc2'); @@ -209,7 +209,7 @@ inc1:; echo > $@ include inc1 include inc2 !, - '', "#MAKEFILE#:7: inc2: $ERR_no_such_file\n#MAKE#: *** No rule to make target 'inc2'. Stop.\n", 512); + '', "echo > inc1\n#MAKEFILE#:7: inc2: $ERR_no_such_file\n#MAKE#: *** No rule to make target 'inc2'. Stop.\n", 512); rmfiles('inc1'); @@ -260,4 +260,25 @@ inc1:; @%s $@ && echo FOO := bar > $@ rmfiles('inc1'); } +# Check that the order of remaking include files is correct: should remake +# them in the same order they were encountered in the makefile. SV 58735 + +run_make_test(q! +-include i1 i2 +-include i3 +-include i4 +%:;@echo $@ +all:; +!, + '', "i1\ni2\ni3\ni4\n#MAKE#: 'all' is up to date.\n"); +rmfiles('foo'); + +# Check the default makefiles... this requires us to invoke make with no +# arguments. Also check MAKEFILES + +$ENV{MAKEFILES} = 'foobar barfoo'; +run_make_with_options(undef, q!-E '%:;@echo $@' -E 'all:;' -E '-include bizbaz' -E '-include bazbiz'!, get_logfile(0)); +$answer = "bizbaz\nbazbiz\nfoobar\nbarfoo\nGNUmakefile\nmakefile\nMakefile\n#MAKE#: 'all' is up to date.\n"; +&compare_output(subst_make_string($answer), &get_logfile(1)); + 1;