Was will mir der Compiler sagen
-
Ich habe gerade das Google C++ Testing framework auf meinem Mac installiert und erfolgreich getestet. Jetzt wollte ich das Beispiel auf einer Linux Maschine (da hab ich keine Root-Rechte) installieren und ebenfalls testen.
Hier der Beispiel Code
MyClass.h#ifndef MYCLASS_H_ #define MYCLASS_H_ class MyClass { public: int method1( int a, int b ); }; #endif /* MYCLASS_H_ */MyClass.cpp
#include "MyClass.h" int MyClass::method1( int a, int b ) { return 7; }MyClassTest.cpp
#include "MyClass.h" #include "gtest/gtest.h" namespace { // The fixture for testing class Foo. class MyClassTest : public ::testing::Test { protected: // You can remove any or all of the following functions if its body // is empty. MyClassTest() { // You can do set-up work for each test here. } virtual ~MyClassTest() { // You can do clean-up work that doesn't throw exceptions here. } // If the constructor and destructor are not enough for setting up // and cleaning up each test, you can define the following methods: virtual void SetUp() { // Code here will be called immediately after the constructor (right // before each test). } virtual void TearDown() { // Code here will be called immediately after each test (right // before the destructor). } // Objects declared here can be used by all tests in the test case for Foo. }; TEST_F(MyClassTest, MethodBarDoesAbc) { MyClass myClass; EXPECT_EQ( 7, myClass.method1(1,1) ); } } // namespace int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }So sieht mein Makefile aus:
CXX = g++
CFLAGS =GTEST_INCLUDE = /pfad/zu/gtest-1.6.0/include
GTEST_LIBS = /pfad/zu/gtest-1.6.0LIBS = -L(GTEST_INCLUDE)
TARGET = MyClassTest
OBJFILES = MyClass.o MyClassTest.o
FILES = MyClass.cpp MyClassTest.cpp$(TARGET): (CXX) $(LIBS) -o $(TARGET) $^
rm *.o$(OBJFILES): (CXX) $(CFLAGS) $(INCLUDE) -c $^
all:$(TARGET)
clean:
rm *.o $(TARGET)Die Pfade im Makefile sind korrekt gesetzt und auch die Bibliothek konnte ich korrekt übersetzen und es läuft auf meinem Mac einwandfrei. Auf der Linux-Maschine erhalte ich aber folgende Fehlerausgabe:
/C++/GTestDemo> make
g++ -I/pfad/zu/gtest-1.6.0/include -c MyClass.cpp MyClassTest.cpp
g++ -L/pfad/zu/gtest-1.6.0 -lgtest -o MyClassTest MyClass.o MyClassTest.o
MyClassTest.o: In function(anonymous namespace)::MyClassTest::MyClassTest()': MyClassTest.cpp:(.text+0x14): undefined reference totesting::Test::Test()'
MyClassTest.o: In function(anonymous namespace)::MyClassTest::~MyClassTest()': MyClassTest.cpp:(.text+0x45): undefined reference totesting::Test::~Test()'
MyClassTest.o: In function(anonymous namespace)::MyClassTest\_MethodBarDoesAbc\_Test::TestBody()': MyClassTest.cpp:(.text+0x180): undefined reference totesting::internal::AssertHelper::AssertHelper(testing::TestPartResult::Type, char const*, int, char const*)'
MyClassTest.cpp:(.text+0x193): undefined reference totesting::internal::AssertHelper::operator=(testing::Message const&) const' MyClassTest.cpp:(.text+0x19f): undefined reference totesting::internal::AssertHelper::~AssertHelper()'
MyClassTest.cpp:(.text+0x1d5): undefined reference totesting::internal::AssertHelper::~AssertHelper()' MyClassTest.o: In functionmain':
MyClassTest.cpp:(.text+0x224): undefined reference totesting::InitGoogleTest(int*, char**)' MyClassTest.cpp:(.text+0x229): undefined reference totesting::UnitTest::GetInstance()'
MyClassTest.cpp:(.text+0x231): undefined reference totesting::UnitTest::Run()' MyClassTest.o: In function__static_initialization_and_destruction_0(int, int)':
MyClassTest.cpp:(.text+0x39b): undefined reference totesting::internal::MakeAndRegisterTestInfo(char const*, char const*, char const*, char const*, void const*, void (*)(), void (*)(), testing::internal::TestFactoryBase*)' MyClassTest.o:(.rodata+0x170): undefined reference totypeinfo for testing::Test'
MyClassTest.o: In functiontesting::internal::scoped\_ptr<std::basic\_string<char, std::char\_traits<char>, std::allocator<char> > >::reset(std::basic\_string<char, std::char_traits<char>, std::allocator<char> >*)': MyClassTest.cpp:(.text.\_ZN7testing8internal10scoped\_ptrISsE5resetEPSs[testing::internal::scoped\_ptr<std::basic\_string<char, std::char\_traits<char>, std::allocator<char> > >::reset(std::basic\_string<char, std::char_traits<char>, std::allocator<char> >*)]+0x24): undefined reference totesting::internal::IsTrue(bool)'
MyClassTest.o: In functiontesting::internal::scoped\_ptr<std::basic\_stringstream<char, std::char\_traits<char>, std::allocator<char> > >::reset(std::basic\_stringstream<char, std::char_traits<char>, std::allocator<char> >*)': MyClassTest.cpp:(.text.\_ZN7testing8internal10scoped\_ptrISt18basic\_stringstreamIcSt11char\_traitsIcESaIcEEE5resetEPS6_[testing::internal::scoped\_ptr<std::basic\_stringstream<char, std::char\_traits<char>, std::allocator<char> > >::reset(std::basic\_stringstream<char, std::char_traits<char>, std::allocator<char> >*)]+0x23): undefined reference totesting::internal::IsTrue(bool)'
MyClassTest.o: In functiontesting::AssertionResult testing::internal::CmpHelperEQ<int, int>(char const*, char const*, int const&, int const&)': MyClassTest.cpp:(.text.\_ZN7testing8internal11CmpHelperEQIiiEENS\_15AssertionResultEPKcS4\_RKT\_RKT0_[testing::AssertionResult testing::internal::CmpHelperEQ<int, int>(char const*, char const*, int const&, int const&)]+0x35): undefined reference totesting::AssertionSuccess()'
MyClassTest.cpp:(.text._ZN7testing8internal11CmpHelperEQIiiEENS_15AssertionResultEPKcS4_RKT_RKT0_[testing::AssertionResult testing::internal::CmpHelperEQ<int, int>(char const*, char const*, int const&, int const&)]+0x8f): undefined reference to `testing::internal::EqFailure(char const*, char const*, testing::internal::String const&, testing::internal::String const&, bool)'
collect2: ld returned 1 exit status
make: *** [MyClassTest] Error 1Was funktioniert hier denn nicht?
-
Du hast vergessen, irgend eine Lib zu linken.
-
Setz das -lgtest ganz an's Ende. Die Reihenfolge spielt beim gcc eine Rolle.
-
Ich hab jetzt mal lgtest ganz ans Ende gesetzt, d.h.
$(CXX) -o $(TARGET) $^ $(LIBS)
Jetzt sieht die Fehlermeldung etwas anders aus:
/C++/GTestDemo> make
g++ -o MyClassTest MyClass.o MyClassTest.o -L/pfad/zu/gtest-1.6.0 -lgtest
/pfad/zu/gtest-1.6.0/libgtest.a(gtest-all.o): In functiontesting::internal::ThreadLocal<testing::TestPartResultReporterInterface*>::~ThreadLocal()': gtest-all.cc:(.text.\_ZN7testing8internal11ThreadLocalIPNS\_31TestPartResultReporterInterfaceEED2Ev[\_ZN7testing8internal11ThreadLocalIPNS\_31TestPartResultReporterInterfaceEED5Ev]+0x16): undefined reference topthread_getspecific'
gtest-all.cc:(.text._ZN7testing8internal11ThreadLocalIPNS_31TestPartResultReporterInterfaceEED2Ev[_ZN7testing8internal11ThreadLocalIPNS_31TestPartResultReporterInterfaceEED5Ev]+0x2b): undefined reference topthread\_key\_delete' /pfad/zu/gtest-1.6.0/libgtest.a(gtest-all.o): In functiontesting::internal::ThreadLocal<std::vector<testing::internal::TraceInfo, std::allocatortesting::internal::TraceInfo > >::~ThreadLocal()':
gtest-all.cc:(.text._ZN7testing8internal11ThreadLocalISt6vectorINS0_9TraceInfoESaIS3_EEED2Ev[_ZN7testing8internal11ThreadLocalISt6vectorINS0_9TraceInfoESaIS3_EEED5Ev]+0x16): undefined reference topthread_getspecific' gtest-all.cc:(.text.\_ZN7testing8internal11ThreadLocalISt6vectorINS0\_9TraceInfoESaIS3\_EEED2Ev[\_ZN7testing8internal11ThreadLocalISt6vectorINS0\_9TraceInfoESaIS3\_EEED5Ev]+0x2b): undefined reference topthread_key_delete'
/pfad/zu/gtest-1.6.0/libgtest.a(gtest-all.o): In functiontesting::internal::ThreadLocal<std::vector<testing::internal::TraceInfo, std::allocator<testing::internal::TraceInfo> > >::GetOrCreateValue() const': gtest-all.cc:(.text.\_ZNK7testing8internal11ThreadLocalISt6vectorINS0\_9TraceInfoESaIS3\_EEE16GetOrCreateValueEv[testing::internal::ThreadLocal<std::vector<testing::internal::TraceInfo, std::allocator<testing::internal::TraceInfo> > >::GetOrCreateValue() const]+0x18): undefined reference topthread_getspecific'
gtest-all.cc:(.text._ZNK7testing8internal11ThreadLocalISt6vectorINS0_9TraceInfoESaIS3_EEE16GetOrCreateValueEv[testing::internal::ThreadLocal<std::vector<testing::internal::TraceInfo, std::allocatortesting::internal::TraceInfo > >::GetOrCreateValue() const]+0x7f): undefined reference topthread\_setspecific' /pfad/zu/gtest-1.6.0/libgtest.a(gtest-all.o): In functiontesting::internal::ThreadLocaltesting::TestPartResultReporterInterface*::CreateKey()':
gtest-all.cc:(.text._ZN7testing8internal11ThreadLocalIPNS_31TestPartResultReporterInterfaceEE9CreateKeyEv[testing::internal::ThreadLocaltesting::TestPartResultReporterInterface*::CreateKey()]+0x16): undefined reference topthread\_key\_create' /pfad/zu/gtest-1.6.0/libgtest.a(gtest-all.o): In functiontesting::internal::ThreadLocal<std::vector<testing::internal::TraceInfo, std::allocatortesting::internal::TraceInfo > >::CreateKey()':
gtest-all.cc:(.text._ZN7testing8internal11ThreadLocalISt6vectorINS0_9TraceInfoESaIS3_EEE9CreateKeyEv[testing::internal::ThreadLocal<std::vector<testing::internal::TraceInfo, std::allocatortesting::internal::TraceInfo > >::CreateKey()]+0x16): undefined reference topthread\_key_create' /pfad/zu/gtest-1.6.0/libgtest.a(gtest-all.o): In functiontesting::internal::ThreadLocaltesting::TestPartResultReporterInterface*::GetOrCreateValue() const':
gtest-all.cc:(.text._ZNK7testing8internal11ThreadLocalIPNS_31TestPartResultReporterInterfaceEE16GetOrCreateValueEv[testing::internal::ThreadLocaltesting::TestPartResultReporterInterface*::GetOrCreateValue() const]+0x16): undefined reference topthread_getspecific' gtest-all.cc:(.text.\_ZNK7testing8internal11ThreadLocalIPNS\_31TestPartResultReporterInterfaceEE16GetOrCreateValueEv[testing::internal::ThreadLocal<testing::TestPartResultReporterInterface*>::GetOrCreateValue() const]+0x7d): undefined reference topthread_setspecific'
collect2: ld returned 1 exit status
make: *** [MyClassTest] Error 1
-
Da scheint noch die Threadbibliothek zu felhen. -lpthread.
-
Ja, das wars. Vielen Dank.
-
Ist übrigens der Linker, der sich beschwert.
