diff --git a/doc/make.texi b/doc/make.texi index 12f70c6..4415bc3 100644 --- a/doc/make.texi +++ b/doc/make.texi @@ -6627,6 +6627,65 @@ Supports dynamically loadable objects for creating custom extensions. Expands to a list of directories that @code{make} searches for included makefiles (@pxref{Include, , Including Other Makefiles}). +@vindex PREREQUISITES @r{(list of prerequsisites not contributing to automatic variables)} +@item PREREQUISITES +This variable may be set to a list of prerequisites that are added +to the list of existing prerequisites. But in contrast to these existing +prerequisites, the ones listed in @code{$(PREREQUISITES)} do not +contribute to any of the list-type automatic variables. +Thus, they are not added to any of the automatic variable lists @code{$^}, +@code{$+}, @code{$?}, @code{$*}, @code{$|}, @code{$(^F)}, @code{$(+F)}, +@code{$(?F)}, @code{$(*F)}, @code{$(^D)}, @code{$(+D)}, @code{$(?D)} and +@code{$(*D)}. + +The rationale behind this variable is to make it easier to extend dependency +lists of existing Makefiles. The following example illustrates this: + +The code below may be considered as a snippet of a large and +possibly rather complex Makefile: + +@example +myappl: main.o file1.o file2.o + gcc -o $@ $^ +@end example + +At a first glance, it lists all the relevant prerequisites, but a +second thought reveals that this is just not true: The target +also depends on the compiler frontend, the linker backend +and the Makefile itself. + +Thus, a more complete snippet should look more like this: + +@example +myappl: main.o file1.o file2.o /usr/bin/gcc /usr/bin/ld Makefile + gcc -o $@ $(filter %.o,$^) +@end example + +Please note the need for GNU Make's $(filter) function besides the +additional prerequisites. + +But for big projects, say the Linux kernel or a toolchain build, +it would be rather laborious to change and fix all the Makefiles +accordingly, and it is more than questionable if such patches +would be welcomed by every project. Fortunately, with @code{PREREQUISITES} +at hand, the upstream Makefiles do not need to be changed at all. +Instead, it is sufficient to assign the additional dependencies to +a target-specific instance of @code{PREREQUISITES} in another Makefile +that simply includes the upstream Makefile. To continue with our +example (and assuming the related upstream Makefile was just called +@code{Makefile}), we could most conveniently add a @code{GNUmakefile} +with the following content: + +@example +include Makefile +myappl: PREREQUISITES:=/usr/bin/gcc /usr/bin/ld Makefile +@end example + +Calling @code{make} now would prefer @code{GNUmakefile} over +@code{Makefile}, thus respecting the additional prerequisites +without affecting the automatic variable @code{$^} in the related +recipe. + @end table @node Conditionals, Functions, Using Variables, Top diff --git a/src/commands.c b/src/commands.c index dd47851..7c08c01 100644 --- a/src/commands.c +++ b/src/commands.c @@ -178,7 +178,7 @@ set_file_variables (struct file *file) bar_len = 0; for (d = file->deps; d != 0; d = d->next) { - if (!d->need_2nd_expansion) + if (!d->need_2nd_expansion && !d->ignore_automatic_vars) { if (d->ignore_mtime) bar_len += strlen (dep_name (d)) + 1; @@ -200,7 +200,7 @@ set_file_variables (struct file *file) qmark_len = plus_len + 1; /* Will be this or less. */ for (d = file->deps; d != 0; d = d->next) - if (! d->ignore_mtime && ! d->need_2nd_expansion) + if (! d->ignore_mtime && ! d->need_2nd_expansion && ! d->ignore_automatic_vars) { const char *c = dep_name (d); @@ -247,7 +247,7 @@ set_file_variables (struct file *file) for (d = file->deps; d != 0; d = d->next) { - if (d->need_2nd_expansion) + if (d->need_2nd_expansion || d->ignore_automatic_vars) continue; slot = hash_find_slot (&dep_hash, d); @@ -269,7 +269,7 @@ set_file_variables (struct file *file) { const char *c; - if (d->need_2nd_expansion || hash_find_item (&dep_hash, d) != d) + if (d->need_2nd_expansion || d->ignore_automatic_vars || hash_find_item (&dep_hash, d) != d) continue; c = dep_name (d); diff --git a/src/dep.h b/src/dep.h index baa64df..bedf41a 100644 --- a/src/dep.h +++ b/src/dep.h @@ -48,7 +48,8 @@ struct nameseq unsigned short changed : 1; \ unsigned short ignore_mtime : 1; \ unsigned short staticpattern : 1; \ - unsigned short need_2nd_expansion : 1 + unsigned short need_2nd_expansion : 1; \ + unsigned short ignore_automatic_vars : 1 struct dep { diff --git a/src/read.c b/src/read.c index 41447f3..36a9418 100644 --- a/src/read.c +++ b/src/read.c @@ -2013,6 +2013,49 @@ record_files (struct nameseq *filenames, int are_also_makes, deps = split_prereqs (depstr); free (depstr); + /* Add prerequisites from the PREREQUISITES variable. */ + for(struct nameseq *n = filenames; n; n = n->next) + { + struct file *f = lookup_file(n->name); + if(f) + { + for(struct variable_set_list *vsl = f->variables; vsl; vsl = vsl->next) + { + struct variable *v = lookup_variable_in_set ("PREREQUISITES", 13, vsl->set); + if(v) + { + // FIXME: How to expand v->value? + struct dep *prereqs_only = split_prereqs(v->value); + if(prereqs_only) + { + struct dep *d = prereqs_only; + while(d) + { + d->ignore_automatic_vars = 1; + d = d->next; + } + /* Append dependencies found in PREREQUISITES to existing dependencies. */ + if(deps) + { + d = deps; + while(d->next) + { + d = d->next; + } + d->next = prereqs_only; + } + else + { + deps = prereqs_only; + } + } + // FIXME: How to release a struct variable? + } + } + // FIXME: How to release a struct file? + } + } + /* We'll enter static pattern prereqs later when we have the stem. We don't want to enter pattern rules at all so that we don't think that they ought to exist (make manual "Implicit Rule Search