CUDA as a language in CMake

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

 
comments powered by Disqus