đ
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.
- Part 1. Installing Clang’s build dependencies
- Part 2. Generating a solution and building it. <– You are here.
- Part 3. Running tests, debugging Clang’s source code.
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.
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.
- It factors in the discussed folder structure â
../llvm-project/llvm
. - 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, runpyenv 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. - 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.
- 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.
Right-click the project and pick Build Dependencies > Project Dependencies… from the context menus. Add a build dependency on llvm-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.
Or the BUILD_ALL
project from CMakePredefinedTargets
to “build everything, including tools”.
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.
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?).
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”.
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.
The
cd
commands are intended to indicate the location for executing subsequent commands. If you’ve already navigated there, ignore them, of cousre :) ↩︎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. ↩︎In addition to include files, a few other output formats are supported. ↩︎