Link errors while trying to compile statically an

2019-07-21 00:28发布

问题:

I've been trying to shift my C++ work in windows on clang lately, and everything so far seems to work right except one thing: Making full static excecutables (without any external dll dependencies like libgcc libstdc++ etc...).

Let me give you an example. We have the following simple program:

#include <string>

int main()
{
    std::string s1 = "Happy"; 
    std::string s2 = " Cow";
    std::string s3 = s1 + s2;
    return 0;
}

If we try to compile it using the following line:

clang++ -static -O0 -std=c++11 bug.cpp

We get the following link error:

F:/Programs/LLVM/bin/../lib/gcc/i686-w64-mingw32/4.8.2\libstdc++.a(string-inst.o):(.text$_ZStplIcSt11char_traitsIcESaIcEESbIT_T0_T1_ERKS6_S8_[__ZStplIcSt11char_traitsIcESaIcEESbIT_T0_T1_ERKS6_S8_]+0x0): multiple definition of `std::basic_string<char, std::char_traits<char>, std::allocator<char> > std::operator+<char, std::char_traits<char>, std::allocator<char> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
C:\Users\THEART~1\AppData\Local\Temp\bug-4d96cd.o:(.text[__ZStplIcSt11char_traitsIcESaIcEESbIT_T0_T1_ERKS6_S8_]+0x0): first
defined here
collect2.exe: error: ld returned 1 exit status
clang++.exe: error: linker (via gcc) command failed with exit code 1 (use -v to see invocation)

We get the same result by using the following flags:

clang++ -static -static-libgcc -static-libstdc++ -O0 -std=c++11 bug.cpp

It should be noted that when using g++ the program compiles and links fine with any of the above two lines. Also obviously when removing the static flags the program compiles just fine with the clang too.

This bug has been chasing me for weeks, so last night i gave it all and started searching for anything that could have been causing it. After some hours of really heavy digging, i thought i should inspect and compare the intermediate output of the two compilers.

Looking on the symbols of the clang generated object file i saw this:

nm bug_clang.o
--------------------
00000000 b .bss
00000000 d .data
00000000 d .eh_frame
00000000 r .gcc_except_table
00000000 r .rdata
00000000 t .text
00000000 t .text
00000001 a @feat.00
         U ___gxx_personality_v0
         U ___main
         U __Unwind_Resume
         U __ZNSaIcEC1Ev
         U __ZNSaIcED1Ev
         U __ZNSs6appendERKSs
         U __ZNSsC1EPKcRKSaIcE
         U __ZNSsC1ERKSs
         U __ZNSsD1Ev
00000000 T __ZStplIcSt11char_traitsIcESaIcEESbIT_T0_T1_ERKS6_S8_
00000000 T _main
00000000 r GCC_except_table0
00000048 r GCC_except_table1

While inspecting the symbols on the g++ generated object file gave me this:

nm bug_g++.o
00000000 b .bss
00000000 d .data
00000000 r .eh_frame
00000000 r .eh_frame$_ZStplIcSt11char_traitsIcESaIcEESbIT_T0_T1_ERKS6_S8_
00000000 d .gcc_except_table
00000000 r .rdata
00000000 r .rdata$zzz
00000000 t .text
00000000 t .text$_ZStplIcSt11char_traitsIcESaIcEESbIT_T0_T1_ERKS6_S8_
         U ___gxx_personality_v0
         U ___main
         U __Unwind_Resume
         U __ZNSaIcEC1Ev
         U __ZNSaIcED1Ev
         U __ZNSs6appendERKSs
         U __ZNSsC1EPKcRKSaIcE
         U __ZNSsC1ERKSs
         U __ZNSsD1Ev
00000000 r __ZStL19piecewise_construct
00000000 T __ZStplIcSt11char_traitsIcESaIcEESbIT_T0_T1_ERKS6_S8_
00000000 T _main

As you can observe there are some internal symbols on the g++ generated object file that does not exist at all or are different in the clang generated object file, namely:

  • Entry "00000000 r .eh_frame$_ZStplIcSt11char_traitsIcESaIcEESbIT_T0_T1_ERKS6_S8_" is missing

(I suppose that it has something to do with the exception handling)

  • Entry "00000000 t .text$_ZStplIcSt11char_traitsIcESaIcEESbIT_T0_T1_ERKS6_S8_" is altered

(I believe that this one exists in the clang object file too as the second "00000000 t .text" entry)

I have not really in depth knowledge on the subject, but my bet would be, that the altered second internal symbol (the one i mention above) on the clang generated object file is the root cause of the problem.

So is this a bug on the clang compiler, or am i doing something wrong?

In case you ask, i am using LLVM v3.6 with MinGW-w64 4.8.2 on Windows that i set up using this guide: https://yongweiwu.wordpress.com/2014/12/24/installing-clang-3-5-for-windows/

Also may i note that another cause that really stalled me when trying to find the cause of the problem is that if i try to compile the snippet using -O2 everything works fine due to the inlining that the compiler does!

I really hope that anyone could help me solve this problem because its driving me nuts!