通过CMake传递给MSVC的标志在NVCC中引起混淆

5

我有一个CMake文件,用于在Windows上构建一些CUDA(NVCC / MSVC)。我正在尝试将MSVC警告级别设置为/ W4,方法如下:

add_compile_options("$<$<COMPILE_LANGUAGE:CUDA>:--compiler-options=/W4>")

在使用CMake 3.9构建时,我遇到了以下警告:

(CudaBuildCore target) ->
  cl : Command line warning D9025: overriding '/W4' with '/W3'

CMake 3.15版本更改了策略,不再自动将 /W3 设置为CUDA标志,但使用该版本我会得到以下结果:

(CudaBuildCore target) ->
  cl : Command line warning D9025: overriding '/W4' with '/W1'

如果我使用--verbose参数进行构建,那么在3.9版本中会看到以下输出:

  "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\bin\nvcc.exe" -gencode=arch=compute_30,code=\"compute_30,compute_30\" --use-local-env -ccbin "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\bin\HostX86\x64" -x cu  -IC:\Users\eddi\Documents\temp\thur\sw\include -IC:\Users\eddi\Documents\temp\thur\sw\shared\common\include -I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\include"     --keep-dir x64\Debug -maxrregcount=0  --machine 64 --compile -cudart static --compiler-options=/W4 --compiler-options= -Xcompiler="/EHsc -Zi -Ob0" -g   -D_WINDOWS -D"FISH_BUILD_TYPE=\"DEBUG\"" -D"CMAKE_INTDIR=\"Debug\"" -D"CMAKE_INTDIR=\"Debug\"" -D_MBCS -Xcompiler "/EHsc /W3 /nologo /Od /Fdfish.dir\Debug\fish.pdb /FS /Zi /RTC1 /MDd /GR" -o fish.dir\Debug\fish_cuda.obj "C:\Users\eddi\Documents\temp\thur\sw\fish_cuda.cpp"

同时,随着3.15版本的发布:

  "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\bin\nvcc.exe" -gencode=arch=compute_30,code=\"compute_30,compute_30\" --use-local-env -ccbin "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\bin\HostX86\x64" -x cu  -IC:\Users\eddi\Documents\temp\thur\sw\include -IC:\Users\eddi\Documents\temp\thur\sw\shared\common\include -I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\include"     --keep-dir x64\Debug -maxrregcount=0  --machine 64 --compile -cudart static --compiler-options=/W4 --compiler-options= -Xcompiler="/EHsc -Zi -Ob0" -g   -D_WINDOWS -D"FISH_BUILD_TYPE=\"DEBUG\"" -D"CMAKE_INTDIR=\"Debug\"" -D"CMAKE_INTDIR=\"Debug\"" -D_MBCS -Xcompiler "/EHsc /W1 /nologo /Od /Fdfish.dir\Debug\fish.pdb /FS /Zi /RTC1 /MDd /GR" -o fish.dir\Debug\fish_cuda.obj "C:\Users\eddi\Documents\temp\thur\sw\fish_cuda.cpp"

Spoiler:这两者是完全相同的,除了 -Xcompiler "/EHsc /W3 /nologo /Od /Fdfish.dir\Debug\fish.pdb /FS /Zi /RTC1 /MDd /GR" 这个部分。
尽管我已经尽力了,但我无法找到引入这些标志的地方(由 CMake 等引入),因此无法开始解决如何改变行为。
编辑1:为故事增加颜色... 我在我的 CMake 安装中使用 grep 命令查找 /nologo 并找到了几个包含以下行的 .cmake 文件:
   35:   set(CMAKE_CL_NOLOGO "/nologo")

我把它们全部改成了变体。
   35:   set(CMAKE_CL_NOLOGO "/nologo_EDD")

但是在这一混乱的选项集合中,它们都没有出现。所以要么我漏掉了什么,要么它们是从CMake之外的某个东西引入的?
编辑2: @squareskittles说:

你可以从CMAKE_CXX_FLAGS_INIT变量中删除默认标志。

很好,我可以理解这种逻辑:它简单明了,并且直接解决了我的即时问题。但这似乎有点生硬,且没有解决第一次产生这些标志的地方。
总之,撇开异议,我把这个不好看的片段添加到了我的脚本中:
message( "--------------------------- ${CMAKE_CXX_FLAGS_INIT}")
string (REGEX REPLACE "/W[0-4]" "" CMAKE_CXX_FLAGS_INIT "${CMAKE_CXX_FLAGS_INIT}")
message( "--------------------------- ${CMAKE_CXX_FLAGS_INIT}")

在CMake 3.9中,我看到:

---------------------------   /DWIN32 /D_WINDOWS /W3 /GR /EHsc
---------------------------   /DWIN32 /D_WINDOWS  /GR /EHsc

如期望一样。但是在3.15版本中,我看到:

---------------------------   /DWIN32 /D_WINDOWS /GR /EHsc
---------------------------   /DWIN32 /D_WINDOWS /GR /EHsc

即使没有政策变化,也不存在/W3标志(更不用说/W1标志了)。但更糟糕的是,在两种情况下,主要问题仍然存在:

nvcc.exe ... --compiler-options=/W4 -Xcompiler="/EHsc -Zi -Ob0" ... -Xcompiler "/EHsc /W3 /nologo /Od /Fdfish.dir\Debug\fish.pdb /FS /Zi /RTC1 /MDd /GR" ...

编辑3:有了一些进展! 通过这个简单的改变:

#add_compile_options("$<$<COMPILE_LANGUAGE:CUDA>:--compiler-options=/W4>")
add_compile_options("$<$<COMPILE_LANGUAGE:CUDA>:-Xcompiler=/W4>")

没有更多的抱怨了!混淆的标记仍然存在,但现在的阅读方式是:

-Xcompiler "/EHsc /W4 /nologo /Od /Ffish.dir\Debug\fish.pdb
  /FS /Zi /RTC1 /MDd /GR"

例如,CMake发现了/W4并覆盖了其默认值。

但是,尽管仔细查看了CMake源代码,我仍然没有确定所有这些操作都在哪里完成。


编辑4:MSVC对所有这些都有一定的帮助。 这些“神秘”的选项是通过从.vcxproj文件自动生成的。如果我使用-Xcompile=/W4方法,则项目XML包含:

<CudaCompile>
  ...
  <AdditionalOptions>%(AdditionalOptions) -Xcompiler="/EHsc -Zi -Ob1"</AdditionalOptions>
  ...
  <Warning>W4</Warning>
 </CudaCompile>

但是使用原始选项 --compiler-options=/W4,我得到以下结果:

<CudaCompile>
   <AdditionalOptions>%(AdditionalOptions) --compiler-options=/W4 -Xcompiler="/EHsc -Zi -Ob1"</AdditionalOptions>
   ...
</CudaCompile>

这一切都有些合理; 如果未指定警告级别,MSVC必须默认为W1,因此出现了警告。

此外,有一个线索是:构建步骤中有以下内容:

-Xcompiler="/EHsc -Zi -Ob0"
-Xcompiler "/EHsc /W1 /nologo /Od ..."

注意一个等号有,而另一个没有,这暗示它们来自不同的地方。

我认为目前我的调查已经足够深入了。


这个回答解决了你的问题吗?如何在Visual Studio 2017中使用CMake设置编译器选项 - Kevin
感谢@squareskittles。我不确定那个链接是否涵盖了我的情况(至少初读时没有)。我遇到的问题似乎与通过NVCC传递给MSVC的两组相互冲突的编译器标志有关。但是我会再次阅读它,看看它是否提供任何线索。 - Edd Inglis
如果目标是将警告标志设置为/W4,并删除/W3/W1,则可以按照链接答案中的建议从CMAKE_CXX_FLAGS_INIT变量中删除默认标志。 - Kevin
谢谢@squareskittles,我已经更新了我的问题,并且很遗憾这似乎还不够。 - Edd Inglis
附言:我在谷歌上搜索了“EHsc /W3 /nologo /Od”,得到了很多结果(目前似乎没有一个有用的),但这意味着它是从某个地方获取的默认标志集。但是,它来自哪里?! - Edd Inglis
2个回答

6
我的问题太啰嗦,以下是简短概括:
我有:
add_compile_options("$<$<COMPILE_LANGUAGE:CUDA>:--compiler-options=/W4>")

但是发现:

add_compile_options("$<$<COMPILE_LANGUAGE:CUDA>:-Xcompiler=/W4>")

基本上,CMake/NVCC/MSVC 管道理解 -Xcompiler 选项覆盖了默认设置,但没有意识到 --compiler-options 是等效的语句,导致命令行存在歧义指令。为了更加适当,请注意修正。

1
顺便说一句,我已经向CMake提出了一个工单:https://gitlab.kitware.com/cmake/cmake/issues/20164 - Edd Inglis

0

我曾经遇到过类似的问题(但是是另一个标志),并使用了CMake的正则表达式来解决。 代码如下。

foreach(flag_var
        CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
        CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
    STRING (REGEX REPLACE "/W3" "/W4" ${flag_var} "${${flag_var}}")
endforeach(flag_var)

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