CMake: 如何通过NVCC传递编译器标志列表

6

我正在尝试编译一些CUDA代码,并希望显示编译器警告。与以下命令等价:

g++ fish.cpp -Wall -Wextra

除了NVCC不理解这些,你必须通过它们:

nvcc fish.cu --compiler-options -Wall --compiler-options -Wextra
nvcc fish.cu --compiler-options "-Wall -Wextra"

我更青睐后一种形式,但实际上,这并不重要。

考虑到这个CMakeLists.txt文件(一个非常简化的例子):

cmake_minimum_required(VERSION 3.9)
project(test_project LANGUAGES CUDA CXX)

list(APPEND cxx_warning_flags "-Wall" "-Wextra") # ... maybe others

add_compile_options("$<$<COMPILE_LANGUAGE:CUDA>:--compiler-options ${cxx_warning_flags}>")
add_executable(test_cuda fish.cu)

但是这个扩展到:
nvcc "--compiler-options  -Wall" -Wextra   ...

显然这是错误的。(省略生成器表达式周围的引号只会让我们陷入破碎的扩展地狱。)

... 跳过几千次 Monte Carlo 编程迭代 ...

我得到了这个宝石:

set( temp ${cxx_warning_flags} )
string (REPLACE ";" " " temp "${temp}")
set( temp2 "--compiler-options \"${temp}\"" )
message( "${temp2}" )

这将会打印出一些看起来鼓舞人心的内容。

--compiler-options "-Wall -Wextra"

但随后

add_compile_options("$<$<COMPILE_LANGUAGE:CUDA>:${temp2}>")

扩展为:

nvcc "--compiler-options \"-Wall -Wextra\""   ...

我不知所措;我是否走到了死路?或者我错过了一些关键的标点组合?

1个回答

7

我回答自己的问题,因为我找到了一些可行的解决方案,但我仍然想听听是否有更好(即:更清洁、更规范)的方法。

TL;DR

foreach(flag IN LISTS cxx_warning_flags)
    add_compile_options("$<$<COMPILE_LANGUAGE:CUDA>:--compiler-options=${flag}>")
endforeach()

详细的描述:

我尝试了这个:

foreach(flag IN LISTS cxx_warning_flags)
    add_compile_options("$<$<COMPILE_LANGUAGE:CUDA>:--compiler-options ${flag}>")
endforeach()

但这仍然给出了。
nvcc  "--compiler-options -Wall" "--compiler-options -Wextra"   
nvcc fatal   : Unknown option '-compiler-options -Wall'

加入一个临时的“但是”:

foreach(flag IN LISTS cxx_warning_flags)
    set( temp --compiler-options ${flag}) # no quotes
    add_compile_options("$<$<COMPILE_LANGUAGE:CUDA>:${temp}>")
endforeach()

给出了一个新的结果:
nvcc  --compiler-options -Wall -Wextra   ...
nvcc fatal   : Unknown option 'Wextra'

我认为这里发生的情况是CMake正在合并重复的--compiler-options标志,但我只是在猜测。
因此,我尝试使用等号消除空格:
foreach(flag IN LISTS cxx_warning_flags)
    add_compile_options("$<$<COMPILE_LANGUAGE:CUDA>:--compiler-options=${flag}>")
endforeach()

恭喜!我们有一位获胜者:

nvcc  --compiler-options=-Wall --compiler-options=-Wextra  ...

结语:

我们能否不用循环来实现它?

add_compile_options("$<$<COMPILE_LANGUAGE:CUDA>:--compiler-options=${cxx_warning_flags}>")

不起作用 (--compiler-options=-Wall -Wextra),但是:

string (REPLACE ";" " " temp "${cxx_warning_flags}")
add_compile_options("$<$<COMPILE_LANGUAGE:CUDA>:--compiler-options=${temp}>")

does工作("--compiler-options=-Wall -Wextra")。

对于这个最后一个选项,我有点惊讶,但我想这是有道理的。总的来说,我认为循环选项在其意图上最清晰。


编辑: 在Confusing flags passed to MSVC through NVCC with CMake中,我花了很多时间发现使用以下命令可能更好:

add_compile_options("$<$<COMPILE_LANGUAGE:CUDA>:-Xcompiler=${flag}>")

自从CMake似乎进行了一些标志合理化以删除重复和歧义,但没有意识到--compiler-options与其所青睐的-Xcompiler相同。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接