【问题标题】:C++ Unity Building a Library File, LNK2005C++ Unity 构建库文件,LNK2005
【发布时间】:2013-01-27 02:25:37
【问题描述】:

我是统一构建的新手。我一直在做一些研究,并从以下方面获得了很好的信息:

但是,现在我开始对我的一些项目进行更改,我有点困惑。

为简单起见,假设我的解决方案中只有 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 &lt;&lt;,而是使用verbose &lt;&lt;。这样做是为了控制何时向控制台显示详细输出。在我的版本变体中,所有详细输出都被跳过。

我在两个项目中都有Verbose.cpp 的副本的原因是,我可以在我的 ExecProj 中获得详细的输出,而无需在调试中构建 LibProj。

Driver.hppClient.cpp 使用 verbose &lt;&lt;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 的 lib 文件并将其从两个项目中删除。但是,我想先了解为什么会这样。

另外,有人能想出更好的方法来解决这个问题吗?

【问题讨论】:

  • 欢迎享受统一构建的乐趣。您想这样做有什么特别的原因吗?
  • 构建时间需要一个多小时。实际上,我的解决方案有 150 多个项目,而 LibProj 有近 1000 个文件。我正在研究加快构建时间的方法。
  • 请不要误用单元标签,因为它适用于 Microsoft Unity。是时候制作一个新标签了。

标签: c++ build lnk2005


【解决方案1】:

我想我知道发生了什么。

Unity.cpp 包含 Verbose.cpp 和 Client.cpp
-Verbose.cpp 有 print 的实现。
-Client.cpp 包含 Verbose.hpp,它引入了 print 的实现。
所以 Unity.obj 有 2 个 print 的实现。

这意味着库 (LibProj.lib) 包含 一个 .obj 文件,其中 print 重复。因此,当我们尝试链接到库时,编译器不知道要使用哪个 print

这适用于常规构建的原因是,通常,Verbose.cpp 创建包含 print 实现的 Verbose.obj,而 Client.cpp 创建包含实现的 Client.obj print 也在其中。这意味着库 (LibProj.lib) 包含 两个 .obj 文件,每个文件中都定义了 print,因此编译器会选择一个(不过我不知道如何) .

为了测试这个理论,我创建了 2 个 Unity 文件。
Unity.cpp 包括 Verbose.cpp
unity2.cpp 包含Client.cpp

有了这个实现,我就可以构建了。这是因为 LibProj.lib 现在有 两个 .obj 文件(Unity.obj 和 Unity2.obj),每个都包含 print 的实现,所以没有符号冲突。

这只是一个有根据的猜测,我保留错误的权利:)。但是,如果我错了,请纠正我。

谢谢。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-05-24
    • 1970-01-01
    • 2020-06-02
    • 2018-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多