Debian 12下使用GNU ld链接libvulkan出现undefined reference问题
GCC链接Vulkan库出现
undefined reference错误,Clang可正常编译的解决办法 问题重现
我在Debian 12系统上学习Vulkan编程,编写了一段枚举系统中Vulkan扩展数量的代码:
#include <iostream> #include <vulkan/vulkan.hpp> int main(int argc, char *argv[]) { VkResult ret; unsigned int propertyCount; ret = vkEnumerateInstanceExtensionProperties(NULL, &propertyCount, NULL); if (ret != VK_SUCCESS) return 1; std::cout << "Vulkan: Extension Count: " << propertyCount << std::endl; return 0; }
使用g++编译时出现链接错误:
$ g++ -lvulkan -o vkExtension vkExtension.cpp /usr/bin/ld: /tmp/user/1000/ccgB9M9N.o: in function `main': vkExtension.cpp:(.text+0xc99): undefined reference to `vkEnumerateInstanceExtensionProperties' collect2: error: ld returned 1 exit status
已确认系统安装了libvulkan库,且库中存在目标符号:
$ cd /usr/lib/x86_64-linux-gnu $ ls -la | grep libvulkan -rw-r--r-- 1 root root 8575696 Mar 22 2023 libvulkan_intel_hasvk.so -rw-r--r-- 1 root root 11115728 Mar 22 2023 libvulkan_intel.so -rw-r--r-- 1 root root 6918024 Mar 22 2023 libvulkan_lvp.so -rw-r--r-- 1 root root 8711344 Mar 22 2023 libvulkan_radeon.so lrwxrwxrwx 1 root root 14 Feb 6 2023 libvulkan.so -> libvulkan.so.1 lrwxrwxrwx 1 root root 20 Feb 6 2023 libvulkan.so.1 -> libvulkan.so.1.3.239 -rw-r--r-- 1 root root 457224 Feb 6 2023 libvulkan.so.1.3.239
通过readelf确认库中存在目标函数符号:
$ readelf -s --wide libvulkan.so.1.3.239 | grep vkEnumerateInstance 136: 0000000000034850 687 FUNC GLOBAL DEFAULT 12 vkEnumerateInstanceExtensionProperties 170: 0000000000034b00 639 FUNC GLOBAL DEFAULT 12 vkEnumerateInstanceLayerProperties 283: 0000000000034d80 709 FUNC GLOBAL DEFAULT 12 vkEnumerateInstanceVersion
使用clang++编译则可成功运行:
$ clang++ -Wall -Wextra -lvulkan -o vkExtension vkExtension.cpp vkExtension.cpp:5:14: warning: unused parameter 'argc' [-Wunused-parameter] int main(int argc, char *argv[]) ^ vkExtension.cpp:5:26: warning: unused parameter 'argv' [-Wunused-parameter] int main(int argc, char *argv[]) ^ 2 warnings generated. $ ./vkExtension Vulkan: Extension Count: 20
解决办法
问题出在GNU链接器(ld)的库顺序规则上:GNU ld会从左到右处理输入文件和库,当遇到-lvulkan时,如果当前还没有需要引用该库符号的目标文件,就会跳过这个库。而Clang使用的LLD链接器对库顺序的容忍度更高,所以可以正常链接。
方法1:调整库参数的位置
将-lvulkan放在源文件之后,让链接器先处理源文件生成的目标文件,再去库中查找需要的符号:
g++ vkExtension.cpp -lvulkan -o vkExtension
方法2:强制链接器保留库
使用-Wl,--no-as-needed参数,强制链接器保留指定的库,即使暂时没检测到引用:
g++ -lvulkan -Wl,--no-as-needed -o vkExtension vkExtension.cpp
推荐使用方法1,这是符合GNU链接器规范的标准写法。
内容的提问来源于stack exchange,提问作者Johannes Krottmayer
相关产品推荐
相关产品推荐

