Утилита для сбора includes в stdafx
От: SVV Беларусь  
Дата: 09.03.14 16:56
Оценка: -2 :)
Всем привет,

есть большой проект, не использующий precompiled headers. и в cpp и в h файлах включаются другие h. какова глубина вложенностей можно только догадываться. Есть ли утилита способная собрать включение всех h файлов в stdafx перед коммитом и для continuous билдов а потом на машине разработчика разобрать stdafx? (чтобы при изменении в единственном h файле не перекомпилировать все исходники)
?
Re: Утилита для сбора includes в stdafx
От: Abyx Россия  
Дата: 09.03.14 17:15
Оценка: -1 :)))
Здравствуйте, SVV, Вы писали:

SVV>Всем привет,


SVV>есть большой проект, не использующий precompiled headers. и в cpp и в h файлах включаются другие h. какова глубина вложенностей можно только догадываться. Есть ли утилита способная собрать включение всех h файлов в stdafx перед коммитом и для continuous билдов а потом на машине разработчика разобрать stdafx? (чтобы при изменении в единственном h файле не перекомпилировать все исходники)

SVV>?

stdafx не нужен, pch тоже
In Zen We Trust
Re[2]: Утилита для сбора includes в stdafx
От: Zhendos  
Дата: 09.03.14 17:38
Оценка:
Здравствуйте, Abyx, Вы писали:

A>stdafx не нужен, pch тоже


Ага, усорение сборки в 1.5 раза никому не нужно.
Re: Утилита для сбора includes в stdafx
От: Ops Россия  
Дата: 10.03.14 21:15
Оценка: 1 (1)
Здравствуйте, SVV, Вы писали:

SVV>есть большой проект, не использующий precompiled headers. и в cpp и в h файлах включаются другие h. какова глубина вложенностей можно только догадываться. Есть ли утилита способная собрать включение всех h файлов в stdafx перед коммитом и для continuous билдов а потом на машине разработчика разобрать stdafx? (чтобы при изменении в единственном h файле не перекомпилировать все исходники)

SVV>?

В билдере что-то похожее было, анализировал проект и собирал все хидеры.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Re: Утилита для сбора includes в stdafx
От: Кодт Россия  
Дата: 11.03.14 09:51
Оценка: 5 (2)
Здравствуйте, SVV, Вы писали:

SVV>есть большой проект, не использующий precompiled headers. и в cpp и в h файлах включаются другие h. какова глубина вложенностей можно только догадываться. Есть ли утилита способная собрать включение всех h файлов в stdafx перед коммитом и для continuous билдов а потом на машине разработчика разобрать stdafx? (чтобы при изменении в единственном h файле не перекомпилировать все исходники)


Если в проекте нет препроцессорной магии, то можно было бы банально грепнуть все хедеры, непосредственно включённые в .cpp
Как-то так
grep -P -h '^\s*#include (?!allheaders\.h)(?!stdafx\.h).*$' *.cpp >allheaders.h

А сам этот allheaders.h включить в stdafx.h куда-нибудь в конец.

Причём у разработчика allheaders.h пустой, а на билд-сервере — собирается грепом, в custom build step или в отдельном проекте-зависимости.
Перекуём баги на фичи!
Re: Утилита для сбора includes в stdafx
От: Lazin Россия http://evgeny-lazin.blogspot.com
Дата: 11.03.14 15:23
Оценка: 1 (1)
Здравствуйте, SVV, Вы писали:

SVV>Всем привет,


SVV>есть большой проект, не использующий precompiled headers. и в cpp и в h файлах включаются другие h. какова глубина вложенностей можно только догадываться. Есть ли утилита способная собрать включение всех h файлов в stdafx перед коммитом и для continuous билдов а потом на машине разработчика разобрать stdafx? (чтобы при изменении в единственном h файле не перекомпилировать все исходники)

SVV>?

Чем больше хедеров, тем больше pch файл, тем медленнее билд, соответственно, включение всяких редко используемых хедеров в stdafx нежелательно. Не знаю как у VC++, но у g++ есть флажок, который позволяет выводить иерархию включения заголовочных файлов. Используя эти данные можно выбрать N самых часто включаемых файлов и добавить их в stdafx. Я в свое время так делал, даже скрипт написал, но сейчас его уже не найти.
Re[2]: Утилита для сбора includes в stdafx
От: SVV Беларусь  
Дата: 12.03.14 06:15
Оценка:
Здравствуйте, Ops, Вы писали:

Ops>В билдере что-то похожее было, анализировал проект и собирал все хидеры.

Не понятно почему микрософт этого не делает. Впрочем я давно заметил что микрософт может очень хорошо сделать какую-то "базу" программы, но из рук вон плохо относится к дополнительным фичам.
Например был сделан WebBrowser для использования другими, но сам IE 4,5,6 версии ни в какое сравнение не шел с Netscape Navigator к примеру.
Re[2]: Утилита для сбора includes в stdafx
От: SVV Беларусь  
Дата: 12.03.14 06:21
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, SVV, Вы писали:


SVV>>есть большой проект, не использующий precompiled headers. и в cpp и в h файлах включаются другие h. какова глубина вложенностей можно только догадываться. Есть ли утилита способная собрать включение всех h файлов в stdafx перед коммитом и для continuous билдов а потом на машине разработчика разобрать stdafx? (чтобы при изменении в единственном h файле не перекомпилировать все исходники)


К>Если в проекте нет препроцессорной магии, то можно было бы банально грепнуть все хедеры, непосредственно включённые в .cpp

К>Как-то так
К>
К>grep -P -h '^\s*#include (?!allheaders\.h)(?!stdafx\.h).*$' *.cpp >allheaders.h
К>

К>А сам этот allheaders.h включить в stdafx.h куда-нибудь в конец.

К>Причём у разработчика allheaders.h пустой, а на билд-сервере — собирается грепом, в custom build step или в отдельном проекте-зависимости.

регулярные выражения это то что мне надо будет осилить, но сейчас это для меня марсианский язык.
думаю что если утилиты нет, то придется ее делать. т.к. на сервере заниматься переносом includes в stdafx не быстро. это лучше делать разработчику перед комитом. те же тестировщики получая исходники даже не станут разбирать этот stdafx.
Вообще, исходники хранятся вместе с cmakelists.txt, так что на сервере можно использовать не только микрософтовский компилятор. Что можете посоветовать более умное чем микрософт? чтобы компилятор сам решал проблему множественного включения headers.
Re: Утилита для сбора includes в stdafx
От: MasterZiv СССР  
Дата: 12.03.14 07:52
Оценка:
On 09.03.2014 20:56, SVV wrote:

> есть большой проект, не использующий precompiled headers. и в cpp и в h

> файлах включаются другие h. какова глубина вложенностей можно только
> догадываться. Есть ли утилита способная собрать включение всех h файлов
> в stdafx перед коммитом и для continuous билдов а потом на машине
> разработчика разобрать stdafx? (чтобы при изменении в единственном h
> файле не перекомпилировать все исходники)


Чёта я не понял, потом почитал топик, и тоже не понял.
Теперь вот спрашиваю: Зачем такое нужно ?
В stdafx.h должны быть включены все заголовки сторонних библиотек,
которые не меняются никогда. Возможно также, туда можно включить
заголовки собственных библиотек, которые очень редко меняются.

В любом случае, набор этих библиотек должен быть строго фиксирован,
и из заголовков то же. Добавляется новая библиотека к использованию --
руками можно добавить файлы.

Зачем парсить исходники на предмет выполнения транзитивного замыкания
включения ?
Posted via RSDN NNTP Server 2.1 beta
Re[3]: Утилита для сбора includes в stdafx
От: MasterZiv СССР  
Дата: 12.03.14 07:53
Оценка:
On 12.03.2014 10:21, SVV wrote:

> можно использовать не только микрософтовский компилятор. Что можете

> посоветовать более умное чем микрософт? чтобы компилятор сам решал
> проблему множественного включения headers.

Вроде в GCC есть такая фича. Поищи.
Posted via RSDN NNTP Server 2.1 beta
Re[3]: Утилита для сбора includes в stdafx
От: Abyx Россия  
Дата: 12.03.14 08:45
Оценка:
Здравствуйте, Zhendos, Вы писали:

A>>stdafx не нужен, pch тоже


Z>Ага, усорение сборки в 1.5 раза никому не нужно.


для ускорения сборки есть unity builds.
In Zen We Trust
Re[3]: Утилита для сбора includes в stdafx
От: Кодт Россия  
Дата: 12.03.14 09:14
Оценка:
Здравствуйте, 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 руками осмысленно? (Внести в него всё, что нужно из буста и т.п.)
Перекуём баги на фичи!
Re[4]: Утилита для сбора includes в stdafx
От: SVV Беларусь  
Дата: 13.03.14 11:34
Оценка:
Здравствуйте, Кодт, Вы писали:

...
SVV>>Вообще, исходники хранятся вместе с cmakelists.txt, так что на сервере можно использовать не только микрософтовский компилятор. Что можете посоветовать более умное чем микрософт? чтобы компилятор сам решал проблему множественного включения headers.

К>Не знаю, что посоветовать.


К>Если для каждого .cpp вести свой собственный прекомпилированный заголовок (отграничивать неизменные внешние хедеры с помощью #pragma hdrstop), — то первая сборка будет длинной, а последующие — быстрыми. Но если каждый раз сборка делается с нуля, то этот подход не прокатит.

К>Вариант собрать stdafx руками осмысленно? (Внести в него всё, что нужно из буста и т.п.)
а реально ли "для каждого .cpp вести свой собственный прекомпилированный заголовок"? я пробовал когда-то пользоваться этой прагмой, но то ли я делал это неправильно то ли оно не работало. В общем надо будет попробовать.
У меня пока что этап подготовки.
Re[2]: Утилита для сбора includes в stdafx
От: SVV Беларусь  
Дата: 13.03.14 11:39
Оценка:
Здравствуйте, 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>включения ?
вот это не понял
Re[5]: Утилита для сбора includes в stdafx
От: MasterZiv СССР  
Дата: 13.03.14 13:42
Оценка:
On 13.03.2014 15:34, SVV wrote:

> а реально ли "для каждого .cpp вести свой собственный прекомпилированный

> заголовок"? я пробовал когда-то пользоваться этой прагмой, но то ли я
> делал это неправильно то ли оно не работало. В общем надо будет попробовать.

А смысл ? Он же (заголовок) будет одноразовый.
Posted via RSDN NNTP Server 2.1 beta
Re[3]: Утилита для сбора includes в stdafx
От: MasterZiv СССР  
Дата: 13.03.14 13:47
Оценка:
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 достаточно поместить включение только их.
Posted via RSDN NNTP Server 2.1 beta
Re[4]: Утилита для сбора includes в stdafx
От: SVV Беларусь  
Дата: 13.03.14 13:51
Оценка:
Здравствуйте, 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 достаточно поместить включение только их.

так понятнее
Re[6]: Утилита для сбора includes в stdafx
От: SVV Беларусь  
Дата: 13.03.14 13:56
Оценка:
Здравствуйте, MasterZiv, Вы писали:

MZ>On 13.03.2014 15:34, SVV wrote:


>> а реально ли "для каждого .cpp вести свой собственный прекомпилированный

>> заголовок"? я пробовал когда-то пользоваться этой прагмой, но то ли я
>> делал это неправильно то ли оно не работало. В общем надо будет попробовать.

MZ>А смысл ? Он же (заголовок) будет одноразовый.

#include "stdafx.h"
#include "header1.h"
...
#include "headerK.h"
#pragma hdrstop//???
...
#include "headerN.h"

насколько я понимаю, речь о том, чтобы при изменении header1..K не перекомпилировать все что лежит в stdafx.h... хотя вот именно тут я очень не уверен, что правильно понял предлагаемое применение hdrstop. с удовольствием послушал бы пояснения.
Re[6]: Утилита для сбора includes в stdafx
От: Кодт Россия  
Дата: 13.03.14 20:03
Оценка:
Здравствуйте, MasterZiv, Вы писали:

MZ>А смысл ? Он же (заголовок) будет одноразовый.


Смысл в том, что файл разбивается на "до прагмы" и "после прагмы", и то, что до прагмы, не перекомпилируется каждый раз.
Туда нужно класть неизменяемые инклуды — стандартных и внешних библиотек.

Как именно компилятор отслеживает неизменность головы файла — не знаю, возможно, что считает хеш. Если хеш поменялся, надо перекомпилировать голову.

Вообще, штука удобная, и использовалась ещё в борланд С++.
Это у микрософта проекты, рождённые визардами, содержали жирный шмат заголовков — <windows.h> + <afx.h>, которые предполагалось включать во все файлы.
Поэтому там такая политика: один общий pch на весь проект, вместо кучи маленьких на каждый файл отдельно.
Перекуём баги на фичи!
Re[4]: Утилита для сбора includes в stdafx
От: Кодт Россия  
Дата: 13.03.14 20:26
Оценка:
Здравствуйте, MasterZiv, Вы писали:

MZ>Нет беды если ты включишь эти заголовки и туда, и сюда. Даже наоборот,

MZ>будет только польза (проект может компилироваться и без включения stdafx.h).

Не, смотри, в чём фокус.

Библиотечный хедер
// <vector>

#ifndef __STD__VECTOR__
#define __STD__VECTOR__
  #include <memory>
  #include <utility>
  #include <algorithm>
  blablabla
#endif


Включаем его так
////////////////////
// stdafx.h
#include <vector>
....


/////////////////////
// main.cpp
#include "stdafx.h"
#include <vector>
.....

// разворачивается

#include "stdafx.h"
                    #include <vector>
                                      #ifndef __STD_VECTOR__
                                      #define __STD_VECTOR__
                                        #include <memory>
                                        #include <utility>
                                        #include <algorithm>
                                        blablabla
                                      #endif
#include <vector>
                  #ifndef __STD_VECTOR__ // а гвардеец уже определён!
                  #endif
.....


То есть, если <vector> попал внутрь stdafx.h, то мы здорово экономим на компиляции.
Больше того, если сравнить две альтернативы
— засунуть все хедеры, упомянутые в .cpp, в stdafx
— не засовывать их туда
то, в первом случае, мы каждый хедер включим ровно по одному разу, а во втором — включим их не менее чем по разу.
То есть, скорость парсинга вырастет.
Зато провалится скорость семантическая: у нас в каждом файле будет избыточное количество объявлений.
Но это же окажется плюсом: меньше шансов нарваться на нарушения ODR или какие-то заковырки из-за порядка включения хедеров.

Идея топикстартера в том, чтобы не руками заполнять stdafx.h, а автоматически.

Рекурсивный спуск по хедерам здесь не нужен: достаточно собрать все хедеры верхнего уровня, а дальше прекомпиляция сама вытащит всё необходимое из глубины.
Больше того, он вреден, потому что в .cpp, скорее всего, никакой условной компиляции не будет, а вот в хедерах она запросто встретится — всякие платформо-зависимые штуки.
Ну и зачем нам повторять логику препроцессора, — пусть сам препроцессор этим занимается.

Ну а чтобы stdafx.h был неизменным (и его можно было держать в системе контроля версий), — я предлагаю подшивку хедеров держать в отдельном, специальном хедере allheaders.h, который включать в stdafx.h руками, в нужную точку, в самом конце перед #endif

На машине разработчика, где некоторые хедеры библиотечные, а некоторые часто меняются, наполнить allheaders.h (или stdafx.h напрямую) зависимостями — это значит перекомпилировать каждый раз вообще всё. Поэтому, в угоду инкрементной сборке, он должен быть пустым.
На билд-сервере — в некоторых сценариях (например, сборка большого проекта каждый раз с нуля) мы можем позволить себе сделать такую подшивку.
Перекуём баги на фичи!
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.