Attached is an enhancement I made to make-3.97.1 which adds a new feature: when a preqrequisite's file name begins with a hyphen, it is marked dontcare (and the hyphen stripped). Then during rebuilding, if that file doesn't exist and can't be remade, 'make' silently proceeds.
This is useful for dependencies in automatically-generated dependency lists: if a header file gets renamed or deleted, 'make' should not be bothered by the nonexistence of the file, as long as the dependency info is regenerated "soon". More detail is available on a page I put together describing my solution to the autodependency problem (which I think is superior to the approach given in the manual): http://www.cs.berkeley.edu/~smcpeak/autodepend/autodepend.html Thanks, -Scott
Patch so that when prerequisite file names begin with a hyphen, their absence is not an error. diff -u make-3.79.1-orig/configure make-3.79.1/configure --- make-3.79.1-orig/configure Fri Jun 23 09:09:54 2000 +++ make-3.79.1/configure Tue Nov 20 18:42:18 2001 @@ -802,7 +802,7 @@ PACKAGE=make -VERSION=3.79.1 +VERSION=3.79.1-sm if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then { echo "configure: error: source directory already configured; run "make distclean" there first" 1>&2; exit 1; } diff -u make-3.79.1-orig/configure.in make-3.79.1/configure.in --- make-3.79.1-orig/configure.in Fri Jun 23 09:09:41 2000 +++ make-3.79.1/configure.in Tue Nov 20 18:42:08 2001 @@ -3,7 +3,7 @@ AC_PREREQ(2.13)dnl dnl Minimum Autoconf version required. AC_INIT(vpath.c)dnl dnl A distinctive file to look for in srcdir. -AM_INIT_AUTOMAKE(make, 3.79.1) +AM_INIT_AUTOMAKE(make, 3.79.1-sm) AM_CONFIG_HEADER(config.h) dnl Regular configure stuff diff -u make-3.79.1-orig/file.c make-3.79.1/file.c --- make-3.79.1-orig/file.c Tue Jun 20 07:00:16 2000 +++ make-3.79.1/file.c Tue Nov 20 17:55:14 2001 @@ -26,6 +26,7 @@ #include "job.h" #include "commands.h" #include "variable.h" +#include "debug.h" /* DB, DB_VERBOSE */ /* Hash table of files the makefile knows how to make. */ @@ -56,6 +57,11 @@ assert (*name != '\0'); + if (*name == '-') { + /* sm: skip dontcare flag; it gets interpreted in enter_file */ + name++; + } + /* This is also done in parse_file_seq, so this is redundant for names read from makefiles. It is here for names passed on the command line. */ @@ -122,9 +128,35 @@ #if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS) char *lname, *ln; #endif + int dontcare_flag = 0; assert (*name != '\0'); + if (*name == '-') + { + /* sm: skip and interpret new flag: + + When the name of a prerequisite file begins with a leading hyphen + ("-"), but that file doesn't exist and can't be remade, we consider + the file to be out of date (so the target gets rebuilt), but ignore + the error. + + This is useful for autodependency rules, when one of the files that + was used to compile some .o file has been renamed or deleted. The + .o file should be recompiled of course, but 'make' shouldn't + complain. When the .o file is recompiled, the autodependency info + will be correctly updated, and the problem won't persist. + + This is in contrast to user-written dependencies, where the user + should take responsibility for maintaining accuracy. + + (sm = Scott McPeak, 11/20/01) + */ + name++; + dontcare_flag = 1; /* originally for Makefiles, has (almost) right effect */ + DB (DB_VERBOSE, (_("Setting dontcare for `%s'.\n"), name)); + } + #if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS) lname = (char *)malloc (strlen (name) + 1); for (n = name, ln = lname; *n != '\0'; ++n, ++ln) @@ -161,6 +193,7 @@ bzero ((char *) new, sizeof (struct file)); new->name = new->hname = name; new->update_status = -1; + new->dontcare = dontcare_flag; if (f == 0) { diff -u make-3.79.1-orig/main.c make-3.79.1/main.c --- make-3.79.1-orig/main.c Tue Jun 13 07:24:45 2000 +++ make-3.79.1/main.c Tue Nov 20 17:49:24 2001 @@ -1072,6 +1072,10 @@ if (print_version_flag) die (0); + /* sm: I want programmatic access to version info inside the Makefile */ + /* (maintainer: feel free to change what this variable is called) */ + define_variable("GNUMAKE_VERSION", 15, VERSION, o_default, 0); + #ifndef VMS /* Set the "MAKE_COMMAND" variable to the name we were invoked with. (If it is a relative pathname with a slash, prepend our directory name @@ -1718,6 +1722,12 @@ mtime = file_mtime_no_search (d->file); any_remade |= (mtime != NONEXISTENT_MTIME && mtime != makefile_mtimes[i]); + } + else + { + DB (DB_BASIC, /* sm: helpful when hacking dontcare */ + (_("Igoring failed Makefile `%s' b/c of dontcare.\n"), + d->file->name)); } } else diff -u make-3.79.1-orig/remake.c make-3.79.1/remake.c --- make-3.79.1-orig/remake.c Tue Jun 20 07:00:17 2000 +++ make-3.79.1/remake.c Tue Nov 20 17:53:48 2001 @@ -681,7 +681,19 @@ } file->updated = 1; - return file->update_status; + + if (file->update_status==2 && file->dontcare) + { + /* sm: I don't change file->update_status, because I want to + minimize the effect of my changes, and I don't think it's + necessary, based on my reading of update_file */ + DBF (DB_BASIC, _("Suppressing error with `%s' because of dontcare.\n")); + return 0; /* interpreted as success by caller */ + } + else + { + return file->update_status; + } } /* Set FILE's `updated' flag and re-check its mtime and the mtime's of all