CMake能否预先设置变量集合,待依赖变量定义后引用其值?
关于CMake中预先设置变量集合获取CUDA库实际路径的问题
这个问题挺典型的,直接按你最初的写法是拿不到实际库路径的,我来给你拆解原因和可行的解决方案:
为什么直接用${MY_CUDA_LIBS}不行?
当你执行SET(MY_CUDA_LIBS CUDA_CUBLAS_LIBRARIES CUDA_CUFFT_LIBRARIES)时,CMake只是把这两个字符串字面量存在了MY_CUDA_LIBS里,并没有关联后续find_package(CUDA)会给这两个变量赋予的实际路径。后续引用${MY_CUDA_LIBS}时,只会输出CUDA_CUBLAS_LIBRARIES CUDA_CUFFT_LIBRARIES这串文字,而不是它们对应的库路径。
解决方案:使用CMake的间接变量引用
CMake支持${${VAR}}这种嵌套引用语法,可以先取出变量名,再解析它的实际值。这里有两种常用的实现方式:
方式1:收集所有库的实际路径到新变量里
如果你只是想把这些库的路径集中存储,可以用循环遍历变量集合,逐个解析:
# 先定义CUDA库变量的名称集合 SET(MY_CUDA_LIBS CUDA_CUBLAS_LIBRARIES CUDA_CUFFT_LIBRARIES) # 查找CUDA包,此时CUDA_*_LIBRARIES变量会被赋值 FIND_PACKAGE(CUDA REQUIRED) # 遍历集合,解析每个变量的实际值 SET(MY_CUDA_LIB_PATHS "") FOREACH(lib_var IN LISTS MY_CUDA_LIBS) # 用${${lib_var}}间接引用变量的值 LIST(APPEND MY_CUDA_LIB_PATHS "${${lib_var}}") ENDFOREACH() # 验证结果(可选) MESSAGE(STATUS "实际的CUDA库路径:${MY_CUDA_LIB_PATHS}")
方式2:封装成INTERFACE库用于链接
如果你的目标是把这些CUDA库链接到自己的可执行文件/库,更优雅的方式是封装成一个INTERFACE库,后续直接链接这个接口库即可:
SET(MY_CUDA_LIBS CUDA_CUBLAS_LIBRARIES CUDA_CUFFT_LIBRARIES) FIND_PACKAGE(CUDA REQUIRED) # 创建一个INTERFACE类型的库,用来封装CUDA依赖 ADD_LIBRARY(my_cuda_deps INTERFACE) FOREACH(lib_var IN LISTS MY_CUDA_LIBS) TARGET_LINK_LIBRARIES(my_cuda_deps INTERFACE "${${lib_var}}") ENDFOREACH() # 链接到你的目标程序 ADD_EXECUTABLE(my_cuda_app main.cu) TARGET_LINK_LIBRARIES(my_cuda_app PRIVATE my_cuda_deps)
额外建议:使用新版CUDAToolkit模块
如果你使用的是CMake 3.10及以上版本,更推荐使用find_package(CUDAToolkit REQUIRED)替代旧的CUDA模块。新版模块提供了更清晰的目标式引用(比如CUDAToolkit::cublas、CUDAToolkit::cufft),处理方式类似:
SET(MY_CUDA_TARGETS CUDAToolkit::cublas CUDAToolkit::cufft) FIND_PACKAGE(CUDAToolkit REQUIRED) ADD_LIBRARY(my_cuda_deps INTERFACE) FOREACH(target IN LISTS MY_CUDA_TARGETS) TARGET_LINK_LIBRARIES(my_cuda_deps INTERFACE ${target}) ENDFOREACH()
内容的提问来源于stack exchange,提问作者SemtexB
相关产品推荐
相关产品推荐

