Created attachment 175436 [details] test case To reproduce this bug run following command: % clang++ -isystem /usr/include test.cpp In file included from test.cpp:1: /usr/include/c++/v1/cstddef:43:15: fatal error: 'stddef.h' file not found #include_next <stddef.h> ^ 1 error generated. File compiles fine without -isystem flag: % clang++ test.cpp % The problem is that stddef.h is clang's internal header and supposed to be in /usr/bin/../lib/clang/3.8.0/include. But since it conflicts with freebsd's stddef.h we do not install it and append /usr/include to the list of include dirs: % clang++ -v test.cpp FreeBSD clang version 3.8.0 (tags/RELEASE_380/final 262564) (based on LLVM 3.8.0) .. skipped ... #include "..." search starts here: #include <...> search starts here: /usr/include/c++/v1 /usr/bin/../lib/clang/3.8.0/include /usr/include End of search list. But when we pass -isystem /usr/include, clang removes appended dir as a duplicate and search path looks like this: % clang++ -v -isystem /usr/include test.cpp FreeBSD clang version 3.8.0 (tags/RELEASE_380/final 262564) (based on LLVM 3.8.0) .. skipped .. ignoring duplicate directory "/usr/include" #include "..." search starts here: #include <...> search starts here: /usr/include /usr/include/c++/v1 /usr/bin/../lib/clang/3.8.0/include End of search list. #include_next does not go through whole list, only from the directory where its parent file is located Some third-party software passes -isystem for cross-compilation cases alogn with --sysroot, namely Qt does it like this: c++ ... --sysroot=/src/FreeBSD/tftproot/rpi/ ... -isystem /src/FreeBSD/tftproot/rpi/usr/include ... and this bug breaks cross-compilation
Created attachment 175437 [details] clang-isystem-fix.diff This patch fixes the problem but I am not sure if it's correct. It adds one more priority check and keeps ExtCSystem include in favor of CSystem one
Short answer: Don't use -isystem /usr/include. If you do so for C++ programs, you mess up the include search path order. If you must do it for some reason, you must also add -isystem entries for the C++ include directories, and at the front of the list. For example, a C++ program will use the following search path by default (where x.y.z is the clang version): #include "..." search starts here: #include <...> search starts here: /usr/include/c++/v1 /usr/bin/../lib/clang/x.y.z/include /usr/include End of search list. From libc++ 3.8.0 onwards, if you include a C standard header, such as <cstddef>, you will get libc++'s wrapper header first. This header sets up a few things, then does #include_next<stddef.h>, and with the above search path, this finds /usr/include/stddef.h. (We don't install clang's internal stddef.h, since it is not compatible with our system headers yet.) However, if you add -isystem /usr/include, you force /usr/include to be the first in the list, e.g. the search path will become: ignoring duplicate directory "/usr/include" #include "..." search starts here: #include <...> search starts here: /usr/include /usr/include/c++/v1 /usr/bin/../lib/clang/x.y.z/include End of search list. If you now include <cstddef>, and it eventually does #include_next<stddef.h>, it will attempt to search the paths *after* /usr/include/c++/v1, and will not be able to find the header. Summary: If for some reason you must completely rebuild the header search path from scratch, you need to add -isystem /usr/include/c++/v1 *before* -isystem /usr/include. But it is better not to do this at all. :)
See Bug 211808
I see the problem arising on two ports, graphics/opencv-core and graphics/blender. Both ports do not compile on CURRENT on several machines, while they compile on other systems, also running CURRENT. The configurations (especially /etc/src.conf and /etc/make.conf) are spread around our systems, so I consider the systems not identical, but very similar. I know this is not enough in terms of mathematical logik and approval.