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.0

    LIBS = -L(GTESTLIBS)lgtestINCLUDE=I(GTEST_LIBS) -lgtest INCLUDE = -I(GTEST_INCLUDE)

    TARGET = MyClassTest
    OBJFILES = MyClass.o MyClassTest.o
    FILES = MyClass.cpp MyClassTest.cpp

    $(TARGET): (OBJFILES)(OBJFILES) (CXX) $(LIBS) -o $(TARGET) $^
    rm *.o

    $(OBJFILES): (FILES)(FILES) (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 to testing::internal::AssertHelper::operator=(testing::Message const&) const' MyClassTest.cpp:(.text+0x19f): undefined reference totesting::internal::AssertHelper::~AssertHelper()'
    MyClassTest.cpp:(.text+0x1d5): undefined reference to testing::internal::AssertHelper::~AssertHelper()' MyClassTest.o: In functionmain':
    MyClassTest.cpp:(.text+0x224): undefined reference to testing::InitGoogleTest(int*, char**)' MyClassTest.cpp:(.text+0x229): undefined reference totesting::UnitTest::GetInstance()'
    MyClassTest.cpp:(.text+0x231): undefined reference to testing::UnitTest::Run()' MyClassTest.o: In function__static_initialization_and_destruction_0(int, int)':
    MyClassTest.cpp:(.text+0x39b): undefined reference to testing::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 function 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> >*)': 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 function 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> >*)': 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 function testing::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 1

    Was funktioniert hier denn nicht?



  • Du hast vergessen, irgend eine Lib zu linken.


  • Mod

    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 function testing::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 to pthread\_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 to pthread_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 function testing::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 to pthread\_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 to pthread\_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 to pthread\_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 to pthread_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


  • Mod

    Da scheint noch die Threadbibliothek zu felhen. -lpthread.



  • Ja, das wars. Vielen Dank.



  • Ist übrigens der Linker, der sich beschwert. 😉


Anmelden zum Antworten