Пайк написал еще об этом в https://talks.golang.org/2012/splash.article:
. В 1984 г. компиляция ps.c
, источника команды Unix ps, наблюдалась #include <sys/stat.h>
37 развремя вся предварительная обработка была сделана.Хотя при этом содержимое отбрасывается 36 раз, большинство реализаций C открывают файл, читают его и сканируют все 37 раз.Фактически, без большой хитрости такое поведение требуется потенциально сложной макросемантикой препроцессора C.
Компиляторы стали достаточно умными, так как: https://gcc.gnu.org/onlinedocs/cppinternals/Guard-Macros.html,, так что это меньшевыпускать сейчас.
Создание одного двоичного файла C ++ в Google позволяет открывать и читать сотни отдельных заголовочных файлов десятки тысяч раз.В 2007 году инженеры по сборке в Google разработали сборку основного двоичного файла Google.Файл содержал около двух тысяч файлов, которые, если их просто объединить, составили 4,2 мегабайта.Ко времени расширения #include на вход компилятора было доставлено более 8 гигабайт, что привело к увеличению 2000 байт на каждый исходный байт C ++.
В качестве еще одной точки данных в 2003 году GoogleСистема сборки была перемещена из одного файла Makefile в дизайн для каждого каталога с более управляемыми, более явными зависимостями.Типичный двоичный файл сократился примерно на 40% по размеру файла, просто из-за более точной записи зависимостей.Несмотря на это, свойства C ++ (или C в этом отношении) делают нецелесообразным автоматическую проверку этих зависимостей, и сегодня у нас все еще нет точного понимания требований к зависимостям больших двоичных файлов Google C ++.
Вопрос о двоичных размерах все еще актуален.Компиляторы (линкеры) довольно консервативны в отношении удаления неиспользуемых символов. Как удалить неиспользуемые символы C / C ++ с помощью GCC и ld?
В Plan 9 было запрещено содержать дополнительные заголовочные файлы #include
;все #includes
должны были находиться в файле C верхнего уровня.Конечно, это требовало некоторой дисциплины - программист должен был перечислять необходимые зависимости ровно один раз, в правильном порядке - но документация помогла, и на практике это сработало очень хорошо.
Это возможное решение,Другая возможность состоит в том, чтобы иметь для вас инструмент, который управляет включениями, например, MakeDeps .
Также существуют сборки для единства, иногда называемые SCU, сборки для одного модуля компиляции.Для этого есть инструменты, такие как https://github.com/sakra/cotire
Использование системы сборки, которая оптимизирует скорость инкрементной компиляции, также может быть полезным.Я говорю о Google Bazel и подобных.Однако он не защищает вас от изменений в заголовочном файле, который включен в большое количество других файлов.
Наконец, в работе есть предложение для модулей C ++, замечательные вещи https://groups.google.com/a/isocpp.org/forum/#!forum/modules. См. Также Что такое модули C ++?