如何理解CMake文档,优先静态库,Cuda混编

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何理解CMake文档,优先静态库,Cuda混编相关的知识,希望对你有一定的参考价值。

在工程搭建时,可能会有将静态库链接成动态库的需求,如出于代码保护的角度,某些模块会发布.a扩展名的静态库,我们要将多个这样的静态库链接成一个动态库。但与直接link目标文件不同的是,ld以默认参数执行时,并把静态库中没有用到的函数过滤掉,导致生成的so并未包含所要的函数,因此要加上--whole-archive参数,以保证所有的函数都包含在生成的so中。
在使用cmake时,CMakeLists.txt的写法如下:
add_library(
$MODULE_NAME
SHARED
$CMAKE_SOURCE_DIR/builttime.c #要生成一个so,至少要包含一个源文件,实在没有可以把库的编译时间戳打到这儿。
)
target_link_libraries(
$MODULE_NAME
$$MODULE_NAME_EXTRA_LDFLAGS
"-Wl,--whole-archive" #告诉编译器,从这里开始,所有的库的内容都包含到so中
$LOCAL_MODULES #可以是以源代码生成的静态库
$PREBUILT_MODULES #可以是预先生成的静态库
"-Wl,--no-whole-archive" #告诉编译器,从这里开始,以后的库的内容不用都包含到so中
)
参考技术A Finding static versions of external libraries.
The only way seems to be setting CMAKE_FIND_LIBRARY_SUFFIXES to contain the desired file suffix(es) (it's a priority list).
61 ###prefer static to dynamic library
62 set(CMAKE_FIND_LIBRARY_SUFFIXES .a$CMAKE_FIND_LIBRARY_SUFFIXES)
CUDA 和 gcc 混编:
70 FILE(GLOB_RECURSE SRC_LIST "src/*.cpp")
71 FOREACH(src $SRC_LIST)
72 MESSAGE( Find: $src )
73 ENDFOREACH(src)
74
75 FILE(GLOB_RECURSE CUDA_SRC_LIST "src/*.cu")
76 FOREACH(src $CUDA_SRC_LIST)
77 MESSAGE( Find: $src )
78 ENDFOREACH(src)
79
80 CUDA_COMPILE(CUDA_TARGETS $CUDA_SRC_LIST)
81 ADD_EXECUTABLE($project_name $CUDA_TARGETS $SRC_LIST)

为啥我无法链接到使用动态并行和可分离编译的 CUDA 静态库?

【中文标题】为啥我无法链接到使用动态并行和可分离编译的 CUDA 静态库?【英文标题】:Why can't I link to my CUDA static library that uses Dynamic Parallelism and Separable Compilation?为什么我无法链接到使用动态并行和可分离编译的 CUDA 静态库? 【发布时间】:2021-12-09 02:41:04 【问题描述】:

我正在尝试创建最基本的 CUDA 应用程序来演示动态并行、单独编译和链接、静态库中的 CUDA 内核,并且我正在尝试使用 CMake 生成 Visual Studio 解决方案。我正在使用 CMake 3.21.3、CUDA 11.4 和 Visual Studio 2019 (16.11.5)。

我有一个 .h 和一个 .cu 文件,我正在将它们编译成一个静态库。我还有一个 main.cpp 文件,其中包含我的库中的标头和指向它的链接。该文件被编译为可执行文件。我的库和可执行文件的代码位于不同的文件夹中,如下所示:

src
 |-MyLib
 |  |-mylib.h
 |  |-mylib.cu
 |  |-CMakeLists.txt
 |
 |-MyMain
 |  |-main.cpp
 |  |-CMakeLists.txt
 |
 |-CMakeLists.txt

mylib.h 和 mylib.cu 包含一个初始化 CUDA 的函数、两个内核:一个父内核和一个子内核,以及一个调用父内核的宿主函数。 mylib.h #includes cuda_runtime.hdevice_launch_parameters.h 让 Visual Studio 开心。

main.cpp简单#includesmylib.h,调用initCUDA函数,然后调用宿主函数调用内核。

库的 CMakeLists 文件如下所示:

cmake_minimum_required(VERSION 3.17 FATAL_ERROR)
project(MyLib LANGUAGES CXX CUDA)

find_package(CUDAToolkit REQUIRED)

add_library($PROJECT_NAME STATIC mylib.h mylib.cu)

target_compile_options($PROJECT_NAME PRIVATE "$<$<AND:$<CONFIG:Debug>,$<COMPILE_LANGUAGE:CUDA>>:-G;-src-in-ptx>") # enable device debug flags

set_target_properties($PROJECT_NAME PROPERTIES CUDA_ARCHITECTURES "52") # this is to make CMake happy
set_target_properties($PROJECT_NAME PROPERTIES CUDA_SEPARABLE_COMPILATION ON)
set_target_properties($PROJECT_NAME PROPERTIES CUDA_RESOLVE_DEVICE_SYMBOLS ON)  # this is required for some reason

target_link_libraries($PROJECT_NAME $CUDAToolkit_LIBRARY_DIR/cudart.lib)

main.cpp 的 CMakeLists 文件如下所示:

cmake_minimum_required(VERSION 3.17 FATAL_ERROR)

project(CUDA_Dynamic_Parallelism)

add_executable($PROJECT_NAME main.cpp)
set_target_properties($PROJECT_NAME PROPERTIES CUDA_SEPARABLE_COMPILATION ON)
target_link_libraries($PROJECT_NAME MyLib)

CMake 配置并生成解决方案,没问题。但是,当我尝试构建时,库似乎构建正常,但是当可执行文件链接时,我收到以下错误: MyLib.lib(MyLib.device-link.obj) : error LNK2001: unresolved external symbol __fatbinwrap_38_cuda_device_runtime_compute_86_cpp1_ii_8b1a5d37

任何想法为什么会发生这种情况以及如何解决它?

【问题讨论】:

【参考方案1】:

只看错误,我猜cuda架构有问题。您使用 CUDA_ARCHITECTURES 52 构建您的 Lib,但您没有在 seconds 项目中指定任何内容。

"__fatbinwrap_38_cuda_device_runtime_compute_86_cpp1_ii_8b1a5d37" 似乎表明它正在寻找具有计算架构 86 的符号。我建议尝试一下。

【讨论】:

以上是关于如何理解CMake文档,优先静态库,Cuda混编的主要内容,如果未能解决你的问题,请参考以下文章

为啥我无法链接到使用动态并行和可分离编译的 CUDA 静态库?

Android Studio手动配置Makefile、CMake

深入理解计算机系统CSAPP Ch7:静动态库制作与神奇的库打桩机制

Visual Studio/CMake 中未解析的外部符号 cuda_library::foo(int)

静态库制作-混编(工程是oc为基础)

CMake+OpenCL+CUDA -> 运行时库可能被隐藏