microsoft / DirectXTK

The DirectX Tool Kit (aka DirectXTK) is a collection of helper classes for writing DirectX 11.x code in C++
https://walbourn.github.io/directxtk/
MIT License
2.55k stars 506 forks source link

Clang on windows fails to compile #451

Closed joshuamaiche closed 4 months ago

joshuamaiche commented 4 months ago

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.

walbourn commented 4 months ago

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.

joshuamaiche commented 4 months ago

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.

walbourn commented 4 months ago

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?

joshuamaiche commented 4 months ago

That should fix it, thanks!