Постоянно и надежно установить g cc глобально включить путь - PullRequest
1 голос
/ 28 мая 2020

Система: LMDE4, 64bit, g cc -8.3.0, VS Code

Целевой файл: https://github.com/opencv/opencv/blob/master/samples/cpp/videocapture_camera.cpp

Теперь, как говорится в заголовке, это начинает меня бесить. Ничего не помогает решить такую ​​простую проблему. И НЕТ, я не хочу всегда использовать "-I", чтобы сообщать компилятору довольно очевидные вещи. Вот что я сделал до сих пор.

в c_cpp_properties. json кода VS:

{
    "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
}

в .bashr c:

#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"

Я почти уверен, что все экспорты .bashr c уже являются грязным обходным путем, и все же я получаю следующее сообщение при компиляции:

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 уже знает (!), Где находится файл, как только я нажимаю «Go to Definition», а g cc - это слепой. Как мне действительно избавиться от этого?

1 Ответ

0 голосов
/ 28 мая 2020

Вот минимальное воспроизведение вашей проблемы в Ubuntu 20.04.

$ 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

Эффект от этого параметра среды согласно Руководству G CC: 3.21 Влияние переменных среды G CC это то же самое, что:

$ 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.

, что соответственно воспроизводит ошибку.

Параметр -isystem задокументирован в Руководстве по G CC : 3.16 Параметры для поиска в каталоге

общее решение вашей проблемы: Не запускайте компиляцию 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.
...

Итак, ваш комментарий:

Я почти уверен, что весь экспорт .bashr c уже является грязным обходным путем

включен деньги 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 теперь как дублированный каталог в порядке поиска <...>; второе вхождение - которое было последним , ранее - удаляется, а первое вхождение сохраняется, идя первое в порядке поиска.

Теперь вызовите диагностику c:

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

Директива препроцессора #include_next не является стандартной директивой, это расширение G CC, задокументированное в руководстве G CC: 2.7 Заголовки оболочки

В то время как #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>, после того, который содержит файл, содержащий директиву. Как правило, просто не связывайтесь с порядком поиска <...>.

Только что обсуждаемая проблема была предметом отчета об ошибке регрессии, поднятого против G CC 6.0 . Как вы можете видеть, разрешение было WONTFIX.


[1] Все ваши .bashrc экспорта в том виде, в каком они были опубликованы, как вы подозреваете, являются плохой практикой.
  • Нет необходимости сообщать препроцессору о каких-либо каталогах поиска в порядке поиска по умолчанию. Вы можете только ошибиться.

  • Каталоги, которые не будут найдены по умолчанию должны быть указаны с помощью -I dir параметров, указанных в командная строка (обычно вводится через параметры конфигурации сборки), чтобы эти нестандартные параметры были видны в журналах сборки для устранения неполадок. «Невидимых рук» следует избегать в системах сборки в максимально возможной степени.

...