image.png
所以,在/usr/include/c++/7/cstdlib中遇到#include_next<stdlib.h>,会跳过/usr/include/c++/7目录,然后在/usr/include目录中找到stdlib.h,搜索成功。

出错的情况

使用以下命令:

g++-7 -isystem"/usr/include" a.cpp -E -v >a.txt

输出如下:

image.png

对比上面的正常情况,这种情况下为什么会出错,就很好理解了:因为在搜索列表中,/usr/include被移到了/usr/include/c++/7之前,所以在/usr/include/c++/7/cstdlib中遇到#include_next<stdlib.h>,就找不到stdlib.h了。

事实上,/usr/include(交叉编译情况下是sysroot/usr/include)本来就在编译器默认的搜索列表中,所以不应该在编译脚本里再把/usr/include加到include_directories中。
就编译OpenCV3.1碰到的这个问题来说,可以在function(ocv_include_directories)中,把以/usr/include结尾的目录过滤掉,解决这个问题。

关于include_next的几个问题

  • 为什么低版本g++不会出错
    因为低版本g++的cstdlib(例如/usr/include/c++/5/cstdlib)中使用的是#include<stdlib.h>而不是#include_next<stdlib.h>。/usr/include/c++/5目录下也没有stdlib.h这个文件。
  • include_next是在头文件中使用的。那么,当在头文件a.h中看到了include_next<b.h>,具体行为是下面列出的哪种?
    (1)在头文件搜索路径列表中,跳过a.h所在路径,在后面的路径中搜索b.h
    (2)在头文件搜索路径列表中,跳过a.h所在路径,在后面的路径中搜索b.h。找到b.h后,再跳过该路径,再在后面的路径中继续搜索b.h
    (3)在头文件搜索路径列表中,从a.h所在路径开始,搜索b.h。找到b.h后,跳过该路径,再在后面的路径中继续搜索b.h
    答案是(1)。
    例如,假设有头文件a.h:
  • #include_next<stdlib.h>
    

    有源文件main.cpp:

    #include <a.h>
    int main(void)
        return 0;
    

    用g++-5编译,g++-5 -I. main.cpp,那么搜索到的stdlib.h是/usr/include/stdlib.h: