passing flags to nvcc via CMake

I have read almost all the StackOverflow answers on passing flags via CMake:

  1. one suggestion was using
set

and separating each value with semicolon will work

set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS};-lineinfo;--use_fast_math;-rdc=true;-lcudadevrt")
  1. another was using
set

and separating each value with space instead of semi-colon

set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS} -lineinfo --use_fast_math -rdc=true -lcudadevrt")
  1. Last way was to set the flags in the command line:
DCMAKE_CUDA_FLAGS=-lineinfo --use_fast_math -rdc=true -lcudadevrt

The first two had no effect. It did not set any flag. The last seemed to work, but I want a way to change flags inside the CMake file, not in the command line.

So how do I set flags inside the CMakeLists.txt file?

CMake version: 3.12

target_compile_options(target PRIVATE $<$<COMPILE_LANGUAGE:CUDA>:
                       --generate-line-info
                       --use_fast_math
                       --relocatable-device-code=true
                       >)

cudadevrt should be linked by default since 3.12.

X-ref:https://gitlab.kitware.com/cmake/cmake/merge_requests/2062/diffs

1 Like

Thanks for your answer. I replaced

set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS} -lineinfo --use_fast_math -rdc=true -lcudadevrt")

with

target_compile_options(target PRIVATE $<$<COMPILE_LANGUAGE:CUDA>:
                       --generate-line-info
                       --use_fast_math
                       --relocatable-device-code=true
                       >)

and it works like a charm!

I have read the explanation in that you linked, but I don’t understand the difference between the two ( why the former doesn’t work where as the latter does )

Any explanation would really help. Thanks!

CMake went through a significant change in how it dealt with CUDA in the 3.8 - 3.12 timeframe.

You can read about it on the CMake github site:

https://github.com/Kitware/CMake/blob/master/Modules/FindCUDA.cmake

The set(CUDA_NVCC_FLAGS… syntax was part of the old (deprecated) methodology. The target_compile_options(… syntax is part of the new methodology (so called “first class language support”).

Your first approach will tell the “whole world” (all the targets) what CUDA flags to use (this is the old way of using CMake).

The second approach sets the flags for “target” only, and by setting it to private the flags will not be inherited by anyone linking with “target”.

The idea is that all your different targets are objects that have properties that can be set/get. They can also inform other targets what is required to link with your target. It’s important to learn the difference between private/public.

This is a very powerful modular approach, that really lets you build large software projects IMO.

This guy explains some of these concepts well:

https://www.youtube.com/watch?v=ztrnb-bVVPo

Robert_Crovella & Jimmy Pettersson, thanks a lot.

Hi, Robert

Do you know how to link the nvshmem in CMake?

I have try something like this

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
include_directories(${NVSHMEM_HOME}/include)

# COMPILE AND LINK
cuda_add_executable(main src/main.cu)

target_link_libraries(main ${NVSHMEM_HOME}/lib/libnvshmem.a "/usr/lib/x86_64-linux-gnu/openmpi/lib/libmpi.so"  )
target_compile_options(main PRIVATE $<$<COMPILE_LANGUAGE:CUDA>:
                        -arch=sm_61;
                        -std=c++11;
                        -rdc=true;
                        -Xcompiler;
                        -pthread
                        -lnvshmem 
                        -lmpi_cxx 
                        -lmpi
                       >)

but it always fails to link the nvsheme library, and it returns me errors like undefined reference to nvsheme_
Could you please help me with this problem?