在 Windows 上链接 GameNetworkingSockets 库会出现 "unresolved external" 错误

Linking with GameNetworkingSockets library on Windows gives "unresolved external" error

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

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

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

error LNK2019: unresolved external symbol __imp_SteamNetworkingUtils

我发现了很多其他问题和此类错误的答案,但没有找到对我有用的东西。

编辑:我读过的 question/answers 之一是 this,即使它很有趣,也没有帮助我解决我的问题,因为它太笼统了。

我想 link 静态地访问这个库,我通过在我的 CMakeLists.txt 文件中使用 :

在我的 CMake 项目中管理它
find_package(GameNetworkingSockets 1.2.0 REQUIRED)
target_include_directories(my_project PRIVATE ${GameNetworkingSockets_INCLUDE_DIR})
target_link_libraries(my_project ${GameNetworkingSockets_LIBRARY})

然后我制作了一个 FindGameNetworkingSockets.cmake 模块文件,我在其中告诉 CMake 为必须预先构建的库寻找 libGameNetworkingSockets_s.aGameNetworkingSockets_s.lib,并查看对于 steam/isteamnetworkingutils.h 找到正确的 header 包含目录 :

# 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}")

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

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 OS 是法语,所以这些是法语错误消息):

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\bin0190~1.0\x64\rc.exe --mt=C:\PROGRA~2\WI3CF2~1\bin0190~1.0\x64\mt.exe --manifests  -- C:\PROGRA~2\MICROS~219\PROFES~1\VC\Tools\MSVC28~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~219\PROFES~1\VC\Tools\MSVC28~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 linker 获取更多信息。我什至不知道错误是在我的项目中还是在我构建项目依赖项的方式中(GameNetworkingSocket、它自己的依赖项以及我正在使用的其他东西,所有这些都构建并安装在我的 sdk文件夹)。任何帮助表示赞赏^^

在 Windows 上,静态 linking 的符号名称与动态的符号名称不同。 未解析符号中的 __imp 前缀意味着,您 link 使用 static 库,但是 header 配置为 dynamic linking: https://whosebug.com/a/5159395/3440745

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

target_compile_definitions(my_project PUBLIC STEAMNETWORKINGSOCKETS_STATIC_LINK)

其实GameNetworkingSockets项目的安装已经提供了现成的配置脚本,所以不需要编写“查找”脚本来使用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)