Clang on windows fails to compile
joshuamaiche opened this issue · 4 comments
Repro steps
C:\DirectXTK>cmake -G=Ninja -B out -DCMAKE_CXX_COMPILER=clang
-- The CXX compiler identification is Clang 16.0.5 with GNU-like command-line
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/Llvm/bin/clang.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Using Shader Model 4.0/9.1 for shaders.
-- Using DirectX Tool Kit for Audio on XAudio 2.8 (Windows 8).
-- Configuring done (1.5s)
-- Generating done (0.0s)
-- Build files have been written to: C:/DirectXTK/out
C:\DirectXTK>cmake --build out
[0/54] Generating HLSL shaders...
[1/54] Building RC object CMakeFiles/xwbtool.dir/XWBTool/xwbtool.rc.res
Microsoft (R) Windows (R) Resource Compiler Version 10.0.10011.16384
Copyright (C) Microsoft Corporation. All rights reserved.
[32/54] Building CXX object CMakeFiles/DirectXTK.dir/Src/ScreenGrab.cpp.obj
FAILED: CMakeFiles/DirectXTK.dir/Src/ScreenGrab.cpp.obj
C:\PROGRA~1\MICROS~2\2022\COMMUN~1\VC\Tools\Llvm\bin\clang.exe -DUNICODE -D_DEBUG -D_UNICODE -D_WIN32_WINNT=0x0602 -IC:/DirectXTK/out/Shaders/Compiled -IC:/DirectXTK/Src -IC:/DirectXTK/Inc -IC:/DirectXTK/Audio -O0 -g -Xclang -gcodeview -std=c++17 -D_DEBUG -D_DLL -D_MT -Xclang --dependent-lib=msvcrtd -msse2 -Wall -Wpedantic -Wextra -Wno-unsafe-buffer-usage -Xclang -include-pch -Xclang C:/DirectXTK/out/CMakeFiles/DirectXTK.dir/cmake_pch.hxx.pch -Xclang -include -Xclang C:/DirectXTK/out/CMakeFiles/DirectXTK.dir/cmake_pch.hxx -MD -MT CMakeFiles/DirectXTK.dir/Src/ScreenGrab.cpp.obj -MF CMakeFiles\DirectXTK.dir\Src\ScreenGrab.cpp.obj.d -o CMakeFiles/DirectXTK.dir/Src/ScreenGrab.cpp.obj -c C:/DirectXTK/Src/ScreenGrab.cpp
In file included from <built-in>:429:
In file included from C:\DirectXTK\out\CMakeFiles\DirectXTK.dir\cmake_pch.hxx:5:
In file included from C:\DirectXTK\Src\pch.h:161:
C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\um\DirectXMath.h:1730:16: error: reference to 'Internal' is ambiguous
return Internal::PermuteHelper<Shuffle, WhichX, WhichY, WhichZ, WhichW>::Permute(V1, V2);
^
C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\um\DirectXCollision.inl:29:11: note: candidate found by name lookup is 'DirectX::Internal'
namespace Internal
^
C:/DirectXTK/Src/ScreenGrab.cpp:350:19: note: candidate found by name lookup is 'DirectX::DX11::Internal'
namespace Internal
^
In file included from <built-in>:429:
In file included from C:\DirectXTK\out\CMakeFiles\DirectXTK.dir\cmake_pch.hxx:5:
In file included from C:\DirectXTK\Src\pch.h:161:
C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\um\DirectXMath.h:1730:82: error: no member named 'Permute' in the global namespace
return Internal::PermuteHelper<Shuffle, WhichX, WhichY, WhichZ, WhichW>::Permute(V1, V2);
~~^
2 errors generated.
[36/54] Building CXX object CMakeFiles/DirectXTK.dir/Src/WICTextureLoader.cpp.obj
FAILED: CMakeFiles/DirectXTK.dir/Src/WICTextureLoader.cpp.obj
C:\PROGRA~1\MICROS~2\2022\COMMUN~1\VC\Tools\Llvm\bin\clang.exe -DUNICODE -D_DEBUG -D_UNICODE -D_WIN32_WINNT=0x0602 -IC:/DirectXTK/out/Shaders/Compiled -IC:/DirectXTK/Src -IC:/DirectXTK/Inc -IC:/DirectXTK/Audio -O0 -g -Xclang -gcodeview -std=c++17 -D_DEBUG -D_DLL -D_MT -Xclang --dependent-lib=msvcrtd -msse2 -Wall -Wpedantic -Wextra -Wno-unsafe-buffer-usage -Xclang -include-pch -Xclang C:/DirectXTK/out/CMakeFiles/DirectXTK.dir/cmake_pch.hxx.pch -Xclang -include -Xclang C:/DirectXTK/out/CMakeFiles/DirectXTK.dir/cmake_pch.hxx -MD -MT CMakeFiles/DirectXTK.dir/Src/WICTextureLoader.cpp.obj -MF CMakeFiles\DirectXTK.dir\Src\WICTextureLoader.cpp.obj.d -o CMakeFiles/DirectXTK.dir/Src/WICTextureLoader.cpp.obj -c C:/DirectXTK/Src/WICTextureLoader.cpp
In file included from <built-in>:429:
In file included from C:\DirectXTK\out\CMakeFiles\DirectXTK.dir\cmake_pch.hxx:5:
In file included from C:\DirectXTK\Src\pch.h:161:
C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\um\DirectXMath.h:1730:16: error: reference to 'Internal' is ambiguous
return Internal::PermuteHelper<Shuffle, WhichX, WhichY, WhichZ, WhichW>::Permute(V1, V2);
^
C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\um\DirectXCollision.inl:29:11: note: candidate found by name lookup is 'DirectX::Internal'
namespace Internal
^
C:/DirectXTK/Src/WICTextureLoader.cpp:197:19: note: candidate found by name lookup is 'DirectX::DX11::Internal'
namespace Internal
^
In file included from <built-in>:429:
In file included from C:\DirectXTK\out\CMakeFiles\DirectXTK.dir\cmake_pch.hxx:5:
In file included from C:\DirectXTK\Src\pch.h:161:
C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\um\DirectXMath.h:1730:82: error: no member named 'Permute' in the global namespace
return Internal::PermuteHelper<Shuffle, WhichX, WhichY, WhichZ, WhichW>::Permute(V1, V2);
~~^
2 errors generated.
[41/54] Building CXX object CMakeFiles/DirectXTK.dir/Src/SpriteBatch.cpp.obj
ninja: build stopped: subcommand failed.
Details
The issue seems to boil down to the code becoming something like this:
namespace Internal { int val = 0; }
template <typename T> int GetVal() { return Internal::val; }
int result = GetVal<int>();
inline namespace DX11 { namespace Internal{} }
Clang on Windows defaults to using -fdelayed-template-parsing
to try to match how MSVC doesn't parse the template body until later in compilation. I'm not sure why, but for some reason, clang-cl
seems to parse the template before the Internal
namespace becomes ambiguous, and clang
seems to parse the template after the ambiguity is introduced. The parsing point seems inconsistent, but on Windows, clang
, clang-cl
, and cl
will all fail to compile the example code above. This might mean that it's just luck that MSVC and clang-cl currently compile when the DX11
namespace introduces an ambiguous Internal
namespace.
One workaround for users is to switch to switch their project from clang
to clang-cl
. If this isn't safe, an alternative could be to add the line
target_compile_options(DirectXTK PRIVATE "-fno-delayed-template-parsing")
to their project, to disable delayed template parsing.
For Windows I'm assuming use of MSVC or MSVC-like compiler: cl.exe, clang-cl, icl.exe, icx.exe.
I could potentially update DirectXMath to use fully qualified name resolution in these cases if that would help.
I tried it, and unfortunately fully-qualified name resolution won't work.
namespace DirectX
{
namespace Internal {}
inline namespace DX11 { namespace Internal {} }
}
means that while DirectX::DX11::Internal
is not ambiguous, DirectX::Internal
is.
The only solution that worked for me was just getting rid of the ambiguity. If DX11::Internal
really is internal, is there a big risk to its name being changed? I was able to get DirectXTK compiling on clang by changing DX11::Internal
to DX11::InlinedInternal
in ScreenGrab.cpp
and WICTextureLoader.cpp
, but I'm not sure if there are consequences I'm not seeing.
Let me know if you want me to put up a PR with those changes.
The use of Internal
in multiple contexts is the problem.
Ok, I propose that I change the DirectXMath library to use DirectX::MathInternal
, and DirectX Tool Kit for DX11 & DX12 to use DirectX::DX1?::ToolKitInternal
.
That should work, yes?
That should fix it, thanks!