Using @llonesmiz , a number of issues were identified.
1. Libraries should be indicated after the objects and sources that use them.
As described here :
The traditional behavior of linkers is to look for external functions from left to right in the libraries specified on the command line. This means that the library containing the function definition should appear after any source files or files of objects that use it. This includes libraries, short-cut -l, as shown in the following command:
$ gcc -Wall calc.c -lm -o calc (correct order)
With some linkers, reverse ordering (placing the -lm option in front of the file that uses it) will result in an error,
$ cc -Wall -lm calc.c -o calc (incorrect order)
main.o: In function 'main':
main.o(.text+0xf): undefined reference to 'sqrt'
because there is no library or object file containing sqrt after 'calc.c. the -lm parameter should appear after the file 'calc.c
2. Library paths must be explicitly specified.
If no lib paths are specified, the linker can search libraries in a series of default folders, thus loading another library. This is what happened in my case - I wanted to link boost_unit_test_framework , but didnโt specify the path, because I assumed that the linker would look in the current folder. What happens at runtime is, after all, if the dll is in the same folder with exe it will find it.
It was a little strange for me that the linker would find lib, as it was named ibboost_unit_test_framework-mgw47-mt-1_52.dll . When I tried to contact a non-existent library, the complainer complained, so I assumed that it wasnโt and the MinGW linker ignored these suffixes.
After some more research, I found this article about the MinGW library paths . MinGW folders search for libs, which can be found at gcc -print-search-dirs output. The article also contains bash magic to understand this conclusion:
gcc -print-search-dirs | sed '/^lib/b 1;d;:1;s,/[^/.][^/]*/\.\./,/,;t 1;s,:[^=]*=,:;,;s,;,; ,g' | tr \; \\012 | grep -v '^ */'
A list of these folders opens. gcc will not, by default, look in the current libs directory. I looked in each of them and the lib that was loaded - libboost_unit_test_framework.a , the static lib.
This leads to the fact that another question is worth mentioning:
3. Static and dynamic layout
I did not indicate if I want boost_unit_test_framework to bind statically or dynamically. In this case, gcc prefers dynamic linking :
Because of these advantages, gcc compiles programs to use shared libraries by default for most systems, if available. Whenever the static library 'LibNAME.a will be used to communicate with the -lNAME option, the compiler first checks an alternative shared library with the same name and the' .so extension.
( so is an extension for dynamic libraries on Unix - on Windows, the equivalent is dll .)
So, it happened that gcc looking for libboost_unit_test_framework.dll in all its default folders, but could not find them. He then searched libboost_unit_test_framework.a and statically linked to it. This led to errors because the sources have #define BOOST_TEST_DYN_LINK and therefore expect lib to be dynamically linked.
To provide static or dynamic binding, -Wl,-Bstatic and -Wl,-Bdynamic linker options come into play as described here .
If I tell the linker that I need dynamic linking:
$ g++ -I/e/code/boost_1_52_0 runner.cpp test1.cpp -o runner -Wl,Bdynamic -lboost_unit_test_framework
This will fail because the linker cannot find the dll .
4.Summary
The problems were:
- libraries listed before sources that used them
- lib path not specified
- link type not specified
- The library name was incorrect.
Final working team:
$ g++ -I/e/code/boost_1_52_0 -o runner runner.cpp test1.cpp -L. -Wl,-Bdynamic -lboost_unit_test_framework-mgw47-mt-1_52