g++ error using -flto option

2019-04-18 17:38发布

问题:

I am trying to enable link time optimization in g++. My program compiles fine without the -flto option. When I add it to my Makefile the object files compile without errors, e.g.

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

But when it comes to link the program:

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

I get a lot of errors like these:

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)

I can't figure out what is going wrong. I compile all my object files using -flto. The libs, namely Boost and GMP, are compiled without -flto option. Is this causing the error? The gcc manual says that its ok to mix object files compiled with & without -flto option. Or am I missing something else, for example what is this plugin the error is speaking about?

I am using G++ 4.6.3 on Debian Wheezy.

UPDATE:

As adviced in the comments I made a minimal example. The code of my test program is only this:

#include "boost/program_options.hpp"

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

When I compile it using:

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

it gives similar errors as described above. If I omit the -static, -flto OR std=c++0x option it compiles without errors. The -fwhole-program option does not change the result. I now also tested with G++ 4.7, same error.

Any suggestions? Is this really a compiler error, or am I still doing something wrong?

回答1:

Since I found no evidence, that there is something wrong with my code, I have posted a Boost bugreport. It was reproduced by other boost users as well, therefore I think it is actually a bug within boost or the g++. By now there was no response from the Boost maintainer. I'll update this post when there is one.

Update

It seems like the g++ linker-plugin is causing the problem (Still I have no idea why). Therefore a possible work around is to disable the linker-plugin by using -fno-use-linker-plugin.



回答2:

Something within the library references the typeinfo of the that particular class (typically things like a "catch" statement for that particular exception or a "dynamic_cast"). Hence the "referenced in section" in your error message.

However, for the typeinfo to be generated, a non-inline non-pure virtual function has to be present in one of the compilation units. If the function is defined within the class definition, this does not count (it is inlined and treated as inlined for linkage, even if you pass "-fno-default-inline").

So, the dynamic_cast or catch statement is probably not working as the author intended; the issue just was never noticed until LTO was attempted on the header.

So, I'd call it a BOOST error and/or a shortcoming of g++.



回答3:

-flto flag must be present in both compile and linker command lines in order to work. -fwhole-program, on the other hand, is not needed at all. LTO will not work with translation units that were not compiled with LTO support, by the way.