C++ 当链接使用相同头文件的两个静态构建的lib时,如何防止已定义对象错误?

C++ 当链接使用相同头文件的两个静态构建的lib时,如何防止已定义对象错误?,c++,linker,static-linking,C++,Linker,Static Linking,我有几个库,我想静态链接在一起。让我们称它们为Lib1,Lib2,Lib3和Lib4Lib4使用Lib1和Lib3(Lib1内部使用Lib2) 我可以很容易地创建DLL,所有的工作都很好。然而,问题是,当我试图将它们构建为静态lib时,我得到了下面给出的已定义对象错误 当我包含Utility.h头文件时,会出现这些错误,该头文件包含一些可以在多个lib中使用的实用函数。目前,我被迫不在中使用它,除非像Lib4,以免在静态构建中遇到任何问题。这不好,只会使创建Utility.h的整个过程无效。我确

我有几个库,我想静态链接在一起。让我们称它们为
Lib1
Lib2
Lib3
Lib4
Lib4
使用
Lib1
Lib3
Lib1
内部使用
Lib2

我可以很容易地创建DLL,所有的工作都很好。然而,问题是,当我试图将它们构建为静态lib时,我得到了下面给出的
已定义对象
错误

当我包含
Utility.h
头文件时,会出现这些错误,该头文件包含一些可以在多个lib中使用的实用函数。目前,我被迫不在中使用它,除非像
Lib4
,以免在静态构建中遇到任何问题。这不好,只会使创建
Utility.h
的整个过程无效。我确实包括了头球后卫,但这似乎与此无关,也无济于事

我的选择是什么?我应该如何着手解决这个问题?我得到的错误:

Severity    Code    Description Project File    Line    Suppression State
Error   LNK2005 "class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl Utils::Logging::operator<<(class std::basic_ostream<char,struct std::char_traits<char> > &,class Utils::Logging::Log const &)" (??6Logging@Utils@@YAAEAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AEAV23@AEBVLog@01@@Z) already defined in FV.lib(FV.obj)   FV_Test_Lib D:\Codes\rika\cpp\port\LibtorchPort\FV_Test_Lib\AntiSpoofer.lib(AntiSpoofer.obj)    1   
Error   LNK2005 "class Utils::Logging::Log Utils::Logging::Logger" (?Logger@Logging@Utils@@3VLog@12@A) already defined in FV.lib(FV.obj)    FV_Test_Lib D:\Codes\rika\cpp\port\LibtorchPort\FV_Test_Lib\AntiSpoofer.lib(AntiSpoofer.obj)    1   
Error   LNK2005 "class std::vector<class std::filesystem::path,class std::allocator<class std::filesystem::path> > __cdecl Utils::GetFileNames(class std::vector<class std::filesystem::path,class std::allocator<class std::filesystem::path> >)" (?GetFileNames@Utils@@YA?AV?$vector@Vpath@filesystem@std@@V?$allocator@Vpath@filesystem@std@@@3@@std@@V23@@Z) already defined in FV.lib(FV.obj)  FV_Test_Lib D:\Codes\rika\cpp\port\LibtorchPort\FV_Test_Lib\AntiSpoofer.lib(AntiSpoofer.obj)    1   
Error   LNK2005 "class std::vector<class std::filesystem::path,class std::allocator<class std::filesystem::path> > __cdecl Utils::GetFiles(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::vector<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::allocator<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > >,bool)" (?GetFiles@Utils@@YA?AV?$vector@Vpath@filesystem@std@@V?$allocator@Vpath@filesystem@std@@@3@@std@@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@3@V?$vector@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@@3@_N@Z) already defined in FV.lib(FV.obj)  FV_Test_Lib D:\Codes\rika\cpp\port\LibtorchPort\FV_Test_Lib\AntiSpoofer.lib(AntiSpoofer.obj)    1   
Error   LNK2005 "class std::vector<class std::filesystem::path,class std::allocator<class std::filesystem::path> > __cdecl Utils::GetFiles(class std::filesystem::path,class std::vector<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::allocator<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > >,bool)" (?GetFiles@Utils@@YA?AV?$vector@Vpath@filesystem@std@@V?$allocator@Vpath@filesystem@std@@@3@@std@@Vpath@filesystem@3@V?$vector@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@@3@_N@Z) already defined in FV.lib(FV.obj)  FV_Test_Lib D:\Codes\rika\cpp\port\LibtorchPort\FV_Test_Lib\AntiSpoofer.lib(AntiSpoofer.obj)    1   
Error   LNK2005 "class std::vector<class std::filesystem::path,class std::allocator<class std::filesystem::path> > __cdecl Utils::GetDirectories(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,bool)" (?GetDirectories@Utils@@YA?AV?$vector@Vpath@filesystem@std@@V?$allocator@Vpath@filesystem@std@@@3@@std@@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@3@_N@Z) already defined in FV.lib(FV.obj)  FV_Test_Lib D:\Codes\rika\cpp\port\LibtorchPort\FV_Test_Lib\AntiSpoofer.lib(AntiSpoofer.obj)    1   
Error   LNK2005 "bool __cdecl Utils::NotIn(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?NotIn@Utils@@YA_NV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@0@Z) already defined in FV.lib(FV.obj)    FV_Test_Lib D:\Codes\rika\cpp\port\LibtorchPort\FV_Test_Lib\AntiSpoofer.lib(AntiSpoofer.obj)    1   
Error   LNK2005 "double __cdecl Utils::Timer::GetSeconds(class std::chrono::time_point<struct std::chrono::steady_clock,class std::chrono::duration<__int64,struct std::ratio<1,1000000000> > >,class std::chrono::time_point<struct std::chrono::steady_clock,class std::chrono::duration<__int64,struct std::ratio<1,1000000000> > >)" (?GetSeconds@Timer@Utils@@YANV?$time_point@Usteady_clock@chrono@std@@V?$duration@_JU?$ratio@$00$0DLJKMKAA@@std@@@23@@chrono@std@@0@Z) already defined in FV.lib(FV.obj)    FV_Test_Lib D:\Codes\rika\cpp\port\LibtorchPort\FV_Test_Lib\AntiSpoofer.lib(AntiSpoofer.obj)    1   
Error   LNK2005 "double __cdecl Utils::Timer::GetElapsedTime(class std::chrono::time_point<struct std::chrono::steady_clock,class std::chrono::duration<__int64,struct std::ratio<1,1000000000> > >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,enum Utils::Timer::Duration,bool)" (?GetElapsedTime@Timer@Utils@@YANV?$time_point@Usteady_clock@chrono@std@@V?$duration@_JU?$ratio@$00$0DLJKMKAA@@std@@@23@@chrono@std@@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@5@W4Duration@12@_N@Z) already defined in FV.lib(FV.obj)    FV_Test_Lib D:\Codes\rika\cpp\port\LibtorchPort\FV_Test_Lib\AntiSpoofer.lib(AntiSpoofer.obj)    1   
Error   LNK2005 "double __cdecl Utils::Timer::GetElapsedNanoSeconds(class std::chrono::time_point<struct std::chrono::steady_clock,class std::chrono::duration<__int64,struct std::ratio<1,1000000000> > >)" (?GetElapsedNanoSeconds@Timer@Utils@@YANV?$time_point@Usteady_clock@chrono@std@@V?$duration@_JU?$ratio@$00$0DLJKMKAA@@std@@@23@@chrono@std@@@Z) already defined in FV.lib(FV.obj)  FV_Test_Lib D:\Codes\rika\cpp\port\LibtorchPort\FV_Test_Lib\AntiSpoofer.lib(AntiSpoofer.obj)    1   
Error   LNK2005 "double __cdecl Utils::Timer::GetElapsedMicroSeconds(class std::chrono::time_point<struct std::chrono::steady_clock,class std::chrono::duration<__int64,struct std::ratio<1,1000000000> > >)" (?GetElapsedMicroSeconds@Timer@Utils@@YANV?$time_point@Usteady_clock@chrono@std@@V?$duration@_JU?$ratio@$00$0DLJKMKAA@@std@@@23@@chrono@std@@@Z) already defined in FV.lib(FV.obj)    FV_Test_Lib D:\Codes\rika\cpp\port\LibtorchPort\FV_Test_Lib\AntiSpoofer.lib(AntiSpoofer.obj)    1   
Error   LNK2005 "double __cdecl Utils::Timer::GetElapsedMilliSeconds(class std::chrono::time_point<struct std::chrono::steady_clock,class std::chrono::duration<__int64,struct std::ratio<1,1000000000> > >)" (?GetElapsedMilliSeconds@Timer@Utils@@YANV?$time_point@Usteady_clock@chrono@std@@V?$duration@_JU?$ratio@$00$0DLJKMKAA@@std@@@23@@chrono@std@@@Z) already defined in FV.lib(FV.obj)    FV_Test_Lib D:\Codes\rika\cpp\port\LibtorchPort\FV_Test_Lib\AntiSpoofer.lib(AntiSpoofer.obj)    1   
Error   LNK2005 "class std::chrono::time_point<struct std::chrono::steady_clock,class std::chrono::duration<__int64,struct std::ratio<1,1000000000> > > __cdecl Utils::Timer::Now(void)" (?Now@Timer@Utils@@YA?AV?$time_point@Usteady_clock@chrono@std@@V?$duration@_JU?$ratio@$00$0DLJKMKAA@@std@@@23@@chrono@std@@XZ) already defined in FV.lib(FV.obj)   FV_Test_Lib D:\Codes\rika\cpp\port\LibtorchPort\FV_Test_Lib\AntiSpoofer.lib(AntiSpoofer.obj)    1   
Error   LNK2005 "void __cdecl Utils::DateTime::Sleep(unsigned long)" (?Sleep@DateTime@Utils@@YAXK@Z) already defined in FV.lib(FV.obj)  FV_Test_Lib D:\Codes\rika\cpp\port\LibtorchPort\FV_Test_Lib\AntiSpoofer.lib(AntiSpoofer.obj)    1   
Error   LNK2005 "double __cdecl Utils::DateTime::GetSeconds(class std::chrono::time_point<struct std::chrono::system_clock,class std::chrono::duration<__int64,struct std::ratio<1,10000000> > >,class std::chrono::time_point<struct std::chrono::system_clock,class std::chrono::duration<__int64,struct std::ratio<1,10000000> > >)" (?GetSeconds@DateTime@Utils@@YANV?$time_point@Usystem_clock@chrono@std@@V?$duration@_JU?$ratio@$00$0JIJGIA@@std@@@23@@chrono@std@@0@Z) already defined in FV.lib(FV.obj)    FV_Test_Lib D:\Codes\rika\cpp\port\LibtorchPort\FV_Test_Lib\AntiSpoofer.lib(AntiSpoofer.obj)    1   
Error   LNK2005 "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl Utils::DateTime::Now(bool)" (?Now@DateTime@Utils@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@_N@Z) already defined in FV.lib(FV.obj)    FV_Test_Lib D:\Codes\rika\cpp\port\LibtorchPort\FV_Test_Lib\AntiSpoofer.lib(AntiSpoofer.obj)    1   
Error   LNK2005 "class std::chrono::time_point<struct std::chrono::system_clock,class std::chrono::duration<__int64,struct std::ratio<1,10000000> > > __cdecl Utils::DateTime::Now(void)" (?Now@DateTime@Utils@@YA?AV?$time_point@Usystem_clock@chrono@std@@V?$duration@_JU?$ratio@$00$0JIJGIA@@std@@@23@@chrono@std@@XZ) already defined in FV.lib(FV.obj) FV_Test_Lib D:\Codes\rika\cpp\port\LibtorchPort\FV_Test_Lib\AntiSpoofer.lib(AntiSpoofer.obj)    1   
Error   LNK2005 "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl Utils::operator*(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,unsigned int)" (??DUtils@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@I@Z) already defined in FV.lib(FV.obj)    FV_Test_Lib D:\Codes\rika\cpp\port\LibtorchPort\FV_Test_Lib\AntiSpoofer.lib(AntiSpoofer.obj)    1   
Error   LNK1169 one or more multiply defined symbols found  FV_Test_Lib D:\Codes\rika\cpp\port\LibtorchPort\x64\Release\FV_Test_Lib.exe 1   

更新 感谢@Scheff和内联头文件中的所有函数,它们各自的链接器错误现在消失了,但是,与日志名称空间中的Logger对象有关的链接器错误仍然存在。即使将其设置为静态也没有任何好处,但仍然会出现以下错误:

Severity    Code    Description Project File    Line    Suppression State
Error   LNK2005 "class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl Utils::Logging::operator<<(class std::basic_ostream<char,struct std::char_traits<char> > &,class Utils::Logging::Log const &)" (??6Logging@Utils@@YAAEAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AEAV23@AEBVLog@01@@Z) already defined in FV.lib(FV.obj)   FV_Test_Lib D:\Codes\rika\cpp\port\LibtorchPort\FV_Test_Lib\AntiSpoofer.lib(AntiSpoofer.obj)    1   
Error   LNK2001 unresolved external symbol "class Utils::Logging::Log Utils::Logging::Logger" (?Logger@Logging@Utils@@3VLog@12@A)   FV_Test_Lib D:\Codes\rika\cpp\port\LibtorchPort\FV_Test_Lib\FV.lib(FV.obj)  1   
Error   LNK1120 1 unresolved externals  FV_Test_Lib D:\Codes\rika\cpp\port\LibtorchPort\x64\Release\FV_Test_Lib.exe 1   


您确定所有静态库都是使用完全相同的编译器版本和编译器标志构建的吗?如果重复的符号以不同的定义结束,那么链接器错误是预期的,也是不可避免的。如果编译相同,它应该折叠得非常好。它们每次都是连续构建的。我重新构建了FV_测试,这是一个使用
FV.lib
(在我的示例中为Lib4)的测试,然后它去构建防喷器、闪烁器、检测器等。据我所知,它们都使用C++17。仅供参考:即使是将其设置为静态也没有任何好处:
static
对于全局变量来说是个坏主意。它会在每个翻译单元中产生一个单独的实例,其中包含此标头。(它不像
静态
成员变量。)
\u declspec(dllimport)
只关注DLL,但不应影响静态链接。我所知道的通常方法(在我意识到
内联
变量之前):在标题中声明一个全局变量
extern
。(如果是DLL,则是代码> > O-DESPECUR(DLRouuts:<代码)>当DLL本身被构建时,否则,代码为“>代码”,“SypScript”(DLLIMPORT),或“代码> > /*NO.YORDESPEC**/<代码>静态库-用“通常”宏欺骗实现。)该定义进入翻译单元(Ak.C++文件)。因此,可以确保只有一个定义。但是如果翻译的话呢。单元是否显示在两个静态库中?(是吗?)
Severity    Code    Description Project File    Line    Suppression State
Error   C7526   'Logger': inline variable is undefined  FV  D:\Codes\fac_ver\cpp\port\LibtorchPort\Dependencies\include\Utility.h   513