public inbox for newlib@sourceware.org
 help / color / mirror / Atom feed
From: "Pekka Seppänen" <pexu@kapsi.fi>
To: newlib@sourceware.org
Subject: newlib, modern C++ and dirent.h revisited
Date: Fri, 12 May 2017 15:19:00 -0000	[thread overview]
Message-ID: <5007a61e81f19f12d4c193904f175bc7@kapsi.fi> (raw)

Hi.

As this problem has some historic weight to it, here's a short recap: 
Unless compiling for a specific host, which ships it's own 
<sys/dirent.h> (which is included by <dirent.h>), newlib's default 
behaviour since 2005 has been to simply #error, which causes tests to 
work as expected (to fail). Since the very beginning (early 1990s?), it 
used to be #include_next, but as <sys/dirent.h> is included by 
<dirent.h>, #include_next <dirent.h> at <sys/dirent.h> will include 
again <dirent.h>, thus producing no easily detectable error -- fair 
enough [1].

At the time the fix was implemented, in order to provide a proper 
<dirent.h> the way was to simply provide an include path where the file 
resides using e.g. -isystem, so that it appears before newlib's 
include/sys. It stills kinda works as of today, but not really, so 
here's why I'm reluctant to use it:

Currently, I'm using newlib for a tiny RTOS that runs on a certain ARM 
based processors. Under the hood, I've implemented dirent.h 
functionality and everything works as expected. To keep the toolchain 
side as clean and tidy as possible, I'm pretty much limiting all the 
customizations to simply running any configuration scripts with the 
options I need. So, e.g. my newlib doesn't really know that it will be 
running hosted on an OS that does dirent.h stuff -- and it really 
doesn't have to. While configure.host is not that involved, doing a 
custom job there would require me to maintain that file and any 
corresponding files under libc/machine/. While it would be nice, I 
simply don't have time for this -- every moment spent building the 
toolchain is taken away from maintaining the actual RTOS and everything 
that sits atop of that (it's not like newlib is the only link in the 
chain).

Now, the majority of application code which runs on the OS is written 
using modern C++ (17 and onwards). For the compiler I'm using GCC, but I 
guess any decent compiler would do it. Again, when (cross-)compiling the 
GCC I'm limiting myself to any options, that are settable via the 
autoconf's configure script because my time is limited and kludges have 
tendency to break. Here's where the things have have changed, not 
perhaps dramatically, but changed nevertheless since the 2005 patch was 
made.

Evolved from Boost.Filesystem, STL has had an (experimental) 
std::(experimental::)filesystem since 2015. I would like to use, as I 
don't have any necessity to reinvent those features. When using GCC, 
this will be compiled as libstdc++fs, as part of the libstdc++. So, when 
the cross-compiling GCC is built, the proper dirent.h must be available 
as filesystem is not a header-only library. To configure native system 
headers for the GCC, as of 2011 --with-native-system-header-dir options 
has been available. It sets up a builtin include location, from which 
the system headers are supposed to be pulled -- in reality, it is of 
course just an additional builtin include path. As an unfortunate 
effect, the native-system-header-dir appears after, not before, the 
include path set up by --with-sysroot prefix (it will appear as 
-isystem, before any CXXFLAGS, set up by autoconf).

So, the default <sys/dirent.h> gets included and the libstdc++fs does 
not get built (the presence of <dirent.h> is determined by autoconf). 
One could do a dirty copy-over kludge here, but I just don't see that as 
a proper thing to do as it'll always pile up. The same goes with simply 
removing the <sys/dirent.h> -- while either would would fix the problem 
for me, it wouldn't so much do it for the others (e.g. the official ARM 
GNU toolchain). Also, hammering the default <sys/dirent.h> with GCC's 
fixincludes isn't any better, as it has no external hooks so one would 
have to manually maintain yet another configuration file.

I presume the source of this problem, and the reason why the 2005 patch 
was written, is the way #include_next works. If you have just one 
<dirent.h>, the #include_next will function just like #include. However, 
things have evolved and nowadays at least both GCC and LLVM (clang) 
support __has_include_next. Unfortunately, only __has_include is part of 
the C++17, but I guess this makes an excellent use case for 
__has_include_next: i) should you not have any next include file, (a 
properly implemented) __has_include_next will return 0, ii) should you 
not have __has_include_next functionality, simply define 
__has_include_next as zero or check, if it's defined (as compilers 
should really define __has_include as __builtin_has_include etc., or 
whatever internal name the particular vendor chooses).

So, instead of simply doing an #error, I would very much like to see 
something like:

#if defined(__has_include_next) && __has_include_next(<dirent.h>)
#  include_next <dirent.h>
#else
#  error "<dirent.h> not supported"
#endif

and it would just work (given that #if would have to be likely split 
into #ifdef/#if etc.): If there's no additional dirent.h, or your 
compiler is of previous generation, you'll get the old error message. 
Should you have both, it'll be included next -- just like the original 
did (or wished to do) back in the day. This way one could also pull a 
standard, uncustomized prebuilt newlib installation and not have to 
worry about <dirent.h> include order so much, would you like to 
implement one yourself. Like I said, of course `the proper' way to do 
this would be customize newlib, but the way configure scripts are 
currently implemented it involves so much work that it's not simply 
worth it -- patching, copying, checking, working this all up as an yet 
another messy script, for every release etc. takes so much time while 
you simply wanted `not to fail so early'.


What do you think? Worth doing, at least looking into, or is there 
something this sort of approach would hinder? Obviously, this would need 
some testing, so that it's not suddenly 2005 all over again.


-- Pekka


[1] https://sourceware.org/ml/newlib/2005/msg00608.html

             reply	other threads:[~2017-05-12 15:19 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-05-12 15:19 Pekka Seppänen [this message]
2017-05-12 15:31 ` Joel Sherrill

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5007a61e81f19f12d4c193904f175bc7@kapsi.fi \
    --to=pexu@kapsi.fi \
    --cc=newlib@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).