fatal error: 'cstdio' file not found

It seems like clang isn't finding my standard C++ headers. Lately I've
been playing with cross-compliers and gcc, (gcc works fine still), and
when I tried to build my code again with clang, it stopped finding headers.

NOTE: The C headers are found fine, it's only the C++ headers that are
affected.

clark@clark-laptop /tmp $ clang++ --version
clang version 1.1 (branches/release_27)
Target: x86_64-pc-linux-gnu
Thread model: posix
clark@clark-laptop /tmp $ g++ --version
g++ (Gentoo 4.5.0 p1.2, pie-0.4.5) 4.5.0
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

clark@clark-laptop /tmp $ cat t.cpp
#include <cstdio>

int main() { return 0; }
clark@clark-laptop /tmp $ g++ t.cpp
clark@clark-laptop /tmp $ clang++ t.cpp
t.cpp:1:10: fatal error: 'cstdio' file not found
#include <cstdio>
         ^
1 diagnostic generated.

So I have two questions:

  1) How can I get clang to show the header search path? clang++
--verbose doesn't seem to work.
  2) Any idea what the problem might be?

Thanks for your help,
  -- Clark

I often use -v -E for that, so you get a verbose dump from the
preprocessor.

Thanks, that found the problem, but I still don't know how to fix it.

It seems that clang is searching through gcc directories. Example:

ignoring nonexistent directory "/usr/include/c++/4.4.3"
ignoring nonexistent directory "/usr/include/c++/4.4.3/x86_64-pc-linux-gnu/"
ignoring nonexistent directory "/usr/include/c++/4.4.3/backward"
ignoring nonexistent directory "/usr/include/c++/4.4.3"
ignoring nonexistent directory "/usr/include/c++/4.4.3/i686-pc-linux-gnu/"
ignoring nonexistent directory "/usr/include/c++/4.4.3/backward"
ignoring nonexistent directory "/usr/include/c++/4.4"
ignoring nonexistent directory "/usr/include/c++/4.4/x86_64-linux-gnu/"
ignoring nonexistent directory "/usr/include/c++/4.4/backward"
ignoring nonexistent directory "/usr/include/c++/4.4"

That goes on for many, many version, however, not gcc 4.5.0 which is the
only non-cross-compiler I have installed right now. How do I add the
4.5.0 paths to the search list?

I'm not sure you can do it without modifying the source, but it should
probably be added to InitHeaderSearch.cpp.

Couldn't it be made to detect the right version by looking at what
directories exist in /usr/include/c++/ and adding the latest version
that's found there?

The current hardcoded paths are kind of ridiculous.

-Alexei

Perhaps the configure script could grab them from GCC by parsing the output from these two ()

echo | `gcc -print-prog-name=cc1` -v
echo | `gcc -print-prog-name=cc1plus` -v

Ignore every line before

#include <...> search starts here:

and after

End of search list.

And you get a list of GCC's search paths (clang -cc1 -v does the same thing, so presumably someone knows about this already...). If you install a new GCC, you'd just need to rerun the configure script.

David

That would make the clang binary non-portable to other systems (which
may have different GCC versions).

I'd rather have this detection be done at clang start time. I really
don't think it would have any significant performance penalty (I'm
guessing the code that tries to find header files would need to do a
bunch of file ops anyway to go through the hardcoded list of paths -
so if that hard-coded list was shorter because we'd add the right
thing to it at start time, we'd save doing all that other work later
on).

-Alexei

Yes, patches accepted that don't break other platforms as well :slight_smile:

-eric

As far as I can see, my headers are in

/usr/lib/gcc/x86_64-pc-linux-gnu/4.5.0/include/g++-v4/

and /usr/include/c++ doesn't even exist.

Just a side note: reinstalling 4.4.4 doesn't fix the problem.

That would make the clang binary non-portable to other systems (which
may have different GCC versions).

The same is true of GCC - the binary is not portable to systems with different locations for the standard headers.

I'd rather have this detection be done at clang start time. I really
don't think it would have any significant performance penalty (I'm
guessing the code that tries to find header files would need to do a
bunch of file ops anyway to go through the hardcoded list of paths -
so if that hard-coded list was shorter because we'd add the right
thing to it at start time, we'd save doing all that other work later
on).

Unfortunately, you seem to be assuming that every system looks like yours. The locations for the standard headers are not the same on other platforms - as Clark points out, some put the headers in /usr/lib/gcc/{target tripple}, while others put them in other random places. Darwin also needs to look in /System/Library/Frameworks and /Library/Frameworks, for example.

Picking up what the system compiler uses in configure would allow clang to work as a drop-in replacement for the system compiler, without needing a huge mess of hard-coded 'standard' locations.

David

Picking up what the system compiler uses in configure would allow clang to work as a drop-in replacement for the system compiler, without needing a huge mess of hard-coded 'standard' locations.

And would break as soon as the user upgraded their version of GCC.

-Alexei

Since the headers are part of the gcc distribution, why not just ask
gcc at run-time? It Just Works (tm).

- Michael Spencer

We can't exactly afford to add the overhead of launching GCC to every
Clang invocation just to find out where it hides its header files.

Sebastian

We could, however, have some sort of configuration file in $prefix/share/clang
(or wherever). configure could write a default configuration based on the host,
and anybody moving binaries between different setups probably deserves
what they get.

John.

Could just compile it in as a bunch of strings also to save overhead once we've
autodetected. Autodetecting is on the list - it just hasn't been high enough priority
for anyone to write a patch.

-eric