microsoft/DirectXTK

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!