8

below is what I execute

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

below is the result of that

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

Below is result of checking libraries regarding to mentioned symobls (I failed to format it in appropriate way)

`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`

As wee see symbols are existing in the libraries and libraries are on the place referred by the corresponding -L command line options.
So, why "undefined refernce"????

MD XF
  • 7,860
  • 7
  • 40
  • 71
OlegG
  • 975
  • 3
  • 10
  • 30

1 Answers1

16

It's very common error, with a very simple solution: Place the libraries you link with after the source and object files.


If an object (or source) file A depends on a library B, then A must come before B on the command line when linking. This is because of how the GNU (and possibly other) linkers solve symbol dependencies.

If doing it the opposite (and wrong) way

g++ -lB A.cpp

then when the linker loads the library B, there are no dependencies on any of the functions in the library, so the linker just discards that library.

So the right way is to put the library last

g++ A.cpp -lB

This is the reason many examples will always put libraries last on the command line.

So for the command line of the question, it should instead be

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

This order is also important for inter-library dependencies. If library L1 depends on library L2, then L1 must be before L2 on the command line.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • 1
    @OlegG The GNU linker looks for dependencies _after_ it loads the code to be linked. So if a library is before the object file it is used in (on the command line) the linker will see that there are no references to any of the functions in the library, and ignore the library. – Some programmer dude Sep 18 '12 at 08:15
  • And, seems, it is specific for Windows GNU compiler. Correct? – OlegG Sep 18 '12 at 08:18
  • 1
    @OlegG It used to be so for many linkers, but I don't really know. To be safe always place libraries after source and/or object files, it's also kind of customary. – Some programmer dude Sep 18 '12 at 08:29
  • 1
    It's certainly still true for GNU ld on my GNU/Linux box. – Jack Kelly Sep 19 '12 at 09:09
  • I've been having this problem, and stumbled onto this Q. I can't quite understand what Joachim's saying on hist original A, could someone please elaborate? – Charles Noon Jul 28 '14 at 21:58
  • How can I handle it when using CMake? – Mariusz Jaskółka Feb 22 '19 at 07:13
  • @CharlesNoon I know it's a few years ago, and I hope you have figured it out by now, but if not then I've updated the answer to explain it better. – Some programmer dude Feb 22 '19 at 07:22
  • 1
    @jaskmar If you use [`target_link_libraries`](https://cmake.org/cmake/help/latest/command/target_link_libraries.html) then CMake will to the right thing automatically. – Some programmer dude Feb 22 '19 at 07:23