Как написать код с поддержкой LTO?

Какие предостережения и недостатки необходимо учитывать при написании кода или сборке сценариев для компиляции с LTO?

Мотивация этого вопроса заключается в том, чтобы лучше понять, почему некоторые проекты не компилируются без ошибок при включенном LTO. В частности я не смог построить ICU с включенным LTO, ни в MSVC, ни в GCC. В других случаях я могу включить LTO с заданной версией набора инструментов, но не с другой (более новой) версией; это происходит, например, с libiconv.

Во всех неудачных случаях, с которыми я встречался, связан сбой соединения из-за неразрешенных символов.

Почему именно это происходит? Это проблема с набором инструментов, со скриптом сборки или с исходным кодом?

0

Решение

В этом ответе обобщены мои выводы относительно некоторых сложностей, возникающих при создании проектов с поддержкой LTO, как в GCC, так и в MSVC.

НКУ

Прежде всего, согласно GCC Wiki, чтобы правильно построить проект с включенным LTO, необходимо:

  1. Удостовериться gcc-ar используется вместо binutils ar;
  2. Удостовериться gcc-ranlib используется вместо binutils ranlib;
  3. Удостовериться gcc-nm используется вместо binutils nm;
  4. компилировать а также связать с -flto,

Это означает, что в традиционном ./configure && make цикл, нужно помнить, установив значение AR=, RANLIB= а также NM= когда актуально. Это в основном это; однако, эти шаги легко пропустить, потому что необходимо изменить значение, например. AR довольно необычно.

Теперь к вопросам:

В GCC 4.8 и более ранних версиях компилятор по умолчанию генерирует толстые объектные файлы. Это означает, что даже если инструменты посткомпиляции (компоновщик, архиватор и т. Д.) Не распознают объекты LTO, они будут работать нормально (но без фактического выполнения LTO).

В GCC 4.9 и более поздних версиях компилятор по умолчанию генерирует тонкие объектные файлы, что означает, что инструменты после компиляции должны распознавать объекты LTO, иначе инструменты не будут работать. Это объясняет, почему иногда сборка LTO проходит при использовании GCC 4.8, но происходит сбой при использовании GCC 4.9 и более поздних версий.

Я также заметил, что сценарии сборки не всегда правильно передают значения некоторых директив конфигурации подпрограммам при необходимости. Например, при сборке статики libiconv с LTO в MinGW-w64, скрипт конфигурации все еще настраивает внутренний libtool с ar вместо gcc-arдаже когда сказали что AR=gcc-ar,

Сборки LTO имеют тенденцию обнаруживать скрытые ошибки, в частности ошибки, вызванные статический инициат фиаско. Они также могут мешать другим оптимизациям, таким как ICF (выполняется Gold).

Наконец, все еще есть ряд ошибок, по-видимому, сохраняющихся в оборудовании LTO. При попытке скомпилировать ICU с MinGW-w64 с LTO и другими включенными оптимизациями я столкнулся с эта ошибка и внутренние ошибки компилятора (internal compiler error: in splice_child_die, at dwarf2out.c, возможно, связанный с использованием -g с LTO).

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

MSVC

Чтобы скомпилировать с LTO в MSVC (который называется LTCG), /GL должны быть использованы при компиляции и /LTCG должны быть использованы при связывании, и это действительно так.

Тем не менее, когда LTCG включен в MSVC, компилятор не испускать традиционные объекты COFF. Он излучает вместо специальный вид объектного файла содержащий ИК чей заголовок (ANON_OBJECT_HEADER_BIGOBJ) отличается от заголовка COFF (IMAGE_FILE_HEADER). Это, очевидно, не должно иметь никакого значения при создании проекта, так как эти детали оставлены для обработки цепочкой инструментов.

Теперь, почему ICU не собирается должным образом, когда LTCG включен в MSVC?

ICU имеет инструмент под названием pkgdata который генерирует объектный код для данной архитектуры. В процессе сборки инструмент используется для сборки других утилит в пакете. Тем не мение, pkgdata пытается угадать целевую архитектуру путем проверки заданного эталонного объектного файла. В Windows инструмент принимает заголовок COFF, а в 32-разрядных сборках он ошибочно определяет, что используется 64-разрядная архитектура (из-за неаккуратной логики внутри pkg_genc.c:getArchitecture()). Следовательно, MSVC 32-битная сборка LTCG дает сбой.

4

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]