🐌
Yours truly is not an expert in compilers, but does enjoy diving into this topic and learning something new from time to time.

This post is split up into 3 pages.

Building

What I prefer to do is to first create a folder that is going to contain a clone of Clang/LLVM’s repo, one or more VS solution folders, a readme, a sub-folder with C/C++ code to test a built Clang executable on, etc.

PS > mkdir llmv-pod
PS > cd llvm-pod

Cloning the repo

Checking out Clang/LLVM’s sources is straightforward1.

PS > cd llvm-pod
PS > git clone https://github.com/llvm/llvm-project.git

Generating a solution

CMake generates a VS solution for Clang. The getting started page suggests generating it in a new folder inside of the cloned repo, e.g., llvm-pod/llvm-project/build. But keeping this folder outside the source tree, next to the repo’s folder works better for me. One benefit such an organization brings is when doing a search for a string in the source files, matches from the build folder don’t pollute the search results.

The structure of the llvm_pod folder

Additionally, it’s convenient to have multiple build folders in certain cases. This is why I pick more specific build folder names like vs-2022-1 over generic ones like build. CMake command line to generate a VS solution that gives me the optimal result is:

PS > cd llvm-pod

PS > mkdir vs-2022-1
PS > cd vs-2022-1

PS > cmake -G "Visual Studio 17 2022" -DLLVM_ENABLE_PROJECTS=clang -DLLVM_OPTIMIZED_TABLEGEN=ON -DPython3_EXECUTABLE="C:/Users/Mykola/.pyenv/pyenv-win/versions/3.11.3/python.exe" -A x64 -Thost=x64 ../llvm-project/llvm

It deviates from the one suggested in the documentation in a number of ways. Let’s quickly go over the differences.

  1. It factors in the discussed folder structure — ../llvm-project/llvm.
  2. CMake doesn’t recognize pyenv’s shims, so -DPython3_EXECUTABLE="... " is there to point it to the Python’s executable. To find out the path to the activated Python version, run pyenv which python in a powershell/cmd window. It’s important to replace back slashes \ in the command’s output with forward slashes /, otherwise Clang/LLVM’s test suites will fail to run.
  3. CMake’s generator for VS 2022 is Visual Studio 17 2022. Assuming you have that version of VS installed too, if you run the command from the docs:
PS > cmake -DLLVM_ENABLE_PROJECTS=clang -G "Visual Studio 15 2017" -A x64 -Thost=x64 ../llvm-project/llvm

CMake will likely great you with a similar error message:

CMake Error at CMakeLists.txt:47 (project):
  Generator

    Visual Studio 15 2017

  could not find any instance of Visual Studio.

-- Configuring incomplete, errors occurred!

The text is a bit misleading. CMake wasn’t looking for literally any instance of VS, as clearly there is VS 2022 installed. What it’s really trying to say is it couldn’t find an instance of VS 20172. Asking for the generator Visual Studio 17 2022 solves the problem.

  1. Clang and LLVM rely on code generation tools — the tablegenning tools. When you’re building Clang and LLVM, first the executables of these tablegenning tools get built. From there, whenever the build process encounters a .td file it invokes a table generator to produce an include file3 from a .td file. The -DLLVM_OPTIMIZED_TABLEGEN=ON switch tells CMake to enable optimizations for the tools. The optimizations speed up build times of Clang/LLVM’s sources. From a couple quick, limited tests on my machine the time to build Clang from scratch goes down from 1 hour 25 minutes to 29 minutes.

Compiling

Open llvm-pod/vs-2022-1/LLVM.sln in Visual Stuido.

Making the optimized tablegen work

If you’ve passed -DLLVM_OPTIMIZED_TABLEGEN=ON to CMake, there’re a few adjustments to make before the solution is ready to be built.

Adding a missing build dependency

The project clang-tblgen-host has to have a build dependency on the project llvm-tblgen-host. Otherwise the two project often start building in parallel and conflict with each other because of that. Which leads to compile errors. Look for clang-tblgen-host under the solution’s root.

The clang-tblgen-host project location

Right-click the project and pick Build Dependencies > Project Dependencies… from the context menus. Add a build dependency on llvm-tblgen-host.

Adding a build dependency on llvm-tblgen-host to clang-tblgen-host

Configuring the Python’s path

The project CONFIGURE_LLVM_NATIVE is responsible for building the optimized tablegenning tools. To carry out its task the project starts a CMake process. Unfortunately, it doesn’t pass on the Python’s path configured on the solution generation step. We’ll have to take care of that ourselves.

Run pyenv which python in a powershell/cmd window, and copy the command’s output into the clipboard. Then open vs-2022-1/CONFIGURE_LLVM_NATIVE.vcxproj in a text editor, find lines starting with "C:\Program Files\CMake\bin\cmake.exe" (including quotes) and add a parameter pointing CMake to the Python’s executable. For me, the parameter to add looks like this "-DPython3_EXECUTABLE=C:/Users/Mykola/.pyenv/pyenv-win/versions/3.11.3/python.exe" and an updated line — like this:

[...]
if %errorlevel% neq 0 goto :cmEnd
"C:\Program Files\CMake\bin\cmake.exe" -G "Visual Studio 17 2022" "-DPython3_EXECUTABLE=C:/Users/Mykola/.pyenv/pyenv-win/versions/3.11.3/python.exe" -DCMAKE_MAKE_PROGRAM=[...]
if %errorlevel% neq 0 goto :cmEnd
[...]

Picking the project to build

As the guide points out, you can either build the clang project to get “just the compiler driver and front end”. I must be missing something, but am not sure why it says “just the compiler driver and front end”, the build results in a fully functioning instance of Clang capable of compiling C/C++ down to binary files.

Solution ‘LLVM’/Clang executables/clang

Or the BUILD_ALL project from CMakePredefinedTargets to “build everything, including tools”.

Solution ‘LLVM’/CMakePredefinedTargets/BUILD_ALL

Pick the one that fits your goals best. Just keep in mind this solution is not meant to be built with the Build Solution or Rebuild Solution options.

Avoid building the entire solution

On the other hand, Clean Solution works just fine, in my experience.

Limiting CPU load

Once a build is in progress, the CPU utilization will reach 100% and chances are the machine will become unresponsive complete with the mouse pointer staggering (Am I saying it like it’s a bad thing?).

100% CPU utilization during a build

There’s a CMake option to limit the number of parallel MS C/C++ compiler processes started per project — -DLLVM_COMPILER_JOBS=N. But since this setting alone is not enough to keep the machine responsive through the build, I don’t use it all.

One way to keep the computer usable for other tasks throughout a Clang build, is to limit the number of concurrent MS C/C++ compilers per project and the number of projects that can be built in parallel. It does work but has an unfortunate outcome. Sometimes there’s no other task to perform during a build. Or there’re tasks, but these aren’t fully utilizing the CPU capacity removed from Clang’s build by limiting concurrency. This means we’re leaving performance on the table and unnecessarily making builds take longer.

Another solution that works much better for me is to lower the priorities of MS C/C++ compiler and linker processes.

Starting from VS 2022 version 17.3, the setting is under Tools > Options > Projects and Solutions -> Build And Run -> Run build at low process priority. “For best effect, restart the IDE after changing the value so that the previous priority MSBuild nodes could close”.

Run build at low process priority

If you’re running an earlier version, it’s possible to lower the processes’ priorities by tweaking the registry:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\cl.exe]
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\cl.exe\PerfOptions]
"CpuPriorityClass"=dword:00000005
"IoPriority"=dword:00000001

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\link.exe]
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\link.exe\PerfOptions]
"CpuPriorityClass"=dword:00000005
"IoPriority"=dword:00000001

Running tests, debugging Clang’s source code

Continue on to Part 3. Running tests, debugging Clang’s source code.


  1. The cd commands are intended to indicate the location for executing subsequent commands. If you’ve already navigated there, ignore them, of cousre :) ↩︎

  2. The 15 in Visual Studio 15 2017 is the version number MS assigned to Visual Studio 2017. Don’t ask me, why the version couldn’t simply be 2017. ↩︎

  3. In addition to include files, a few other output formats are supported. ↩︎