G++ ошибка с использованием опции -flto

Я пытаюсь включить оптимизацию времени ссылки в g++. Моя программа отлично компилируется без опции -flto. Когда я добавляю его в свой Makefile, объектные файлы компилируются без ошибок, например.

g++ main.cpp -I ../includes -std=c++0x -fopenmp -Wall -pedantic -Wno-vla -flto -D INFO_ -c -o .obj/main.o

Но когда дело доходит до ссылки на программу:

g++ -fwhole-program -I ../includes -std=c++0x -fopenmp -Wall -pedantic -Wno-vla -flto -D INFO_ .obj/main.o .obj/atom.o .obj/bee.o .obj/colony.o ../includes/.obj/error.o ../includes/.obj/CmdLine.o ../includes/boost_lib_deb/libboost_program_options.a ../includes/gmp_lib_deb/lib/libgmpxx.a ../includes/gmp_lib_deb/lib/libgmp.a -o BeeBench

Я получаю много таких ошибок:

includes/gmp_lib_deb/lib/libgmpxx.a ../includes/gmp_lib_deb/lib/libgmp.a -o BeeBench
`typeinfo for boost::program_options::too_many_positional_options_error' referenced in section `.rodata._ZTVN5boost15program_options33too_many_positional_options_errorE[vtable for boost::program_options::too_many_positional_options_error]' of ../includes/boost_lib_deb/libboost_program_options.a(cmdline.o): defined in discarded section `.gnu.linkonce.t._ZTIN5boost15program_options33too_many_positional_options_errorE' of .obj/main.o (symbol from plugin)

`typeinfo for boost::program_options::too_many_positional_options_error' referenced in section `.rodata._ZTIN5boost16exception_detail19error_info_injectorINS_15program_options33too_many_positional_options_errorEEE[typeinfo for boost::exception_detail::error_info_injector<boost::program_options::too_many_positional_options_error>]' of ../includes/boost_lib_deb/libboost_program_options.a(cmdline.o): defined in discarded section `.gnu.linkonce.t._ZTIN5boost15program_options33too_many_positional_options_errorE' of .obj/main.o (symbol from plugin)
`typeinfo for boost::program_options::invalid_command_line_style' referenced in section `.rodata._ZTVN5boost15program_options26invalid_command_line_styleE[vtable for boost::program_options::invalid_command_line_style]' of ../includes/boost_lib_deb/libboost_program_options.a(cmdline.o): defined in discarded section `.gnu.linkonce.t._ZTIN5boost15program_options26invalid_command_line_styleE' of .obj/main.o (symbol from plugin)

Я не могу понять, что происходит не так. Я скомпилирую все мои объектные файлы с помощью -flto. Библиотеки, а именно Boost и GMP, скомпилированы без опции -flto. Это вызывает ошибку? В руководстве gcc говорится, что его нормально смешивать файлы объектов, скомпилированные с опцией -flto и без нее. Или я пропустил что-то еще, например, что это за плагин, о котором говорит ошибка?

Я использую g++ 4.6.3 в Debian Wheezy.

UPDATE:

Как явствует из комментариев, я сделал минимальный пример. Код моей тестовой программы:

#include "boost/program_options.hpp"

int main ( int argC, char* argV[] )
{
    return 0;
}

Когда я скомпилирую его, используя:

g++ -o test -I ../includes -Wall -std=c++0x test.cpp -flto -fwhole-program -static

он дает аналогичные ошибки, как описано выше. Если я опускаю параметр -static, -flto OR std = С++ 0x, он компилируется без ошибок. Параметр -fwhole-program не изменяет результат. Я теперь также тестировал с g++ 4.7, ту же ошибку.

Любые предложения? Действительно ли это ошибка компилятора, или я все еще делаю что-то неправильно?

Ответы

Ответ 1

Поскольку я не нашел никаких доказательств, что с моим кодом что-то не так, я разместил Boost bugreport. Он также был воспроизведен другими пользователями с повышенными правами, поэтому я думаю, что это на самом деле ошибка в boost или g++. К настоящему времени от сопровождающего Boost ответа не последовало. Я буду обновлять этот пост, когда он есть.

Обновить

Похоже, что glink-плагин g++ вызывает проблему (все же я понятия не имею, почему). Поэтому возможная работа - отключить компоновщик-плагин, используя -fno-use-linker-plugin.

Ответ 2

Что-то внутри библиотеки ссылается на typeinfo этого конкретного класса (обычно такие вещи, как оператор catch для этого конкретного исключения или "dynamic_cast" ). Следовательно, "ссылка в разделе" в вашем сообщении об ошибке.

Однако для создания типаinfo в одном из блоков компиляции должна присутствовать нестрочная нечистая виртуальная функция. Если функция определена в определении класса, это не считается (она встроена и рассматривается как встроенная для привязки, даже если вы передаете "-fno-default-inline" ).

Итак, оператор dynamic_cast или catch не работает, как предполагал автор; проблема просто не замечалась до тех пор, пока в заголовке не была предпринята попытка LTO.

Итак, я бы назвал это ошибкой BOOST и/или недостатком g++.

Ответ 3

Флаг

-flto должен присутствовать в командных строках компиляции и компоновщика для работы. -fwhole-program, с другой стороны, вообще не требуется. Кстати, LTO не будет работать с единицами перевода, которые не были скомпилированы с поддержкой LTO.