Search code examples
c++visual-c++clangclang-cl

Mixing cl, clang-cl and clang in the same project


Context

I am developing a cross-platform project that depends on a highly performance sensitive open-source library. This library supports a number of different compilers, but the most performant version is compiled via clang, due to inline assembly which isn't supported by the MSVC compiler (cl). This has highlighted to me that clang is capable of compiling code on Windows, and emitting highly performant dll libraries, but that there is also a deficit in my understanding of the interoperability of the MSVC toolchain and the clang ecosystem.

Question

To what extent is code compiled with clang, interoperable with the MSVC toolchain?

  • Are binaries emitted by clang ABI compatible with binaries emitted by cl, up to and including the latest language standard?
  • Specifically, can a static library (.a) compiled with clang be consumed by the MSVC toolchain? (ie. symbol definitions are not dllexport/imported).
  • Can clang emit 32-bit binaries?
  • I recognise clang-cl is simply a driver for clang, but are there any practical limitations or other reasons not to favour clang-cl over cl for new projects?

Solution

  • Specifically, can a static library (.a) compiled with clang be consumed by the MSVC toolchain? (ie. symbol definitions are not dllexport/imported).

    Yes. I have a fairly large Windows (MFC-based) project in which I use the native MSVC compiler to build all components that actually use any MFC (or other WinAPI) code, but use clang-cl for one particular "core" module (built as a static library). All code in that core module is strictly Standard-compliant (C++17, currently, but vide infra). I have been using this MSVC+clang combination for some years and have yet to experience any issues related to ABI incompatibility. (But note that static libraries on Windows have the ".lib" extension, not ".a".)

    Are binaries emitted by clang ABI compatible with binaries emitted by cl, up to and including the latest language standard?

    Yes – but you'll need VS 2022 for C++20 or later: The clang-cl compiler (V11) that comes with VS 2019 only recognizes up to (and including) C++17; however, clang-cl V13 (as installed by VS 2022) can be set to use C++20 or C++23. (Also note that the library I mentioned above makes heavy use of the "STL" containers, like std::vector.)

    Can clang emit 32-bit binaries?

    Yes. Switching between 64-bit and 32-bit target architectures within the VS IDE works equally well for both MSVC and clang-cl projects. This also seems to work when switching to ARM64 targets (assuming you have installed the required tools), but I can't verify the final output, as I don't have access to an ARM64-based Windows system.

    I recognise clang-cl is simply a driver for clang, but are there any practical limitations or other reasons not to favour clang-cl over cl for new projects?

    I have tried building my entire project with the clang-cl tools but – so far – without success. This may be due to the fact that I am using MFC (I get a whole chunk of duplicate and/or missing symbols at link time). However, building simple, console-mode programs for Windows with clang-cl works just fine.

    And, one further note: The run-time performance of my final program is considerably greater (i.e. faster) when compiling that core library with clang-cl, compared to the same code compiled with MSVC.