Re: Windows binary for make with HAVE_CASE_INSENSITIVE_FS flag

Cesar Strauss <[email protected]>
Newsgroups gmane.comp.gnu.make.windows
Message-ID <[email protected]>
On 2/7/2010 09:53, Eli Zaretskii wrote:
>> Date: Fri, 02 Jul 2010 11:42:47 +0000
>> From: Greg Chicares<[email protected]>
>> CC: James<[email protected]>, Eli Zaretskii<[email protected]>
>>
>> On 2010-07-01 20:40Z, James wrote:
>>>
>>> Shouldn't HAVE_CASE_INSENSITIVE_FS be the default on a build for Windows?
>>
>> Here's a test case which that would break:
>>
>> http://old.nabble.com/Case-aware-file-matching-for-case-preserving-file-systems-td17297685.html
>
> More generally, GNU Make is used with many projects that came from the
> Posix world, and therefore expect case-sensitive filesystems.
> Therefore, Make internals assume such a system in too many places, and
> you need to fix them all before you'll have a truly case-insensitive
> build of Make that won't trip on problems such as the one above.

I think I have found a way for GNU Make to accept a mix of 
case-sensitive and case-insensitive rules on Windows. Unfortunately, I 
do not have the time to create a proper polished patch for contribution. 
I attach my current work below, in the hope that it will be useful. I 
also include a test-case for it.

Regards,
Cesar

_______________________________________________
Make-w32 mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/make-w32
Makefile (text/plain, 650 B)
SRCDIR=..
VPATH=$(SRCDIR)

SOURCE=$(SRCDIR)/A.IN $(SRCDIR)/MixEd.ext $(SRCDIR)/lower.x $(SRCDIR)/upper.X

all: ci cs

# Case insensitive targets
ci: a.out mixed.out

# Case sensitive targets
cs: lower.out upper.out
cs: Hello HELLO

# Begin case-insensitive rules
prep::
	touch $(SRCDIR)/A.IN
	touch $(SRCDIR)/MixEd.ext
%.out: %.in
	cp $< $@
mixed.out: mixed.ext
	cp $< $@

# Begin case-sensitive rules
prep::
	touch $(SRCDIR)/lower.x
	touch $(SRCDIR)/upper.X
%.out: %.x
	@echo Using lower-case rule
	cp $< $@
%.out: %.X
	@echo Using upper-case rule
	cp $< $@
Hello:
	@echo $@
HELLO:
	@echo $@

clean:
	rm -f *.out

distclean: clean
	rm -f $(SOURCE)
mixed_case_rules.patch (text/plain, 9.3 KB)
diff -rup make-3.81/implicit.c make-3.81-new/implicit.c
--- old/make-3.81/implicit.c	Wed May 28 23:57:40 2008
+++ new/make-3.81/implicit.c	Wed May 28 23:30:55 2008
@@ -27,7 +27,8 @@ Foundation, Inc., 51 Franklin St, Fifth 
 
 static int
 pattern_search PARAMS ((struct file *file, int archive,
-                        unsigned int depth, unsigned int recursions));
+                        unsigned int depth, unsigned int recursions,
+                        int strict_case));
 
 /* For a FILE which has no commands specified, try to figure out some
    from the implicit pattern rules.
@@ -36,16 +37,19 @@ pattern_search PARAMS ((struct file *fil
    or returns 0 if no implicit rule was found.  */
 
 int
-try_implicit_rule (struct file *file, unsigned int depth)
+try_implicit_rule (struct file *file, unsigned int depth, int strict_case)
 {
-  DBF (DB_IMPLICIT, _("Looking for an implicit rule for `%s'.\n"));
+  if (strict_case)
+    DBF (DB_IMPLICIT, _("Looking for an implicit rule for `%s'.\n"));
+  else
+    DBF (DB_IMPLICIT, _("Looking for a case-insensitive implicit rule for `%s'.\n"));
 
   /* The order of these searches was previously reversed.  My logic now is
      that since the non-archive search uses more information in the target
      (the archive search omits the archive name), it is more specific and
      should come first.  */
 
-  if (pattern_search (file, 0, depth, 0))
+  if (pattern_search (file, 0, depth, 0, strict_case))
     return 1;
 
 #ifndef	NO_ARCHIVES
@@ -55,7 +59,7 @@ try_implicit_rule (struct file *file, un
     {
       DBF (DB_IMPLICIT,
            _("Looking for archive-member implicit rule for `%s'.\n"));
-      if (pattern_search (file, 1, depth, 0))
+      if (pattern_search (file, 1, depth, 0, strict_case))
 	return 1;
     }
 #endif
@@ -198,7 +202,8 @@ get_next_word (char *buffer, unsigned in
 
 static int
 pattern_search (struct file *file, int archive,
-                unsigned int depth, unsigned int recursions)
+                unsigned int depth, unsigned int recursions,
+                int strict_case)
 {
   /* Filename we are searching for a rule for.  */
   char *filename = archive ? strchr (file->name, '(') : file->name;
@@ -698,13 +703,13 @@ pattern_search (struct file *file, int a
               /* @@ dep->changed check is disabled. */
               if (((f = lookup_file (name)) != 0 && f->is_target)
                   /*|| ((!dep->changed || check_lastslash) && */
-                  || file_exists_p (name))
+                  || (strict_case ? file_exists_p (name) : (access (name, F_OK) == 0)))
                 continue;
 
               /* This code, given FILENAME = "lib/foo.o", dependency name
                  "lib/foo.c", and VPATH=src, searches for "src/lib/foo.c".  */
               vname = name;
-              if (vpath_search (&vname, (FILE_TIMESTAMP *) 0))
+              if (vpath_search (&vname, (FILE_TIMESTAMP *) 0, strict_case))
                 {
                   DBS (DB_IMPLICIT,
                        (_("Found prerequisite `%s' as VPATH `%s'\n"),
@@ -735,7 +740,8 @@ pattern_search (struct file *file, int a
                   if (pattern_search (intermediate_file,
                                       0,
                                       depth + 1,
-                                      recursions + 1))
+                                      recursions + 1,
+                                      strict_case))
                     {
                       d->intermediate_file = intermediate_file;
                       d->intermediate_pattern = intermediate_file->name;
@@ -751,7 +757,8 @@ pattern_search (struct file *file, int a
                      so we won't go through the search again later.  */
                   if (intermediate_file->variables)
                     free_variable_set (intermediate_file->variables);
-                  file_impossible (name);
+                  if (strict_case==0)
+                    file_impossible (name);
                 }
 
               /* A dependency of this rule does not exist. Therefore,
diff -rup make-3.81/make.h make-3.81-new/make.h
--- old/make-3.81/make.h	Wed May 28 23:57:40 2008
+++ new/make-3.81/make.h	Wed May 28 23:30:55 2008
@@ -459,7 +459,7 @@ extern void install_default_implicit_rul
 
 extern void build_vpath_lists PARAMS ((void));
 extern void construct_vpath_list PARAMS ((char *pattern, char *dirpath));
-extern int vpath_search PARAMS ((char **file, FILE_TIMESTAMP *mtime_ptr));
+extern int vpath_search PARAMS ((char **file, FILE_TIMESTAMP *mtime_ptr, int strict_case));
 extern int gpath_search PARAMS ((char *file, unsigned int len));
 
 extern void construct_include_path PARAMS ((char **arg_dirs));
diff -rup make-3.81/remake.c make-3.81-new/remake.c
--- old/make-3.81/remake.c	Wed May 28 23:57:40 2008
+++ new/make-3.81/remake.c	Wed May 28 23:30:55 2008
@@ -39,7 +39,7 @@ Foundation, Inc., 51 Franklin St, Fifth 
 #include <io.h>
 #endif
 
-extern int try_implicit_rule PARAMS ((struct file *file, unsigned int depth));
+extern int try_implicit_rule PARAMS ((struct file *file, unsigned int depth, int strict_case));
 
 
 /* The test for circular dependencies is based on the 'updating' bit in
@@ -450,8 +450,10 @@ update_file_1 (struct file *file, unsign
 
   if (!file->phony && file->cmds == 0 && !file->tried_implicit)
     {
-      if (try_implicit_rule (file, depth))
+      if (try_implicit_rule (file, depth, 1))
 	DBF (DB_IMPLICIT, _("Found an implicit rule for `%s'.\n"));
+      else if (try_implicit_rule (file, depth, 0))
+	DBF (DB_IMPLICIT, _("Found an case-insensitive implicit rule for `%s'.\n"));
       else
 	DBF (DB_IMPLICIT, _("No implicit rule found for `%s'.\n"));
       file->tried_implicit = 1;
@@ -958,8 +960,10 @@ check_dep (struct file *file, unsigned i
 
       if (!file->phony && file->cmds == 0 && !file->tried_implicit)
 	{
-	  if (try_implicit_rule (file, depth))
+	  if (try_implicit_rule (file, depth, 1))
 	    DBF (DB_IMPLICIT, _("Found an implicit rule for `%s'.\n"));
+	  else if (try_implicit_rule (file, depth, 0))
+	    DBF (DB_IMPLICIT, _("Found an case-insensitive implicit rule for `%s'.\n"));
 	  else
 	    DBF (DB_IMPLICIT, _("No implicit rule found for `%s'.\n"));
 	  file->tried_implicit = 1;
@@ -1230,7 +1234,7 @@ f_mtime (struct file *file, int search)
 	{
 	  /* If name_mtime failed, search VPATH.  */
 	  char *name = file->name;
-	  if (vpath_search (&name, &mtime)
+	  if (vpath_search (&name, &mtime, 1) || vpath_search (&name, &mtime, 0)
 	      /* Last resort, is it a library (-lxxx)?  */
 	      || (name[0] == '-' && name[1] == 'l'
 		  && library_search (&name, &mtime)))
@@ -1533,7 +1537,7 @@ library_search (char **lib, FILE_TIMESTA
       /* Now try VPATH search on that.  */
 
       file = libbuf;
-      if (vpath_search (&file, mtime_ptr))
+      if (vpath_search (&file, mtime_ptr, 1) || vpath_search (&file, mtime_ptr, 1))
 	{
 	  *lib = file;
 	  return 1;
diff -rup make-3.81/vpath.c make-3.81-new/vpath.c
--- old/make-3.81/vpath.c	Wed May 28 23:57:40 2008
+++ new/make-3.81/vpath.c	Wed May 28 23:51:23 2008
@@ -48,7 +48,7 @@ static struct vpath *general_vpath;
 
 static struct vpath *gpaths;
 
-static int selective_vpath_search PARAMS ((struct vpath *path, char **file, FILE_TIMESTAMP *mtime_ptr));
+static int selective_vpath_search PARAMS ((struct vpath *path, char **file, FILE_TIMESTAMP *mtime_ptr, int strict_case));
 
 /* Reverse the chain of selective VPATH lists so they
    will be searched in the order given in the makefiles
@@ -334,7 +334,7 @@ gpath_search (char *file, unsigned int l
    Otherwise we return 0.  */
 
 int
-vpath_search (char **file, FILE_TIMESTAMP *mtime_ptr)
+vpath_search (char **file, FILE_TIMESTAMP *mtime_ptr, int strict_case)
 {
   register struct vpath *v;
 
@@ -351,11 +351,11 @@ vpath_search (char **file, FILE_TIMESTAM
 
   for (v = vpaths; v != 0; v = v->next)
     if (pattern_matches (v->pattern, v->percent, *file))
-      if (selective_vpath_search (v, file, mtime_ptr))
+      if (selective_vpath_search (v, file, mtime_ptr, strict_case))
 	return 1;
 
   if (general_vpath != 0
-      && selective_vpath_search (general_vpath, file, mtime_ptr))
+      && selective_vpath_search (general_vpath, file, mtime_ptr, strict_case))
     return 1;
 
   return 0;
@@ -370,7 +370,8 @@ vpath_search (char **file, FILE_TIMESTAM
 
 static int
 selective_vpath_search (struct vpath *path, char **file,
-                        FILE_TIMESTAMP *mtime_ptr)
+                        FILE_TIMESTAMP *mtime_ptr,
+                        int strict_case)
 {
   int not_target;
   char *name, *n;
@@ -500,10 +501,19 @@ selective_vpath_search (struct vpath *pa
 	     Now NAME is the name of the directory to look in.  */
 	  *n = '\0';
 
-	  /* We know the directory is in the hash table now because either
-	     construct_vpath_list or the code just above put it there.
-	     Does the file we seek exist in it?  */
-	  exists_in_cache = exists = dir_file_exists_p (name, filename);
+	  if (strict_case)
+	    {
+	      /* We know the directory is in the hash table now because either
+	         construct_vpath_list or the code just above put it there.
+	         Does the file we seek exist in it?  */
+	      exists_in_cache = exists = dir_file_exists_p (name, filename);
+	    }
+	  else
+	    {
+	      /* If using a case insensitive search, avoid the case sensitive
+	         lookup function above and force a real filesystem check. */
+	      exists_in_cache = exists = 1;
+	    }
 #endif
 	}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.