# включить все .cpp файлы в единый блок компиляции?

Недавно мне приходилось работать с некоторыми проектами Visual Studio С++ с обычными конфигурациями Debug и Release, но также "Release All" и "Debug All", которые я никогда раньше не видел.

Оказывается, у автора проектов есть один ALL.cpp, который # включает все другие .cpp файлы. * Все конфигурации просто создают этот файл ALL.cpp. Разумеется, это исключается из регулярных конфигураций, и регулярные конфигурации не строят ALL.cpp

Я просто подумал, что это обычная практика? Какие выгоды он приносит? (Моя первая реакция заключалась в том, что он плохо пахнет.)

С какими ловушками вы столкнетесь с этим? Я могу подумать, что если у вас есть анонимные пространства имен в вашем .cpps, они больше не являются 'private' для этого cpp, но теперь видны и в других cpps?

Все проекты создают библиотеки DLL, поэтому наличие данных в анонимных пространствах имен не будет хорошей идеей, не так ли? Но функции были бы в порядке?

Приветствия.

Ответы

Ответ 1

Он упоминается некоторыми (и google-способными) как "Unity Build". Он связывает безумно быстро и компилируется достаточно быстро. Это отлично подходит для сборок, которые вам не нужно выполнять, например, с помощью сборки релиза с центрального сервера, но это не обязательно для инкрементного построения.

И это PITA для поддержания.

EDIT: здесь первая ссылка google для получения дополнительной информации: http://buffered.io/posts/the-magic-of-unity-builds/

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

Брюс Доусон гораздо лучше написал об этом в своем блоге: http://randomascii.wordpress.com/2014/03/22/make-vc-compiles-fast-through-parallel-compilation/

Ответ 2

Unity создает улучшенные скорости сборки по трем основным причинам. Первая причина заключается в том, что все общие файлы заголовков нужно анализировать только один раз. Многие проекты на С++ содержат много файлов заголовков, которые включены большинством или всеми CPP файлами, а избыточный синтаксический анализ этих данных является основной стоимостью компиляции, особенно если у вас много коротких исходных файлов. Предварительно скомпилированные файлы заголовков могут помочь с этой стоимостью, но обычно есть много файлов заголовков, которые не были предварительно скомпилированы.

Следующая основная причина, по которой построение единства улучшает скорость сборки, заключается в том, что компилятор вызывается меньше раз. При запуске компилятора есть несколько затрат на запуск.

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

Unity builds также может дать лучший код-gen.

Unity builds НЕ быстрее из-за уменьшения дискового ввода-вывода. Я профилировал многие сборки с помощью xperf, и я знаю, о чем говорю. Если у вас достаточно памяти, то кэш-память ОС будет избегать избыточных операций ввода-вывода - последующие чтения заголовка будут поступать из кеша операционной системы. Если у вас недостаточно памяти, то сборка единиц может даже сократить время сборки, вызывая отставание памяти памяти компилятора от доступной памяти и выгружаемой страницы.

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

Ответ 3

Интересно, пытается ли ALL.cpp поместить весь проект в единый блок компиляции, чтобы улучшить способность компилятора оптимизировать программу для размера?

Обычно некоторые оптимизации выполняются только в отдельных единицах компиляции, таких как удаление дублированного кода и встраивание.

Тем не менее, я, похоже, помню, что недавние компиляторы (Microsoft, Intel, но я не думаю, что это включает GCC) могут сделать эту оптимизацию для нескольких единиц компиляции, поэтому я подозреваю, что этот "трюк" не имеет особого значения.

Тем не менее, было бы интересно узнать, есть ли какая-то разница.

Ответ 4

Я согласен с Брюсом; по моему опыту, я попытался реализовать Unity Build для одного из моих .dll-проектов, в котором было тонны заголовка и большого количества .cpps; чтобы сократить общее время компиляции на VS2010 (уже исчерпали параметры инкрементной сборки), но вместо того, чтобы сокращать время компиляции, у меня закончилась нехватка памяти, а Build даже не смог завершить компиляцию.

Однако добавить; Я обнаружил, что включение возможности многопроцессорной компиляции в Visual Studio помогает в сокращении времени компиляции; Я не уверен, что такой вариант доступен для других компиляторов платформы.

Ответ 6

У нас есть мультиплатформенный проект для MacOS и Windows. У нас есть много больших шаблонов и много заголовков для включения. Мы сократили время сборки с помощью Visual Studio 2017 msvc, используя предварительно скомпилированные заголовки. Для MacOS мы несколько дней пытались сократить время сборки, но предварительно скомпилированные заголовки только сократили время сборки до 85%. Использование одного .cpp файла было прорывом. Мы просто создаем этот ALL.cpp с помощью скрипта. Наш ALL.cpp содержит список включений всех .cpp файлов нашего проекта. Мы сократили время сборки до 30% с помощью XCode 9.0. Единственным недостатком было то, что мы должны были давать имена всем частным неименованным пространствам имен модулей компиляции в .cpp-Files. В противном случае локальные имена будут конфликтовать.