Возможно, я нашел ошибку в gcc, я не смог найти ничего, связанного с этим в Интернете, поэтому я хочу знать, видел ли кто-нибудь это раньше.
Я использую «Ubuntu 16.04.0 LTS» с:
gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.6)
, но эта проблема может быть воспроизведена и в более поздних версиях gcc, gcc-6 и gcc-7.
Вот https://github.com/mihaipop11/gcc-linux Вы можете найти ссылку на репозиторий Github, содержащий все источники, но я также объясню это ниже.
Как воспроизвести:
У нас есть эта хорошая маленькая программа с этими файлами:
// main.cpp
#include <iostream>
#include INCLUDE_FILE
int main()
{
std::cout << "Works this time" << std::endl;
}
и заголовочный файл внутри папки, скажем, с именем include
, не имеет значения, что пусто, это только для демонстрационных целей.
// include.hpp
//empty header
В целом структура выглядит так:
<dir>
├── main.cpp
└── include
└── include.hpp
Шаг компиляции:
Я проанализировал два случая, и ошибка появляется во втором.
Первый случай:
<dir>
имя папки, в которой хранятся файлы, должно быть названо как угодно, кроме того, что содержит строку linux
, например: test-notlinux
В целом структура выглядит так:
test-notlinux
├── main.cpp
└── include
└── include.hpp
Сейчас, cd test-notlinux
и попробуйте скомпилировать источники:
g++ "-D INCLUDE_FILE=\"${PWD}/include/include.hpp\"" main.cpp
g++ "-D INCLUDE_FILE=<${PWD}/include/include.hpp>" main.cpp
Результат: Обе команды работают как положено. Нет проблем здесь.
Второй случай:
<dir>
имя папки, в которой хранятся файлы, содержит строку linux
, например: test-linux
В целом структура выглядит так:
test-linux
├── main.cpp
└── include
└── include.hpp
Сейчас, cd test-linux
и попробуйте скомпилировать источники:
// first command should work
g++ "-D INCLUDE_FILE=\"${PWD}/include/include.hpp\"" main.cpp
// but this ...
g++ "-D INCLUDE_FILE=<${PWD}/include/include.hpp>" main.cpp
Результат: Вторая команда, очевидно, заменяет linux
строка из имени dir с 1
Выход: /tmp/test-1/include/include.hpp: No such file or directory
Кто-нибудь знает что-нибудь об этом?
Первое, что linux
это макрос, определенный для 1
, В <> в случае, когда макрос раскрывается, тогда как в «» случае токен является строкой.
Второе, что linux
определяется только при использовании расширений GNU, поэтому просто скомпилируйте -std=c++{98,11,14,17,2a}
или же -ansi
и это не будет определено (только __linux__
, __linux
а также __gnu_linux__
будет).
Других решений пока нет …