If you have ever created or built a CUDA CMake project in the past, you have probably heard about the FindCUDA
CMake module. Prior to CMake 3.8, it has been providing this module to support compiling CUDA code and linking with CUDA libraries. This approach is not perfect though. Unlike other libraries, CUDA provides not only some libraries but a compiler as well. To let CMake use nvcc
to compile something, the FindCUDA
module provides macros like cuda_add_executable
(similar to add_executable
). Essentially, it has to duplicate a lot of features already in CMake specifically for CUDA support. These all changed with CUDA becoming a language in CMake 3.8. In this blog post, I will talk about how to use CUDA in CMake 3.8+.
Enabling CUDA as a language
The first thing you have to do is to set CUDA as a language in your CMake project. This can be easily done with
project(<project-name> LANGUAGES CUDA)
Setting compiler flags
We can follow the same way we set compiler flags for C/C++ source.
set(CMAKE_CUDA_FLAGS "-Wall")
set(CMAKE_CUDA_FLAGS_DEBUG "-g")
Creating libraries and executables
The CUDA specific cuda_add_executable
and cuda_add_library
macros are no longer necessary. Simply use add_executable
and add_library
to build executables and libraries which contain CUDA code. CMake will use different compiler depending on the file extension and link everything properly in the end.
add_executable(cuda_exe c_file.c cuda_file.cu)
Enabling separable compilation
Unlike with FindCUDA
, we have to enable CUDA device code separable compilation on a per target basis now.
set_property(TARGET <target-name> PROPERTY CUDA_SEPARABLE_COMPILATION ON)
Since CMake 3.11, we can also directly set the CMAKE_CUDA_SEPARABLE_COMPILATION
property which will internally be used to initialize the value of CUDA_SEPARABLE_COMPILATION
on each target.
set(CMAKE_CUDA_SEPARABLE_COMPILATION ON)
Finding CUDA libraries
Sometimes you may just want to link to certain CUDA libraries with pure C/C++ code. We could find those libraries relying on the new CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES
. This variable contains the paths that nvcc
implicitly uses to find libraries.
find_library(CUDA_LIB <lib-name> PATHS ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES})
Conclusion
With CMake 3.8, we have a new way to use CUDA in our CMake projects. It could be a bit difficult to get started because CUDA-related changes are not documented in a single place. The things I mentioned above are just what I have to change in my own CMake project to make CUDA work again. There are more things this release introduced that you may need. None the less, I hope you have a smoother transition from an old CMake version with my tips above.
References
- CMAKE_<LANG>_IMPLICIT_LINK_DIRECTORIES
- CUDA_SEPARABLE_COMPILATION
- CMAKE_CUDA_SEPARABLE_COMPILATION
- Building Cross-Platform CUDA Applications with CMake