Question

I'm new to unity builds. I've been doing some research and I've gotten great info from:

However, now that I started making changes to some of my projects, I'm a little confused.

For simplicity's sake, let's say I have only 2 projects in my solution. A library project (it creates a .lib file) and an executable project. Let's call them LibProj and ExecProj.

This is how each project looks like:

LibProj
>include
>>Client.hpp<br>
>>Driver.hpp<br>
>>Verbose.hpp

>source
>>Client.cpp<br>
>>Verbose.cpp

ExecProj
>source
>>MyMainFile.cpp<br>
  Verbose.cpp

Verbose.cpp is used for debugging purposes. It wraps the ostream, so instead of using cout <<, I use verbose <<. This is done to control when verbose output is displayed to the console. In my release variants, all verbose output is skipped.

The reason why I have a copy of Verbose.cpp in both projects is so that I can get verbose output in my ExecProj without having to build LibProj in debug.

Driver.hpp and Client.cpp use verbose <<. MyMainFile.cpp calls functions in both of them.

Needless to say, with the normal way of building everything works.

Now the problem...

I created Unity.cpp inside LibProj. Its contents are:

#include "Client.cpp"
#include "Verbose.cpp"

LibProj builds just fine. However, when I build ExecProj, it breaks during linking:

LibProj.lib(Unity.obj) : error LNK2005: "public: void __thiscall VerboseMonitor::print(char const *,int)"
(?print@VerboseMonitor@@QAEXPBDH@Z) already defined in Verbose.obj
LibProj.lib(Unity.obj) : error LNK2005: "public: __thiscall VerboseStream::VerboseStream(void)" 
(??0VerboseStream@@QAE@XZ) already defined in Verbose.obj
C:\Users\\...\ExecProj.exe : fatal error
LNK1169: one or more multiply defined symbols found

So basically, it complains because we are redefining the verbose functions that already exist in the lib file.

My question is, why does it work when the files are compiled separately, but it doesn't work with the unity build?

What makes one .lib file different than the other? I mean, technically LibProj.lib has symbols for VerboseMonitor::print in both build cases, and those symbols are redefined by ExecProj. However, the unity build case fails.

One way to work around this issue is by creating another lib file that only contains Verbose.cpp and removing it from both projects. However, I would like to understand why this is happening first.

Also, can someone think of a better way to work around this problem?

Was it helpful?

Solution

I think I know what's going on.

Unity.cpp contains Verbose.cpp and Client.cpp
-Verbose.cpp has the implentation of print.
-Client.cpp includes Verbose.hpp which brings in the implementation of print.
So Unity.obj has 2 implementations of print.

This means that the library (LibProj.lib) contains one .obj file with print duplicates. So when we try link to the library, the compiler doesn't know which print to use.

The reason why this works on regular builds is that normally, Verbose.cpp creates Verbose.obj which contains an implementation of print in it, and Client.cpp creates Client.obj which contains an implementation of print in it as well. This means that the library (LibProj.lib) contains two .obj files with print defined in each, so the compiler picks one (I don't know how, though).

To test this theory, I created 2 Unity files.
Unity.cpp includes Verbose.cpp
Unity2.cpp includes Client.cpp

With this implementation, I'm able to build. That's because LibProj.lib now has two .obj files (Unity.obj & Unity2.obj), each containing an implementation of print, so there's no symbol clashing.

This is just an educated guess and I reserve the right to be wrong :). However, if I'm wrong, please correct me.

Thanks.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top