MinGW + Boost:未定义引用`WSAStartup @ 8'

Ole*_*egG 8 c++ windows mingw wsastartup

以下是我执行的内容

D:\Just4Fun\software\>make -f Makefile.hands stest
g++.exe -g -D_WIN32_WINNT=0x0601 -ID:\Boost\boost_1_51_0 -LD:\Boost\boost_1_51_0\stage\lib -LD:\MinGW\lib -lboost_system-mgw46-d-1_51 -lboost_filesystem-mgw46-d-1_51 -lboost_iostreams-mgw46-d-1_51 -lws2_32 -lwsock32 -o TestSerial.exe TestSerial.cpp

以下是结果

C:\Users\oleg\AppData\Local\Temp\ccXpC7RG.o: In function 'ZN5boost4asio6detail17winsock_init_base7startupERNS2_4dataEhh': D:/Boost/boost_1_51_0/boost/asio/detail/impl/winsock_init.ipp:39: undefined reference to 'WSAStartup@8'C:\Users\oleg\AppData\Local\Temp\ccXpC7RG.o: In function 'ZN5boost4asio6detail17winsock_init_base7cleanupERNS2_4dataE': D:/Boost/boost_1_51_0/boost/asio/detail/impl/winsock_init.ipp:48: undefined reference to 'WSACleanup@0' collect2: ld returned 1 exit status make: *** [stest] Error 1

下面是检查库提到的symobls的结果(我没有以适当的方式格式化它)

`d:\ MinGW\lib> nm -C libws2_32.a | grep WSAStartup
00000000 T WSAStartup @ 8
00000000 I imp _WSAStartup @ 8

d:\ MinGW\lib> nm -C libws2_32.a | grep WSACleanup
00000000 T WSACleanup @ 0
00000000 I imp _WSACleanup @ 0

d:\ MinGW\lib> nm -C libwsock32.a | grep WSACleanup
00000000 T WSACleanup @ 0
00000000 I imp _WSACleanup @ 0

d:\ MinGW\lib> nm -C libwsock32.a | grep WSAStartup
00000000 T WSAStartup @ 8
00000000 I imp _WSAStartup @ 8`

我们看到符号存在于库中,库位于相应的-L命令行选项所引用的位置.
那么,为什么"未定义参考"????

Som*_*ude 15

这是一个非常常见的错误,有一个非常简单的解决方案:在源文件和目标文件之后放置链接的库.


如果对象(或源)文件A依赖于库B,则链接时A必须位于命令行上的B之前.这是因为GNU(以及可能的其他)链接器如何解决符号依赖性.

如果这样做是相反的(和错误的)方式

g++ -lB A.cpp
Run Code Online (Sandbox Code Playgroud)

然后当链接器加载库B时,库中的任何函数都没有依赖关系,因此链接器只丢弃该库.

所以正确的方法是将库放在最后

g++ A.cpp -lB
Run Code Online (Sandbox Code Playgroud)

就是这个原因很多例子将始终把库最后在命令行上.

因此,对于问题的命令行,它应该是

g++.exe -g -D_WIN32_WINNT=0x0601 -ID:\Boost\boost_1_51_0 \
    -LD:\Boost\boost_1_51_0\stage\lib -LD:\MinGW\lib \
    -o TestSerial.exe TestSerial.cpp \
    -lboost_system-mgw46-d-1_51 -lboost_filesystem-mgw46-d-1_51 -lboost_iostreams-mgw46-d-1_51 -lws2_32 -lwsock32
Run Code Online (Sandbox Code Playgroud)

此顺序对于库间依赖性也很重要.如果库L1依赖于库L2,那么L1必须在命令行上的L2之前.