Building with CMake, Ninja and Clang on Windows

28,127

Solution 1

I finally found a way to use my favoured tools in a way that pleases me. It's not perfect, but it works better than Florians approach with setting the system name to Generic (which I've been using for some time now)

I first set up VS Code to use the VS developers terminal as its standard terminal. I did this by adding the following line to the VS Code preferences

"terminal.integrated.shell.windows": "C:\\MeineProgramme\\Visual_Studio\\2017\\BuildTools\\Common7\\Tools\\LaunchDevCmd.bat"

After starting the terminal within VS Code I need to call the respective batch file which sets the required environment variables (in my case vcvars64.bat). These can be found in

C:\MeineProgramme\Visual_Studio\2017\BuildTools\VC\Auxiliary\Build

After navigating to my build directory I run CMake with the following options

cmake .. -G Ninja -DCMAKE_CXX_COMPILER:PATH="C:\MeineProgramme\LLVM\bin\clang-cl.exe" -DCMAKE_LINKER:PATH="C:\MeineProgramme\LLVM\bin\lld-link.exe"

this encourages CMake to use all my installed LLVM tools. Not only clang and lld (make sure to use lld-link which supports the options led by a /), but also llvm-ar and llvm-ranlib. The only MS build tool used is the resource compiler which I don't use at the moment.

So far success I think.

Don't hesitate to contact me or comment below if you got further questions.

Solution 2

Inspired by the "Ways to Compile with Clang on Windows" blog post from @Unspongeful and after some extended testing, the following command line worked for me (and yes, it's one big command I just splitted into several lines for better readability):

> cmake -E env LDFLAGS="-fuse-ld=lld-link" PATH="<path\to\ninja>" 
      cmake -H. -G Ninja -Bbuild 
         -DCMAKE_C_COMPILER:PATH="%ProgramFiles(x86)%\LLVM\bin\clang.exe" 
         -DCMAKE_CXX_COMPILER:PATH="%ProgramFiles(x86)%\LLVM\bin\clang.exe" 
         -DCMAKE_C_COMPILER_ID="Clang" 
         -DCMAKE_CXX_COMPILER_ID="Clang" 
         -DCMAKE_SYSTEM_NAME="Generic"

Here is some background information:

It seems at the moment you have to bypass a lot of CMake's automatic checks to get it working. So probably check with the CMake team or raise an issue to get this scenario officially supported.

And the last part with a Generic system is probably not the best choice, because it will skip Windows specific settings like the .exe suffix.

But it was the only constellation that actually worked:

-- The C compiler identification is Clang
-- The CXX compiler identification is Clang
-- Check for working C compiler: C:/Program Files (x86)/LLVM/bin/clang.exe
-- Check for working C compiler: C:/Program Files (x86)/LLVM/bin/clang.exe -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: C:/Program Files (x86)/LLVM/bin/clang.exe
-- Check for working CXX compiler: C:/Program Files (x86)/LLVM/bin/clang.exe -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: build

Solution 3

I was running into similar problems when trying to use clang cmake and msvc 2017 together. At least for a very simple test project, I was able to get everything running, but I'm quite new to that stuff, so maybe my solution won't solve your probles.

Anyway. As far as I know, you should use clang-cl.exe rather than clang.exe with VS. However, building still failed for me in x86 configurations due to some linker problems regarding x86 vs x64 library incompatibilities.

So here's my solution to get both, x64 and x86 configurations, building in VS 2017.

  1. Download and install BOTH windows clang/llvm installers from http://releases.llvm.org/download.html. You don't have to add them to the path, as we'll explicitly specify the path later.
  2. Create a folder with a CMakeLists.txt, and open that in VS via the Open Folder dialog.
  3. In the CMake menu, select Change CMake Settings > CMakeLists.txt. This will generate a CMakeSettings.json containing settings for all build configs.
  4. Specify the paths of the x64/x86 cmake compilers in the cmakeCommandArgs for all configurations. Mine looks like this:

    {    // See https://go.microsoft.com//fwlink//?linkid=834763 for more information about this file.
    
    "configurations": [
        {
            "name": "x86-Debug",
            "generator": "Ninja",
            "configurationType": "Debug",
            "inheritEnvironments": [ "msvc_x86" ],
            "buildRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build\\${name}",
            "installRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\install\\${name}",
            "cmakeCommandArgs": "-D CMAKE_CXX_COMPILER=D:/windows/LLVM5_x86/bin/clang-cl.exe",
            "buildCommandArgs": "-v",
            "ctestCommandArgs": ""
        },
        {
            "name": "x86-Release",
            "generator": "Ninja",
            "configurationType": "RelWithDebInfo",
            "inheritEnvironments": [ "msvc_x86" ],
            "buildRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build\\${name}",
            "installRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\install\\${name}",
            "cmakeCommandArgs": "-D CMAKE_CXX_COMPILER=D:/windows/LLVM5_x86/bin/clang-cl.exe",
            "buildCommandArgs": "-v",
            "ctestCommandArgs": ""
        },
        {
            "name": "x64-Debug",
            "generator": "Ninja",
            "configurationType": "Debug",
            "inheritEnvironments": [ "msvc_x64" ],
            "buildRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build\\${name}",
            "installRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\install\\${name}",
            "cmakeCommandArgs": "-D CMAKE_CXX_COMPILER=D:/windows/LLVM5/bin/clang-cl.exe",
            "buildCommandArgs": "-v",
            "ctestCommandArgs": ""
        },
        {
            "name": "x64-Release",
            "generator": "Ninja",
            "configurationType": "RelWithDebInfo",
            "inheritEnvironments": [ "msvc_x64" ],
            "buildRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build\\${name}",
            "installRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\install\\${name}",
            "cmakeCommandArgs": "-D CMAKE_CXX_COMPILER=D:/windows/LLVM5/bin/clang-cl.exe",
            "buildCommandArgs": "-v",
            "ctestCommandArgs": ""
        }
    ]
    

    }

Now you should be able to build both x64 and x86 configurations without errors.

Share:
28,127

Related videos on Youtube

Simon
Author by

Simon

Updated on December 02, 2020

Comments

  • Simon
    Simon over 3 years

    This question is from 2017 and probably outdated. Please take the provided instructions with a pinch of salt since better solutions might be available now.


    Dear fellow C++ coders,

    after using the Visual Studio toolchain for building on windows for a while, I decided to give Clang 5 a shot.

    I installed the LLVM 5.0.0 binaries, the Ninja build environment, the VS 2017 Tools and CMake 3.9.3. The final aim is to be able to compile C and C++ applications for Windows using VS Code with the CMake integration as "IDE" and Clang with LLD as compiler and linker.

    The compilation and execution of a simple program worked perfectly fine (screenshot of the respective terminal history). Clang automatically detected the standard lib for Windows within the VS Tools directories and produced an executable output.

    The next step was setting up a simple build with Ninja (screenshot of ninja.build file and terminal history). The build process worked as expected and produced a working executable, just like before.

    The problems begun when I started to integrate CMake into the process. My expectation is that CMake produces a ninja build file and runs it, correct? I tried the following CMakeLists file

    cmake_minimum_required(VERSION 3.9)
    
    project(Test)
    
    add_executable(Test main.c)
    

    and called CMake with cmake -G Ninja. The resulting output was disappointing and I don't understand enough to figure out respectively solve the problem myself.

    -- The C compiler identification is Clang 5.0.0
    -- The CXX compiler identification is Clang 5.0.0
    -- Check for working C compiler: C:/Meine_Programme/LLVM/bin/clang.exe
    -- Check for working C compiler: C:/Meine_Programme/LLVM/bin/clang.exe -- broken
    CMake Error at C:/Meine_Programme/CMake/share/cmake-3.9/Modules/CMakeTestCCompiler.cmake:51 (message):
      The C compiler "C:/Meine_Programme/LLVM/bin/clang.exe" is not able to
      compile a simple test program.
    
      It fails with the following output:
    
       Change Dir: D:/Dateien/Downloads/Test/CMakeFiles/CMakeTmp
    
      
    
      Run Build Command:"C:/Meine_Programme/Ninja_Build/ninja.exe" "cmTC_eeb5c"
    
      [1/2] Building C object CMakeFiles\cmTC_eeb5c.dir\testCCompiler.c.obj
    
      FAILED: CMakeFiles/cmTC_eeb5c.dir/testCCompiler.c.obj 
    
      C:\Meine_Programme\LLVM\bin\clang.exe /nologo /DWIN32 /D_WINDOWS /W3 /MDd
      /Zi /Ob0 /Od /RTC1 /showIncludes
      /FoCMakeFiles\cmTC_eeb5c.dir\testCCompiler.c.obj
      /FdCMakeFiles\cmTC_eeb5c.dir\ -c testCCompiler.c
    
      clang.exe: error: no such file or directory: '/nologo'
    
      clang.exe: error: no such file or directory: '/DWIN32'
    
      clang.exe: error: no such file or directory: '/D_WINDOWS'
    
      clang.exe: error: no such file or directory: '/W3'
    
      clang.exe: error: no such file or directory: '/MDd'
    
      clang.exe: error: no such file or directory: '/Zi'
    
      clang.exe: error: no such file or directory: '/Ob0'
    
      clang.exe: error: no such file or directory: '/Od'
    
      clang.exe: error: no such file or directory: '/RTC1'
    
      clang.exe: error: no such file or directory: '/showIncludes'
    
      clang.exe: error: no such file or directory:
      '/FoCMakeFiles\cmTC_eeb5c.dir\testCCompiler.c.obj'
    
      clang.exe: error: no such file or directory:
      '/FdCMakeFiles\cmTC_eeb5c.dir\'
    
      ninja: build stopped: subcommand failed.
    
      
    
      
    
      CMake will not be able to correctly generate this project.
    Call Stack (most recent call first):
      CMakeLists.txt:3 (project)
    
    
    -- Configuring incomplete, errors occurred!
    See also "D:/Dateien/Downloads/Test/CMakeFiles/CMakeOutput.log".
    See also "D:/Dateien/Downloads/Test/CMakeFiles/CMakeError.log".
    

    I guess that the problem is related to CMake calling clang with VS style options using slash instead of preceded by minus, like clang requires.

    Thanks for helping me out guys, I appreciate it :-)

    Just leave me a comment if you require further information.

    Answer to Florians post

    I tried Florians command but omitted the path to ninja for a shorter notation and it turned out to work just fine.

    cmake -E env LDFLAGS="-fuse-ld=lld"  cmake -H. -G Ninja -Bbuild -DCMAKE_C_COMPILER:PATH="C:\MeineProgramme\LLVM\bin\clang.exe" -DCMAKE_CXX_COMPILER:PATH="C:\MeineProgramme\LLVM\bin\clang++.exe" -DCMAKE_C_COMPILER_ID="Clang" -DCMAKE_CXX_COMPILER_ID="Clang" -DCMAKE_SYSTEM_NAME="Generic"
    

    CMake produced a ninja build file.

    I ran ninja all to build the executable as Test. I renamed it to Test.exe and the program executed happily. So far... success!!! But much more complicated than I expected.

    • Antonio
      Antonio over 6 years
      Not an answer to your actual question, but might help: stackoverflow.com/a/38174328/2436175
    • Simon
      Simon over 6 years
      @Antonio Thanks for your reply but it looks like CMake is not able to specify a toolset for Ninja. I tried cmake -G Ninja -T LLVM-VS2017 but it told me, that the specification of a toolset is not supported for the respective generator, to bad :-(I wouldn't been surprised if it worked because, as mentioned above, I actually do have all required tools installed except VS Studio
  • Simon
    Simon over 6 years
    Huh... that is a much longer command than I expected. Let me try your suggestion and I will report back. Thank you much for your extensive research man.
  • Florian
    Florian over 6 years
    @Simon You are welcome. And yes, probably it's better/easier to put all this into a CMake toolchain file. If you have verified the above command line, I can add a toolchain approach for easier handling (like in this blog post from @MatthewHungerford).
  • Simon
    Simon over 6 years
    I started an issue on CMakes Gitlab. If you'd like to have a look... gitlab.kitware.com/cmake/cmake/issues/17329#
  • Simon
    Simon over 6 years
    Thank you for your effort florestan, but I am not sure if you understood my question correctly. I am not asking for a problem with the VS integration. I want to avoid VS where possible and only installed the VS tools for access to the Windows standard libraries and headers. My problem is that CMake doesn't detect clang or clang-cl as a valid compiler with Ninja as generator.
  • florestan
    florestan over 6 years
    OK, I got your question wrong, sorry. Interestingly, even my VS wasn't able to use the correct compiler without specifying it explicitly as stated above. I played a little without VS and I only can confirm your problem :-( CMake seems to completely ignore the CMAKE_CXX_COMPILER argument in this case.
  • Simon
    Simon over 6 years
    I updated my question with an answer to your post. Can you provide me with additional information i.e. a single CMakeLists.txt?
  • Florian
    Florian over 6 years
    @Simon I'll add some more information during the next days. Just one thing about the path to ninja. Since it's the PATH environment variable we are overwriting it would in your case just be PATH="C:\MeineProgramme\Ninja\bin" (without the executable).
  • Simon
    Simon over 6 years
    Oops, my bad :-/ well... it turned out to be just fine ;-)
  • florestan
    florestan about 6 years
    You could probably also use the x64 Native Tools Command Prompt for VS 2017 shortcut located at C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Visual Studio 2017\Visual Studio Tools\VC. This would call the vcvars64.bat for you automatically.
  • Royi
    Royi over 5 years
    What are the variables needed for Ninja for that? I want to be able to imitate this on my own cmd window.
  • Simon
    Simon over 5 years
    @Royi I'm don't understand. What do you mean? This works with normal cmd but you either have to have Visual_Studio\2017\BuildTools\VC\Auxiliary\Build on the path or reference vcvars64.bat with the full path. The call to cmake is the same in every environment.
  • Royi
    Royi over 5 years
    You say this encourages CMake to use all my installed LLVM tools.. Namely some System Environment Settings which were set in vcvars64.bat made that happen. I asked if you specifically which ones (Because it adds many).
  • Simon
    Simon over 5 years
    Huh, I got no clue but LLVM needs the include and library variables set to be able to find the required files during build. Why don't you just execute the environment script?
  • Adam McKee
    Adam McKee over 5 years
    There is an open issue with CMake to add support for Clang (not just Clang-cl) on Windows: gitlab.kitware.com/cmake/cmake/issues/16439
  • mathstuf
    mathstuf over 4 years
    Setting the CMAKE_<LANG>_COMPILER_ID flags manually is not a good idea. You end up skipping CMake's other compiler extraction logic (such as compiler versions which ends up making checks for C++ language level support (e.g., -std=c++17) fail.