Precompiled Headers Explained
Почти все разработчики, использующие Visual C++, сталкиваются с файлом stdafx.h
, в который можно положить много-много различных директив препроцессора. И так мало понимают, зачем это нужно и как с этим работать...
Precompiled Header
Вы, наверное, слышали о понятии Precompiled Header
. Precompiled Header
- это механизм, позволяющий компиляторам сократить время сборки приложения путем прекомпиляции
редко меняющихся файлов исходного кода приложения. В первую очередь - это библиотечный код, точнее заголовочные файлы.
Рассмотрим программу Hello World
:
#include <tchar.h> #include <iostream> int _tmain(int argc, _TCHAR* argv[]) { std::cout << "Hello World!" << std::endl; return 0; }
А теперь внимание: после обработки этого файла прекомпилятором, его размер возрастает до 996 килобайт! Я повторюсь: 996 килобайт, из которых 854 составляют полезный код (остальное - комментарии), а размер рабочего кода программы - аж 142 байта. Похоже, для компиляции нашего простейшего cpp-файла компилятору прийдется изрядно потрудиться. Причем над каждым cpp-файлом проекта.
Естественно, лучше предварительно обработать неизменящиеся куски кода, превратив их в удобный и быстрый формат для последующей обработки в составе исходного кода приложения. Компиляторы Visual C++ и GCC поддерживают такую обработку и она носит имя Precompiled Header
.
Использование Precompiled Header в Visual C++
Мастер создания проекта Visual C++ предлагает свои услуги по настройке Precompiled Header. В простейшем случае, среда дает разработчику возможность выбора - использовать этот механизм или нет. В большинстве случаев использование Precompiled Header настраивается автоматически.
Анализ настроек Precompiled Header мастеров Visual C++
Что же мы получаем при автоматической настройке Precompiled Header средой разработки Visual Studio?
- Заголовочный файл
stdafx.h
В этом файле содержатся, как правило, только директивы препроцессора, подключающие внешние заголовочные файлы.
- cpp-файл
stdafx.cpp
Состоит из единственной директивы
#include "stdafx.h"
и используется для генерации Precompiled Header. Следующая картинка демонстрирует свойства файлаstdafx.cpp
, раздел C/C++, подраздел Precompiled Headers: - Каждый cpp-файл проекта, использующий Precompiled Header, обязан включать этот заголовочный файл соответствующей директивой
#include "stdafx.h"
При этом компилятор игнорирует любой текст до момента включения
stdafx.h
! А в случае его отсутствия - выдает ошибкуfatal error C1010: unexpected end of file while looking for precompiled header. Did you forget to add '#include "stdafx.h"' to your source?
- Использование Precompiled Header установлено на уровне cpp-файлов всего проекта, как показано на картинке:
Настройка Precompiled Header вручную
Опираясь на вышенаписанное, последовательность действий простая:
- Создать файл
CommonIncludes.h
- Создать файл
CommonIncludes.cpp
и добавить туда одну строчку -#include "CommonIncludes.h"
- Поменять нужные настройки Precompiled Headers в свойствах файла
CommonIncludes.cpp
- Поменять настройки Precompiled Headers на уровне проекта или на уровне отдельных cpp-файлов
- Добавить
#include "CommonIncludes.h"
в начало соответствующих cpp-файлов исходного кода
Продвинутое использование Precompiled Header
Как правило, в stdafx.h
, созданный визардом, лепят все, что можно влепить. В результате в каждый cpp-файл включается совершенно ненужный ему контент! Поэтому, логично включать в stdafx.h
только наиболее используемые заголовочные файлы.
Директивы прекомпилятора в stdafx.h
распостраняются одинаковым образом на все cpp-файлы, включающие данный заголовочный файл. Бывает, необходимо настроить поведение библиотеки (в рамках отдельного cpp-файла или группы таких файлов) путем определения каких-то символов перед включением соответствующего заголовочного файла. Первое, что приходит на ум, - определить эти символы в cpp-файле и еще раз включить заголовочный файо библиотеки. Но, нет, я же писал, что компилятор игнорирует любой исходный код до строчки #include "stdafx.h"
! Соответственно, повторное включение заголовочных файлов будет просто проигнорировано. Получается, нужно удалять включения заголовочных файлов библиотек из stdafx.h
и добавлять их в каждый отдельный cpp-файл.
Также, проект не ограничен одним Precompiled Header! Вполне можно содзать пару файлов Subsystem1Includes.h
, Subsystem1Includes.cpp
, отвечающих за отдельный Precompiled Header в рамках некоторой группы файлов исходного кода.
Компилятор Visual C++ имеет ограничение на размер pch-файла. На практике это выглядит следующим образом:
error C3859: virtual memory range for PCH exceeded; please recompile with a command line option of '-Zm130' or greater fatal error C1076: compiler limit : internal heap limit reached; use /Zm to specify a higher limit
В таком случае спасет опция компилятора /Zm:
20 коммент.:
Спасибо большое! Очень помогло разобраться с проблемой компиляции с использованием Precompiled Headers.
Благодарю, замечательная статья. То, что надо, и кратко.
Помогли исправить ошибку и просветили. Спасибо
Огромное человеческое спасибо! Сколько времени с C++ работаю, а так с Precompiled Headers и не удосуживался разобраться. А тут все четко, коротко и понятно. Всего Вам хорошего и еще раз спасибо за статью! =)
Я буду лаконичен-спасибо
Статья хорошая, но не "предлОгает", а "предлАгает".
:)
не очень понятное объяснение для "чайника", но спасибо за попытку :)
спасибо большое - сам бы никогда не разобрался
настроил эти хедеры, раза в 3 вроде убыстрилась сборка.
а ключ /MP не пробовали?
Спасибо! Опция /Zm очень пригодилась.
Кому после этого непонятно - учите "Албанский". А автору спасибо 1 минута и в голове всё стало на свои места.
ну громаднейшие спасибо!!!!!!!!!!!!!!!!а то мучался долго!
К сожалению, не все компиляторы это поддерживают, но спасибо мелкомягким и на этом!
прочитал, сделал, радуюсь
спасибо, коротко и ясно!)
I've been surfing on-line more than three hours these days, yet I by no means discovered any attention-grabbing article like yours. It is pretty price sufficient for me. In my view, if all webmasters and bloggers made excellent content as you probably did, the internet might be much more helpful than ever before.
Review my page: free movies online
Hey would you mind stating which blog platform you're working with? I'm looking to start my
own blog in the near future but I'm having a difficult time selecting between BlogEngine/Wordpress/B2evolution and Drupal. The reason I ask is because your design seems different then most blogs and I'm looking for something
unique. P.S Apologies for being off-topic but
I had to ask!
my website: freepressreleasenow.com
Greetings! I've been following your website for a long time now and finally got the bravery to go ahead and give you a shout out from Lubbock Tx! Just wanted to say keep up the good work!
Take a look at my site; tv online
My page: tvlinks
I am curious to find out what blog platform you're working with? I'm having some small security issues with
my latest blog and I'd like to find something more secure. Do you have any solutions?
Also visit my page rideanything.com
my webpage > free tv online
Thank you for every other informative site.
The place else could I am getting that kind of info written in such a perfect way?
I've a mission that I'm just now running on, and I've been at the glance out for such info.
Feel free to visit my blog tvlinks
Для новичков про stdafx.h - http://www.viva64.com/ru/b/0265/
Отправить комментарий