#c #cmake #build #clang
#c #cmake #сборка #clang
Вопрос:
Чтобы оптимизировать время компиляции, я хотел бы включить сборку Unity (через CMake) для моего проекта embedded system (C ). Отлично работает, но, как я вижу, есть некоторые побочные эффекты.
Одна важная вещь, которую я заметил, это то, что связанный двоичный файл имеет другой размер (больше), чем по сравнению с «обычной» сборкой. Просматривая файл elf, я заметил, что в двоичном файле, созданном Unity, меньше символов по сравнению с другим. Как я вижу, во время компиляции происходит некоторое встраивание (изначально я думал, что встраивание происходит во время соединения?), И поэтому размер двоичного файла увеличивается, когда встроенные функции используются несколько раз.
Из-за встраивания, которое происходит при сборке Unity, время выполнения также немного короче.
Сейчас меня беспокоит то, что с ростом исходного кода я получаю разные сегменты Unity, и поэтому встраивание на самом деле не является детерминированным.
Если мое предположение верно, есть ли способ решить эту проблему?
Комментарии:
1. Это было бы не только встраивание. Сборка Unity упрощает компилятору обнаружение и устранение мертвого кода (функции, которые не вызываются, код, который не достигнут, И т. Д.). Отдельная компиляция означает, что компилятор не всегда может это сделать, поскольку он не может видеть разные блоки компиляции (например, определить, что функция в одном блоке компиляции не вызывается другим модулем компиляции в той же программе). Хотя компоновщики могут технически анализировать разные модули компиляции, они редко ищут мертвый код (вместо этого их цель — убедиться, что используемые символы найдены и с ними установлены ссылки).
Ответ №1:
Сначала к этому аспекту
(изначально я думал, что встраивание происходит во время соединения?)
Зависит от компилятора и контекста, но в целом здесь задействованы и компилятор, и компоновщик.
Для общего вопроса:
Как вы определяете для себя сегменты Unity? Я предполагаю, что вы имеете в виду фактически несколько единиц перевода. Если это так, то на самом деле ничто не отличается от «общих» схем построения (каждый .cpp приводит к одной единице перевода), поэтому ваши проблемы не будут иметь ничего общего с UnityBuild в деталях. В качестве наилучшей практики: если вы используете UnityBuilds, убедитесь, что ваш проект / решение всегда подходит для «обычных» сборок, а также для UnityBuild. Это означает, например: избегайте глобального использования пространств имен всегда (в .cpp и .h), убедитесь, что вы не сталкиваетесь с фиаско статического порядка инициализации (очень актуально для вашего вопроса здесь), избегайте множества случаев использования анонимных пространств имен (грустно, я знаю …), используйте строгую схему защиты включения и так далее…
Комментарии:
1. Сегменты Unity выбираются CMake.
CMAKE_UNITY_BUILD_BATCH_SIZE
имеет значение20
. Возможно, помогло бы ручное определение сегментов.2. Хорошо, как я и ожидал. Тогда нет большей разницы в создании обычных единиц перевода. Просто в основном имейте в виду, что значение файлов заголовка и файлов реализации сливаются воедино, а влияние содержимого .cpp на сборку имеет такое же качество, как и у заголовочных файлов сейчас.