在尝试使用Windows上的clang静态编译可执行文件时链接错误

时间:2015-04-19 06:34:44

标签: c++ gcc clang clang++

我最近一直试图在Windows上改变我的C ++工作,到目前为止,所有东西似乎都正常工作,除了一件事:制作完全静态的excecutables(没有任何外部dll依赖,如libgcc libstdc ++等......)。

让我举个例子。 我们有以下简单程序:

#include <string>

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

如果我们尝试使用以下行编译它:

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

我们收到以下链接错误:

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)

我们使用以下标志得到相同的结果:

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

应该注意的是,当使用g ++时,程序可以编译并与上述两行中的任何一行完美链接。显然当删除静态标志时,程序也可以用clang编译得很好。

这个bug一直在追我几个星期,所以昨晚我全力以赴,开始寻找可能导致它的任何事情。经过几个小时的挖掘,我认为我应该检查并比较两个编译器的中间输出。

查看clang生成的目标文件的符号,我看到了:

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

检查g ++生成的目标文件上的符号时,给了我:

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

正如您所看到的,g ++生成的目标文件中有一些内部符号根本不存在或者在clang生成的目标文件中有所不同,即:

  • 输入“00000000 r .eh_frame $ _ZStplIcSt11char_traitsIcESaIcEESbIT_T0_T1_ERKS6_S8_“缺少

(我认为它与异常处理有关)

  • 条目“00000000 t .text $ _ZStplIcSt11char_traitsIcESaIcEESbIT_T0_T1_ERKS6_S8_”已更改

(我相信这个也存在于clang对象文件中,作为第二个“00000000 t .text”条目)

我对这个问题没有真正深入的了解,但我的赌注是,在clang生成的目标文件中改变的第二个内部符号(我在上面提到的那个)是问题的根本原因。

这是clang编译器的错误,还是我做错了什么?

如果你问,我在使用本指南设置的Windows上使用LLVM v3.6和MinGW-w64 4.8.2:https://yongweiwu.wordpress.com/2014/12/24/installing-clang-3-5-for-windows/

另外我可能会注意到,在尝试查找问题原因时,另一个真正让我失望的原因是,如果我尝试使用-O2编译代码片段,由于编译器的内联工作,一切正常!

我真的希望有人能帮我解决这个问题,因为它让我疯了!

0 个答案:

没有答案