3

My solution has three projects: GoogleTest (for using Google Test), Vi (for the bulk of the logic) and ViTests (for the unit tests using Vi). The ViTests project references the Vi project and the Google Test project.

Vi has the following code in v1.h

#pragma once

namespace Vi
{
    class Vi1
    {
    public:
        int SomeInt();
    };
}

And the matching v1.cpp

#include "vi1.h"

namespace Vi
{
    int Vi1::SomeInt()
    {
        return 123;
    }
}

The test function in ViTests follows

TEST(Vi1Foo, SomeIntIsSame)
{
    Vi1 v = Vi1{};
    EXPECT_EQ(123, v.SomeInt());
}

The linker error says there's an unresolved symbol SomeInt. However, I can make the linker error go away by inlining the function like so:

namespace Vi
{
    class Vi1
    {
    public:
        int SomeInt() { return 123; }
    };
}

Why is the unit test project not finding the SomeInt function definition when it's placed in a separate cpp file?

Thanks.

Extra details incase useful: I'm using Visual Studio 2015.

The error message:

Error   LNK2019 unresolved external symbol "public: int __thiscall Vi::Vi1::SomeInt(void)" (?SomeInt@Vi1@Vi@@QAEHXZ) referenced in function "private: virtual void __thiscall ViTests::Vi1Foo_SomeIntIsSame_Test::TestBody(void)" (?TestBody@Vi1Foo_SomeIntIsSame_Test@ViTests@@EAEXXZ) Vi_Tests    C:\Users\MyName\Vi\Vi_Tests\Vi_Tests.obj    1

Project types: Vi is Win32 Application, ViTests is Win32 Console Application, GoogleTest is a static library.

Phlox Midas
  • 4,093
  • 4
  • 35
  • 56
  • Are you linking towards the file with the function definition? – набиячлэвэли Jul 04 '15 at 22:45
  • I don't know what you mean. I should include the cpp file name in the list of "additional dependencies"? – Phlox Midas Jul 04 '15 at 22:51
  • How can I link toward the file with the function definition? – Phlox Midas Jul 04 '15 at 23:00
  • Yes, you probably do, but I never used VS before – набиячлэвэли Jul 04 '15 at 23:44
  • Can you copy/paste the actual error message? Also, is the inline version of `Vi1::SomeInt()` that makes things work inside `namespace Vi`? – Michael Burr Jul 05 '15 at 06:34
  • I pasted the error message. Yes, the inline version is inside the Vi namespace. I'll update the code in my post to reflect this. – Phlox Midas Jul 05 '15 at 10:00
  • You say that "Vi is a Win32 application" and "ViTests is a Win32 console application". Since the problem occurs while linking ViTests, the problem is probably that `V1.obj` needs to be linked into the `ViTests` application. – Michael Burr Jul 06 '15 at 03:35
  • I tried this and Visual Studio gives an error saying that I cannot add this reference as this would create a circular dependency (ViTests already references GoogleTest and Vi). – Phlox Midas Jul 06 '15 at 08:24
  • 1
    I'm not sure what it means for a C++ Win32 Console project (like `ViTests`) to reference a C++ Win32 Application project (like `Vi`). `ViTests` needs to link in `V1.obj` - either directly as an object file, or indirectly via a static library that has been created with `V1.obj` being a member of. I'm not sure if referencing the Win32 Application project will do either of those things. I think you'll need to add `V1.obj` (and possibly other object files) as a input file to the linker in the `ViTests` project. – Michael Burr Jul 06 '15 at 22:52

2 Answers2

5

I was working under a silly false assumption. I was assuming that VS would just pickup the cpp files because I was referencing the project containing them and including the correct header files but this isn't the case.

nabijaczleweli said I should link "towards the file with the function definition". After a bit of exploring online I found out how to do this. I found this post outlining a solution. The cpp files themselves must be added to the test project. This was done by right-clicking on ViTests, selecting "Add Existing Files" and selecting vi1.cpp.

This worked but I was quite unhappy with this solution because I had to add these files as I needed them. I found I could get around this changing the type of project Vi was to a static library. This is described here. Michael Burr's comment describes a way of linking to the object files that would also work.

I wouldn't have figured this out so quickly without the help of the posters in this thread. Thank you very much people.

Community
  • 1
  • 1
Phlox Midas
  • 4,093
  • 4
  • 35
  • 56
1

You didn't specify what is the type of the projects. I'm guessing they are DLLs, and as such non-inlined functions or classes you wish to use outside them need to exported: either declared as __declspec(dllexport) at the source or listed at a DEF file.

If you go with __declspec(dllexport), remember to __declspec(dllimport) the functions at the consuming project. This is typically achieved with a macro used as a qualifier at the .h file, which resolved differently on different projects.

Ofek Shilon
  • 14,734
  • 5
  • 67
  • 101