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:
And you can crosscheck the available "Platform Toolsets" in any VS project's property page:
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:
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
How to Provider User with Autocomplete Suggestions for Given Boost::Spirit Grammar
How to Make My Split Work Only on One Real Line and Be Capable to Skip Quoted Parts of String
Rewinding Std::Cout to Go Back to the Beginning of a Line
Adding List Items or Nodes in Linked List
Clean C++ Granular Friend Equivalent? (Answer: Attorney-Client Idiom)
How to Create Unique_Ptr That Holds an Allocated Array
Declare Variables at Top of Function or in Separate Scopes
When Should Your Destructor Be Virtual
How to Reduce Compile Time, and Linking Time for Visual C++ Projects (Native C++)
Does New[] Call Default Constructor in C++
Determine If Type Is a Pointer in a Template Function
Translating Python Dictionary to C++
C++ Convert Integer to String at Compile Time
How to Target Windows Xp in Microsoft Visual Studio C++
Is There Any Way a C/C++ Program Can Crash Before Main()