6. pyxc: Installing LLVM

Next: connect the working pyxc frontend to LLVM.

Do not add code generation yet. This chapter has one smaller boundary:

installed LLVM -> find_package(LLVM) succeeds

Chapter 7 depends on LLVM headers and libraries. If discovery is unreliable now, every later build error will be harder to diagnose.

Work in:

cd code/chapter-06

6.1 Make CMake Require LLVM

The C++ source stays the same as Chapter 5. In CMakeLists.txt, add:

find_package(LLVM REQUIRED CONFIG)

message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")

include_directories(SYSTEM ${LLVM_INCLUDE_DIRS})
add_definitions(${LLVM_DEFINITIONS})

CONFIG tells CMake to find LLVM's installed LLVMConfig.cmake. The two status messages make the selected version and installation path visible during every configure.

If LLVM is already installed, try the verification immediately:

cmake -S . -B build

Expected shape:

-- Found LLVM <version>
-- Using LLVMConfig.cmake in: <path>
-- Configuring done

If that works, build and run the unchanged frontend:

cmake --build build
./build/pyxc

Otherwise, choose one installation path below.

6.2 Install with Homebrew on macOS or Linux

Install LLVM and the separately packaged linker/debugger tools:

brew install llvm lld lldb

Homebrew keeps LLVM separate from the system toolchain. Ask Homebrew for the prefix rather than hard-coding /opt/homebrew or /usr/local:

brew --prefix llvm
brew --prefix lld
brew --prefix lldb

For the current shell, export a project-specific LLVM location:

export PYXC_LLVM_ROOT="$(brew --prefix llvm)"
export PATH="$PYXC_LLVM_ROOT/bin:$(brew --prefix lld)/bin:$(brew --prefix lldb)/bin:$PATH"

Then configure pyxc explicitly:

cmake -S . -B build \
  -DLLVM_DIR="$PYXC_LLVM_ROOT/lib/cmake/llvm"
cmake --build build

Using LLVM_DIR is more precise than hoping CMake searches the correct prefix. It points directly to the directory containing LLVMConfig.cmake.

Verify the tools:

llvm-config --version
clang --version
lld --version
lldb --version

Homebrew may not provide a convenient llvm-lit command. If neither llvm-lit nor lit exists, install the Python package:

python3 -m pip install lit
lit --version

6.3 Install a Released Build on Windows

Download the current Windows release installer from the official LLVM releases page.

During installation, allow the installer to add LLVM to PATH, or add its bin directory afterward. A typical installation prefix is:

C:\Program Files\LLVM

Open a new PowerShell session and verify:

clang --version
lld --version
lldb --version

Configure pyxc with the LLVM CMake package directory:

cmake -S . -B build `
  -DLLVM_DIR="C:\Program Files\LLVM\lib\cmake\llvm"
cmake --build build

If lit is missing:

py -m pip install lit
lit --version

If the release package does not contain the development CMake files required by find_package, use a package manager that provides LLVM development files or build LLVM from source.

6.4 Build LLVM from Source

Use this route when you want a specific revision, need all development files, or plan to work on LLVM itself.

Install the prerequisites first:

CMake 3.20 or newer
Ninja
Python 3.8 or newer
a working C and C++ compiler
Git

Clone the monorepo:

git clone --depth 1 https://github.com/llvm/llvm-project.git
cd llvm-project

Choose explicit build and installation directories. Replace the example install prefix with a location you own:

cmake -S llvm -B build -G Ninja \
  -DCMAKE_BUILD_TYPE=Release \
  -DCMAKE_INSTALL_PREFIX="$PWD/install" \
  -DLLVM_ENABLE_PROJECTS="clang;lld;lldb" \
  -DLLVM_INSTALL_UTILS=ON

Build:

cmake --build build

This can consume substantial time, memory, and disk space. If linking exhausts memory, reconfigure with a smaller link-job limit:

-DLLVM_PARALLEL_LINK_JOBS=1

Optionally run LLVM's tests:

cmake --build build --target check-all

Install into the chosen prefix:

cmake --build build --target install

Then configure pyxc against it:

cd /path/to/pyxc-llvm-tutorial/code/chapter-06
cmake -S . -B build \
  -DLLVM_DIR=/path/to/llvm-project/install/lib/cmake/llvm
cmake --build build

You may also configure pyxc directly against an LLVM build tree:

cmake -S . -B build \
  -DLLVM_DIR=/path/to/llvm-project/build/lib/cmake/llvm

6.5 Diagnose CMake Discovery Failures

If CMake reports:

Could not find a package configuration file provided by "LLVM"

find the configuration file:

find /path/to/llvm -name LLVMConfig.cmake

Then pass its containing directory—not the file itself—as LLVM_DIR:

cmake -S . -B build -DLLVM_DIR=/path/containing/LLVMConfig.cmake

If CMake cached a wrong LLVM installation, use a new build directory:

cmake -S . -B build-llvm \
  -DLLVM_DIR=/correct/path/lib/cmake/llvm
cmake --build build-llvm

This avoids mixing configuration from two LLVM versions.

6.6 Verify the Complete Boundary

Run:

llvm-config --version
llvm-config --cmakedir

The second command should identify the directory you pass as LLVM_DIR.

Then configure, build, and test:

cmake -S . -B build \
  -DLLVM_DIR="$(llvm-config --cmakedir)"
cmake --build build
llvm-lit -v test/  # use `lit -v test/` if installed from pip

The chapter source still behaves like Chapter 5. The new result is entirely in the build system:

CMake found LLVM headers, definitions, version, and package configuration

Useful official references:

Next: Chapter 7 gives every AST node a codegen() method and emits LLVM IR.

6.7 Need Help?

Build issues? Questions?

Include:

  • Your operating system and version
  • The chapter number
  • The exact command you ran
  • The complete error message
  • The output of c++ --version and cmake --version
  • The output of llvm-config --version for Chapter 6 and later