我是unity构建的新手。我一直在做一些研究,我得到了很多信息:
- http://buffered。io/文章/the-magic-of-unity-builds/
- http://oj.blackapache.net.s3.amazonaws.com/UnityBuilds.html
然而,现在我开始改变我的一些项目,我有点困惑。
为简单起见,假设我的解决方案中只有2个项目。一个库项目(它创建一个.lib文件)和一个可执行项目。我们叫它们LibProj和ExecProj。
这是每个项目的样子:
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
用于调试目的。它包装了ostream,所以我不用cout <<
,而是用verbose <<
。这样做是为了控制何时将详细输出显示到控制台。在我的版本变体中,所有的详细输出都被跳过。
我在两个项目中都有Verbose.cpp
副本的原因是,我可以在我的ExecProj中获得详细的输出,而不必在调试中构建LibProj。
Driver.hpp
和Client.cpp
使用verbose <<
。MyMainFile.cpp
调用两个函数
不用说,用正常的方式构建一切都可以。
现在的问题是…
我在LibProj中创建了Unity.cpp
。其内容为:
#include "Client.cpp"
#include "Verbose.cpp"
LibProj构建得很好。但是,当我构建ExecProj时,它在链接期间中断:
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
基本上,它抱怨是因为我们重新定义了lib文件中已经存在的详细函数。
我的问题是,为什么当文件单独编译时它可以工作,但它不能与统一构建一起工作?
是什么使一个.lib文件与另一个不同?我的意思是,技术上LibProj.lib
在两个构建情况下都有VerboseMonitor::print
的符号,这些符号由ExecProj重新定义。但是,统一构建案例失败。
解决这个问题的一种方法是创建另一个仅包含Verbose.cpp的库文件,并将其从两个项目中删除。但是,我想先了解一下为什么会发生这种情况。
还有,有人能想出一个更好的方法来解决这个问题吗?
我想我知道是怎么回事了。
Unity.cpp包含Verbose.cpp和Client.cpp
-Verbose.cpp实现了打印.
-Client.cpp包括Verbose.hpp,它带来了打印的实现。所以团结。Obj有两种print的实现。
这意味着库(libproject .lib)包含一个与print重复的 .obj文件。因此,当我们尝试链接到库时,编译器不知道使用哪个print。
这在常规构建中起作用的原因是,Verbose.cpp通常会创建Verbose。其中包含的实现,打印, Client.cpp创建Client。Obj,其中包含的实现,并在其中打印。这意味着库(libproject .lib)包含两个 .obj文件,每个文件中都定义了print,因此编译器选择一个(尽管我不知道如何)。为了验证这个理论,我创建了2个Unity文件。Unity.cpp包含Verbose.cpp
unity .cpp包含Client.cpp
通过这个实现,我可以构建。这是因为LibProj。lib现在有两个 .obj文件。obj,Unity2.obj),每个都包含一个print的实现,所以没有符号冲突。
这只是一个有根据的猜测,我保留错误的权利:)然而,如果我错了,请纠正我。
谢谢。