永久可靠地设置gcc包含全局路径

时间:2020-05-28 00:44:54

标签: c++ gcc visual-studio-code include default

系统:LMDE4、64位,gcc-8.3.0,VS代码

目标文件:https://github.com/opencv/opencv/blob/master/samples/cpp/videocapture_camera.cpp

现在,正如标题所述,这开始激怒我。解决这种简单问题没有任何工作。不,我不想一直使用“ -I”向编译器讲述很明显的事情。这是我到目前为止所做的。

在VS Code的c_cpp_properties.json中:

{
    "configurations": [
        {
            "name": "Linux",
            "includePath": [
                "${workspaceFolder}/**",
                "/usr/include/**"
            ],
            "defines": [],
            "compilerPath": "/usr/bin/gcc",
            "cStandard": "c11",
            "cppStandard": "gnu++14",
            "intelliSenseMode": "clang-x64",
            "browse": {
                "path": [
                    "/usr/include/"
                ]
            }
        }
    ],
    "version": 4
}

在.bashrc中:

#C Include
export C_INCLUDE_PATH="/usr/include"
export C_INCLUDE_PATH=$C_INCLUDE_PATH:"/usr/include/opencv2"

#C++ Include
export CPLUS_INCLUDE_PATH="/usr/include"
export CPLUS_INCLUDE_PATH=$CPLUS_INCLUDE_PATH:"/usr/include/c++/8/"
export CPLUS_INCLUDE_PATH=$CPLUS_INCLUDE_PATH:"/usr/include/opencv2"

#C/C++ Include
export CPATH="/usr/include"

我很确定所有.bashrc导出都已经是一个肮脏的解决方法,并且仍然在编译时收到以下消息:

In file included from /usr/include/c++/8/bits/stl_algo.h:59,
                 from /usr/include/c++/8/algorithm:62,
                 from /usr/include/opencv2/core/base.hpp:55,
                 from /usr/include/opencv2/core.hpp:54,
                 from ~/LearnDummy/helloworld.cpp:1:
/usr/include/c++/8/cstdlib:75:15: fatal error: stdlib.h: Datei oder Verzeichnis nicht gefunden
 #include_next <stdlib.h>
               ^~~~~~~~~~
compilation terminated.

很好... stdlib.h是未知的(耶稣!)... find /usr -name stdlib.h给了我

/usr/include/stdlib.h 
/usr/include/c++/8/stdlib.h 
/usr/include/c++/8/tr1/stdlib.h 
/usr/include/x86_64-linux-gnu/bits/stdlib.h 
/usr/include/i386-linux-gnu/bits/stdlib.h 

此外,VS Code已经知道(!),一旦单击“转到定义”,文件仍然在哪里,而gcc仍然是盲目的。我该如何摆脱呢?

1 个答案:

答案 0 :(得分:0)

这是您在Ubuntu 20.04上遇到的问题的minimal repro

$ g++ --version
g++ (Ubuntu 9.3.0-10ubuntu2) 9.3.0
...

$ cat main.cpp
#include <cstdlib>

int main ()
{
  return EXIT_SUCCESS;
}

$ export CPLUS_INCLUDE_PATH="/usr/include"; g++ -c main.cpp
In file included from main.cpp:1:
/usr/include/c++/9/cstdlib:75:15: fatal error: stdlib.h: No such file or directory
   75 | #include_next <stdlib.h>
      |               ^~~~~~~~~~
compilation terminated.

请注意,export CPLUS_INCLUDE_PATH="/usr/include"与您的 .bashrc中的相同设置。

如果我们删除该环境设置,则不会发生错误:

$ export CPLUS_INCLUDE_PATH=; g++ -c main.cpp; echo Done
Done

根据the GCC Manual: 3.21 Environment Variables Affecting GCC,该环境设置的效果 等同于:

$ g++ -isystem /usr/include -c main.cpp
In file included from main.cpp:1:
/usr/include/c++/9/cstdlib:75:15: fatal error: stdlib.h: No such file or directory
   75 | #include_next <stdlib.h>
      |               ^~~~~~~~~~
compilation terminated.

相应地会重现错误。

the GCC Manual: 3.16 Options for Directory Search中记录了-isystem选项

您的问题的一般解决方案是:请勿以任何方式运行g++编译 效果 g++ ... -isystem /usr/include ...

可以避免以这种方式运行g++命令,因为该选项 -isystem /usr/include是不必要的。 /usr/include是默认的搜索目录 用于预处理器。您无需告诉它在那里查找系统头文件- 通过环境设置或VS Code配置或其他任何方式。

请参阅预处理程序对C ++的默认搜索顺序:-

$ echo | g++ -x c++ -E -Wp,-v -
ignoring duplicate directory "/usr/include/x86_64-linux-gnu/c++/9"
ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/include-fixed"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/../../../../x86_64-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/include/c++/9
 /usr/include/x86_64-linux-gnu/c++/9
 /usr/include/c++/9/backward
 /usr/lib/gcc/x86_64-linux-gnu/9/include
 /usr/local/include
 /usr/include/x86_64-linux-gnu
 /usr/include           ### <- There it is ###
End of search list.
...

所以您的评论:

我很确定所有.bashrc导出都已经是一个肮脏的解决方法

在钱上 1 。但是更糟糕的是,.bashrc设置:

export CPLUS_INCLUDE_PATH="/usr/include"

将问题转变为 bash个人资料的持久功能。

错误如何发生?

-isystem /usr/include与预处理程序的搜索顺序之间的差异 可以在这里看到:

$ echo | g++ -x c++ -isystem /usr/include -E -Wp,-v -
ignoring duplicate directory "/usr/include/x86_64-linux-gnu/c++/9"
ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/include-fixed"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/../../../../x86_64-linux-gnu/include"
ignoring duplicate directory "/usr/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/include           ### <- Was previously last, now is first ###
 /usr/include/c++/9
 /usr/include/x86_64-linux-gnu/c++/9
 /usr/include/c++/9/backward
 /usr/lib/gcc/x86_64-linux-gnu/9/include
 /usr/local/include
 /usr/include/x86_64-linux-gnu
End of search list.
...

如您所见,/usr/include现在在<...>搜索中被检测为重复目录 订购;第二次出现-以前是 last -被删除,第一次出现是 保留,在搜索顺序中排在第一位。

现在召回诊断:

/usr/include/c++/9/cstdlib:75:15: fatal error: stdlib.h: No such file or directory
   75 | #include_next <stdlib.h>
      |               ^~~~~~~~~~

预处理器指令#include_next不是标准指令,它是 在the GCC manual: 2.7 Wrapper Headers

中记录的GCC扩展名

#include <stdlib.h>的意思是:

从头开始,包含在stdlib.h搜索顺序中发现的第一个名为<...>的文件

#include_next <stdlib.h>的意思是:

包括从stdlib.h搜索顺序中发现的名为<...>的下一个文件。 目录,紧随正在处理的文件之后。

<...>搜索顺序中唯一包含stdlib.h的目录是/usr/include。所以, 如果预处理器在#include_next <stdlib.h>中任何目录dir中的任何文件中遇到<...> 搜索顺序,虽然/usr/include<...>搜索顺序中排在第一位,但是没有目录 在dir搜索顺序中晚于<...>的位置,将找到<stdlib.h>。还有错误。

#include_next <foobar.h>仅在<...>搜索顺序将包含以下内容的目录 在包含该指令的文件所在的文件之后的<foobar.h>。根据经验, 只是不要弄乱<...>的搜索顺序。

刚才讨论的问题是a regression bug-report raised against GCC 6.0的主题。 如您所见,分辨率为WONTFIX


[1]您怀疑,您发布的所有.bashrc出口都是不当行为。

  • 没有必要告诉预处理器中的任何搜索目录 其默认搜索顺序。你只能把事情弄错。

  • 默认情况下将 找不到的目录由 在命令行上指定的-I dir选项(通常通过参数注入) 的构建配置),以便这些非默认选项在构建日志中可见 解决问题。在构建系统中应避免“看不见的手” 最大程度的实践。