Am 13.07.19 um 14:46 schrieb Paul Smith:
On Wed, 2019-07-10 at 18:15 +0200, Christof Warlich wrote:
Am 10.07.19 um 14:44 schrieb Paul Smith:
Let me know how you want to proceed.
As I want to tackle the most challenging part first, I'd like to suggest to
do the copyright assignment after the technical side is in a decent shape.
But as I said, no problem to do it fist if that's more appropriate.
That's no problem. However you prefer is fine with me.
Copyright assignment these days is pretty straightforward and can be
done via email instead of sending paper documents around like in the
old days, so it's not as long a process.
One item to note: if you work for a company which has rights to your
work, then they would need to sign off on this as well.
Cheers!
Hi Paul, all,
attached is a first "proof of concept" patch that uses the specific variable
PREREQUISTES to add prerequisites that do not affect automatic
variables. It's not complete (see the points below), but should be good
enough to ask for initial feedback on whether the general approach makes
sense.
Here are the points that I'm aware of that are missing:
1. Currently, PREREQUISITES is only considered when it is defined
as a target specific variable in an ordinary rule. The code to handle
the case when PREREQUISITES is a global variable (or when in is
defined in a pattern rule?!) is still missing.
2. Variables and functions are not expanded. Could you give me a
quick hint on how this should be done? I've found lookup_variable()
to expand global variables, but this would require to do the parsing
manually and would not be of much use with functions.
3. What about the "struct file" pointer and the "struct variable" pointer
returned by lookup_variable() and lookup_variable_in_set() respectively:
Do I need to free memory when done with them, and if so, may I just
use free()?
Thanks for any feedback and your precious time,
Chris
P.S.: There is a small Makefile that could be used for a quick test of the
current (limited) functionality:
target: PREREQUISITES=hi ho
target: foo bar
@echo "dependency-only prerequisites: ${PREREQUISITES}"
@echo "ordinary prerequisites: $^"
rm -rf hi ho foo bar
hi ho foo bar:
touch $@
Running make with this Makefile yields:
$ make target
touch foo
touch bar
touch hi
touch ho
dependency-only prerequisites: hi ho
ordinary prerequisites: foo bar
rm -rf hi ho foo bar
as desired, i.e. both "hi" and "ho" are recognized as prerequisites but were
not added to $^.
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
_______________________________________________
Bug-make mailing list
Bug-make@gnu.org
https://lists.gnu.org/mailman/listinfo/bug-make