首先我们先来看下include_next的用法
比如我们想include , 在cmath头文件中你可以看到有类似include_next 的语法,他跟传统的include不同,他不会从你的search path list的头部开始查找,他会跳出当前路径从下一个entry进行查找,比如我们来看例子
![23e57eaa37c37b9e3a740d67826220d1.png](https://i-blog.csdnimg.cn/blog_migrate/af6959d48b06c812a0035839fc3cf6fe.jpeg)
cmath在/usr/include/c++/6.1.1中, 但是math.h同时出现在下面两个文件夹中:
![ce4284bdd00a9a8017c3aea377d8d6e9.png](https://i-blog.csdnimg.cn/blog_migrate/a7bd3a224c1bf4d30b6e3897c6c2953a.jpeg)
此时我们不想让他的math.h是在c++/6.1.1中截获,而是在/usr/include/math.h中找到,同时我们根据第一张图的列表确确实实发现此时6.1.1的路径在第一个,这个时候include_next就起作用了,他会跳出当前cmath的路径进行查找,自然而然就找到/usr/include/math.h了
![07758b87ceeb8c52c482033dc55408d0.png](https://i-blog.csdnimg.cn/blog_migrate/4cc452aed867b11528a3bdaa3da2ccd9.jpeg)
但是当我们使用了-isystem的时候,情况就不一样了
g++ -isystem /usr/include
可以看到此时的/usr/include被你放到了顶端,此时你的include_next自然而然跳过了他的c++/6.1.1,同时又因为此时的/usr/include被你放在了最上面,所以他的最终结果就是找不到任何内容了
你可以运行一个简单例子来复现这个错误:
![89330bb34ab23706b655c491d9e078e9.png](https://i-blog.csdnimg.cn/blog_migrate/9a2b532a5276ce98b0d69048a37c21d2.jpeg)
你会发现这样都会编译不过,原因就在于-isystem / include_next的结合,我们一个个来说。
![f9832e65ef20bace8e74b80d6c51795f.png](https://i-blog.csdnimg.cn/blog_migrate/a0766694801007cc5010babeed009d27.jpeg)
首先来说下-isystem,他的作用是抑制编译器对后面所包含的include的路径的wanring,让编译器认为这是系统级别的头文件,请不要对他们产生任何的wraning,但是除此之外,这个-isystem却带来了一些副作用 - 他会修改你的header search list. 他会把你在后面指定的directory放在你整个system header directories的头部。 如果目录已经出现在你的search list中,那么他会从当前的位置进行删除。
同时,GCC 6.1.1之后C++ headers为了更好的支持standard C头文件,使用了#include_next的方式,比如在cmath里你可以找到类似#include_next .问题就出在了这个#include_next, 他不像传统#include一样会从整个search path的头部开始查找,他仅仅会从当前文件的下一个search path文件路径进行查找。同时,因为你的-isystem把/usr/include移到了整个cmath的之前,所以math.h就找不到了
相关math.h的查找过程可以通过 #include_next的用法 来查看
PS:
- 如果错误出现在CMake中,可以通过尝试设置-DCMAKE_NO_SYSTEM_FROM_IMPORTED=1来解决
- CMake之所以会出现错误的原因是因为他的find_package会添加对应的path到system include paths,所以尽量避免当目录已经在system search path中再利用-isystem来进行添加
![6f0e458a8eb20aa96809b762e738acf7.png](https://i-blog.csdnimg.cn/blog_migrate/7468a7076e0fc35bd3dbafe707194825.jpeg)