Building Cross-Platform CUDA Applications with CMake

Originally published at:

Cross-platform software development poses a number of challenges to your application’s build process. How do you target multiple platforms without maintaining multiple platform-specific build scripts, projects, or makefiles? What if you need to build CUDA code as part of the process? CMake is an open-source, cross-platform family of tools designed to build, test and package…

Very nicely done by connecting the dots. Thank you.

We've wrapped some of this complexity in a set of CMake macros:

One of the most useful things is being able to pass files without a .cu extension through to nvcc, important when using modern C++ programming models that allow you to target multiple backends (e.g. RAJA, Kokkos, Agency).

Very nice, thanks for sharing. I look forward to seeing the documentation...

With the new CUDA support you can now use the LANGUAGE source file property to state that a file should be treated as CUDA.

set_source_files_properties(main.cpp PROPERTIES LANGUAGE CUDA)
add_executable(as_cu main.cpp)

Indeed, thanks for keeping us honest!

It does indeed - that's what we use internally to make it work. A user would do:

blt_add_executable(NAME blah SOURCES main.cpp DEPENDS_ON cuda)

and the source file properties would be handled automatically.

So I tried to switch the "particle" library in the example from STATIC to SHARED one, but I got linker errors: Undefined reference to '_ZN8particle7advanceEf'

When building with `make VERBOSE=1` it turns out that the final compilation command doesn't even try link against the particle shared library, although it clearly should due the target_link_libraries(particle_test PRIVATE particles)` call.

Any idea what could be wrong?

How do we pass nvcc flags using this new version of CMake?

You can specify nvcc flags by using the global language variables such as CMAKE_CUDA_FLAGS / CMAKE_CUDA_FLAGS_DEBUG and CMAKE_CUDA_FLAGS_RELEASE or the target_compile_options command.

It seems that the only way to make nvcc use C++11 is setting "target_compile_features(particles PUBLIC cxx_std_11)".

However "set(CMAKE_CXX_STANDARD 11)" will disable "target_compile_features(particles PUBLIC cxx_std_11)".

Is that a bug?

CMake 3.10.0
CUDA 9.0

And "set(CUDA_SEPARABLE_COMPILATION ON)" is no longer usable.

Where can I find the document of these variables? I can't find them in CMake documents.

They are documented using the <lang> placeholder as these variables exist for each support language ( C/C++/Fortran/CUDA/...)

I'm using CMake to generate VS project. And I find a possible bug of CMake. (Is it appropriate to report here?)

CMake 3.10.0
VS 2017

Some facts:

Library targets **don't** enable device link (CUDA Linker option in VS) no matter CUDA_SEPARABLE_COMPILATION is ON or OFF.

Executable target **always** enable device link no matter CUDA_SEPARABLE_COMPILATION is ON or OFF.


For the example project in your article, it's OK because the executable target `particle_test` also has `.cu` files. So nvcc will link `particle` and `particle_test` with `-dlink`.

However, if the executable target `particle_test` doesn't have `.cu` files (for example my project, link is at the bottom), nvcc will not run so the library `particle` will not do device link. This will cause the common error `__cudaRegisterLinkedBinary` in the final link.

I have to enable device link manually for the library target in VS CUDA Linker.

- - -

My project link:

I have posted it here:

Can I put inside my CMakeLists.txt a line like LIST(APPEND CMAKE_CUDA_FLAGS "-std=c++11") ? Cause I get the following error when compiling in VS2017

ErrorMSB5016The name ""\"-std" contains an invalid character """. C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\VC\VCTargets\BuildCustomizations\CUDA 9.0.targets

Nevermind, I found the problem. When using LIST(APPEND ...) it includes a semi-colon between the current value and the value I want to append.

Instead using SET(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -std=c++11") gives no error

Thanks for the article, it looks promising. Since FindCUDA has been superseded, how do you require a specific version of CUDA? Is there some other way to specify the required version?

I also received this same error. Were you ever able to resolve this?