У меня есть куча устаревшего кода, для которого мне нужно писать модульные тесты. Он везде использует предварительно скомпилированные заголовки, поэтому почти все файлы .cpp зависят от stdafx.h, что затрудняет разрушение зависимостей для написания тестов.
Моим первым побуждением было удалить все эти файлы stdafx.h, которые по большей части содержат директивы #include, и поместить эти #includes непосредственно в исходные файлы по мере необходимости.
Это потребовало бы отключения предварительно скомпилированных заголовков, поскольку они зависят от наличия файла, такого как stdafx.h, для определения места остановки предварительно скомпилированных заголовков.
Есть ли способ сохранить предварительно скомпилированные заголовки без зависимостей stdafx.h? Есть ли лучший способ подойти к этой проблеме?
ПОЖАЛУЙСТА, ГОЛОСОВАТЬ ЗА ЭТО: visualstudio.uservoice.com/forums/121579-visual-studio/…
Да, есть способ получше. Для каждого исходного файла может использоваться только один предварительно скомпилированный заголовок, но pch может быть указан для исходного файла каждый или набора исходных файлов. Вы также можете указать, какие исходные файлы используют или не используют предварительно скомпилированный заголовок. Смотрите мой ответ ниже.





Нет, вероятно, есть способ получше НЕТ.
Однако для данного отдельного файла .cpp вы можете решить, что вам не нужен предварительно скомпилированный заголовок. Вы можете изменить настройки для этого файла .cpp и удалить строку stdafx.h.
(На самом деле, я не понимаю, как предварительно скомпилированная схема заголовка мешает написанию ваших модульных тестов).
Да, есть способ получше. Смотрите мой ответ ниже. Ответ @Len Holgate также работает.
Нет. Предварительно скомпилированные заголовки полагаются на один заголовок, включенный всеми источниками, скомпилированными таким образом. вы можете указать для одного источника (или всех) вообще не использовать предварительно скомпилированные заголовки, но это не то, что вам нужно.
В прошлом компилятор Borland C++ выполнял предварительную компиляцию без определенного заголовка. однако, если два исходных файла включали одни и те же заголовки, но с разными приказ, они были скомпилированы отдельно, поскольку, действительно, порядок файлов заголовков в C++ может иметь значение ...
Таким образом, это означает, что предварительно скомпилированные заголовки Borland сэкономили время только в том случае, если вы очень жестко включали исходные коды в одном и том же порядке или если бы один включаемый файл был включен (первым) всеми другими файлами ... - звучит знакомо?!?!
Не правда; вы можете указать другой предварительно скомпилированный заголовок для каждого отдельного исходного файла или указать, что некоторые исходные файлы используют один, а другие нет.
Мой совет - не удаляйте предварительно скомпилированные заголовки, если вы не хотите, чтобы ваши сборки были мучительно медленными. В основном у вас есть три варианта:
Я использую только предварительно скомпилированные заголовки для кода, который должен включать материал afx___ - обычно это просто пользовательский интерфейс, который я не тестирую. Код пользовательского интерфейса обрабатывает пользовательский интерфейс и вызывает функции, у которых есть модульные тесты (хотя в большинстве случаев их нет из-за устаревшего приложения).
Для большей части кода я не использую предварительно скомпилированные заголовки.
ГРАММ.
Когда вы обычно используете предварительно скомпилированные заголовки, "stdafx.h" служит двум целям. Он определяет набор стабильных распространенных включаемых файлов. Также в каждом файле .cpp он служит маркером того, где заканчиваются предварительно скомпилированные заголовки.
Похоже, что вы хотите сделать:
Итак, теперь у вас есть минимальный набор зависимостей, и вы по-прежнему используете предварительно скомпилированные заголовки. Потеря заключается в том, что вы не прекомпилируете общий набор заголовков только один раз. Это было бы большим успехом для полной перестройки. Для режима разработки, когда вы перекомпилируете только несколько файлов за раз, это не принесет успеха.
Спасибо. Я выбрал вариант этого подхода. stdafx.h может содержать только #includes внешних библиотек (заголовки Windows, STL, boost и т. д.). Все внутренние заголовки приложений должны быть включены непосредственно в файлы .cpp.
да. Имя "stdafx.h / stdafx.pch" просто условное. Вы можете дать каждому .cpp собственный предварительно скомпилированный заголовок. Этого, вероятно, проще всего добиться с помощью небольшого скрипта для редактирования XML в вашем .vcproj. Обратная сторона: вы получаете большой стек предварительно скомпилированных заголовков, и они не разделяются между TU.
Можно, но умно? Точно не могу сказать.
Предварительно скомпилированные заголовки основаны на идее, что все будет включать один и тот же набор материалов. Если вы хотите использовать предварительно скомпилированные заголовки, вам придется жить с зависимостями, которые это подразумевает. Все сводится к компромиссу между зависимостями и скоростью сборки. Если вы можете построить в разумные сроки с отключенными предварительно скомпилированными заголовками, то обязательно сделайте это.
Еще одна вещь, которую следует учитывать, - это то, что у вас может быть один компьютер для каждой библиотеки. Таким образом, вы можете разделить свой код на более мелкие библиотеки, и каждая из них будет иметь более жесткий набор зависимостей.
Да, есть способ получше.
Проблема, IMHO, с «стилем мастера» предварительно скомпилированных заголовков заключается в том, что они поощряют ненужное связывание и усложняют повторное использование кода, чем должно быть. Кроме того, код, который был написан в стиле «просто вставьте все в stdafx.h», может быть проблематичным в обслуживании, поскольку изменение чего-либо в любом файле заголовка, вероятно, приведет к перекомпиляции всей кодовой базы каждый раз. Из-за этого простой рефакторинг может длиться вечно, поскольку каждое изменение и цикл перекомпиляции занимают намного больше времени, чем следовало бы.
И снова ИМХО, лучший способ - использовать #pragma hdrstop, / Yc и / Yu. Это позволяет легко настраивать конфигурации сборки, в которых используются предварительно скомпилированные заголовки, а также конфигурации сборки, которые не используют предварительно скомпилированные заголовки. Файлы, использующие предварительно скомпилированные заголовки, не имеют прямой зависимости от самого предварительно скомпилированного заголовка в исходном файле, что позволяет создавать их с предварительно скомпилированным заголовком или без него. Файл проекта определяет, какой исходный файл создает предварительно скомпилированный заголовок, а строка #pragma hdrstop в каждом исходном файле определяет, какие включения берутся из предварительно скомпилированного заголовка (если используется), а какие - непосредственно из исходного файла ... Это означает, что когда при обслуживании вы должны использовать конфигурацию, в которой не используются предварительно скомпилированные заголовки, и будет перестроен только код, который вам нужно перестроить после изменения файла заголовка. При выполнении полных сборок вы можете использовать предварительно скомпилированные конфигурации заголовков, чтобы ускорить процесс компиляции. Еще одна хорошая вещь в использовании параметра сборки без предварительно скомпилированного заголовка заключается в том, что он гарантирует, что ваши файлы cpp включают только то, что им нужно, и включают все, что им нужно (что сложно, если вы используете `` стиль мастера '' предварительно скомпилированного заголовка.
Я немного писал о том, как это работает здесь: http://www.lenholgate.com/blog/2004/07/fi-stlport-precompiled-headers-warning-level-4-and-pragma-hdrstop.html (не обращайте внимания на информацию о / FI), и у меня есть несколько примеров проектов, которые создаются с помощью метода #pragma hdrstop и / Yc / Yu здесь: http://www.lenholgate.com/blog/2008/04/practical-testing-16---fixing-a-timeout-bug.html.
Конечно, переход от использования предварительно скомпилированного заголовка в стиле мастера к более контролируемому стилю часто бывает нетривиальным ...
Смотрите: stackoverflow.com/questions/7282853/… - спасибо.
Предварительно скомпилированные заголовки могут сэкономить много времени при пересборке проекта, но если предварительно скомпилированный заголовок изменяется, исходный файл каждый в зависимости от заголовка будет перекомпилирован, независимо от того, повлияет ли это изменение на это или нет. К счастью, предварительно скомпилированные заголовки используются для компилировать, а не для связь; каждый исходный файл не обязательно должен использовать предварительно скомпилированный заголовок такой же.
pch1.h:
#include <bigHeader1.h>
#include ...
pch1.cpp:
#include "pch1.h"
source1.cpp:
#include "pch1.h"
[code]
pch2.h:
#include <bigHeader2.h>
#include ...
pch2.cpp:
#include "pch2.h"
source2.cpp
#include "pch2.h"
[code]
Выберите pch1.cpp, щелкните правой кнопкой мыши, Свойства, Свойства конфигурации, C / C++, Предварительно скомпилированные заголовки.
Предварительно скомпилированный заголовок: Создать (/ Yc)
Предварительно скомпилированный заголовочный файл: пч1.h
Предварительно скомпилированный выходной файл заголовка: $ (intDir) pch1.pch
Выберите source1.cpp
Предварительно скомпилированный заголовок: Использование (/ Yu)
Предварительно скомпилированный заголовочный файл: пч1.h
Предварительно скомпилированный выходной файл заголовка: $ (intDir) pch1.pch (я не думаю, что это важно для / Yu)
Сделайте то же самое для pch2.cpp и source2.cpp, за исключением того, что установите Заголовочный файл и Выходной файл заголовка на pch2.h и pch2.pch. Это подходит для меня.
Лично я использую предварительно скомпилированные заголовки (как для обычного кода, так и для модульных тестов), но использую имя Precompiled.h / cpp. Предварительно скомпилированные заголовки для модульных тестов включают дополнительные заголовки, что ускоряет компиляцию.