How to Tell Cmake to Use Clang on Windows

How do I tell CMake to use Clang on Windows?

You also need - in addition to the Clang compilers itself - an build/link environment for Windows.

The latest CMake 3.6 builds do have several integrated supported Clang build environments on Windows (e.g. Visual Studio, Cygwin; see Release Notes).

I've just run a successful test with

  • LLVM-3.9.0-r273898-win32.exe from http://llvm.org/builds/
  • cmake-3.6.0-rc4-win64-x64.msi from https://cmake.org/download/
  • Microsoft VS2015 Community Edition Version 14.0.23107.0

All installed to their standard paths with their bin directories in the global PATH environment.

The part you need to know is setting the right toolset with the CMake -T"LLVM-vs2014" command line option. During the configuration process CMake will let you know which compiler it has found/taken.

CMakeLists.txt

cmake_minimum_required(VERSION 3.6)

project(HelloWorld)

file(
WRITE main.cpp
"#include <iostream>\n"
"int main() { std::cout << \"Hello World!\" << std::endl; return 0; }"
)
add_executable(${PROJECT_NAME} main.cpp)

Windows Console

...> mkdir VS2015
...> cd VS2015
...\VS2015> cmake -G"Visual Studio 14 2015" -T"LLVM-vs2014" ..
-- The C compiler identification is Clang 3.9.0
-- The CXX compiler identification is Clang 3.9.0
-- Check for working C compiler: C:/Program Files (x86)/LLVM/msbuild-bin/cl.exe
-- Check for working C compiler: C:/Program Files (x86)/LLVM/msbuild-bin/cl.exe -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: C:/Program Files (x86)/LLVM/msbuild-bin/cl.exe
-- Check for working CXX compiler: C:/Program Files (x86)/LLVM/msbuild-bin/cl.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: .../VS2015
...\VS2015> cmake --build .
Microsoft (R)-Buildmodul, Version 14.0.23107.0
[...]
...\VS2015> Debug\HelloWorld.exe
Hello World!

Installation Hints

Please note that I have added LLVM to my search paths during setup:

LLVM Installation with Add to PATH

And you can crosscheck the available "Platform Toolsets" in any VS project's property page:

VS Project Properties - Platform Toolsets

References

  • What is the -D define to tell Cmake where to find nmake?
  • Linker for Clang?
  • Switching between GCC and Clang/LLVM using CMake

Configure CMake in windows to use clang from command line to get modern OpenMP support

I was able to duplicate this error for the Clang+MSVC case. Because we are attempting to use the Visual-Studio-tailored compiler from outside Visual Studio (i.e. the command line), it is necessary to initialize the VS build environment in our command line before using the compiler. The VCVarsXX.bat files accomplish this; they are part of the VS Command Prompt tools. So by picking your architecture (x86, x64, etc) and running the script, this should allow CMake to build the simple test program with clang-cl and proceed. Here is where it is located for VS 2019:

>"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" x86

>cmake -G Ninja -DCMAKE_CXX_COMPILER=clang-cl ..
-- The CXX compiler identification is Clang 8.0.1
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/Llvm/bin/clang-cl.exe
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/Llvm/bin/clang-cl.exe -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
...

To expand on the OpenMP issue, I personally found using find_package(OpenMP REQUIRED) to be pretty fruitless. As you mentioned, I also received this CMake error:

Could NOT find OpenMP_CXX (missing: OpenMP_CXX_FLAGS OpenMP_CXX_LIB_NAMES)

There are a few suggestions on this site (for example here and here) claiming that populating all of the variables manually allows FindOpenMP.cmake to successfully find the libraries. I tried this with your example CMake file, with some success:

cmake_minimum_required (VERSION 2.8)
project(test_openmp LANGUAGES CXX)

set(OpenMP_CXX "${CMAKE_CXX_COMPILER}")
set(OpenMP_CXX_FLAGS "-Xclang -fopenmp")
set(OpenMP_CXX_LIB_NAMES "libomp" "libiomp5")
set(OpenMP_libomp_LIBRARY libomp)
set(OpenMP_libiomp5_LIBRARY libiomp5)

#OPENMP
find_package(OpenMP REQUIRED)
if(OPENMP_FOUND)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}")
endif()

# Library
add_library(example_lib SHARED example_lib.h example_lib.cpp)
target_link_libraries(example_lib PUBLIC ${OpenMP_CXX_LIBRARIES})
target_compile_definitions(example_lib PRIVATE EXEMPLE_LIB_EXPORT)

# Executable
add_executable(test_openmp test_openmp.cpp)
target_link_libraries(test_openmp example_lib)

This succeeded in "finding" the libraries on the second CMake configuration attempt (the first always yielded the same Could NOT find OpenMP_CXX error as before):

>cmake -G Ninja -DCMAKE_CXX_COMPILER=clang-cl ..
-- Found OpenMP_CXX: -Xclang -fopenmp (found version "3.1")
-- Found OpenMP: TRUE (found version "3.1")
-- Configuring done
-- Generating done

However, this failed to build the executable, as none of the CMake OpenMP variables (particularly OpenMP_CXX_LIBRARIES) actually point to the library location. The shortcomings of CMake's FindOpenMP.cmake have been raised on the CMake issue site here, and there appear to be relevant limitations on the LLVM/Clang end as well.


Regardless, the cleanest way I was able to get the example working was to ditch find_package() altogether. The following allowed me to successfully generate the buildsystem, and compile and run the executable:

cmake_minimum_required (VERSION 2.8)
project(test_openmp LANGUAGES CXX)

set(OpenMP_LIBRARY_DIR "C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/Llvm/lib")
set(OpenMP_CXX_FLAGS "-Xclang -fopenmp")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")

# Tell CMake where to find the OpenMP libraries.
link_directories(${OpenMP_LIBRARY_DIR})

# Library
add_library(example_lib SHARED example_lib.h example_lib.cpp)
# Link in the OpenMP libraries.
target_link_libraries(example_lib PUBLIC libomp libiomp5md)
target_compile_definitions(example_lib PRIVATE EXEMPLE_LIB_EXPORT)

# Executable
add_executable(test_openmp test_openmp.cpp)
target_link_libraries(test_openmp example_lib)

How to use Clang-CL LLVM with VS2019 CMAKE?

This doesn't work with VS2019. In vs2019 you MUST specify the toolset as ClangCL.
This change isn't documented anywhere as far as I can see.
I was only able to figure this out via trial and error.

cmake -G"Visual Studio 2019" -T ClangCL ..

Here is the output you'll get.

PS D:\Github\glfw> cmake -S . -B build -T ClangCl
-- Building for: Visual Studio 16 2019
-- Selecting Windows SDK version 10.0.18362.0 to target Windows 10.0.19041.
-- The C compiler identification is Clang 10.0.0 with MSVC-like command-line
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/Llvm/x64/bin/clang-cl.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Looking for pthread.h
-- Looking for pthread.h - not found
-- Found Threads: TRUE
-- Could NOT find Doxygen (missing: DOXYGEN_EXECUTABLE)
-- Using Win32 for window creation
-- Configuring done
-- Generating done
-- Build files have been written to: D:/Github/glfw/build

Here is what it will look like:

Sample Image

EDIT:

You can also set the toolset manually like this:

# Must be called before project call
set(CMAKE_GENERATOR_TOOLSET "ClangCL")

project(FOOBAR
LANGUAGES "CXX"
)

Building a simple C++ project on Windows, using CMake and clang

If I remember correctly, Clang attempts to use MSVC's standard library on Windows by default, since Clang's own standard library doesn't work on Windows yet.

If you don't have MSVC installed, this causes problems.

The easiest solution is to install MSYS2 and use MSYS2's patched Clang, which uses GCC's libraries by default. As a nice bonus, MSYS2 also comes with an up-to-date GCC version.


Alternatively, you can use -target flag to tell Clang to use GCC's libraries. If I remember correctly, this is done by adding -target x86_64-w64-mingw32 to both compiler and linker flags.

(If it doesn't work, try -target x86_64-w64-windows-gnu, I can't remember which one it is. Replace x86_64 with i686 if you're using a 32-bit compiler.)

Building with CMake, Ninja and Clang on Windows

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.

CMake: How to compile C on Windows with clang and lld with MinGW-w64 runtime

Please see the documentation on toolchains here: https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html#cross-compiling-using-clang

Since you're overriding the default Clang target, CMake needs to know about this during compiler detection. By the time you're in the CMakeLists.txt, it is too late. The following clang-x86_64_windows_gnu.cmake toolchain file might work (I can't test it without replicating your environment):

set(CMAKE_C_COMPILER clang)
set(CMAKE_C_COMPILER_TARGET x86_64-windows-gnu)

set(CMAKE_EXE_LINKER_FLAGS_INIT "-fuse-ld=lld")
set(CMAKE_MODULE_LINKER_FLAGS_INIT "-fuse-ld=lld")
set(CMAKE_SHARED_LINKER_FLAGS_INIT "-fuse-ld=lld")

Then your CMakeLists.txt was wrong, it should be:

cmake_minimum_required(VERSION 3.20)
project(P1 LANGUAGES C)

add_executable(c1 c1.c)

Notice the order of the cmake_minimum_required and project commands. They should always be the first two lines in your CMakeLists.txt, in that order.

Switching between GCC and Clang/LLVM using CMake

CMake honors the environment variables CC and CXX upon detecting the C and C++ compiler to use:

$ export CC=/usr/bin/clang
$ export CXX=/usr/bin/clang++
$ cmake ..
-- The C compiler identification is Clang
-- The CXX compiler identification is Clang

The compiler specific flags can be overridden by putting them into a make override file and pointing the CMAKE_USER_MAKE_RULES_OVERRIDE variable to it. Create a file ~/ClangOverrides.txt with the following contents:

SET (CMAKE_C_FLAGS_INIT                "-Wall -std=c99")
SET (CMAKE_C_FLAGS_DEBUG_INIT "-g")
SET (CMAKE_C_FLAGS_MINSIZEREL_INIT "-Os -DNDEBUG")
SET (CMAKE_C_FLAGS_RELEASE_INIT "-O3 -DNDEBUG")
SET (CMAKE_C_FLAGS_RELWITHDEBINFO_INIT "-O2 -g")

SET (CMAKE_CXX_FLAGS_INIT "-Wall")
SET (CMAKE_CXX_FLAGS_DEBUG_INIT "-g")
SET (CMAKE_CXX_FLAGS_MINSIZEREL_INIT "-Os -DNDEBUG")
SET (CMAKE_CXX_FLAGS_RELEASE_INIT "-O3 -DNDEBUG")
SET (CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT "-O2 -g")

The suffix _INIT will make CMake initialize the corresponding *_FLAGS variable with the given value. Then invoke cmake in the following way:

$ cmake -DCMAKE_USER_MAKE_RULES_OVERRIDE=~/ClangOverrides.txt ..

Finally to force the use of the LLVM binutils, set the internal variable _CMAKE_TOOLCHAIN_PREFIX. This variable is honored by the CMakeFindBinUtils module:

$ cmake -D_CMAKE_TOOLCHAIN_PREFIX=llvm- ..

Setting _CMAKE_TOOLCHAIN_LOCATION is no longer necessary for CMake version 3.9 or newer.

Putting this all together you can write a shell wrapper which sets up the environment variables CC and CXX and then invokes cmake with the mentioned variable overrides.

Also see this CMake FAQ on make override files.



Related Topics



Leave a reply



Submit