可执行文件看不到 Vulkan 动态库并抛出链接器错误LNK2019

Executable doesn't see Vulkan dynamic lib and throws an linker-error LNK2019

提问人:Paulus 提问时间:11/13/2023 最后编辑:Paulus 更新时间:11/14/2023 访问量:86

问:

我想用 C++/Vulkan 编写应用程序,而不需要预装的 VulkanSDK

因此,我通过“git submodule”vulkan-headers repo添加,将VulkanRT复制到binaries-directory,并为该项目编写了CMake列表。

项目层次结构:

root/
     binaries/
         vulkan-1.dll
     src/
         main.cpp
         CMakeLists.txt - list that makes an executable
     CMakeLists.txt - main list

CMakeLists.txt:

cmake_minimum_required(VERSION 3.20 FATAL_ERROR)

project(proj LANGUAGES C CXX)

set(VULKAN_DLL ${CMAKE_CURRENT_SOURCE_DIR}/binaries/vulkan-1.dll)

add_subdirectory(vendor) # builds deps
add_subdirectory(src)

src/CMakeLists.txt:

set(PROJECT_SOURCE
    main.cpp
)

add_executable(${PROJECT_NAME} ${PROJECT_SOURCE})

set(INCLUDE_DIR ../vendor)
target_include_directories(${PROJECT_NAME} PUBLIC
    ${CMAKE_CURRENT_SOURCE_DIR}
    ...
)

target_link_libraries(${PROJECT_NAME} PRIVATE
    ...
)

set_target_properties(${PROJECT_NAME} PROPERTIES
    CXX_STANDARD 20
    CXX_STANDARD_REQUIRED On
)

# Command that copies a vulkan-1.dll in exec directory
add_custom_command(
    TARGET ${PROJECT_NAME} PRE_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy
    ${VULKAN_DLL}
    $<TARGET_FILE_DIR:${PROJECT_NAME}>
)

在构建一个项目后,我发现了一个链接错误:

C:\dev\octo>cmake -B=build -S=.
-- Including Win32 support
-- GLM: Version 0.9.9.9
-- Build spdlog: 1.12.0
-- Build type:
CMake Deprecation Warning at vendor/tinyobjloader/CMakeLists.txt:4 (cmake_minimum_required):
  Compatibility with CMake < 3.5 will be removed from a future version of
  CMake.

  Update the VERSION argument <min> value or use a ...<max> suffix to tell
  CMake that the project does not need compatibility with older versions.


-- Configuring done (0.1s)
-- Generating done (0.1s)
-- Build files have been written to: C:/dev/octo/build

C:\dev\octo>cmake --build build
MSBuild version 17.7.2+d6990bcfa for .NET Framework

  glfw.vcxproj -> C:\dev\octo\build\vendor\glfw\src\Debug\glfw3.lib
  imgui.vcxproj -> C:\dev\octo\build\vendor\Debug\imgui.lib
  spdlog.vcxproj -> C:\dev\octo\build\vendor\spdlog\Debug\spdlogd.lib
  tinyobjloader.vcxproj -> C:\dev\octo\build\vendor\tinyobjloader\Debug\tinyobjloader.lib
device.obj : error LNK2019: unresolved external symbol vkCreateInstance referenced in function "private: void __cdecl O
cto::Device::CreateInstance(void)" (?CreateInstance@Device@Octo@@AEAAXXZ) [C:\dev\octo\build\src\octo.vcxproj]

构建后捕获链接错误

构建 Windows 会议:MVSC 2022 版本 - amd64 通过命令构建: cmake -B=构建 -S=。 cmake --构建构建

我只是试着做这样的事情。

set(BIN_DIR ${CMAKE_CURRENT_SOURCE_DIR}/binaries)
if(WIN32)
    set(ENV{PATH} "${BIN_DIR};$ENV{PATH}")
endif()

我也试过命令,没有任何帮助。install()

自定义复制命令从字面上将 vulkan-1.dll 复制到可执行文件夹,但链接阶段下降并出现错误LNK2019

cmake dll 器错误 vulkan 动态链接

评论

0赞 Paulus 11/13/2023
@Tsyvarev我想我会留下图像并通过文本附加错误。
0赞 Tsyvarev 11/13/2023
错误消息意味着链接器已考虑了您传递给它的所有库,但这些库都没有定义错过的函数。在发布的 CMake 代码中,我没有看到与 vulkan 库的链接(通过使用左右)。是否与可执行文件一起复制到目录中与此类错误完全无关target_link_libraries.dll
0赞 Paulus 11/13/2023
@Tsyvarev 我们需要在 中明确指定依赖关系吗?我正在使用 ,理论上它应该尝试在运行时解析其依赖项,我错了吗?target_link_librariesDLL
0赞 Tsyvarev 11/13/2023
“理论上它应该尝试在运行时解析其依赖项” - Windows 在运行时仅解析那些为可执行文件指定的依赖项。若要将库文件指定为依赖项,需要将该文件的名称显式传递给链接器。
0赞 Paulus 11/13/2023
@Tsyvarev Okey,我应该怎么做?添加到行 ?如果我这样做,那么我会得到链接器错误,因为他不会看到文件。喜欢这个target_link_librariesPRIVATE vulkan-1vulkan-1.libLINK : fatal error LNK1104: cannot open file 'vulkan-1.lib'

答:

0赞 Paulus 11/14/2023 #1

如果您遇到这个问题是因为您还希望创建一个独立的 Vulkan 应用程序,并发现尝试像常规库一样解决此问题是行不通的。

这是为什么的答案!

Vulkan 是一个提供函数的低级 API。这些函数使用显卡上可用的 GPU 函数调用 proc.addresses。如果你想玩一款使用 Vulkan API 的游戏,你不需要急于下载 Vulkan SDK,对吧?现在,让我们进入细节。

当您更新 GPU 供应商驱动程序时,默认情况下会安装 Vulkan 作为调用 GPU 函数的机会之一。但是,此 Vulkan 安装是函数和处理程序(如 PFN_vkCreate)的集合,它调用实际的 GPU 函数。vulkan-1.lib 文件将它们抽象为您熟悉的函数(如果您以前使用过 Vulkan API)。

那么,我们是否无法将 Vulkan 用作独立应用程序?

不,我们可以。

为此目的(这是我发现的):

  1. vulkan-headersvulkan-loader。第一个包含 Vulkan 标头,第二个是可以从 GPU 检索函数处理程序并将其加载为 VulkanAPI 的实际库。
  2. 沃尔克。正如我注意到的那样,该库可以在不引用 vulkan.h 头文件等的情况下工作。该库获取 GPU 处理程序,并提供自己的函数用于实例化、获取设备列表、设备创建、队列等。(不确定图层)
  3. 自己动手。您可以获取并存储调用实际 GPU 函数的实际 Vulkan 过程。它看起来像这样:(PFN_vkGetDeviceProcAddr)vkGetInstanceProcAddr(inst, "vkGetDeviceProcAddr");

到目前为止,这就是我所知道的关于在运行时加载 Vulkan API 的功能的全部内容。我希望这些信息能帮助您更好地了解 Vulkan 以及使用动态 Vulkan 实现应用程序的可能性。感谢您的关注。

评论

0赞 Paulus 11/15/2023
@solidpixel okey,lmao。