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:VS: Link CUDA binaries with the device runtime library 'cudadevrt' (!2062) · Merge requests · CMake / CMake · GitLab

3 Likes

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:

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”).

1 Like

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:

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?

1 Like

The CMake target_link_libraries command automatically adds the -llibrary-name option to the command line. You don’t need to add it again using target_compile_options. As for the undefined reference, is “nvsheme_” spelled correctly?

404 - page not found

fixed.

1 Like