jimporter / mettle

A C++20 unit test framework
https://jimporter.github.io/mettle
BSD 3-Clause "New" or "Revised" License
122 stars 12 forks source link

Default libmettle build fails to be linked from c++ (g++) #32

Closed luav closed 6 years ago

luav commented 6 years ago

Majority of linux-es use g++ as default system compiler (c++) and default build of mettle refuses to be linked from the binaries built with c++ (g++):

$ g++ -std=c++14 -lmettle -o test_01_basic test_01_basic.cpp
/tmp/cc8wl2kf.o: In function `main':
test_01_basic.cpp:(.text+0x24): undefined reference to `mettle::detail::drive_tests(int, char const**, std::vector<mettle::compiled_suite<mettle::test_result ()>, std::allocator<mettle::compiled_suite<mettle::test_result ()> > > const&)'
collect2: error: ld returned 1 exit status

$ g++ --version
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609

But clang++ binaries link libmettle fine:

$ clang++ -std=c++14 -lmettle -o test_01_basic test_01_basic.cpp
$ clang++ --version
clang version 3.8.0-2ubuntu4 (tags/RELEASE_380/final)
Target: x86_64-pc-linux-gnu

Probably, it makes sense to perform default mettle build using default system compiler instead of clang++.

luav commented 6 years ago

All build files (build.bfg, build/build.ninja) use c++ as a compiler, which is g++. Then I don't understand why the libmettle is successfully linked from clang++ but not from g++ (which is used to build the library itself). The library itself is built fine and had the symbolds that can't be found by g++:

$ nm -gC /usr/local/lib/libmettle.so | grep drive_tests
000000000018d675 T mettle::detail::drive_tests(int, char const**, std::vector<mettle::compiled_suite<mettle::test_result ()>, std::allocator<mettle::compiled_suite<mettle::test_result ()> > > const&)
jimporter commented 6 years ago

With GCC (and often with other CC-like compilers), library files should be specified after the object (or source) files that require a symbol from the library. This should work:

g++ -std=c++14 -o test_01_basic test_01_basic.cpp -lmettle 

I'm actually a little surprised that it works under clang.

luav commented 6 years ago

@jimporter thaks a lot! It works! It would be nice to update the example in the tutorial to match any compiler (https://jimporter.github.io/mettle/tutorial/#building-the-test):

$ clang++ -std=c++14 -lmettle -o test_first test_first.cpp

to

$ c++ -std=c++14 -o test_first test_first.cpp -lmettle

PS I have a similar error in the CodeBlocks IDE but the order of linking there seems to be correct, which is weird:

g++ -Wnon-virtual-dtor -Winit-self -Wcast-align -Wundef -Wunreachable-code -Wmissing-include-dirs -Weffc++ -Wzero-as-null-pointer-constant -std=c++14 -fexceptions -fstack-protector-strong -DREVISION=1156/49969180201c -D_FORTIFY_SOURCE=2 -DFTRACE_GLOBAL -DMEMBERSHARE_BYCANDS -DINTEROVP_LINKS -DNOPREFILTER -DGESTCHAINS_MCANDS -DDYNAMIC_GAMMA -DMCCHAINS_RANKED -Wredundant-decls -Winline -Wswitch-default -Wmain -Wall -g -Wsuggest-final-types -Wsuggest-final-methods -DDEBUG -D_GLIBCXX_DEBUG -DTRACE=2 -DVALIDATE=2 -DUTEST -Wnon-virtual-dtor -Wredundant-decls -Wundef -Wunreachable-code -Wmissing-include-dirs -Weffc++ -Wzero-as-null-pointer-constant -std=c++14 -Iexport -Iinclude -Iexport/shared -Iimport -c /media/truecrypt1/projects/clustering/daoc/lib/tests/test_01_basic.cpp -o obj/Debug/tests/test_01_basic.o
g++ -L/usr/local/lib -o "bin/Debug/TestBasic" obj/Debug/tests/test_01_basic.o   -lstdc++fs -lmettle
obj/Debug/tests/test_01_basic.o: In function `main':
/usr/local/include/mettle/driver/lib_driver.hpp:18: undefined reference to `mettle::detail::drive_tests(int, char const**, std::__debug::vector<mettle::compiled_suite<mettle::test_result ()>, std::allocator<mettle::compiled_suite<mettle::test_result ()> > > const&)'
collect2: error: ld returned 1 exit status
jimporter commented 6 years ago

It would be nice to update the example in the tutorial to match any compiler (https://jimporter.github.io/mettle/tutorial/#building-the-test)

Whooooops! Fixed.

As for the CodeBlocks thing, I'm not sure what the issue is there, but maybe you need to swap -lstdc++fs and -lmettle? Or maybe one of the compilation options is doing something weird? I'm not familiar with all of them and maybe one of them is affecting the ABI. (For example, some of your -Iwhatever options might be causing GCC to load a different version of the C++ standard library and that's causing an ABI incompatibility. That's just a guess though.)

luav commented 6 years ago

Thank you for the hints, I will fight with the IDE :-)

luav commented 6 years ago

It was -D_GLIBCXX_DEBUG

jimporter commented 6 years ago

Ah yeah, that would probably do it. Good to see it's working now!