Читая мелкий шрифт переключателя -I
в GCC, я довольно шокирован, обнаружив, что его использование в системе переопределений командной строки включает в себя. Из документов препроцессора
"Вы можете использовать -I
для переопределения файла системного заголовка, заменив свою собственную версию, так как эти каталоги ищутся перед стандартными каталогами файлов системного заголовка."
Кажется, они не лгут. В двух разных системах Ubuntu с GCC 7, если я создаю файл endian.h
:
#error "This endian.h shouldn't be included"
... и затем в том же каталоге создайте main.cpp
(или main.c, такая же разница):
#include <stdlib.h>
int main() {}
Затем компиляция с g++ main.cpp -I. -o main
(или лязгом, такая же разница) дает мне:
In file included from /usr/include/x86_64-linux-gnu/sys/types.h:194:0,
from /usr/include/stdlib.h:394,
from /usr/include/c++/7/cstdlib:75,
from /usr/include/c++/7/stdlib.h:36,
from main.cpp:1:
./endian.h:1:2: error: #error "This endian.h shouldn't be included"
Итак, stdlib.h включает этот файл types.h, который в строке 194 просто говорит #include <endian.h>
. Мое очевидное заблуждение (и, возможно, чужое) заключалось в том, что угловые скобки предотвратили бы это, но - я сильнее, чем я думал.
Хотя не достаточно достаточно , потому что вы даже не можете исправить это, предварительно введя / usr / include в командной строке, потому что:
"Если стандартный системный каталог включения или каталог, указанный с помощью -isystem
, также указан с -I
, опция -I
игнорируется. Каталог по-прежнему ищется, но как системный каталог на его нормальное положение в системе включает цепь. "
Действительно, подробный вывод для g++ -v main.cpp -I/usr/include -I. -o main
оставляет / usr / include внизу списка:
#include "..." search starts here:
#include <...> search starts here:
.
/usr/include/c++/7
/usr/include/x86_64-linux-gnu/c++/7
/usr/include/c++/7/backward
/usr/lib/gcc/x86_64-linux-gnu/7/include
/usr/local/include
/usr/lib/gcc/x86_64-linux-gnu/7/include-fixed
/usr/include/x86_64-linux-gnu
/usr/include
Цвет меня удивил. Я думаю, чтобы сделать это вопрос:
Какая законная причина для большинства проектов использовать -I
, учитывая эту чрезвычайно серьезную проблему? Вы можете переопределить произвольные заголовки в системах на основе случайных коллизий имен. Разве не все должны использовать -iquote
вместо этого?