Hi, Ludovic Courtès <l...@gnu.org> writes:
> The GNU make warnings come from this impenetrable function: > > --8<---------------cut here---------------start------------->8--- > FILE_TIMESTAMP > file_timestamp_cons (const char *fname, time_t stamp, long int ns) > { > int offset = ORDINARY_MTIME_MIN + (FILE_TIMESTAMP_HI_RES ? ns : 0); > FILE_TIMESTAMP s = stamp; > FILE_TIMESTAMP product = (FILE_TIMESTAMP) s << FILE_TIMESTAMP_LO_BITS; > FILE_TIMESTAMP ts = product + offset; > > if (! (s <= FILE_TIMESTAMP_S (ORDINARY_MTIME_MAX) > && product <= ts && ts <= ORDINARY_MTIME_MAX)) > { > char buf[FILE_TIMESTAMP_PRINT_LEN_BOUND + 1]; > const char *f = fname ? fname : _("Current time"); > ts = s <= OLD_MTIME ? ORDINARY_MTIME_MIN : ORDINARY_MTIME_MAX; > file_timestamp_sprintf (buf, ts); > OSS (error, NILF, > _("%s: Timestamp out of range; substituting %s"), f, buf); > } > > return ts; > } > --8<---------------cut here---------------end--------------->8--- > > What’s OLD_MTIME? > > --8<---------------cut here---------------start------------->8--- > /* The file does not exist, and we assume that it is older than any > actual file. */ > #define OLD_MTIME 2 > > /* The smallest and largest ordinary timestamps. */ > #define ORDINARY_MTIME_MIN (OLD_MTIME + 1) > --8<---------------cut here---------------end--------------->8--- > > That would mean that any file with mtime < 3 is considered bogus, but > then, why wouldn’t things fail on other machines as well? I spent a bit of time looking at the relevant code in GNU Make. The special MTIME values of 0, 1, and 2 seem to apply only to GNU Make's *internal* representation of the timestamp. 'file_timestamp_cons', which converts a standard POSIX time to the internal representation, seems to properly handle times near the POSIX epoch by adding ORDINARY_MTIME_MIN (via 'offset') to the POSIX time, after multiplying it by 2^30 (if FILE_TIMESTAMP_HI_RES is enabled). > I’m looking for ideas! :-) Note that the date printed in the warning (ORDINARY_MTIME_MAX), represented as a POSIX time (seconds past the epoch), is precisely 2^34 seconds minus one nanosecond. The problem doesn't seem to be that 'stamp' is too small, because if it were, then the following line in 'file_timestamp_cons', ts = s <= OLD_MTIME ? ORDINARY_MTIME_MIN : ORDINARY_MTIME_MAX; would substitute ORDINARY_MTIME_MIN, which is close to the POSIX epoch, and the warning message would print a time near 1970, instead of one near 2514 (ORDINARY_MTIME_MAX). Rather, it appears that the 'stamp' passed into 'file_timestamp_cons' was close to or larger than 2^34, which is approximately the largest timestamp that GNU make supports when FILE_TIMESTAMP is 64 bits and FILE_TIMESTAMP_HI_RES is enabled. My guess is that maybe our near-zero timestamps are somewhere being adjusted downwards by a timezone conversion, using an unsigned integer type, causing them to wrap around to near the maximum value of that type. Note that although 'stamp' usually comes from a file 'mtime' as returned by stat(2), it can also come from an 'ar' archive member. In make-4.3/src/remake.c, 'f_mtime' includes the following code: --8<---------------cut here---------------start------------->8--- member_date = ar_member_date (file->hname); mtime = (member_date == (time_t) -1 ? NONEXISTENT_MTIME : file_timestamp_cons (file->hname, member_date, 0)); --8<---------------cut here---------------end--------------->8--- Mark