есть большой проект, не использующий precompiled headers. и в cpp и в h файлах включаются другие h. какова глубина вложенностей можно только догадываться. Есть ли утилита способная собрать включение всех h файлов в stdafx перед коммитом и для continuous билдов а потом на машине разработчика разобрать stdafx? (чтобы при изменении в единственном h файле не перекомпилировать все исходники)
?
Здравствуйте, SVV, Вы писали:
SVV>Всем привет,
SVV>есть большой проект, не использующий precompiled headers. и в cpp и в h файлах включаются другие h. какова глубина вложенностей можно только догадываться. Есть ли утилита способная собрать включение всех h файлов в stdafx перед коммитом и для continuous билдов а потом на машине разработчика разобрать stdafx? (чтобы при изменении в единственном h файле не перекомпилировать все исходники) SVV>?
Здравствуйте, SVV, Вы писали:
SVV>есть большой проект, не использующий precompiled headers. и в cpp и в h файлах включаются другие h. какова глубина вложенностей можно только догадываться. Есть ли утилита способная собрать включение всех h файлов в stdafx перед коммитом и для continuous билдов а потом на машине разработчика разобрать stdafx? (чтобы при изменении в единственном h файле не перекомпилировать все исходники) SVV>?
В билдере что-то похожее было, анализировал проект и собирал все хидеры.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Здравствуйте, SVV, Вы писали:
SVV>есть большой проект, не использующий precompiled headers. и в cpp и в h файлах включаются другие h. какова глубина вложенностей можно только догадываться. Есть ли утилита способная собрать включение всех h файлов в stdafx перед коммитом и для continuous билдов а потом на машине разработчика разобрать stdafx? (чтобы при изменении в единственном h файле не перекомпилировать все исходники)
Если в проекте нет препроцессорной магии, то можно было бы банально грепнуть все хедеры, непосредственно включённые в .cpp
Как-то так
Здравствуйте, SVV, Вы писали:
SVV>Всем привет,
SVV>есть большой проект, не использующий precompiled headers. и в cpp и в h файлах включаются другие h. какова глубина вложенностей можно только догадываться. Есть ли утилита способная собрать включение всех h файлов в stdafx перед коммитом и для continuous билдов а потом на машине разработчика разобрать stdafx? (чтобы при изменении в единственном h файле не перекомпилировать все исходники) SVV>?
Чем больше хедеров, тем больше pch файл, тем медленнее билд, соответственно, включение всяких редко используемых хедеров в stdafx нежелательно. Не знаю как у VC++, но у g++ есть флажок, который позволяет выводить иерархию включения заголовочных файлов. Используя эти данные можно выбрать N самых часто включаемых файлов и добавить их в stdafx. Я в свое время так делал, даже скрипт написал, но сейчас его уже не найти.
Здравствуйте, Ops, Вы писали:
Ops>В билдере что-то похожее было, анализировал проект и собирал все хидеры.
Не понятно почему микрософт этого не делает. Впрочем я давно заметил что микрософт может очень хорошо сделать какую-то "базу" программы, но из рук вон плохо относится к дополнительным фичам.
Например был сделан WebBrowser для использования другими, но сам IE 4,5,6 версии ни в какое сравнение не шел с Netscape Navigator к примеру.
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, SVV, Вы писали:
SVV>>есть большой проект, не использующий precompiled headers. и в cpp и в h файлах включаются другие h. какова глубина вложенностей можно только догадываться. Есть ли утилита способная собрать включение всех h файлов в stdafx перед коммитом и для continuous билдов а потом на машине разработчика разобрать stdafx? (чтобы при изменении в единственном h файле не перекомпилировать все исходники)
К>Если в проекте нет препроцессорной магии, то можно было бы банально грепнуть все хедеры, непосредственно включённые в .cpp К>Как-то так К>
К>А сам этот allheaders.h включить в stdafx.h куда-нибудь в конец.
К>Причём у разработчика allheaders.h пустой, а на билд-сервере — собирается грепом, в custom build step или в отдельном проекте-зависимости.
регулярные выражения это то что мне надо будет осилить, но сейчас это для меня марсианский язык.
думаю что если утилиты нет, то придется ее делать. т.к. на сервере заниматься переносом includes в stdafx не быстро. это лучше делать разработчику перед комитом. те же тестировщики получая исходники даже не станут разбирать этот stdafx.
Вообще, исходники хранятся вместе с cmakelists.txt, так что на сервере можно использовать не только микрософтовский компилятор. Что можете посоветовать более умное чем микрософт? чтобы компилятор сам решал проблему множественного включения headers.
On 09.03.2014 20:56, SVV wrote:
> есть большой проект, не использующий precompiled headers. и в cpp и в h > файлах включаются другие h. какова глубина вложенностей можно только > догадываться. Есть ли утилита способная собрать включение всех h файлов > в stdafx перед коммитом и для continuous билдов а потом на машине > разработчика разобрать stdafx? (чтобы при изменении в единственном h > файле не перекомпилировать все исходники)
Чёта я не понял, потом почитал топик, и тоже не понял.
Теперь вот спрашиваю: Зачем такое нужно ?
В stdafx.h должны быть включены все заголовки сторонних библиотек,
которые не меняются никогда. Возможно также, туда можно включить
заголовки собственных библиотек, которые очень редко меняются.
В любом случае, набор этих библиотек должен быть строго фиксирован,
и из заголовков то же. Добавляется новая библиотека к использованию --
руками можно добавить файлы.
Зачем парсить исходники на предмет выполнения транзитивного замыкания
включения ?
On 12.03.2014 10:21, SVV wrote:
> можно использовать не только микрософтовский компилятор. Что можете > посоветовать более умное чем микрософт? чтобы компилятор сам решал > проблему множественного включения headers.
Здравствуйте, SVV, Вы писали:
SVV>регулярные выражения это то что мне надо будет осилить, но сейчас это для меня марсианский язык.
Оно там простое: пробежаться по всем файлам, (*.cpp)
в каждом из них найти строки #include ....., не содержащие собственно stdafx.h и allheaders.h,
свалить всё найденное в общую кучу (>allheaders.h)
Можно и проще: найти вообще все #include, записать в allheaders.h,
а поскольку он включается только в stdafx.h, то даже include-guard'ы не потребуются.
То же самое легко сделать и не грепом, а любым другим скриптом. На вин-сервере, наверняка, есть powershell, но я в ps не силён вообще.
SVV>думаю что если утилиты нет, то придется ее делать. т.к. на сервере заниматься переносом includes в stdafx не быстро. это лучше делать разработчику перед комитом. те же тестировщики получая исходники даже не станут разбирать этот stdafx.
Так не надо мудрить с stdafx. Пусть он будет такой, каким его визард проекта сделал один раз, — только дописать внутрь allheaders.h, и всё.
Тестировщики ничего нового в нём не увидят, а allheaders.h — это служебный хедер.
Если очень постараться, то можно сделать так, что даже stdafx.pch будет пересобираться лишь тогда, когда allheaders.h поменялся, — а не каждый раз после комми
SVV>Вообще, исходники хранятся вместе с cmakelists.txt, так что на сервере можно использовать не только микрософтовский компилятор. Что можете посоветовать более умное чем микрософт? чтобы компилятор сам решал проблему множественного включения headers.
Не знаю, что посоветовать.
Если для каждого .cpp вести свой собственный прекомпилированный заголовок (отграничивать неизменные внешние хедеры с помощью #pragma hdrstop), — то первая сборка будет длинной, а последующие — быстрыми. Но если каждый раз сборка делается с нуля, то этот подход не прокатит.
Вариант собрать stdafx руками осмысленно? (Внести в него всё, что нужно из буста и т.п.)
... SVV>>Вообще, исходники хранятся вместе с cmakelists.txt, так что на сервере можно использовать не только микрософтовский компилятор. Что можете посоветовать более умное чем микрософт? чтобы компилятор сам решал проблему множественного включения headers.
К>Не знаю, что посоветовать.
К>Если для каждого .cpp вести свой собственный прекомпилированный заголовок (отграничивать неизменные внешние хедеры с помощью #pragma hdrstop), — то первая сборка будет длинной, а последующие — быстрыми. Но если каждый раз сборка делается с нуля, то этот подход не прокатит. К>Вариант собрать stdafx руками осмысленно? (Внести в него всё, что нужно из буста и т.п.)
а реально ли "для каждого .cpp вести свой собственный прекомпилированный заголовок"? я пробовал когда-то пользоваться этой прагмой, но то ли я делал это неправильно то ли оно не работало. В общем надо будет попробовать.
У меня пока что этап подготовки.
Здравствуйте, MasterZiv, Вы писали:
MZ>On 09.03.2014 20:56, SVV wrote:
>> есть большой проект, не использующий precompiled headers. и в cpp и в h >> файлах включаются другие h. какова глубина вложенностей можно только >> догадываться. Есть ли утилита способная собрать включение всех h файлов >> в stdafx перед коммитом и для continuous билдов а потом на машине >> разработчика разобрать stdafx? (чтобы при изменении в единственном h >> файле не перекомпилировать все исходники)
MZ>Чёта я не понял, потом почитал топик, и тоже не понял. MZ>Теперь вот спрашиваю: Зачем такое нужно ? MZ>В stdafx.h должны быть включены все заголовки сторонних библиотек, MZ>которые не меняются никогда. Возможно также, туда можно включить MZ>заголовки собственных библиотек, которые очень редко меняются.
именно! потому как сейчас тот же vector может включаться в собственных headers
MZ>В любом случае, набор этих библиотек должен быть строго фиксирован, MZ>и из заголовков то же. Добавляется новая библиотека к использованию -- MZ>руками можно добавить файлы.
когда нет stdafx вновь используемая библиотека добавляется в тот h/cpp где используется. в другом месте тоже понадобилась эта библиотека — опять идет включение тех же h внешней библиотеки. При наличии stdafx кто-то один ручками добавит туда h.
MZ>Зачем парсить исходники на предмет выполнения транзитивного замыкания MZ>включения ?
вот это не понял
On 13.03.2014 15:34, SVV wrote:
> а реально ли "для каждого .cpp вести свой собственный прекомпилированный > заголовок"? я пробовал когда-то пользоваться этой прагмой, но то ли я > делал это неправильно то ли оно не работало. В общем надо будет попробовать.
On 13.03.2014 15:39, SVV wrote:
> MZ>В любом случае, набор этих библиотек должен быть строго фиксирован, > MZ>и из заголовков то же. Добавляется новая библиотека к использованию -- > MZ>руками можно добавить файлы. > когда нет stdafx вновь используемая библиотека добавляется в тот h/cpp > где используется. в другом месте тоже понадобилась эта библиотека — > опять идет включение тех же h внешней библиотеки. При наличии stdafx > кто-то один ручками добавит туда h.
Нет беды если ты включишь эти заголовки и туда, и сюда. Даже наоборот,
будет только польза (проект может компилироваться и без включения stdafx.h).
> > MZ>Зачем парсить исходники на предмет выполнения транзитивного замыкания > MZ>включения ?
Можно сказать по-другому: если исходник включает заголовок header1.h,
а заголовок header1.h включает заголовок header2.h, то в
stdafx.h достаточно поместить включение заголовка header1.h,
header2.h туда добавлять уже не нужно.
Обычно библиотеки пишутся так, что есть N (где N это малое число)
заголовков, которые нужно включать использующим приложениям.
В stdafx.h достаточно поместить включение только их.
Здравствуйте, MasterZiv, Вы писали:
>> MZ>Зачем парсить исходники на предмет выполнения транзитивного замыкания >> MZ>включения ?
MZ>Можно сказать по-другому: если исходник включает заголовок header1.h, MZ>а заголовок header1.h включает заголовок header2.h, то в MZ>stdafx.h достаточно поместить включение заголовка header1.h, MZ>header2.h туда добавлять уже не нужно.
MZ>Обычно библиотеки пишутся так, что есть N (где N это малое число) MZ>заголовков, которые нужно включать использующим приложениям. MZ>В stdafx.h достаточно поместить включение только их.
Здравствуйте, MasterZiv, Вы писали:
MZ>On 13.03.2014 15:34, SVV wrote:
>> а реально ли "для каждого .cpp вести свой собственный прекомпилированный >> заголовок"? я пробовал когда-то пользоваться этой прагмой, но то ли я >> делал это неправильно то ли оно не работало. В общем надо будет попробовать.
MZ>А смысл ? Он же (заголовок) будет одноразовый.
насколько я понимаю, речь о том, чтобы при изменении header1..K не перекомпилировать все что лежит в stdafx.h... хотя вот именно тут я очень не уверен, что правильно понял предлагаемое применение hdrstop. с удовольствием послушал бы пояснения.
Здравствуйте, MasterZiv, Вы писали:
MZ>А смысл ? Он же (заголовок) будет одноразовый.
Смысл в том, что файл разбивается на "до прагмы" и "после прагмы", и то, что до прагмы, не перекомпилируется каждый раз.
Туда нужно класть неизменяемые инклуды — стандартных и внешних библиотек.
Как именно компилятор отслеживает неизменность головы файла — не знаю, возможно, что считает хеш. Если хеш поменялся, надо перекомпилировать голову.
Вообще, штука удобная, и использовалась ещё в борланд С++.
Это у микрософта проекты, рождённые визардами, содержали жирный шмат заголовков — <windows.h> + <afx.h>, которые предполагалось включать во все файлы.
Поэтому там такая политика: один общий pch на весь проект, вместо кучи маленьких на каждый файл отдельно.
Здравствуйте, MasterZiv, Вы писали:
MZ>Нет беды если ты включишь эти заголовки и туда, и сюда. Даже наоборот, MZ>будет только польза (проект может компилироваться и без включения stdafx.h).
То есть, если <vector> попал внутрь stdafx.h, то мы здорово экономим на компиляции.
Больше того, если сравнить две альтернативы
— засунуть все хедеры, упомянутые в .cpp, в stdafx
— не засовывать их туда
то, в первом случае, мы каждый хедер включим ровно по одному разу, а во втором — включим их не менее чем по разу.
То есть, скорость парсинга вырастет.
Зато провалится скорость семантическая: у нас в каждом файле будет избыточное количество объявлений.
Но это же окажется плюсом: меньше шансов нарваться на нарушения ODR или какие-то заковырки из-за порядка включения хедеров.
Идея топикстартера в том, чтобы не руками заполнять stdafx.h, а автоматически.
Рекурсивный спуск по хедерам здесь не нужен: достаточно собрать все хедеры верхнего уровня, а дальше прекомпиляция сама вытащит всё необходимое из глубины.
Больше того, он вреден, потому что в .cpp, скорее всего, никакой условной компиляции не будет, а вот в хедерах она запросто встретится — всякие платформо-зависимые штуки.
Ну и зачем нам повторять логику препроцессора, — пусть сам препроцессор этим занимается.
Ну а чтобы stdafx.h был неизменным (и его можно было держать в системе контроля версий), — я предлагаю подшивку хедеров держать в отдельном, специальном хедере allheaders.h, который включать в stdafx.h руками, в нужную точку, в самом конце перед #endif
На машине разработчика, где некоторые хедеры библиотечные, а некоторые часто меняются, наполнить allheaders.h (или stdafx.h напрямую) зависимостями — это значит перекомпилировать каждый раз вообще всё. Поэтому, в угоду инкрементной сборке, он должен быть пустым.
На билд-сервере — в некоторых сценариях (например, сборка большого проекта каждый раз с нуля) мы можем позволить себе сделать такую подшивку.