10

I have a simple test file, TestMe.cpp:

#include <gtest/gtest.h>

TEST(MyTest, SomeTest) {
  EXPECT_EQ(1, 1);
}

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

I have Google Test built as a static library. (I can provide the makefile if it's relevant.)

I can compile TestMe.cpp from a command-line with no problem:

g++ TestMe.cpp -IC:\gtest-1.5.0\gtest-1.5.0\include -L../gtest/staticlib -lgtest -o TestMe.exe

It runs as expected.

However, I cannot get this to compile in Qt. My Qt project file, in the same directory:

SOURCES += TestMe.cpp
INCLUDEPATH += C:\gtest-1.5.0\gtest-1.5.0\include
LIBS += -L../gtest/staticlib -lgtest

This results in 17 "unresolved external symbol" errors related to gtest functions.

I'm pulling my hair out here, as I'm sure it's something simple. Any ideas?

Here are some of the external symbols that are undefined:

TestMe.obj:-1: error:  unresolved external symbol "public: int __thiscall testing::UnitTest::Run(void)" (?Run@UnitTest@testing@@QAEHXZ) referenced in function _main
TestMe.obj:-1: error:  unresolved external symbol "public: static class testing::UnitTest * __cdecl testing::UnitTest::GetInstance(void)" (?GetInstance@UnitTest@testing@@SAPAV12@XZ) referenced in function _main
TestMe.obj:-1: error:  unresolved external symbol "void __cdecl testing::InitGoogleTest(int *,char * *)" (?InitGoogleTest@testing@@YAXPAHPAPAD@Z) referenced in function _main
TestMe.obj:-1: error:  unresolved external symbol "public: __thiscall testing::internal::AssertHelper::~AssertHelper(void)" (??1AssertHelper@internal@testing@@QAE@XZ) referenced in function "private: virtual void __thiscall MyTest_SomeTest_Test::TestBody(void)" (?TestBody@MyTest_SomeTest_Test@@EAEXXZ)
Dave Mateer
  • 17,608
  • 15
  • 96
  • 149

3 Answers3

7

I never could get this to work as a static library, but it's working as a DLL.

First, I had to build Google Test as a DLL. I did not have any success getting this to work in Visual Studio, so I just used mingw32-make. You can use the Makefile provided in the source, making the following changes:

gtest-all.o : $(GTEST_SRCS_)
    $(CXX) $(CPPFLAGS) -DGTEST_CREATE_SHARED_LIBRARY=1 -I$(GTEST_DIR) $(CXXFLAGS) -c \
            $(GTEST_DIR)/src/gtest-all.cc

gtest_main.o : $(GTEST_SRCS_)
    $(CXX) $(CPPFLAGS) -DGTEST_CREATE_SHARED_LIBRARY=1 -I$(GTEST_DIR) $(CXXFLAGS) -c \
            $(GTEST_DIR)/src/gtest_main.cc

gtest.dll : gtest-all.o
    $(CXX) -shared -o $@ $^ -Wl,--out-implib,gtest_dll.lib

gtest_main.dll : gtest-all.o gtest_main.o
    $(CXX) -shared -o $@ $^ -Wl,--out-implib,gtest_main_dll.lib

Then, when compiling your test project, you must:

  • Define GTEST_LINKED_AS_SHARED_LIBRARY=1
  • Set a library reference to either gtest_dll.lib or gtest_main_dll.lib.
  • Paste gtest.dll or gtest_main.dll in the same directory as your executable.

(My understanding is that you use gtest_main only if you are NOT providing your own main() function.)

Here is a sample Qt pro file based on the one I have this is (finally!) working:

DEFINES += GTEST_LINKED_AS_SHARED_LIBRARY=1
SOURCES += main.cpp MyClassTests.cpp
INCLUDEPATH += ../path/to/gtest/includes
LIBS += -L../path/to/gtest/libraries -lgtest_dll \
    -L../ClassLibrary/bin -lMyClass
CONFIG += console
Dave Mateer
  • 17,608
  • 15
  • 96
  • 149
  • Thanks a lot for this!. I also did this with Qt5, mingw4.7.2 and gtest 1.6.0. I did not need to define GTEST_LINKED_AS_SHARED_LIBRARY=1 and instead of -lgtest_dll, I did -lgtest. Also note that the Makefile also contains a target to build a sample program, this breaks by the changes above (instead just make gtest.dll) – Thirler Feb 06 '13 at 07:54
  • Can you please explain: is MyClassTests.cpp contains second main function(for tests)? I have issus with two main functions in build http://stackoverflow.com/questions/37765182/multiple-main-delcaration-in-qtcreator-project-which-uses-googletest And what is ClassLibrary & ClassLibrary/bin dir? – Vyacheslav Jun 11 '16 at 16:05
3

I'm using Qt + gtest/gmock without any issues. I've just tested all possible combinations of absolute/relative paths with different slashes, but I couldn't reproduce your problem. Have you checked the contents of "LIBS" variable from Makefile.Debug generated by qmake?

Here's some generic piece of advice: don't use any absolute paths, because your code won't compile on other machines than your own, unless you'll download it to exacly same location (which might not be possible due to different Qt setup, etc.). Use relative paths instead, also for 3rd party libs.

I keep the 3rd party libraries in version control system (you use one, right?). I have a "3rdparty" directory and for each project that uses those libs, I add svn:external property pointing to explicitly specified version of 3rd party lib. The last part is important, because it ensures that you'll be able to build every revision of your project, even when you update 3rd party library.

chalup
  • 8,358
  • 3
  • 33
  • 38
  • Good advice. What you outline above (relative paths, svn) is essentially what we use here. (Although we're not taking advantage of svn:external.) I was going to worry about restructuring after I got it working. The Makefile.Debug looks OK. Are you on Windows? Because this is all working fine on Linux ... I'm only having problems on Windows. – Dave Mateer May 06 '10 at 19:26
  • Could you pastebin your qmake project file? Did you build gtest and gmock by running mingw32-make in both 'make' directories? – bbigras Dec 07 '10 at 17:40
  • 4
    Here's gmock.pro (http://pastebin.com/mKqS3Mxk) and gmock.pri (http://pastebin.com/re4nXer6). Just put them into gmock sources, add gmock subdirectory as SUBDIR to .pro with TEMPLATE=SUBDIRS (I assume your project has such one top level .pro file) and add "include(gmock.pri)" (with correct path of course) to your tests' .pro files. Since gmock include gtest, there is no need to build and link to gtest separately (of course if you don't need gmock, you can create similar .pro/.pri files for gtest). – chalup Dec 07 '10 at 19:21
  • Used TEMPLATE=subdirs (no caps for subdirs) instead, works like a charm! Lib location is automatically determined this way, loving it! Still need a magic path to the includes ofcourse, that's the only thing that's missing from the above. – Joost Nov 05 '14 at 15:04
0

I think you are ok for your qmake file. But Why is INCLUDEPATH absolute and LIBS relative. I would try setting LIBS absolute also.

From here http://doc.trolltech.com/4.6/qmake-variable-reference.html#includepath

But what the main problem is (I think) you need to put forward slashes in INCLUDEPATH. In the docs it is like this.

INCLUDEPATH += C:/gtest-1.5.0/gtest-1.5.0/include
pastjean
  • 1,307
  • 11
  • 21