cmake:解决error LNK2005: void * __cdecl operator new(unsigned __int64) already defined in LIBCMTD.lib

当以/MT选项编译MFC项目时,会报下面的错误

1>nafxcwd.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator new(unsigned __int64)" (??2@YAPEAX_K@Z) 已经在 LIBCMTD.lib(new_scalar.obj) 中定义
1>nafxcwd.lib(afxmem.obj) : error LNK2005: "void __cdecl operator delete(void *)" (??3@YAXPEAX@Z) 已经在 LIBCMTD.lib(delete_scalar.obj) 中定义
1>nafxcwd.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator new[](unsigned __int64)" (??_U@YAPEAX_K@Z) 已经在 LIBCMTD.lib(new_array.obj) 中定义
1>nafxcwd.lib(afxmem.obj) : error LNK2005: "void __cdecl operator delete[](void *)" (??_V@YAXPEAX@Z) 已经在 LIBCMTD.lib(delete_array.obj) 中定义
1>J:\gfirfid\project.vs\bin\Debug\Ast2600FaceSample.exe : fatal error LNK1169: 找到一个或多个多重定义的符号

关于为什么会报这个错误,还是要看microsoft官方的说明:
A LNK2005 error occurs when the CRT library and MFC libraries are linked in the wrong order in Visual C++

英文一大堆,其实简要说来就是,CRT库和MFC库都定义了new,delete和 DllMain 函数,这些函数要求先链接 MFC 库,然后再链接 CRT 库。
因为连接顺序不正确造成编译错误。

解决办法–修改连接顺序

如果你是手工创建的MSVC工程,解决办法很简单,网上类似的文章很多,方法都一样,就是修改uafxcwd.lib,libmcmtd.lib的连接顺序,确保uafxcwd.lib在libmcmtd.lib前面。
参见:https://www.cnblogs.com/qingtian224/p/5833456.html

解决办法–/FORCE选项

还有个比较懒的办法,就是用在连接命令中加上/FORCE选项,忽略这个错误
cmake:解决error LNK2005: void * __cdecl operator new(unsigned __int64) already defined in LIBCMTD.lib_第1张图片

这样以来上面的连接错误就成警告:

1>LINK : warning LNK4075: 忽略“/INCREMENTAL”(由于“/FORCE”规范)
1>nafxcwd.lib(afxmem.obj) : warning LNK4006: "void * __cdecl operator new(unsigned __int64)" (??2@YAPEAX_K@Z) 已在 LIBCMTD.lib(new_scalar.obj) 中定义;已忽略第二个定义
1>nafxcwd.lib(afxmem.obj) : warning LNK4006: "void __cdecl operator delete(void *)" (??3@YAXPEAX@Z) 已在 LIBCMTD.lib(delete_scalar.obj) 中定义;已忽略第二个定义
1>nafxcwd.lib(afxmem.obj) : warning LNK4006: "void * __cdecl operator new[](unsigned __int64)" (??_U@YAPEAX_K@Z) 已在 LIBCMTD.lib(new_array.obj) 中定义;已忽略第二个定义
1>nafxcwd.lib(afxmem.obj) : warning LNK4006: "void __cdecl operator delete[](void *)" (??_V@YAXPEAX@Z) 已在 LIBCMTD.lib(delete_array.obj) 中定义;已忽略第二个定义
1>J:\gfirfid\project.vs\bin\Debug\Ast2600FaceSample.exe : warning LNK4088: 因 /FORCE 选项生成了映像;映像可能不能运行

个人认为这个办法是不可取的,属于掩盖问题,掩耳盗铃。

解决办法–cmake脚本

如果你的项目是cmake脚本创建的,手工修改MSVC的工程配置就不可取了。要从修改cmake脚本下手才能根本解决,不留后患。

	# WITH_STATIC_CRT在这里指定是否开启/MT (静态库连接)选项
	# 根据 WITH_STATIC_CRT 决定是否在_target中定义_AFXDLL宏
	# 这里$<...>用到了生CMAKE成器表达式(cmake-generator-expressions),参见CMAKE官方文档
	target_compile_definitions(${_target} PRIVATE $<$>:_AFXDLL> )
	if(WITH_STATIC_CRT)
		# 定义nafxcw 和libcmt的连接顺序,库名根据$表达式决定是否有d后缀
		# Debug版本为 nafxcwd,libcmtd,Release版本为nafxcw,libcmt
		target_link_libraries(${_target} nafxcw$<$:d> libcmt$<$:d>)
	endif()

你可能感兴趣的:(开发工具,cmake,CMake进阶)