> From: "Mark Galeck (CW)" <mgal...@brocade.com> > Date: Thu, 10 Dec 2009 13:06:14 -0800 > > I have 2 subdirectories foobar0 and foobar1, and only in foobar1 there is a= > file foobar.s . There is no file foobar.o . > > The makefile is: > > SHELL=Dcmd.exe > > vpath %.s .\foobar0 .\foobar1 > > %.o : %.s > echo $< > > foobar0\foobar.s:; > > > This behaves as expected: > > C:\tmp>make foobar.o > echo .\foobar1/foobar.s > > However, if I change all the backslashes to forward-slashes, then I get: > > C:\tmp>make foobar.o > make: *** No rule to make target `foobar.s', needed by `foobar.o'. Stop.
The behavior with the forward slashes is the "correct" one (see below for the reasons I put ``correct'' in quotes). Backslashes are not treated by Make on Windows in a 100% consistent manner, because in some cases they have special semantics. One such special case is in file-name wildcards, where a backslash quotes special wildcard characters. Another is in searching for files along vpath: Make looks up its database of known files by literally comparing hash values of the file names as strings, so foobar1/foobar.s and foobar1\foobar.s are not considered equal, and the search fails. This is your case. If you replace the backslash with forward slashes only in the last line of your Makefile, it will work (after applying the patch below). That is because, when Make searches vpath, it looks for .\foobar0/foobar.s and .\foobar1/foobar.s, but your Makefile specifies foobar0\foobar.s, so Make thinks the file foobar0\foobar.s is not mentioned in the Makefile. If you use forward slashes everywhere, then Make realizes that file foobar0/foobar.s _is_ mentioned in the Makefile. I found and fixed a small bug in how the leading ".\" was treated on Windows: it should be treated the same as "./", but it wasn't. The patch below fixes that. However, this does not (and cannot) make the backslash version of your Makefile behave 100% like the version with forward slashes, due to the fact that targets of the Makefile are looked up by comparing hash values of their strings, and the different flavor of slashes defeats the comparison. Paul, do you see any potential problems in providing on Windows a special version of the hash macros that would treat forward and back-slashes the same? The above explains why the behavior with backslashes was different. As to why the behavior with forward slashes is correct: this seems to be because you have the foobar0/foobar.s target in the Makefile, but not foobar1/foobar.s, while in reality the file that exists is foobar1/foobar.s. This seems to dupe Make into thinking that it found the right prerequisite as foobar0/foobar.s, and it does not proceed looking for foobar1/foobar.s. If you change the order of directories in the vpath line, the commands will work as you expect. There is a long comment in the function vpath.c:selective_vpath_search which seems to describe why files mentioned as targets in the Makefile are treated specially, but I don't understand what it says. Perhaps Paul or someone else could help in explaining the current behavior. (I added help-make to the list of addressees, because this question was first asked there.) Here's the patch mentioned above that I will install in the development sources: 2009-12-11 Eli Zaretskii <e...@gnu.org> * file.c (lookup_file) [HAVE_DOS_PATHS]: Treat '\\' like we do with '/'. --- file.c~ 2006-03-17 18:24:20.000000000 +0200 +++ file.c 2009-12-11 13:12:13.760750000 +0200 @@ -102,10 +102,20 @@ while (name[0] == '[' && name[1] == ']' && name[2] != '\0') name += 2; #endif - while (name[0] == '.' && name[1] == '/' && name[2] != '\0') + while (name[0] == '.' +#ifdef HAVE_DOS_PATHS + && (name[1] == '/' || name[1] == '\\') +#else + && name[1] == '/' +#endif + && name[2] != '\0') { name += 2; - while (*name == '/') + while (*name == '/' +#ifdef HAVE_DOS_PATHS + || *name == '\\' +#endif + ) /* Skip following slashes: ".//foo" is "foo", not "/foo". */ ++name; } _______________________________________________ Make-w32 mailing list Make-w32@gnu.org http://lists.gnu.org/mailman/listinfo/make-w32