【发布时间】:2017-05-15 22:48:32
【问题描述】:
我最近尝试在同一台机器上切换到另一个 Linux 发行版后构建我的 https://github.com/eyalroz/cuda-api-wrappers/ 库的示例。奇怪的是,我遇到了链接问题。命令:
/usr/bin/c++ -Wall -std=c++11 -g CMakeFiles/device_management.dir/examples/by_runtime_api_module/device_management.cpp.o -o examples/bin/device_management -rdynamic lib/libcuda-api-wrappers.a -Wl,-Bstatic -lcudart_static -Wl,-Bdynamic -lpthread -ldl -lrt
找不到 CUDA 运行时库,我得到:
CMakeFiles/device_management.dir/examples/by_runtime_api_module/device_management.cpp.o: In function `cuda::device::peer_to_peer::get_attribute(cudaDeviceP2PAttr, int, int)':
/home/eyalroz/src/mine/cuda-api-wrappers/src/cuda/api/device.hpp:38: undefined reference to `cudaDeviceGetP2PAttribute'
collect2: error: ld returned 1 exit status
但是如果我添加-L/usr/local/cuda/lib64 它构建得很好。这以前没有发生过;它不会发生在我检查过的另一台机器上,甚至不会发生在同一 CMakeLists.txt 中使用 CUDA 运行时的其他目标上(如 version_managament)。
FindCUDA 似乎可以找到所有内容,因为 ${CUDA_LIBRARIES} 的值是 /usr/local/cuda/lib64/libcudart_static.a;-lpthread;dl;/usr/lib/x86_64-linux-gnu/librt.so。而CMakeLists.txt中的目标行是:
add_executable(device_management EXCLUDE_FROM_ALL examples/by_runtime_api_module/device_management.cpp)
target_link_libraries(device_management cuda-api-wrappers ${CUDA_LIBRARIES})
正如其他相关问题的答案中所建议的那样(例如here)。为什么会这样?我应该“手动”添加-L 开关吗?
编辑:遵循@RobertCrovella 的建议,这里是 ld 搜索路径:
$ gcc -print-search-dirs | sed '/^lib/b 1;d;:1;s,/[^/.][^/]*/\.\./,/,;t 1;s,:[^=]*=,:;,;s,;,; ,g' | tr \; \\012 | tr ':' "\n" | tail -n +3
/usr/local/cuda/lib64/x86_64-linux-gnu/5/
/usr/local/cuda/lib64/x86_64-linux-gnu/
/usr/local/cuda/lib/
/usr/lib/gcc/x86_64-linux-gnu/5/
/usr/x86_64-linux-gnu/lib/x86_64-linux-gnu/5/
/usr/x86_64-linux-gnu/lib/x86_64-linux-gnu/
/usr/x86_64-linux-gnu/lib/
/usr/lib/x86_64-linux-gnu/5/
/usr/lib/x86_64-linux-gnu/
/usr/lib/
/lib/x86_64-linux-gnu/5/
/lib/x86_64-linux-gnu/
/lib/
/usr/lib/x86_64-linux-gnu/5/
/usr/lib/x86_64-linux-gnu/
/usr/lib/
/usr/local/cuda/lib64/
/usr/x86_64-linux-gnu/lib/
/usr/lib/
/lib/
/usr/lib/
$ ld --verbose | grep SEARCH_DIR | tr -s ' ;' \\012
SEARCH_DIR("=/usr/local/lib/x86_64-linux-gnu")
SEARCH_DIR("=/lib/x86_64-linux-gnu")
SEARCH_DIR("=/usr/lib/x86_64-linux-gnu")
SEARCH_DIR("=/usr/local/lib64")
SEARCH_DIR("=/lib64")
SEARCH_DIR("=/usr/lib64")
SEARCH_DIR("=/usr/local/lib")
SEARCH_DIR("=/lib")
SEARCH_DIR("=/usr/lib")
SEARCH_DIR("=/usr/x86_64-linux-gnu/lib64")
SEARCH_DIR("=/usr/x86_64-linux-gnu/lib")
注意事项:
- 是的,我知道
CMakeLists.txt那里很丑。
【问题讨论】:
-
可能(不太可能?)两台机器上的
ld链接器搜索路径配置不同。 IMO,将ld链接器搜索路径(不是动态库加载路径)设置为自动搜索/usr/local/cuda/lib64将是不寻常,所以我认为最好的建议是明确识别-L /desired/path/to/cuda/libs.您可以使用here 建议的方法之一(例如在第三个答案中)来比较两台机器之间的ld链接器搜索路径(不是动态库加载路径),以证明或反驳这个理论。 -
假设您显示的第一个
c++命令行是在通过和失败的机器之间相同发出的,那么这不是/不应该是 CMake 问题,我不不认为。至少任何 CMake 配置都无法解释这种行为差异。因此,对行为差异的调查可能会遵循我之前评论中指出的路径。 -
抛开库是问题恰好是 CUDA 运行时 API 库这一事实不谈,究竟是什么让这个问题成为关于 CUDA 的问题?不就是“cmake 和 g++ 在一个系统上找不到库,而是在另一个概念上相同的系统上找到库。为什么?”
-
@RobertCrovella:不幸的是,我无法在我替换的操作系统上发出命令 :-( 另外,请参阅编辑 - ld 搜索路径不包含 CUDA 库目录,但 gcc 确实包含它看看我想的环境。
-
如果您希望
CMake发出非常适合各种CUDA 安装的命令,那么我的建议是强制CMake发出正在执行链接的c++命令以一种明智的方式——即明确地包含我已经提到的-L开关。如果这是您的意图,那么这恰好在另一台机器上按原样工作的事实是一个红鲱鱼,IMO,您应该提出问题来询问“我怎样才能让 CMake 添加必要的-L切换到在这种情况下这个命令行?”