Почему g++ не находит предварительно скомпилированный заголовок, который находится в пути -I include?

Я пытаюсь создать предварительно скомпилированный заголовок и исполняемый файл, например:

g++ -g -Wall -std=c++17 \
    -c ./src/pch.hpp -o ./build/pch.hpp.gch

g++ -g -Wall -std=c++17 \
        -c ./src/*.cpp  \
        -I./build/ -include pch.hpp

Файл pch.hpp.gch создан правильно. Но для каждого из файлов .cpp я получаю следующую ошибку:

1 error generated.
<built-in>:1:10: fatal error: 'pch.hpp' file not found
#include "pch.hpp"

Я думаю, что моя строка компиляции верна, основываясь на документации по предварительно скомпилированным заголовкам gcc :

  • -I./build/ указывает ему добавить каталог build в путь поиска.
  • -include pch.hpp добавляет директиву #include <pch.hpp> к каждому файлу.
  • Компилятор ищет предварительно скомпилированные заголовки с суффиксом .gch для каждой из своих директив #include.

Почему моя строка компиляции не работает должным образом?


Я пробовал некоторые вещи, которые действуют и дают лучшие результаты, но мне они не кажутся правильными.

Если я изменю включение для поиска файла .gch, файл будет найден в соответствии с моими ожиданиями. То есть -include pch.hpp.gch вместо -include pch.hpp .
Но тогда PCH интерпретируется как бинарный файл, и компиляция не выполняется:

g++ -g -Wall -std=c++17 \
        -c ./src/*.cpp  \
        -I./build/ -include pch.hpp.gch
./build/pch.hpp.gch:2:22: error: source file is not valid UTF-8

Я не удивлен, что #include <pch.hpp.gch> не компилируется. Но я упомянул об этом, потому что это, кажется, показывает, что в моей исходной команде выполняется поиск в папке build (как я и ожидал), но механизм, который знает, что нужно использовать файл .gch вместо обычного заголовка, не активен. Странный.

Кроме того, если я добавлю папку src в путь поиска заголовка, это сработает:

g++ -g -Wall -std=c++17 \
        -c ./src/*.cpp  \
        -I./src/ -I./build/ -include pch.hpp

Я не понимаю, почему добавление другого, неуместного include-path ничего не решает. Странный.


Мое текущее рабочее решение — полностью отказаться от директивы -I include-path и указать более полный путь к build/pch.hpp:

g++ -g -Wall -std=c++17 \
        -c ./src/*.cpp  \
        -include ./build/pch.hpp

Этот работает, как и ожидалось. Я не уверен, зачем это нужно, хотя это странно и неудобно.

Это то, как предполагается использовать PCH? Почему моя исходная линия не работает и что я должен делать вместо этого?


person nihohit    schedule 30.04.2019    source источник


Ответы (1)


Из документации:

Предварительно скомпилированный заголовочный файл ищется, когда в компиляции встречается #include. При поиске включаемого файла (см. Путь поиска в препроцессоре C) компилятор ищет предварительно скомпилированный заголовок в каждом каталоге непосредственно перед поиском включаемого файла в этом каталоге. Искомое имя — это имя, указанное в #include с добавлением «.gch». Если предварительно скомпилированный заголовочный файл нельзя использовать, он игнорируется.

Например, если у вас есть #include "all.h", а all.h.gch находится в том же каталоге, что и all.h, то по возможности используется предварительно скомпилированный заголовочный файл, а в противном случае используется исходный заголовок.

Это означает, что компилятор должен иметь возможность найти ОБА h-файл и gch-файл при сборке cpp. Таким образом, они ОБА должны находиться в одном и том же каталоге или включать один и тот же путь поиска.

person Andrey Chistyakov    schedule 07.05.2019
comment
Так почему же, когда я использую -include ./build/pch.hpp без дополнительного пути поиска, компилятор не найдет исходный заголовочный файл, и все же он все еще работает? - person nihohit; 08.05.2019
comment
Ваш второй вариант вообще пропускает предварительно скомпилированный заголовок. Компилятор включает pch.hpp в качестве типичного заголовочного файла. - person Andrey Chistyakov; 09.05.2019