[gnu.utils.bug] make 3.58 bug

whitcomb@VIVALDI.BERKELEY.EDU (Gregg Whitcomb) (02/23/90)

dependency files created during a make are not searched for using VPATH
when used by other target files.

example:

two subdirectories were created.  "obj" for object files and "src" for the
source file.

---------------------------

contents:

src: target.x
obj: 

here's the makefile:
---------------------------
% more tmakefile
VPATH = ../src
target: target.c
target.c: target.x
        cp $(<D)target.x $(<D)$@
---------------------------

here's the execution:
---------------------------
% /usr/local/make -f ../tmakefile -C obj
cp ../src/target.x ../src/target.c
cc     target.c   -o target
cpp: error 0: No source file target.c
make: *** [target] Error 1
---------------------------

the cc command should have been:
cc ../src/target.c -o target

If the makefile runs again, it works (since target.c exists now)
---------------------------
% !!
/usr/local/make -f ../tmakefile -C obj
cc     ../src/target.c   -o target
---------------------------

-Gregg Whitcomb (whitcomb@ic.berkeley.edu)

dudek@ksr.UUCP (Glen Dudek) (02/27/90)

In article <9002221907.AA07652@vivaldi.Berkeley.EDU> whitcomb@VIVALDI.BERKELEY.EDU (Gregg Whitcomb) writes:
>
>dependency files created during a make are not searched for using VPATH
>when used by other target files.
>
>here's the makefile:
>VPATH = ../src
>target: target.c
>target.c: target.x
>        cp $(<D)target.x $(<D)$@
>
>here's the execution:
>% /usr/local/make -f ../tmakefile -C obj
>cp ../src/target.x ../src/target.c
>cc     target.c   -o target
>cpp: error 0: No source file target.c
>make: *** [target] Error 1
>
>the cc command should have been:
>cc ../src/target.c -o target
>
>If the makefile runs again, it works (since target.c exists now)
>
>-Gregg Whitcomb (whitcomb@ic.berkeley.edu)

This is a problem with the directory cache in gnumake.  When the
'../src' directory is first search, a cache is kept of its contents.
Even though 'target.c' is subsequently built, the directory cache is
not updated so the file is not found.

I made a change to the directory caching code so that the directory
cache is updated if the directory to be searched is cached, the file is
*not* found in the directory cache, and the directory has been updated
more recently than the cached copy.  Note that a stat of the directory
to find the modification time is only performed if the file is not
found in the cache.

Here are context diffs for version 3.56... Should these be sent to
someone specific, or is this newsgroup enough?

	Glen Dudek
	dudek@ksr.com

*** /tmp/,RCSt1a25523	Mon Feb 26 11:49:08 1990
--- dir.c	Tue Nov 14 09:05:16 1989
***************
*** 47,52 ****
--- 47,53 ----
      char *name;			/* Name of the directory.  */
      struct dirfile **files;	/* Files in this directory.  */
      DIR *dirstream;		/* Stream reading this directory.  */
+     time_t last_mtime;		/* Time directory last updated */
    };
  
  #ifndef	DIRECTORY_BUCKETS
***************
*** 85,90 ****
--- 86,92 ----
    register unsigned int hash = 0;
    register char *p;
    register struct directory *dir;
+   struct stat st;
  
    for (p = name; *p != '\0'; ++p)
      HASH (hash, *p);
***************
*** 102,107 ****
--- 104,113 ----
        dir->next = directories[hash];
        directories[hash] = dir;
        dir->name = savestring (name, p - name);
+       if (stat (name, &st) < 0)
+ 	  dir->last_mtime = -1;
+       else
+ 	  dir->last_mtime = st.st_mtime;
        dir->dirstream = opendir (name);
        if (dir->dirstream == 0)
  	/* Couldn't open the directory.  Mark this by
***************
*** 140,145 ****
--- 146,152 ----
    register struct directory *dir;
    register struct dirfile *df;
    register struct direct *d;
+   struct stat st;
  
    dir = find_directory (dirname);
  
***************
*** 168,204 ****
    /* The file was not found in the hashed list.
       Try to read the directory further.  */
  
!   if (dir->dirstream == 0)
!     /* The directory has been all read in.  */
!     return 0;
! 
!   while ((d = readdir (dir->dirstream)) != 0)
      {
!       /* Enter the file in the hash table.  */
!       register unsigned int newhash = 0;
!       register unsigned int i;
!       for (i = 0; i < D_NAMLEN(d); ++i)
! 	HASH (newhash, d->d_name[i]);
!       newhash %= DIRFILE_BUCKETS;
!       df = (struct dirfile *) xmalloc (sizeof (struct dirfile));
!       df->next = dir->files[newhash];
!       dir->files[newhash] = df;
!       df->name = savestring (d->d_name, D_NAMLEN(d));
!       df->impossible = 0;
  
!       /* Check if the name matches the one we're searching for.  */
!       if (filename != 0
! 	  && newhash == hash && streq (d->d_name, filename))
! 	return 1;
      }
  
!   /* If the directory has been completely read in,
!      close the stream and reset the pointer to nil.  */
!   if (d == 0)
      {
!       --open_directories;
!       closedir (dir->dirstream);
!       dir->dirstream = 0;
      }
  
    return 0;
--- 175,237 ----
    /* The file was not found in the hashed list.
       Try to read the directory further.  */
  
!   if (dir->dirstream != 0)
      {
!       /* The directory has not yet been all read in.  */
  
!       while ((d = readdir (dir->dirstream)) != 0)
! 	{
! 	  /* Enter the file in the hash table.  */
! 	  register unsigned int newhash = 0;
! 	  register unsigned int i;
! 	  for (i = 0; i < D_NAMLEN(d); ++i)
! 	      HASH (newhash, d->d_name[i]);
! 	  newhash %= DIRFILE_BUCKETS;
! 	  df = (struct dirfile *) xmalloc (sizeof (struct dirfile));
! 	  df->next = dir->files[newhash];
! 	  dir->files[newhash] = df;
! 	  df->name = savestring (d->d_name, D_NAMLEN(d));
! 	  df->impossible = 0;
! 
! 	  /* Check if the name matches the one we're searching for.  */
! 	  if (filename != 0
! 	      && newhash == hash && streq (d->d_name, filename))
! 	      return 1;
! 	}
! 
!       /* If the directory has been completely read in,
! 	 close the stream and reset the pointer to nil.  */
!       if (d == 0)
!         {
! 	  --open_directories;
! 	  closedir (dir->dirstream);
! 	  dir->dirstream = 0;
!         }
      }
  
!   if (stat (dirname, &st) != -1 && dir->last_mtime != st.st_mtime)
      {
!       register struct dirfile *fp;
!       register int i;
! 
!       dir->last_mtime = st.st_mtime;
! 
!       /* The directory is out of date.  Free up memory from
! 	 previous scan */
!       for (i = 0; i < DIRFILE_BUCKETS; i++)
!         {
! 	  while (dir->files[i] != NULL)
! 	    {
! 	      fp = dir->files[i];
! 	      dir->files[i] = fp->next;
! 	      free (fp);
! 	    }
!         }
!       dir->dirstream = opendir (dirname);
!       if (++open_directories == MAX_OPEN_DIRECTORIES)
! 	  /* Read the entire directory and then close it.  */
! 	  (void) dir_file_exists_p (dirname, (char *) 0);
!       return dir_file_exists_p (dirname, filename);
      }
  
    return 0;
-- 
--
Glen Dudek
dudek@ksr.com (ksr!dudek@uunet.uu.net)