Search code examples
cmakecudanvcccompiler-flags

CMake + CUDA + separable compilation -> "nvcc doesn't know what to do with ' ' "


I use CMake for a project of mine involving CUDA. Recently I have had to turn on "separable compilation" of the some of my CUDA code:

set(CUDA_SEPARABLE_COMPILATION ON)

but then, building started to fail. As an example, the following would happen:

/usr/local/cuda/bin/nvcc -gencode arch=compute_30,code=compute_30 --std=c++11 \
   -Xcompiler -Wall -O3 -DNDEBUG "" "" "" "" -m64 -ccbin /usr/bin/cc \
   -dlink /some/where/generated_foo.cu.o -o /some/where/foo_intermediate_link.o
nvcc fatal   : Don't know what to do with ''

(lines broken and names shortened for readability)

So, the problem is that something triggers CMake to add some empty (quoted) strings to the command-line, which nvcc doesn't like. Other than that the command seems fine.

Now, -O3 -DNDEBUG are my nvcc compilation flags for release builds. But I've certainly not added any empty-string flags anywhere. I tried looking into how FindCUDA constructs the nvcc invocation, but couldn't quite figure out where these empty strings are coming.

Without going into the specifics of my CMakeLists.txt, could this possibly be a well-known issue with CMake's FindaCUDA module which has a general workaround?

Note: I use GNU/Linux Mint 18.3, CMake 3.5, and CUDA 9.1.


Solution

  • It turns out this is a known CMake issue.

    The workaround is to only set build-config-specific compilation flags for the active build config, e.g. instead of having:

    set(CUDA_NVCC_FLAGS_RELEASE ${CUDA_NVCC_FLAGS_RELEASE} -O3)
    set(CUDA_NVCC_FLAGS_DEBUG ${CUDA_NVCC_FLAGS_DEBUG} -g --generate-line-info)
    

    in your CMakeLists.txt, use:

    if (CMAKE_BUILD_TYPE_UPPER STREQUAL "RELEASE")
        set(CUDA_NVCC_FLAGS_RELEASE ${CUDA_NVCC_FLAGS_RELEASE} -O3)
    elseif (CMAKE_BUILD_TYPE_UPPER STREQUAL "DEBUG")
        set(CUDA_NVCC_FLAGS_DEBUG ${CUDA_NVCC_FLAGS_DEBUG} -g --generate-line-info)
    endif (CMAKE_BUILD_TYPE_UPPER STREQUAL "RELEASE")
    

    instead (or more cases if you have multiple build types).

    Another possible alternative is to not use FindCUDA at all, as CMake has added support for CUDA as a "first-class" language beginning with some 3.X release (not sure what X is).