122

I get this error, but I don't know how to fix it.

I'm using Visual Studio 2013. I made the solution name MyProjectTest This is the structure of my test solution:

The structure

-function.h

#ifndef MY_FUNCTION_H
#define MY_FUNCTION_H

int multiple(int x, int y);
#endif

-function.cpp

#include "function.h"

int multiple(int x, int y){
    return x*y;
}

-main.cpp

#include <iostream>
#include <cstdlib>
#include "function.h"

using namespace std;

int main(){
    int a, b;
    cin >> a >> b;
    cout << multiple(a, b) << endl;

    system("pause");
    return 0;
}

I'm a beginner; this is a simple program and it runs without error. I read on the Internet and became interested in the unit test, so I created a test project:

Menu FileNewProject...InstalledTemplatesVisual C++TestNative Unit Test Project

Name: UnitTest1
Solution: Add to solution

Then the location auto-switched to the path of the current open solution.

This is the folder structure of the solution:

Folder structure

I only edited file unittest1.cpp:

#include "stdafx.h"
#include "CppUnitTest.h"
#include "../MyProjectTest/function.h"

using namespace Microsoft::VisualStudio::CppUnitTestFramework;

namespace UnitTest1
{
    TEST_CLASS(UnitTest1)
    {
    public:

        TEST_METHOD(TestEqual)
        {
            Assert::AreEqual(multiple(2, 3), 6);
            // TODO: Your test code here
        }

    };
}

But I get:

error LNK2019: unresolved external symbol.

I know that the implementation of function multiple is missing. I tried to delete the function.cpp file and I replaced the declaration with the definition, and it ran. But writing both declaration and definition in the same file is not recommended.

How can I fix this error without doing that? Should I replace it with #include "../MyProjectTest/function.cpp" in file unittest.cpp?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
phibao37
  • 2,230
  • 4
  • 26
  • 35
  • 1
    possible duplicate of [What is an undefined reference/unresolved external symbol error and how do I fix it?](http://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix) – WhozCraig Nov 10 '13 at 05:02
  • 13
    **BE CAREFUL** In a *Windows* environment, static libraries have a `.LIB` file extension. To complicate things... dynamic link libraries (i.e. `*.DLL`) can have an accompanying *import library* which also has a `.LIB` file extension. This import library lists all the goodies provided by the `*.DLL`. For more information, please read: [Beginner's Guide to Linkers](http://www.lurklurk.org/linkers/linkers.html) – Pressacco Jun 12 '15 at 19:36
  • 11
    Why should he be careful?? – marshal craft Jan 10 '18 at 07:44

12 Answers12

97

One option would be to include function.cpp in your UnitTest1 project, but that may not be the most ideal solution structure. The short answer to your problem is that when building your UnitTest1 project, the compiler and linker have no idea that function.cpp exists, and also have nothing to link that contains a definition of multiple. A way to fix this is making use of linking libraries.

Since your unit tests are in a different project, I'm assuming your intention is to make that project a standalone unit-testing program. With the functions you are testing located in another project, it's possible to build that project to either a dynamically or statically linked library. Static libraries are linked to other programs at build time, and have the extension .lib, and dynamic libraries are linked at runtime, and have the extension .dll. For my answer I'll prefer static libraries.

You can turn your first program into a static library by changing it in the projects properties. There should be an option under the General tab where the project is set to build to an executable (.exe). You can change this to .lib. The .lib file will build to the same place as the .exe.

In your UnitTest1 project, you can go to its properties, and under the Linker tab in the category Additional Library Directories, add the path to which MyProjectTest builds. Then, for Additional Dependencies under the Linker - Input tab, add the name of your static library, most likely MyProjectTest.lib.

That should allow your project to build. Note that by doing this, MyProjectTest will not be a standalone executable program unless you change its build properties as needed, which would be less than ideal.

kevintodisco
  • 5,061
  • 1
  • 22
  • 28
  • In 'Linker->Input Tab', I had to prefix '(OutDir)' for static library, that is '$(OutDir)MyProjectTest.lib', although location of both 'MyProject' and 'MyTestProject' kept in same root folder. – Pabitra Dash Aug 24 '18 at 10:58
  • 23
    So every time you want to run unit tests you should convert your testee project into a static library, and every time where you actually want to run your program you convert it back to an executable, how is this a solution? – A. Smoliak Jan 01 '19 at 12:09
  • 1
    If MyProjectTest is a dll, can we test it? We just add the import lib or we must add the obj files? – aviit Dec 31 '19 at 11:29
  • "You can turn your first program into a static library by changing it in the projects properties. There should be an option under the General tab where the project is set to build to an executable (.exe). You can change this to .lib. The .lib file will build to the same place as the .exe" Doing this was enough for my case. The rest was already handled by VS. – Ekrem Solmaz May 13 '20 at 20:27
42

In the Visual Studio solution tree, right click on the project 'UnitTest1', and then AddExisting item → choose the file ../MyProjectTest/function.cpp.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Niyaz Ivanov
  • 657
  • 5
  • 6
24

Since I want my project to compile to a stand-alone EXE file, I linked the UnitTest project to the function.obj file generated from function.cpp and it works.

Right click on the 'UnitTest1' project → Configuration PropertiesLinkerInputAdditional Dependenciesadd "..\MyProjectTest\Debug\function.obj".

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
harrygg
  • 664
  • 1
  • 7
  • 12
  • 1
    How about the case when MyProjectTest is a dll? Can you setting for it? – aviit Dec 31 '19 at 11:30
  • 1
    If we have many obj file. can we add some thing like this *.obj? Your solution worked with me but I don't want to manually add every new obj files. – aviit Dec 31 '19 at 11:35
11

I just ran into this problem in Visual Studio 2013. Apparently now, having two projects in the same solution and setting the the dependencies is not enough. You need to add a project reference between them. To do that:

  1. Right-click on the project in the solution explore
  2. Click Add => References...
  3. Click the Add New Reference button
  4. Check the boxes for the projects that this project relies on
  5. Click OK
Kevin Dill
  • 186
  • 1
  • 10
  • 1
    What do you mean by setting the dependencies? I added the reference but it still complained. https://devblogs.microsoft.com/cppblog/cpp-testing-in-visual-studio/ suggested that would suffice. – tschumann Jul 30 '19 at 10:07
9

It turned out I was using .c files with .cpp files. Renaming .c to .cpp solved my problem.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
cahit beyaz
  • 4,829
  • 1
  • 30
  • 25
8

Another way you can get this linker error (as I was) is if you are exporting an instance of a class from a DLL file, but have not declared that class itself as import/export.

#ifdef  MYDLL_EXPORTS
   #define DLLEXPORT __declspec(dllexport)
#else
   #define DLLEXPORT __declspec(dllimport)
#endif

class DLLEXPORT Book // <--- This class must also be declared as export/import
{
    public:
        Book();
        ~Book();
        int WordCount();
};

DLLEXPORT extern Book book; // <-- This is what I really wanted, to export book object

So even though primarily I was exporting just an instance of the Book class called book above, I had to declare the Book class as export/import class as well otherwise calling book.WordCount() in the other DLL file was causing a link error.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
zar
  • 11,361
  • 14
  • 96
  • 178
3

Check the character set of both projects in Configuration PropertiesGeneralCharacter Set.

My UnitTest project was using the default character set Multi-Byte while my libraries were in Unicode.

My function was using a TCHAR as a parameter.

As a result, in my library my TCHAR was transformed into a WCHAR, but it was a char* in my UnitTest: the symbol was different because the parameters were really not the same in the end.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Enyx
  • 163
  • 3
  • 10
2

I just discovered that LNK2019 occurs during compilation in Visual Studio 2015 if forgetting to provide a definition for a declared function inside a class.

The linker error was highly cryptic, but I narrowed it down to what was missing by reading through the error and provided the definition outside the class to clear this up.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Mushy
  • 2,535
  • 10
  • 33
  • 54
  • The issue in some cases is that the headers containing the class defs are all nicely referenced/included but their corresponding cpps may not be [made available](https://stackoverflow.com/a/19886507/2128797) to the linker. Best way to check is to flick through the project external dependencies in Solution Explorer. It would be beneficial for VS to issue some kind of file existence/inclusion warning regarding the error though. – Laurie Stearn Mar 30 '18 at 12:08
1

For me it works if I add this line below in .vcxproj in the itemGroup cpp file, which is connected to the header file.

<ClCompile Include="file.cpp" />
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Nejc Galof
  • 2,538
  • 3
  • 31
  • 70
1

In Visual Studio 2017 if you want to test public members, simply put your real project and test project in the same solution, and add a reference to your real project in the test project.

See C++ Unit Testing in Visual Studio from the MSDN blog for more details. You can also check Write unit tests for C/C++ in Visual Studio as well as Use the Microsoft Unit Testing Framework for C++ in Visual Studio, the latter being if you need to test non public members and need to put the tests in the same project as your real code.

Note that things you want to test will need to be exported using __declspec(dllexport). See Exporting from a DLL Using __declspec(dllexport) for more details.

user276648
  • 6,018
  • 6
  • 60
  • 86
1

In my case, set the cpp file to "C/C++ compiler" in "property"->"general", resolve the LNK2019 error.

  • Can you fix the last part of your answer (seems comprehensible)? Also the actual spelling of user interface elements. ***Without*** "Edit:", "Update:", or similar - the question/answer should appear as if it was written today. – Peter Mortensen Jan 27 '21 at 20:33
0

In the beginning of your header file function.h include

#ifdef __cplusplus
extern "C" {
#endif

Like this:

    #ifndef MY_FUNCTION_H
    #define MY_FUNCTION_H
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    int multiple(int x, int y);

    #ifdef __cplusplus
    }
    #endif
    
    #endif

This will tell the cpp compiler on your Unit Test project to compile this .h file as C-file, generating the objects with the expected symbol names