Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Undefined reference when linking with googletest

When i try to build googletest (and googlemock) 1.8.0 i get an undefined reference to MakeAndRegisterTestInfo when i try to link with libgtest.a. It works fine with version 1.7.0 with the same cmake/make setup. I guess i could use 1.7.0 but then i need to download and build gmock separately.

CMakeFiles/unittest.dir/test/test_led.cpp.o: In function `__static_initialization_and_destruction_0(int, int)':
    test_led.cpp:(.text+0x23d): undefined reference to `testing::internal::MakeAndRegisterTestInfo(char const*, char const*, char const*, char const*, void const*, void (*)(), void (*)(), testing::internal::TestFactoryBase*)'
    collect2: error: ld returned 1 exit status
    make[2]: *** [bin/unittest] Error 1
    make[1]: *** [CMakeFiles/unittest.dir/all] Error 2
    make[1]: *** Waiting for unfinished jobs....

Other symbols in the libgtest.a works perfectly fine (example ::testing::InitGoogleTest) but as soon as i try to add a test with the macro TEST_F i get this error.

This is my testcase setup:

#include "gtest/gtest.h"

namespace {
// The fixture for testing (used by TEST_F).
class Foo : public ::testing::Test {
protected:
    Foo();
    virtual ~Foo() {};    
    virtual void SetUp();
    virtual void TearDown();
};

Foo::Foo() {
};

void Foo::SetUp()
{
};

void Foo::TearDown()
{
};

TEST_F(Foo, Init) {
};
} // namespace

int main(int argc, char **argv)
{
    ::testing::InitGoogleTest(&argc, argv);
    int ret = RUN_ALL_TESTS();
    return ret;
}

Cmake google test snippet: It downloads from a local folder. It builds and i get a libgtest.a file.

### Unit test ###
# Google test
ExternalProject_Add(EXT_googletest
                    PREFIX ${CMAKE_CURRENT_BINARY_DIR}
                    DOWNLOAD_COMMAND ""
                    SOURCE_DIR ${CMAKE_SOURCE_DIR}/../external/googletest
                    BUILD_COMMAND make all
                    # Disable install step
                    INSTALL_COMMAND "")
# Create a libgtest target to be used as a dependency by test programs
set(LIBGTEST_STATIC ${CMAKE_CURRENT_BINARY_DIR}/.../googlemock/gtest/libgtest.a)

add_executable(unittest
              "test/test_foo.cpp")
target_link_libraries(unittest main_app_lib
                               ${LIBGTEST_STATIC}
                               ${CMAKE_THREAD_LIBS_INIT})

NM output libgtest.a 1.8.0

user@system$ nm .../libgtest.a |grep MakeAndRegisterTestInfo
000000000000743a T _ZN7testing8internal23MakeAndRegisterTestInfoEPKcS2_S2_S2_NS0_12CodeLocationEPKvPFvvES7_PNS0_15TestFactoryBaseE

NM output libgtest.a 1.7.0 (working file)

user@system$ nm .../libgtest.a |grep MakeAndRegisterTestInfo
0000000000005968 T _ZN7testing8internal23MakeAndRegisterTestInfoEPKcS2_S2_S2_PKvPFvvES6_PNS0_15TestFactoryBaseE

Solved:

There was an old version of google test installed on build machine which headers were used by cmake.

like image 914
user1178014 Avatar asked Aug 29 '16 13:08

user1178014


1 Answers

@user1178014 answered his own question but since there are no posted answers I am writing it up:

If you downloaded the gtest source directly and used the make install from the downloaded gtest repository it may have installed header files under /usr/local/include/gtest. If you later use apt-get to install the libgtest-dev debian package it installs the header files under /usr/include/gtest. If the version installed from the debian package is newer, your Makefile can pick up the older header files from /usr/include and give you link errors even though you are correctly linking the new libgtest.a archive.

The solution is to look for /usr/local/include/gtest and /usr/include/gtest to see if they both exist. If they do then delete the older directory. If /usr/include/gtest is the older directory, you may want to remove it by uninstalling the libgtest-dev package.

like image 136
nmgeek Avatar answered Nov 15 '22 10:11

nmgeek