user821596
user821596

Reputation: 97

Clang++ undefined reference errors with GMock

I did a dist-upgrade yesterday and now I'm getting undefined reference errors when I compile tests using GMock and clang++; it is working fine with g++ though. GTest and GMock are compiled from source and installed with Cmake.

I was wondering if anyone knows why it isn't linking properly?

I'm compiling with:

clang++-3.7 -Wall -Wextra -pedantic -std=c++11 -Wshadow a.cpp -o a.out -lgtest -lgmock -pthread

I'm gettting these errors:

/tmp/a-bb74fa.o: In function `testing::internal::FunctionMockerBase<int ()>::DescribeDefaultActionTo(std::tuple<> const&, std::ostream*) const':
a.cpp:(.text._ZNK7testing8internal18FunctionMockerBaseIFivEE23DescribeDefaultActionToERKSt5tupleIJEEPSo[_ZNK7testing8internal18FunctionMockerBaseIFivEE23DescribeDefaultActionToERKSt5tupleIJEEPSo]+0x8e): undefined reference to `testing::internal::FormatFileLocation(char const*, int)'
/tmp/a-bb74fa.o: In function `testing::internal::ExpectationBase::DescribeLocationTo(std::ostream*) const':
a.cpp:(.text._ZNK7testing8internal15ExpectationBase18DescribeLocationToEPSo[_ZNK7testing8internal15ExpectationBase18DescribeLocationToEPSo]+0x43): undefined reference to `testing::internal::FormatFileLocation(char const*, int)'
clang: error: linker command failed with exit code 1 (use -v to see invocation)

make: *** [a.out] Error 1

The source code:

#include<gtest/gtest.h>
#include<gmock/gmock.h>
#include <iostream>

class printable{
    public:
        virtual int print() = 0;
};

class A{
    public:
        A( printable* b ) :
            obj( b )
        {}
        int doit(){return obj->print();}
    private:
        printable* obj;
};

class MockPrintable : public printable{
    public:
        MOCK_METHOD0( print, int() );
};

TEST( test, returnStuff ){
    MockPrintable b;
    A a( &b );
    EXPECT_CALL( b, print() )
    .WillOnce( testing::Return( 1 ) )
    .WillOnce( testing::Return( 2 ) )
    .WillOnce( testing::Return( 3 ) );
    EXPECT_EQ( 1,a.doit() );
    EXPECT_EQ( 2,a.doit() );
    EXPECT_EQ( 3,a.doit() );
}

int main( int argc, char* argv[] ){
    ::testing::InitGoogleMock( &argc, argv );
    return RUN_ALL_TESTS();
}

edit:

I've narrowed the problem down somewhat to libgcc-5-dev and libstdc++-5-dev packages.

libstdc++-5-dev causes this error:

/usr/local/include/gtest/gtest.h:54:10: fatal error: 'limits' file not found
#include <limits>

libstdc++-5-dev causes a lot of undefined reference errors relating to gmock.

I can't seem to link against older versions using -l and -L. Searching around turns up results advising against trying to statically link against these and to use older versions of the compiler instead. But, the compiler dependencies now requires the same *-5-dev packages according to apt-get.

You can prevent apt-get from using these package by inserting this into /etc/apt/preferences:

Package: libgcc-5-dev
Pin: release *
Pin-Priority: -1

Package: libstdc++-5-dev
Pin: release *
Pin-Priority: -1

and just dist-upgrade from there, but it prevents g++, clang and other things from updating so it isn't worth it; apt-get suggests removing clang as part of dist-upgrade anyhow.

Lastly, I tried to use the precompiled-binary for clang-3.8 from their website but it gave me a humongous wall of undefined reference to std::< everything >. I did get a hello world program to compile though so it can at least find std::cout and std::endl.

Upvotes: 1

Views: 1907

Answers (1)

Jan Henke
Jan Henke

Reputation: 875

I think you are victim of the ABI change introduced with libstdc++ in v5. They had to change the implementation of std::string, because C++11 mandates a particular implementation while was not the case before. That lead to changes in symbol names. The problem is specific to migrating from pre-v5 libstdc++ (gcc) to v5 or higher and should therefore not happen again.

Upvotes: 1

Related Questions