Возник вопрос по пониманию правильной работы Precompiled headers.
Если какие-то заголовочные файлы включены в precompiled header, то что делать с включением этих же файлов в *.cpp (напрямую или опосредованно через другие h)? Замелдяют ли такие включения компиляцию, или механизм precompiled headers учитывает эту ситуацию и не включает такие файлы каждый раз в исходник?
Два варианта действий с такими включениями:
1. Удалять, так как компилятор включает и парсит все заголовки без разбора, и включение этих же инклудов в *.cpp делает precompiled headers бесполезным;
2. Оставлять, компилятор это учитывает и не включает их;
Интересует поведение компилятора в Visual Studio, а также gcc.
Еще могут быть тонкости, как именно компилятор различает, что включать а что не включать. Например, в vc++ при включенном PCH требуется чтобы в каждый файл включался stdafx.h (его можно включить во все файлы сразу опцией 'Forced include file'. При "умной" реализации компилятор должен составлять список путей ко ВСЕМ заголовочным файлам, попавшим в "дерево включений" (то есть корень — stdafx.h, ветви — все инклуды, включенные в него, все инклуды включенные в эти инклуды и т.д.), и исключать из обработки такие инклуды, если они включены где-то напрямую. При "глупой" реализации компилятор может, например, тупо сравнивать имя на "stdafx.h" и исключать из повторной компиляции только его, а все остальные — компилировать каждый раз.
Не понял сути проблемы. Конпелятор ничего ниоткуда не исключает. Он может хоть двадцать раз включать один и тот же хедер. Собственно, для этого и придумали
Здравствуйте, _Butch_, Вы писали:
_B_>Не понял сути проблемы. Конпелятор ничего ниоткуда не исключает. Он может хоть двадцать раз включать один и тот же хедер. Собственно, для этого и придумали _B_>
_B_>#pragma once
_B_>
_B_>PCH в данном контексте ничего не меняет.
Про него я даже не подумал Тогда поясните с учетом #pragma once
Rule of thumb: твой проект должен компилироваться независимо от того, используешь ли ты прекомпиляцию заголовков или нет. Естественно файлы при этом включать нужно. Компилятор каждый раз их включает, только не читает с диска и не парсит заново каждый раз.
Здравствуйте, ELazin, Вы писали:
EL>Rule of thumb: твой проект должен компилироваться независимо от того, используешь ли ты прекомпиляцию заголовков или нет. Естественно файлы при этом включать нужно. Компилятор каждый раз их включает, только не читает с диска и не парсит заново каждый раз.
То есть, если я вас правильно понял, наличие или отсутствие #include в файлах исходников не влияет на работу precompiled headers; достаточно добавить определенный заголовочный файл в список предкомпилируемых заголовков (stdafx.h в msvc), и он не будет парситься каждый раз при включении через #include, а будет браться из базы precompiled headers?
Здравствуйте, c-smile, Вы писали:
CS>Не обязательно stdafx.h CS>Я собираю static html.lib , в качестве precompiled header file указан файл html.h который включается во все .cpp файлы той библиотки.
Здравствуйте, x-code, Вы писали:
XC>Здравствуйте, ELazin, Вы писали:
EL>>Rule of thumb: твой проект должен компилироваться независимо от того, используешь ли ты прекомпиляцию заголовков или нет. Естественно файлы при этом включать нужно. Компилятор каждый раз их включает, только не читает с диска и не парсит заново каждый раз.
XC>То есть, если я вас правильно понял, наличие или отсутствие #include в файлах исходников не влияет на работу precompiled headers; достаточно добавить определенный заголовочный файл в список предкомпилируемых заголовков (stdafx.h в msvc), и он не будет парситься каждый раз при включении через #include, а будет браться из базы precompiled headers?
Нет, pch это какое-то сериализованное состояние парсера/компилятора. Оно просто загружается перед компиляцией файла в память, а дальше компилятор работает как обычно (ложные воспоминания, как во Вспомнить Всё, понимаешь?)
Здравствуйте, x-code, Вы писали:
XC>Про него я даже не подумал Тогда поясните с учетом #pragma once
#pragma once отдельно оптимизируются, вне зависимости от включения хедера в прекомпайлед хедере.
В компиляторах есть оптимизация для сокращенной обработки уже влюченных хедеров.
Она детектит #pragma once или #ifdef-гард, перед которым нет ничего (кроме, возможно, whitespace и комментариев).
При обнаружении #pragma once или #ifdef-гарда, хедер не парсится полновесным препроцессором.
Как показали опыты на оной из версий MSVC, в MSVC такая оптимизация лучше работает для #pragma once, чем для #ifdef-гарда.
Гипотетически, ускорить компиляцию можно применением #ifdef-гарда совместно с его внешней проверкой:
#ifndef _WINDOWS_
#include <windows.h> // внутри там #ifndef _WINDOWS_ \ #define _WINDOWS_#endif
Практически затраты на поддержку такого вряд ли оправданы.
XC>То есть, если я вас правильно понял, наличие или отсутствие #include в файлах исходников не влияет на работу precompiled headers; достаточно добавить определенный заголовочный файл в список предкомпилируемых заголовков (stdafx.h в msvc), и он не будет парситься каждый раз при включении через #include, а будет браться из базы precompiled headers?
Он не будет перечитываться с диска при каждом включении, вместо этого твой pch будет считываться компилятором при компиляции каждой единицы трансляции один раз. Pch это не объектник, компилируется твоя единица трансляции (срр) а не заголовок.
Здравствуйте, ELazin, Вы писали:
EL>Rule of thumb: твой проект должен компилироваться независимо от того, используешь ли ты прекомпиляцию заголовков или нет. Естественно файлы при этом включать нужно. Компилятор каждый раз их включает, только не читает с диска и не парсит заново каждый раз.
И как этого добиться при использовании Force Include ?