Stdafx h что это
Для чего используется «stdafx.h» в Visual Studio?
Файл с именем stdafx.h генерируется автоматически, когда я запускаю проект в Visual Studio 2010. Мне нужно создать кроссплатформенную библиотеку C ++, поэтому я не могу / не могу использовать этот заголовочный файл.
Для чего stdafx.h используется? Это нормально, что я просто удалил этот заголовочный файл?
Это не уникально для Windows, но это старая проблема, с которой сталкиваются все компиляторы, которые должны компилироваться с большим API, таким как Windows.
Компилятор может значительно сэкономить время, если ему не нужно начинать компилировать каждый файл Cpp, а также десятки включений буквально с нуля каждый раз.
Хитрость заключается в назначении специального заголовочного файла в качестве отправной точки всех цепочек компиляции, так называемого файла «предварительно скомпилированного заголовка», который обычно является файлом с именем stdafx.h просто по историческим причинам.
Я не верю, что этот трюк уникален для компиляторов Microsoft, и при этом я не думаю, что это была оригинальная разработка.
В Visual Studio 2010 этот параметр управляется из графического интерфейса пользователя посредством щелчка правой кнопкой мыши по проекту CPP, выбора «Свойства» и перехода к «Свойства конфигурации \ C / C ++ \ Precompiled Headers». Для других версий Visual Studio расположение в графическом интерфейсе будет другим.
Обратите внимание: если вы отключите предварительно скомпилированные заголовки (или запустите свой проект с помощью инструмента, который их не поддерживает), это не сделает вашу программу незаконной; это просто означает, что ваш инструмент будет компилировать все с нуля каждый раз.
Если вы создаете библиотеку без зависимостей Windows, вы можете легко закомментировать или удалить файлы #include из stdafx.h файла. Нет необходимости удалять файл как таковой, но, очевидно, вы также можете сделать это, отключив параметр заголовка прекомпиляции выше.
Для новичков про stdafx.h
Статья рассчитана на людей, которые знакомятся со средой Visual Studio и пытаются компилировать в ней свои Си++-проекты. В незнакомой среде всё кажется странным и непонятным. Особенно новичков раздражает файл stdafx.h, из-за которого возникают странные ошибки во время компиляции. Очень часто всё заканчивается тем, что новичок долгое время везде старательно отключает Precompiled Headers. Чтобы помочь людям разобраться что к чему, и была написана эта статья.
Для чего нужны Precompiled Headers
Precompiled headers предназначены для ускорения сборки проектов. Обычно программисты начинают знакомиться с Visual C++, используя крошечные проекты. На них сложно заметить выигрыш от precompiled headers. Что с ними, что без них, на глаз программа компилируется одинаковое время. Это добавляет путаницы. Человек не видит для себя пользы от этого механизма и решает, что он для специфичных задач и ему никогда не понадобится. И иногда считает так многие годы.
На самом деле, precompiled headers весьма полезная технология. Пользу от него можно заметить, даже если в проекте всего несколько десятков файлов. Особенно выигрыш становится заметен, если используются такие тяжёлые библиотеки как boost.
Всё это приводит к тому, что препроцессор в компиляторе вновь и вновь выполняет идентичную работу. Он должен читать одни и те же файлы, вставлять их друг в друга, выбирать #ifdef ветки и подставлять значения макросов. Происходит колоссальное дублирование одних и тех же операций.
Можно существенно сократить объем работы, которую должен проделать препроцессор при компиляции проекта. Идея в том, чтобы заранее препроцессировать группу файлов и затем просто подставлять готовый фрагмент текста.
На самом деле, делается ещё ряд шагов. Можно хранить не просто текст, а более обработанную информацию. Я не знаю, как именно устроено в Visual C++. Но, например, можно хранить текст уже разбитый на лексемы. Это ещё больше ускорит процесс компиляции.
Как работают Precompiled Headers
Файл, который содержит precompiled headers, имеет расширение «.pch». Имя файла обычно совпадает с названием проекта. Естественно, это и другие используемые имена можно изменить в настройках. Файл может быть весьма большим и зависит от того, как много заголовочных файлов в нём раскрыто. Например, в проекте PVS-Studio он занимает около 3 мегабайт.
Файл *.pch возникает после компиляции stdafx.cpp. Файл собирается с ключом «/Yc». Этот ключ как раз и говорит компилятору, что нужно создать precompiled headers. Файл stdafx.cpp может содержать одну строчку: #include «stdafx.h».
В файле «stdafx.h» находится самое интересное. Сюда нужно включить заголовочные файлы, которые будут заранее препроцессироваться. В качестве примера, вот файл stdafx.h, используемый нами в PVS-Studio (файл сокращён для статьи):
Директивы «#pragma warning» нам нужны, чтобы избавиться от предупреждений, выдаваемых на стандартные библиотеки.
Теперь во все файлы *.c/*.cpp следует включить «stdafx.h». Заодно стоит удалить из этих файлов заголовки, которые уже включаются с помощью «stdafx.h».
А что делать, если используются хотя и похожие, но разные наборы заголовочных файлов? Например, такие:
Нужно делать отдельные precompiled headers? Так сделать можно, но не нужно.
Как использовать Precompiled Headers
При создании нового проекта Wizard в Visual Studio создаёт два файла: stdafx.h и stdafx.cpp. Именно с помощью них и реализуется механизм precompiled headers.
На самом деле, эти файлы могут называться, как угодно. Важно не название, а параметры компиляции в настройках проекта.
В *.c/*.cpp файле можно использовать только один precompiled header. Однако, в одном проекте может присутствовать несколько разных precompiled headers. Пока будем считать, что он у нас только один.
Итак, если вы воспользовались wizard-ом, то у вас уже есть файлы stdafx.h и stdafx.cpp. Плюс выставлены все необходимые ключи компиляции.
Если в проекте не использовался механизм precompiled headers, то давайте рассмотрим, как его включить. Предлагаю следующую последовательность действий:
Вот мы и включили механизм precompiled headers. Теперь, если мы запустим компиляцию, то будет создан *.pch файл. Однако, затем компиляция остановится из-за ошибок.
Для всех *.c/*.cpp файлов мы указали, что они должны использовать precompiled headers. Этого мало. Теперь в каждый из файлов нужно добавить #include «stdafx.h».
Заголовочный файл «stdafx.h» должен включаться в *.c/*.cpp файл самым первым. Обязательно! Иначе всё равно возникнут ошибки компиляции.
Если подумать, в этом есть логика. Когда файл «stdafx.h» находится в самом начале, то можно подставить уже препроцессированный текст. Этот текст всегда одинаков и ни от чего не зависит.
Представьте ситуацию, если бы мы могли включить до «stdafx.h» ещё какой-то файл. А в этом файле возьмём и напишем: #define bool char. Возникает неоднозначность. Мы меняем содержимое всех файлов, в которых упоминается «bool». Теперь просто так нельзя взять и подставить заранее препроцессированный текст. Ломается весь механизм «precompiled headers». Думаю, это одна из причин, почему «stdafx.h» должен быть расположен в начале. Возможно, есть и другие.
Life hack
Прописывать #include «stdafx.h» во все *.c/*.cpp файлы достаточно утомительно и не интересно. Дополнительно получится ревизия в системе контроля версий, где будет изменено огромное количество файлов. Нехорошо.
Ещё одно неудобство вызывают сторонние библиотеки, включаемые в проект в виде файлов с кодом. Править эти файлы нет смыла. По правильному для них нужно отключить использование «precompiled headers». Однако, если используется несколько мелких сторонних библиотек, это неудобно. Программист постоянно спотыкается об precompiled headers.
Есть вариант, как использовать precompiled headers легко и просто. Способ подойдёт не везде и всегда, но мне он часто помогал.
Можно не прописывать во все файлы #include «stdafx.h», а воспользоваться механизмом «Forced Included File».
Идём на вкладку настроек «Advanced». Выбираем все конфигурации. В поле «Forced Included File» пишем:
Теперь «stdafx.h» автоматически будет включаться в начало ВСЕХ компилируемых файлов. PROFIT!
Больше не потребуется писать #include «stdafx.h» в начале всех *.c/*.cpp файлов. Компилятор сделает это сам.
Что включать в stdafx.h
Это очень важный момент. Бездумное включение в «stdafx.h» всего подряд не только не ускорит компиляцию, но и наоборот замедлит её.
Все файлы, включающие «stdafx.h», зависят от его содержимого. Пусть в «stdafx.h» включен файл «X.h». Если вы поменяете хоть что-то в «X.h», это может повлечь полную перекомпиляцию всего проекта.
Правило. Включайте в «stdafx.h» только те файлы, которые никогда не изменяются или меняются ОЧЕНЬ редко. Хорошими кандидатами являются заголовочные файлы системных и сторонних библиотек.
Если включаете в «stdafx.h» собственные файлы из проекта, соблюдайте двойную бдительность. Включайте только те файлы, которые меняются очень- очень редко.
Если какой-то *.h файл меняется раз в месяц, это уже слишком часто. Как правило, редко удаётся сделать все правки в h-файле с первого раза. Обычно требуется 2-3 итерации. Согласитесь, 2-3 раза полностью перекомпилировать весь проект — занятие неприятное. Плюс полная перекомпиляция потребуется всем вашим коллегам.
Несколько Precompiled Headers
Зачем в одном проекте может понадобиться несколько precompiled headers? Действительно, это нужно не часто. Но приведу пару примеров.
В проекте используются одновременно *.c и *.cpp файлы. Для них нельзя использовать единый *.pch файл. Компилятор выдаст ошибку.
Нужно создать два *.pch файла. Один должен получаться при компилировании C-файла (xx.c), а другой при компилировании C++-файла (yy.cpp). Соответственно, в настройках надо указать, чтобы в С-файлах использовался один precompiled header, а в С++-файлах — другой.
Примечание. Не забудьте указать разные имена для *.pch файлов. Иначе один файл будет перетирать другой.
Другая ситуация. Одна часть проекта использует одну большую библиотеку, а другая часть другую большую библиотеку.
Естественно, не стоит всем участкам кода знать про обе библиотеки. В (неудачных) библиотеках могут пересекаться имена каких-то сущностей.
Логично сделать два precompiled headers и использовать их в разных участках программы. Как уже отмечалось, можно задать произвольные имена файлов, из которых генерируются *.pch файлы. Да и имя *.pch файла тоже можно изменить. Всё это, конечно, требуется делать аккуратно, но ничего сложного в использовании двух precompiled headers нет.
Типовые ошибки при использовании Precompiled Headers
Прочитав внимательно материал выше, вы сможете понять и устранить ошибки, связанные с stdafx.h. Но давайте ещё раз пройдёмся по типовым ошибкам компиляции и разберём их причины. Повторенье — мать ученья.
Fatal error C1083: Cannot open precompiled header file: ‘Debugproject.pch’: No such file or directory
Вы пытаетесь скомпилировать файл, который использует precompiled header. Но соответствующий *.pch файл отсутствует. Возможные причины:
Fatal error C1010: unexpected end of file while looking for precompiled header. Did you forget to add ‘#include «stdafx.h»’ to your source?
Сообщение говорит само за себя, если его прочитать. Файл компилируется с ключом /Yu. Это значит, что следует использовать precompiled header. Но в файл не включён «stdafx.h».
Нужно вписать в файл #include «stdafx.h».
Если это невозможно, то следует не использовать precompiled header для этого *.c/*.cpp файла. Уберите ключ /Yu.
Fatal error C1853: ‘project.pch’ precompiled header file is from a previous version of the compiler, or the precompiled header is C++ and you are using it from C (or vice versa)
В проекте присутствуют как C (*.c), так и C++ (*.cpp) файлы. Для них нельзя использовать единый precompiled header (*.pch файл).
Из-за precompiled header компилятор глючит
Скорее всего, что-то сделано не так. Например, #include «stdafx.h» расположен не в самом начале.
Этот код не скомпилируется. Компилятор выдаст на первый взгляд странное сообщение об ошибке:
Компилятор считает, что все, что указано до строчки #include «stdafx.h» (включительно), является precompiled header. При компиляции файла компилятор заменит все, что до #include «stdafx.h» на текст из *.pch файла. В результате теряется строчка «int A = 10».
Содержимое файла «my.h» не будет использоваться. В результате, нельзя будет использовать функции, объявленные в этом файле. Такое поведение очень сбивает программистов с толку. Они «лечат» его полным отключением precompiled headers и потом рассказывают байки о глючности Visual C++. Запомните, компилятор — это один из наиболее редко глючащих инструментов. В 99.99% случаев надо не злиться на компилятор, а искать ошибку у себя (Proof).
Чтобы таких ситуаций не было, ВСЕГДА пишите #include «stdafx.h» в самом начале файла. Комментарии перед #include «stdafx.h» можно оставить. Они всё равно никак не участвуют в компиляции.
Ещё один вариант — используйте Forced Included File. См. выше раздел «Life hack».
Из-за precompiled headers проект постоянно перекомпилируется целиком
В stdafx.h включён файл, который регулярно редактируется. Или случайно включён автогенерируемый файл.
Внимательно проверьте содержимое файла «stdafx.h». В него должны входить только заголовочные файлы, которые не изменяются или изменяются крайне редко. Учтите, что включённые файлы могут не меняться, но внутри они ссылаются на другие изменяющиеся *.h файлы.
Творится что-то непонятное
Иногда может возникнуть ситуация, что вы поправили код, а ошибка не исчезает. Отладчик показывает непонятные вещи.
Причиной может быть *.pch файл. Как-то так получилось, что компилятор не замечает изменения в одном из заголовочных файлов и не перестраивает *.pch файл. В результате, подставляется старый код. Возможно, это происходило из-за каких-то сбоев, связанных с временем модификации файлов.
Это ОЧЕНЬ редкая ситуация. Но она возможна и про неё надо знать. Я за многие годы программирования сталкивался с ней только 2-3 раза. Помогает полная перекомпиляция проекта.
Проект, использующий precompiled headers не удаётся проверить с помощью PVS-Studio или CppCat
Это наиболее частая ситуация, с которой к нам обращаются в поддержку. Подробности изложены в документации: «Устранение неисправностей при работе PVS-Studio». Здесь опишу ситуацию кратко.
Если решение (solution) компилируется, это вовсе не значит, что оно правильно устроено. Часто одно решение (solution) содержит множество проектов. В каждом проекте используются свои precompiled headers (имеется свой stdafx.h и stdafx.cpp).
Возникают проблемы, когда начинают использовать файлы из соседнего проекта. Это удобно и так часто делается. Вот только забывают, что в *.cpp файле написано: #include «stdafx.h».
И, какой из stdafx.h подхватится, это интересный вопрос. Но раз программа компилируется — программисту везёт.
К сожалению, нам сложно повторить поведение, которое возникает при использовании *.pch файла. «Честный» препроцессор работает по-другому.
В том, что solution, на самом деле, устроен не верно, можно убедиться, временно отключив precompiled headers. Сразу может вылезти масса интересных ошибок, и программист будет искренне удивляться, каким же чудом компилировался его проект.
За подробностями вновь делаю отсылку к документации. Плюс, если что-то всё равно не ясно, мы подскажем в поддержке.
Заключение
Как вы увидели, ничего сложного в precompiled headers нет. Все «многочисленные глюки компилятора», с которыми сталкивается программист при их использовании, на самом деле, являются непониманием принципов работы. Надеюсь, эта статья поможет устранить непонимание.
Precompiled headers являются очень полезным механизмом, позволяющим существенно увеличить скорость компиляции проектов.
include stdafx h что это
Primary tabs
Forums:
При создании нового проекта (C++, далее любой из подпроектов, типа Console App, MFC App, или ATL Service) Visual Studio генерит кучку файлов, которые составляют костяк приложения.
Кстати — при создании приложения типа Conlsole Application в Visual Studio 2010 stdafx.h содержит следующие строки =
Среди этих файлов имеются два, которые служат для генерации файла предкомпилированных заголовков (precompiled headers). Первый — stdafx.h, в нем хранятся все «основные» include-ы проекта, но, как правило, не входящие в сам проект, т.е. файлы типа=
В свойствах проекта для всех файлов ставиться опция «use this precompiled header» и указывается stdafx.h
Исключение — stfafx.cpp, для него указывается «create precompiled header file» и, опять таки, указывается stdafx.h
Q: Для чего это сделано.
Q: Почему возникает ошибка «error looking precompiled header directive».
A: В каждом source-файле, для которого стоит опция «use this precompiled header» #include «stdafx.h» должно идти первым include
Q: Как избавится от генерации PCH-файлов
A: В свойствах проекта для файлов выставить «Not Using Precompiled Headers» или «Automatically Generate»
Q: Где находятся эти опции
Q: Я настроил компиляцию DEBUG-версии на отказ использования PCH, но при компиляции RELEASE ошибка опять возникла.
A: Project setting для DEBUG/RELEASE представляю разные сущности. См. пред. пункт Q/A и настрой все для RELEASE-конфигурации.
Почему первый вариант записи в Microsoft Visual Studio компилирует:
а второй (более простой) нет:
Компилятор выдает ошибку
1>c:usersadmindocumentsvisual studio 2013projectsconsoleapplication1consoleapplication1consoleapplication1.cpp(4): warning C4627: ‘#include ‘: skipped when looking for precompiled header use
В чем отличие и с чем это связано?
2 ответа 2
Лазер. h — это у вас надо спросить, что это за файл. Какой-то пользовательский включаемый файл, смотрите у себя в проекте, что в нем находится.
#define MAX_LOADSTRING 100 — это никакая не библиотека, а макрос. Означает, что в любом месте программы, где используется строчка «MAX_LOADSTRING», эта мнемоника будет заменена на 100.
Файлы предварительно скомпилированных заголовков
Параметры компилятора для предкомпилированных заголовков — /Y. На страницах свойств проекта параметры находятся в разделе Свойства конфигурации > Предкомпилированные заголовки C/C++. Можно не использовать предкомпилированные заголовки, а также указать имя файла заголовка и путь к выходному файлу.
Настраиваемый предварительно скомпилированный код
Для больших проектов, для которых требуется значительное время, может потребоваться создать настраиваемые предварительно скомпилированные файлы. Компиляторы Microsoft C и C++ содержат параметры для предварительной компиляции любого кода C или C++, включая встроенный код. Данная возможность позволяет скомпилировать стабильное тело кода, сохранять скомпилированное состояние кода в файле, а при последующих компиляциях объединять предварительно скомпилированный код с кодом, который еще находится в стадии разработки. Каждая последующая компиляция выполняется быстрее, так как стабильный код не нужно компилировать повторно.
Случаи использования предварительной компиляции исходного кода
Предварительно скомпилированный код полезен во время цикла разработки, чтобы сократить время компиляции, особенно если:
Всегда используется большой текст кода, в который редко вносятся изменения.
Программа состоит из нескольких модулей, каждый из которых использует стандартный набор включаемых файлов, а также одни и те же параметры компиляции. В этом случае все включаемые файлы можно предварительно скомпилировать в один предкомпилированный заголовок.
Первая компиляция, которая создает файл предкомпилированного заголовка (PCH), занимает немного больше времени, чем последующие компиляции. Последующие компиляции могут выполняться быстрее, включая предварительно скомпилированный код.
Можно предварительно скомпилировать программы C и C++. В программировании на языке C++ распространенной практикой является отделение сведений об интерфейсе класса в файлы заголовков. Впоследствии эти файлы заголовков можно будет включать в программы, использующие класс. Предварительная компиляция этих заголовков позволяет сократить время, затрачиваемое программой на компиляцию.
Хотя для каждого исходного файла можно использовать только один файл предкомпилированного заголовка (PCH), в проекте можно использовать несколько файлов PCH.
Два варианта предварительной компиляции кода
Можно предварительно скомпилировать любой код C или C++ — вы не ограничены предварительной компиляцией только файлов заголовков.
Для предварительной компиляции требуется планирование, но при предварительной компиляции исходного кода, отличного от простых файлов заголовков, обеспечивается значительно более быстрая компиляция.
Предварительная компиляция кода рекомендуется, когда известно, что исходные файлы используют общие наборы файлов заголовков, но не содержат их в том же порядке, или если требуется включить исходный код в предварительную компиляцию.
Параметры предкомпилированного заголовка см. в разделах /Yc (создание файла предкомпилированного заголовка) и /Yu (использование файла предкомпилированного заголовка). Для создания предкомпилированного заголовка используйте /Yc. При использовании с необязательной прагмой hdrstop параметр /Yc позволяет предварительно компилировать как файлы заголовков, так и исходный код. Выберите /Yu, чтобы использовать существующий предкомпилированный заголовок в существующей компиляции. Можно также использовать /Fp с параметрами /Yc и /Yu, чтобы предоставить альтернативное имя предкомпилированному заголовку.
В справочных разделах, посвященных параметрам компилятора /Yu и /Yc, обсуждаются способы доступа к этой функции в среде разработки.
Правила согласованности предкомпилированных заголовков
Поскольку файлы PCH содержат сведения о среде компьютера, а также сведения об адресах памяти для программы, файл PCH следует использовать только на том компьютере, на котором он был создан.
Правила целостности для пофайлового использования предкомпилированных заголовков
Параметр компилятора /Yu позволяет указать, какой файл PCH следует использовать.
При использовании файла PCH компилятор предполагает ту же среду компиляции, которая использует последовательные параметры компилятора, прагмы и т. д., которые действуют при создании файла PCH, если не указано иное. Если компилятор обнаруживает несогласованность, он выдает предупреждение и по возможности определяет несогласованность. Такие предупреждения не обязательно указывают на проблему с файлом PCH. Они просто предупреждают о возможных конфликтах. Требования к согласованности для файлов PCH описаны в следующих разделах.
Согласованность параметров компилятора
Следующие параметры компилятора могут вызвать предупреждение о несогласованности при использовании файла PCH:
Макросы, созданные с помощью параметра препроцессора (/D), должны быть одинаковыми в компиляциях, создавшими файл PCH, и текущей компиляцией. Состояние определенных констант не проверяется, но при их изменениях могут возникать непредсказуемые результаты.
Файлы PCH не работают с параметрами/E и /EP.
Файлы PCH должны быть созданы с помощью параметра создания сведений о просмотре (/FR) или исключения локальных переменных (/Fr), прежде чем последующие компиляции, использующие файл PCH, смогут использовать эти параметры.
C7 совместимо (/Z7)
Если при создании файла PCH этот параметр включен, последующие компиляции, использующие файл PCH, могут использовать отладочную информацию.
Если при создании файла PCH параметр «C7 совместимо (/Z7)» отключен, последующие компиляции, использующие файл PCH и/Z7, вызывают предупреждение. Отладочная информация помещается в текущий OBJ-файл, а локальные символы, определенные в файле PCH, недоступны отладчику.
Согласованность пути включаемых файлов
В файле PCH не содержатся сведения о пути включаемых файлов, который применялся при создании. При использовании файла PCH компилятор всегда использует путь включаемых файлов, указанный в текущей компиляции.
Согласованность исходного файла
При указании параметра использования файла предкомпилированного заголовка (/Yu) компилятор игнорирует все директивы препроцессора (включая прагмы), отображаемые в исходном коде, который будет предварительно скомпилирован. Компиляция, указанная такими директивами препроцессора, должна совпадать с компиляцией, используемой для параметра создания файла предкомпилированного заголовка (/Yc).
Согласованность прагмы
Прагмы, обработанные во время создания файла PCH, обычно влияют на файл, с которым впоследствии используется файл PCH. Прагмы comment и message не влияют на оставшуюся часть компиляции.
Они влияют только на код в файле PCH; они не влияют на код, который впоследствии использует файл PCH:
Эти прагмы сохраняются как часть предкомпилированного заголовка и влияют на оставшуюся часть компиляции, использующую предкомпилированный заголовок:
alloc_text
auto_inline
check_stack
code_seg
data_seg
function
include_alias
init_seg
inline_depth
inline_recursion
intrinsic
optimize
pack
pointers_to_members
setlocale
vtordisp
warning
Правила целостности для параметров компилятора /Yc и /Yu
При использовании предкомпилированного заголовка, созданного с помощью параметра /Yc или/Yu, компилятор сравнивает текущую среду компиляции с той, которая существовала при создании файла PCH. Не забудьте указать среду, соответствующую предыдущей (с помощью параметров компилятора, прагм и т. д.) для текущей компиляции. Если компилятор обнаруживает несогласованность, он выдает предупреждение и по возможности определяет несогласованность. Такие предупреждения не обязательно указывают на проблему с файлом PCH. Они просто предупреждают о возможных конфликтах. В следующих разделах объясняются требования к согласованности для предкомпилированных заголовков.
Согласованность параметров компилятора
В таблице ниже перечислены параметры компилятора, которые могут вызвать предупреждение о несогласованности при использовании предкомпилированного заголовка.
Параметр | name | Правило |
---|---|---|
/D | Определение констант и макросов | Должны быть одинаковыми в компиляции, создавшей предкомпилированный заголовок, и в текущей компиляции. Состояние определенных констант не проверяется, но если файлы зависят от значений измененных констант, могут возникать непредсказуемые результаты. |
/E или /EP | Копирование выходных данных препроцессора в стандартный вывод | Предкомпилированные заголовки не работают с параметром /E или /EP. |
/FR или /FR | Создание сведений о браузере исходного кода Майкрософт | Чтобы параметры /Fr и /FR были допустимыми вместе с параметром /Yu, они также должны применяться при создании предкомпилированного заголовка. При последующих компиляциях, использующих предкомпилированный заголовок, также создаются сведения о браузере исходного кода. Сведения о браузере помещаются в один SBR-файл, и на него ссылаются другие файлы так же, как и сведения CodeView. Нельзя переопределить размещение сведений о браузере исходного кода. |
/GA, /GD, /GE, /Gw или /GW | Параметры протокола Windows | Должны быть одинаковыми в компиляции, создавшей предкомпилированный заголовок, и в текущей компиляции. Если эти параметры различаются, выдается предупреждение. |
/ZI | Создание полной отладочной информации | Если при создании предкомпилированного заголовка этот параметр включен, последующие компиляции, использующие предварительную компиляцию, могут использовать отладочную информацию. Если при создании предкомпилированного заголовка параметр /Zi не был включен, последующие компиляции, использующие предварительную компиляцию и параметр /Zi, выдают предупреждение. Отладочная информация помещается в текущий OBJ-файл, а локальные символы, определенные в предкомпилированном заголовке, недоступны отладчику. |
Средство предварительно откомпилированных заголовков предназначено для использования только в исходных файлах C и C++.
Использование предкомпилированных заголовков в проекте
В предыдущих разделах представлен обзор предкомпилированных заголовков: /Yc и /Yu, параметра /FP и прагмы hdrstop. В этом разделе описывается метод использования в проекте параметров заголовков, предкомпилированных вручную. В конце раздела приводится пример файла makefile и кода, который управляет им.
Чтобы ознакомиться с другим подходом к использованию в проекте параметров заголовков, предкомпилированных вручную, изучите один из файлов makefile, расположенных в каталоге MFC\SRC, который создается во время установки Visual Studio по умолчанию. Подход в этих файлах makefile аналогичен представленному в этом разделе, однако в них используются макросы служебной программы обслуживания Майкрософт (NMAKE) и обеспечивается больший контроль над процессом сборки.
PCH-файлы в процессе построения
База кода проекта программного обеспечения обычно содержится в нескольких исходных файлах C или C++, объектных файлах, библиотеках и файлах заголовков. Как правило, файл makefile координирует объединение этих элементов в исполняемый файл. На следующем рисунке показана структура файла makefile, использующего файл предкомпилированного заголовка. Имена макросов и имена файлов на рисунке соответствуют приведенным в примере кода в разделах Пример файла makefile для PCH и Пример кода для PCH.
На рисунке для отображения последовательности процесса сборки используются три схематических элемента. Прямоугольники представляют каждый файл или макрос; три макроса представляют один или несколько файлов. Затененные области представляют каждое действие компиляции или компоновки. Стрелки показывают, какие файлы и макросы объединяются во время процесса компиляции или компоновки.
Структура файла makefile, использующего файл предкомпилированного заголовка
Начиная с верхней части диаграммы, STABLEHDRS и BOUNDRY являются макросами NMAKE, в которых вы перечислите файлы, которые, скорее всего, не потребуют перекомпиляции. Эти файлы компилируются с помощью командной строки
CL /c /W3 /Yc$(BOUNDRY) applib.cpp myapp.cpp
только если файл предкомпилированного заголовка (STABLE.pch) не существует или если вы вносите изменения в файлы, перечисленные в двух макросах. В любом случае файл предкомпилированного заголовка будет содержать код только из файлов, перечисленных в макросе STABLEHDRS. Перечислите последний файл, который необходимо предварительно откомпилировать в макросе BOUNDRY.
Файлы, перечисленные в этих макросах, могут быть файлами заголовков или файлами исходного кода C или C++. (Один PCH-файл нельзя использовать одновременно с модулями C и C++.) Обратите внимание, что можно использовать макрос hdrstop для отмены предварительной компиляции в какой бы то ни было момент в файле. Дополнительные сведения см. в разделе hdrstop.
Далее APPLIB.obj на схеме представляет код поддержки, используемый в окончательном приложении. Он создается из APPLIB.cpp, файлов, перечисленных в макросе UNSTABLEHDRS, и предварительно скомпилированного кода из предкомпилированного заголовка.
MYAPP.obj представляет конечное приложение. Он создается из файла MYAPP.cpp, файлов, перечисленных в макросе UNSTABLEHDRS, и предварительно скомпилированного кода из предкомпилированного заголовка.
Наконец, создается исполняемый файл (MYAPP.EXE) путем связывания файлов, перечисленных в макросе OBJS (APPLIB.obj и MYAPP.obj).
Образец файла makefile для PCH
Помимо макросов STABLEHDRS, BOUNDRY и UNSTABLEHDRS, показанных на рисунке «Структура файла makefile, использующего файл предкомпилированного заголовка» в разделе PCH-файлы в процессе сборки, этот файл makefile предоставляет макрос CLFLAGS и макрос LINKFLAGS. Эти макросы необходимо использовать для перечисления параметров компилятора и компоновщика, которые применяются при сборке отладочной или финальной версии исполняемого файла приложения. Также имеется макрос LIBS, в котором перечислены библиотеки, необходимые для проекта.
Эта функция позволяет использовать один и тот же файл makefile во время разработки и для финальных версий программы — используйте DEBUG=0 для финальных версий. Следующие строки команды являются эквивалентными.
Дополнительные сведения о файлах makefile см. в разделе Справочник по NMAKE. См. также разделы Параметры компилятора MSVC и Параметры компоновщика MSVC.
Пример кода для PCH
Следующие исходные файлы используются в файле makefile, который описан в разделах PCH-файлы в процессе сборки и Образец файла makefile для PCH. Обратите внимание, что комментарии содержат важную информацию.