[patch] dirent.h problem with include_next

James E Wilson wilson@specifix.com
Sun Oct 2 00:46:00 GMT 2005

This turned up while I was trying to get libmudflap to compile for a
mips-elf target.  libmudflap uses dirent.h, and has a configure test for
it.  The configure test worked the first time, i.e. showed that dirent.h
was not supported, but then suddenly started failing after I did an
install, i.e. claimed that dirent.h was supported.

The problem is easy to show with a simple testcase.  I've attached a
typescript showing the problem.  mips-elf does not have dirent.h
support.  I get an error when I try to compile a testcase that uses
dirent.h in the build tree.  But then, after an install, the testcase
works instead of failing, making it look like I have dirent.h support
when I don't.

The problem here is that we are including the build tree dirent.h, which
includes the build tree sys/dirent.h, which does an include_next which
finds the installed dirent.h.  Since dirent.h is protected against
multiple inclusion, the install tree dirent.h does nothing.  So the
testcase works instead of failing as expected.

One way to resolve this problem is to modify sys/dirent.h to undefine
the macro defined in dirent.h.  This way, if we accidentally include the
newlib dirent.h a second time, then we end up with an infinite include
loop.  This is a little gross, but at least we get an error as desired,
and libmudflap configure works as expected.  I've attached a file
showing a trimmed down copy of the result.

An alternative solution here would be to replace the #include_next with
a #error.  If someone does have an alternative dirent.h file, then I see
no reason why we can't force them to install it in the proper place, and
thus avoid the need for the #include_next here.  I note that there is
only one other newlib header that uses #include_next, and that is
limits.h.  However, in this case we are practically guaranteed to find
gcc's version of limits.h, so this does not have the problem of the
dirent.h usage.

The attached patch has been tested with a full mips-elf toolchain build
and make check.  There were no regressions.
Jim Wilson, GNU Tools Support, http://www.specifix.com
-------------- next part --------------
aretha$ cat tmp.c
#include <dirent.h>
main (void)
  return 0;
aretha$ cat tmp.script
./xgcc -B./ -B../mips-elf/newlib/ -B../mips-elf/libgloss/mips/ -B../../new-combined/libgloss/mips/ -I../../new-combined/newlib/libc/include tmp.c -Tpmon.ld
aretha$ sh tmp.script
In file included from ../../new-combined/newlib/libc/include/dirent.h:6,
                 from tmp.c:1:
../../new-combined/newlib/libc/include/sys/dirent.h:16:25: error: dirent.h: No such file or directory
aretha$ cd ..
aretha$ make install >& output
aretha$ cd gcc
aretha$ sh tmp.script
-------------- next part --------------

                 from /home/wilson/COMBINED-TREE/install/lib/gcc/mips-elf/4.1.0/../../../../mips-elf/include/dirent.h:6,
                 from ../../new-combined/newlib/libc/include/sys/dirent.h:16,
                 from /home/wilson/COMBINED-TREE/install/lib/gcc/mips-elf/4.1.0/../../../../mips-elf/include/dirent.h:6,
                 from ../../new-combined/newlib/libc/include/sys/dirent.h:16,
                 from ../../new-combined/newlib/libc/include/dirent.h:6,
                 from tmp.c:1:
/home/wilson/COMBINED-TREE/install/lib/gcc/mips-elf/4.1.0/../../../../mips-elf/include/dirent.h:6:24: error: #include nested too deeply
-------------- next part --------------
2005-09-29  James E. Wilson  <wilson@specifix.com>

	* libc/include/sys/dirent.h (_DIRENT_H_): Undef.

Index: dirent.h
RCS file: /services/cvs/cvsroot/gnusense/newlib/newlib/libc/include/sys/dirent.h,v
retrieving revision
diff -p -r1.1.1.1 dirent.h
*** dirent.h	8 Jul 2004 13:15:34 -0000
--- dirent.h	29 Sep 2005 23:23:16 -0000
*** 9,14 ****
--- 9,18 ----
  #ifdef __cplusplus
  extern "C" {
+ /* To force an error, we must undef this in case we find a second copy of
+    the main dirent.h file.  This can happen if the first copy is in the
+    build tree, and the second copy is in the install tree.  */
+ #undef _DIRENT_H_
  #include_next <dirent.h>
  #ifdef __cplusplus

More information about the Newlib mailing list