在 Windows 上与 GameNetworkingSockets 库链接时出现“未解决的外部”错误 [重复]

Linking with GameNetworkingSockets library on Windows gives "unresolved external" error [duplicate]

提问人:aTom 提问时间:1/15/2022 最后编辑:aTom 更新时间:1/15/2022 访问量:311

问:

我有一个使用一些第三方库(GameNetworkingSockets)的CMake C++项目。

我的目标是 linux 和 windows,但我每天都在我的 linux 机器上工作,所以我不太习惯使用 msvc 构建应用程序。

今天,我的应用程序在 linux 上构建并运行良好,但在使用 MSVC 2019 在 Windows 上构建时无法链接此库:

error LNK2019: unresolved external symbol __imp_SteamNetworkingUtils

我发现了很多关于这种错误的其他问题和答案,但我没有发现任何对我有用的东西。

编辑:我读到的问题/答案之一就是这个问题,即使它非常有趣,它也没有帮助我解决我的问题,因为它太笼统了。

我想静态链接到这个库,我在我的 CMake 项目中通过在我的文件中使用它来管理它:CMakeLists.txt

find_package(GameNetworkingSockets 1.2.0 REQUIRED)
target_include_directories(my_project PRIVATE ${GameNetworkingSockets_INCLUDE_DIR})
target_link_libraries(my_project ${GameNetworkingSockets_LIBRARY})

我制作了一个模块文件,在其中我告诉 CMake 查找或查找必须事先构建的库,并查找以找到正确的标头包含目录:FindGameNetworkingSockets.cmakelibGameNetworkingSockets_s.aGameNetworkingSockets_s.libsteam/isteamnetworkingutils.h

# Try to find GameNetworkingSockets lib

# Check for SDK_ROOT
if( NOT SDK_ROOT )
  message(FATAL_ERROR "You have to set SDK_ROOT before calling find_package().")
endif()

# Set search paths
set( _GameNetworkingSockets_HEADER_SEARCH_DIR "${SDK_ROOT}/include/GameNetworkingSockets" )
set( _GameNetworkingSockets_LIB_SEARCH_DIR "${SDK_ROOT}/lib" )

# Search for the headers
FIND_PATH(GameNetworkingSockets_INCLUDE_DIR "steam/isteamnetworkingutils.h" PATHS "${_GameNetworkingSockets_HEADER_SEARCH_DIR}")

# Search for the library
FIND_LIBRARY(GameNetworkingSockets_LIBRARY NAMES libGameNetworkingSockets_s.a GameNetworkingSockets_s.lib PATHS ${_GameNetworkingSockets_LIB_SEARCH_DIR} NO_DEFAULT_PATH)

INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(GameNetworkingSockets DEFAULT_MSG GameNetworkingSockets_LIBRARY GameNetworkingSockets_INCLUDE_DIR)
message(STATUS "GameNetworkingSockets library was found : ${GameNetworkingSockets_LIBRARY}")
message(STATUS "GameNetworkingSockets header was found in : ${GameNetworkingSockets_INCLUDE_DIR}")

在linux或windows中运行CMake时,我可以看到库及其头目录被找到:

linux
-- GameNetworkingSockets library was found : /sdk/debug/lib/libGameNetworkingSockets_s.a
-- GameNetworkingSockets header was found in : /sdk/debug/include/GameNetworkingSockets

windows
-- GameNetworkingSockets library was found : C:/sdk/debug/lib/GameNetworkingSockets_s.lib
-- GameNetworkingSockets header was found in : C:/sdk/debug/include/GameNetworkingSockets

然后,在 linux 上构建时(使用 Ninja 生成器):

[...]
[245/245 4.5/sec] Linking CXX executable my_project

通过查看可执行文件,我可以看到许多与库相关的符号,即使名称被篡改:nm my_project | grep SteamNetworkingUtils

0000000000c39ee0 T SteamNetworkingUtils
000000000143c278 b _ZGVZ20SteamNetworkingUtilsE7s_utils
0000000000c537a0 t _ZN21ISteamNetworkingUtils20SetConfigValueStructERK28SteamNetworkingConfigValue_t27ESteamNetworkingConfigScopel
0000000000c34cd0 T _ZN21ISteamNetworkingUtilsD1Ev
0000000000c34cd0 t _ZN21ISteamNetworkingUtilsD2Ev
0000000000c39d30 T _ZN25SteamNetworkingSocketsLib21CSteamNetworkingUtils13GetTimeSecureEv
0000000000c39790 T _ZN25SteamNetworkingSocketsLib21CSteamNetworkingUtils14GetConfigValueE27ESteamNetworkingConfigValue27ESteamNetworkingConfigScopelP30ESteamNetworkingConfigDataTypePvPm
0000000000c394c0 T _ZN25SteamNetworkingSocketsLib21CSteamNetworkingUtils14SetConfigValueE27ESteamNetworkingConfigValue27ESteamNetworkingConfigScopel30ESteamNetworkingConfigDataTypePKv
0000000000c393c0 T _ZN25SteamNetworkingSocketsLib21CSteamNetworkingUtils15AllocateMessageEi
0000000000c393e0 T _ZN25SteamNetworkingSocketsLib21CSteamNetworkingUtils17GetLocalTimestampEv
0000000000c39a10 T _ZN25SteamNetworkingSocketsLib21CSteamNetworkingUtils18GetConfigValueInfoE27ESteamNetworkingConfigValuePPKcP30ESteamNetworkingConfigDataTypeP27ESteamNetworkingConfigScopePS1_
0000000000c39bc0 T _ZN25SteamNetworkingSocketsLib21CSteamNetworkingUtils19GetFirstConfigValueEv
0000000000c39400 T _ZN25SteamNetworkingSocketsLib21CSteamNetworkingUtils22SetDebugOutputFunctionE38ESteamNetworkingSocketsDebugOutputTypePFvS1_PKcE
0000000000c39c30 T _ZN25SteamNetworkingSocketsLib21CSteamNetworkingUtils30SteamNetworkingIPAddr_ToStringERK21SteamNetworkingIPAddrPcmb
0000000000c39ca0 T _ZN25SteamNetworkingSocketsLib21CSteamNetworkingUtils32SteamNetworkingIdentity_ToStringERK23SteamNetworkingIdentityPcm
0000000000c39c70 T _ZN25SteamNetworkingSocketsLib21CSteamNetworkingUtils33SteamNetworkingIPAddr_ParseStringEP21SteamNetworkingIPAddrPKc
0000000000c39cd0 T _ZN25SteamNetworkingSocketsLib21CSteamNetworkingUtils35SteamNetworkingIdentity_ParseStringEP23SteamNetworkingIdentityPKc
0000000000c39d10 T _ZN25SteamNetworkingSocketsLib21CSteamNetworkingUtils8GetAppIDEv
0000000000c39390 T _ZN25SteamNetworkingSocketsLib21CSteamNetworkingUtilsD0Ev
0000000000c39370 t _ZN25SteamNetworkingSocketsLib21CSteamNetworkingUtilsD1Ev
0000000000c39370 T _ZN25SteamNetworkingSocketsLib21CSteamNetworkingUtilsD2Ev
0000000000c35520 t _ZN25SteamNetworkingSocketsLib23CSteamNetworkingSocketsC1EPNS_21CSteamNetworkingUtilsE
0000000000c35520 T _ZN25SteamNetworkingSocketsLib23CSteamNetworkingSocketsC2EPNS_21CSteamNetworkingUtilsE
0000000001302548 D _ZTVN25SteamNetworkingSocketsLib21CSteamNetworkingUtilsE
000000000130e418 d _ZZ20SteamNetworkingUtilsE7s_utils

但是,当使用 MSVC 2019 在 Windows 下构建时,仍然是忍者生成器(对不起,我的 Windows 操作系统是法语的,所以这些是法语错误消息):

FAILED: my_project.exe 
cmd.exe /C "cd . && "C:\Program Files\CMake\bin\cmake.exe" -E vs_link_exe --intdir=CMakeFiles\my_project.dir --rc=C:\PROGRA~2\WI3CF2~1\10\bin\100190~1.0\x64\rc.exe --mt=C:\PROGRA~2\WI3CF2~1\10\bin\100190~1.0\x64\mt.exe --manifests  -- C:\PROGRA~2\MICROS~2\2019\PROFES~1\VC\Tools\MSVC\1428~1.299\bin\Hostx64\x64\link.exe /nologo @CMakeFiles\my_project.rsp  /out:my_project.exe /implib:my_project.lib /pdb:my_project.pdb /version:0.0 /machine:x64 /debug /INCREMENTAL /subsystem:console  && cd ."
LINK Pass 1: command "C:\PROGRA~2\MICROS~2\2019\PROFES~1\VC\Tools\MSVC\1428~1.299\bin\Hostx64\x64\link.exe /nologo @CMakeFiles\my_project.rsp /out:my_project.exe /implib:my_project.lib /pdb:my_project.pdb /version:0.0 /machine:x64 /debug /INCREMENTAL /subsystem:console /MANIFEST /MANIFESTFILE:CMakeFiles\my_project.dir/intermediate.manifest CMakeFiles\my_project.dir/manifest.res" failed (exit code 1120) with the following output:
servernetworkmanager.cpp.obj : error LNK2019: symbole externe non résolu __imp_SteamNetworkingUtils référencé dans la fonction "public: bool __cdecl ServerNetworkManager::InitSteamDatagramConnectionSockets(void)" (?InitSteamDatagramConnectionSockets@ServerNetworkManager@@QEAA_NXZ)
servernetworkmanager.cpp.obj : error LNK2019: symbole externe non résolu __imp_SteamNetworkingSockets référencé dans la fonction "public: bool __cdecl ServerNetworkManager::InitSteamDatagramConnectionSockets(void)" (?InitSteamDatagramConnectionSockets@ServerNetworkManager@@QEAA_NXZ)
servernetworkmanager.cpp.obj : error LNK2019: symbole externe non résolu __imp_GameNetworkingSockets_Init référencé dans la fonction "public: bool __cdecl ServerNetworkManager::InitSteamDatagramConnectionSockets(void)" (?InitSteamDatagramConnectionSockets@ServerNetworkManager@@QEAA_NXZ)
servernetworkmanager.cpp.obj : error LNK2019: symbole externe non résolu __imp_GameNetworkingSockets_Kill référencé dans la fonction "public: void __cdecl ServerNetworkManager::ShutdownSteamDatagramConnectionSockets(void)" (?ShutdownSteamDatagramConnectionSockets@ServerNetworkManager@@QEAAXXZ)
my_project.exe : fatal error LNK1120: 4 externes non résolus

这就是我被困住的地方,我不知道该何去何从。我从CLI构建所有内容,但是我尝试在Visual Studio中打开CMake项目,并且遇到了相同的错误。我不知道如何从 MSVC 链接器获取更多信息。我什至不知道错误是出在我的项目中,还是出在我构建项目依赖项的方式上(GameNetworkingSocket、它自己的依赖项以及我正在使用的其他东西,所有这些都构建并安装在我的文件夹中)。任何帮助都值得赞赏^^sdk

C 可视化 C++ CMake 链接器错误

评论

0赞 aTom 1/15/2022
非常感谢您的评论,这真的很有帮助,过去 2 天我一直在为此苦苦挣扎:/答案就在我面前(通常是^^)。如果你把你的意见写进一个答案,我会尽快接受它。
1赞 Tsyvarev 1/15/2022
@AlanBirtles:为什么你要关闭一个关于使用特定库作为(非常!关于错误消息的一般问题?确实,目标问题给出了错误的原因。但它没有提供在使用特定 3d 方库时如何修复错误的信息。(你不认为每个人都应该在使用项目之前检查它,是吗?

答:

2赞 Tsyvarev 1/15/2022 #1

在 Windows 上,静态链接的符号名称与动态链接的符号名称不同。 未解析符号中的前缀表示,您与静态库链接,但标头配置为动态链接https://stackoverflow.com/a/5159395/3440745__imp

默认情况下,项目 GameNetworkingSockets 将其标头视为动态链接。要将其切换到“静态模式”,请添加编译定义:STEAMNETWORKINGSOCKETS_STATIC_LINK

target_compile_definitions(my_project PUBLIC STEAMNETWORKINGSOCKETS_STATIC_LINK)

实际上,项目 GameNetworkingSockets 的安装提供了现成的配置脚本,因此无需编写“Find”脚本即可使用:find_package

find_package(GameNetworkingSockets 1.2.0 REQUIRED)
# For dynamic linking use target without '_s' suffix.
target_link_libraries(my_project PUBLIC GameNetworkingSockets::GameNetworkingSockets_s)