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

168 Views Asked by At

I wanted to write an application in C++/Vulkan without requiring the pre-installed VulkanSDK.

So, I have added through "git submodule" vulkan-headers repo, copy VulkanRT to binaries-directory and wrote CMake lists for the project.

Project Hierarchy:

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

And after building an project I caught a linking error:

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]

Caught linking error after build

Building for Windows, conf: MVSC 2022 Release - amd64 Building though commands: cmake -B=build -S=. cmake --build build

I just tried do something like that.

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

And I also tried install() command, nothing helps.

Custom copy command literally copies vulkan-1.dll to executable folder, but linkage stage falling with error LNK2019

1

There are 1 best solutions below

1
Paulus On

If you came across this question because you are also looking to create a standalone Vulkan application and find that attempting to solve this issue like a regular library isn't working.

Here's the answer why!

Vulkan is a low-level API that provides functions. These functions call proc.addresses with GPU functions available on your graphics card. If you want to play a game that uses the Vulkan API, you don't need to rush and download the Vulkan SDK, right? Now, let's get into the details.

When you update your GPU vendor drivers, Vulkan is installed by default as one of opportunities to call GPU functions. HOWEVER, this Vulkan installation is a collection of functions and handlers like PFN_vkCreate, which calls an actual GPU function. The vulkan-1.lib file abstracts them into functions that you are familiar with if you have worked with Vulkan API before.

So, are we unable to use Vulkan as a standalone application?

No, we can.

For that purpose (this is what I found):

  1. Vulkan-Headers and Vulkan-Loader. The first one contains Vulkan headers, and the second one is the actual library that can retrieve function handlers from your GPU and load them as VulkanAPI.
  2. volk. That library as I noticed that solution will work without any reference to vulkan.h header-files and etc. That library gets GPU handlers and provides own function for instantiation, getting devices list, device creation, queues and more. (Not sure about layers)
  3. Do it yourself. You could get and store actual Vulkan procedures that call actual GPU functions. It will look like this: (PFN_vkGetDeviceProcAddr)vkGetInstanceProcAddr(inst, "vkGetDeviceProcAddr");

Thus far, this is all I know about the capabilities of loading Vulkan API at runtime. I hope this information helps you understand Vulkan a bit better and the possibilities of implementing applications using dynamic Vulkan. Thank you for your attention.