Является ли сокращение числа единиц перевода cpp хорошей идеей? - PullRequest
13 голосов
/ 14 мая 2009

Я считаю, что если классов много, время компиляции значительно увеличивается, когда я использую один * .h и один * .cpp файл на класс. Я уже использую предварительно скомпилированные заголовки и инкрементные ссылки, но время компиляции очень велико (да, я использую boost;)

Итак, я придумал следующий трюк:

  • определены * .cpp файлы как не компилируемые
  • определены * .cxx файлы как компилируемые
  • добавлен один * .cxx файл для приложения модуль и в него включены все * .cpp файлы этого модуля.

Таким образом, вместо 100+ единиц перевода я получил только 8 единиц перевода. Время компиляции сократилось в 4-5 раз.

Недостатком является то, что вам нужно вручную включать все файлы * .cpp (но это не совсем кошмар обслуживания, так как если вы забудете включить что-то, что вам напомнит компоновщик), и что некоторые удобства VS IDE не работают с эта схема, например Перейти / перейти к реализации и т. Д.

Итак, вопрос в том, действительно ли большое количество модулей перевода cpp является единственно верным способом? Мой трюк - известная картина, или я что-то упускаю? Спасибо!

Ответы [ 8 ]

5 голосов
/ 14 мая 2009

Один существенный недостаток этого подхода вызван наличием одного файла .obj для каждой единицы перевода.

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

В случае больших единиц перевода, более вероятно, что на каждую единицу ссылаются и включается соответствующий файл .obj. Большие двоичные файлы могут быть проблемой в некоторых случаях. Также возможно, что некоторые компоновщики достаточно умны, чтобы включать только необходимые функции / переменные, а не целые файлы .obj.

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

4 голосов
/ 14 мая 2009

Я видел, что вы делаете в видеоиграх, поскольку он помогает компилятору оптимизировать его, иначе он не смог бы сэкономить много памяти. Я видел, как «uber build» и «массовая сборка» относятся к этой идее. И если это поможет ускорить сборку, почему бы и нет ..

3 голосов
/ 14 мая 2009

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

  1. Увеличено время компиляции во время разработки. Обычно разработчик изменяет несколько файлов за раз, и компиляция, вероятно, будет быстрее для 3-4 маленьких файлов, чем для одного очень большого файла.
  2. Как вы упомянули, сложнее ориентироваться в коде, ИМХО, это крайне важно.
  3. Вы можете иметь некоторые помехи между файлами .cpp, включенными в один файл .cxx:

    а. Обычной практикой является определение локально в файле cpp (для отладочных сборок) нового макроса для проверки утечки памяти. К сожалению, это не может быть сделано до включения заголовков с использованием размещения новых (как это делают некоторые заголовки STL и BOOST)

    б. Обычной практикой является добавление объявлений в файлах cpp. При вашем подходе это может привести к проблемам с заголовками, включенными позже

    с. Конфликты имен более вероятны

ИМХО, намного более чистый (но, возможно, более дорогой) способ ускорить время компиляции - использовать какую-то распределенную систему сборки. Они особенно эффективны для чистых сборок.

3 голосов
/ 14 мая 2009

Объединение большего количества файлов исходного кода C ++ в один файл - это подход, о котором упоминалось несколько раз в последнее время, особенно когда люди строили большие системы и извлекали сложные заголовочные файлы (тогда это будет толчком) .

Как вы упомянули VS, я обнаружил, что количество включаемых файлов в проекте и особенно размер пути включения, похоже, влияет на время компиляции Visual C ++ гораздо больше, чем время компиляции в g ++. Это особенно актуально для множества вложенных включений (опять же, это делает boost), так как для поиска всех включаемых файлов, необходимых для исходного кода, необходимо большое количество файловых поисков. Объединение кода в один исходный файл означает, что компилятор может быть намного умнее при поиске указанных включений, плюс их явно меньше, так как можно ожидать, что файлы в том же подпроекте, вероятно, будут содержать очень похожие набор заголовочных файлов.

Подход "много блоков компиляции" к разработке на C ++ обычно исходит из желания разъединить классы и минимизировать зависимости между классами, поэтому компилятор должен перестраивать минимальный набор файлов только в случае внесения каких-либо изменений. Как правило, это хороший подход, но часто он не может быть реализован в подпроекте просто потому, что файлы в нем имеют зависимости друг от друга, так что вы все равно получите довольно большие пересборки.

2 голосов
/ 14 мая 2009

Я не уверен, уместно ли это в вашем случае, но, возможно, вы можете использовать декларацию вместо определения, чтобы уменьшить количество #include, которые вам нужно сделать. Кроме того, возможно, вы можете использовать идиому pimpl для той же цели. Мы надеемся, что это уменьшит количество исходных файлов, которые нужно каждый раз перекомпилировать, и количество заголовков, которые нужно извлечь.

1 голос
/ 14 мая 2009

Концепция называется Unid Build

1 голос
/ 14 мая 2009

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

0 голосов
/ 14 мая 2009

Исходя из поста «Острозуб», я бы хотел рассмотреть некоторые исполняемые файлы более подробно. Если они отличаются, я бы ограничил вашу технику отладкой сборок и прибегнул к исходной конфигурации проекта для основной сборки выпуска. При проверке исполняемого файла я также смотрю на его объем памяти и использование ресурсов при запуске и во время работы.

...