Open-source project
numba/llvmlite avatar
numba/llvmlite

llvmlite: a small LLVM binding aimed squarely at JIT compiler authors

A lightweight LLVM python binding for writing JIT compilers

2,301 stars376 forksPythonBSD-2-Clause

At a glance

What is it?
Not a general LLVM wrapper but a deliberately narrow one: a C shim, a ctypes layer and a pure Python IR builder. The compatibility table is the most useful page in the README.
Who is it for?
llvmlite exists because binding LLVM's C++ API to Python at full fidelity is a mistake, and everything in its design follows from that decision. If you are writing a JIT compiler, the pure Python IR builder is the part you will actually use, and the fact that materialising a module goes through LLVM's own IR parser rather than incremental C++ calls is what turns segfaults into readable errors.
Can I use it commercially?
Yes. BSD-2-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 13 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 28, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Three layers, and only the third is Python

The README describes llvmlite's architecture in three bullet points, and the whole design is in them. There is a small C wrapper around the parts of the LLVM C++ API that are not already exposed by the LLVM C API. There is a ctypes Python wrapper around that C API. And there is a pure Python implementation of the subset of the LLVM IR builder that Numba needs.

Only the third layer is pure Python, and that is the layer the project considers its own. GitHub reports Python as the language with a BSD-2-Clause license, 2,301 stars, 376 forks and 164 open issues, last pushed on 2026-09-25. The repository tree shows the separation clearly: `ffi/` holds the C wrapper and its own `build.py`, `llvmlite/` is the Python package, and `examples/` contains the runnable demonstrations.

The reason for not using a Python C extension is stated directly: it is a plain shared library accessed through ctypes, so there is no need to wrestle with Python's compiler requirements and C++ 11 compatibility. That decision has consequences. Installing llvmlite from source needs a C++ toolchain and an LLVM development install, which is exactly why the project steers you to prebuilt binaries first.

Why the old llvmpy binding was abandoned

The README has a section titled why llvmlite, and it is really an argument against its predecessor, llvmpy, which it links as the earlier project. The complaint is that llvmpy exposed a lot of LLVM APIs but that the mapping of C++-style memory management to Python was error prone.

The argument continues: Numba and many JIT compilers do not need a full LLVM API, only the IR builder, the optimizer and the JIT compiler interfaces. So the design decision is to be incomplete on purpose.

The listed benefits follow from that. The IR builder is pure Python code, decoupled from LLVM's frequently-changing C++ APIs, so a C++ refactor upstream does not reach into your Python. Most of llvmlite uses the LLVM C API, which is small and stable, which lowers maintenance cost when the LLVM version changes. The Python binding layer has sane memory management. And llvmlite is described as faster than llvmpy thanks to the simpler architecture, with the specific claim that the Numba test suite runs twice as fast as it was.

That last claim is the one to hold loosely. It is a statement about test suite wall time, which measures how quickly the compiler tooling can be exercised, not how fast compiled code runs. Both matter, but only one of them is about your program's performance.

The compatibility table is the page to bookmark

llvmlite pins an LLVM version exactly rather than declaring a range, and the README keeps a historical table so you can work out which llvmlite to install for the LLVM you have. The current line: as of version 0.48.0, llvmlite requires LLVM 22.x.x on all architectures.

The table then works backwards. Versions 0.45.0 through 0.47.x need LLVM 20.x.x, 0.44.0 needs 15.x.x or 16.x.x, 0.41.0 to 0.43.0 need 14.x.x, 0.40.0 through 0.40.1 accept 11.x.x and 14.x.x with 12.x.x and 13.x.x marked untested but possibly working, and 0.37.0 through 0.39.1 need 11.x.x. Older entries continue down to 0.1.0 through 0.5.1 on LLVM 3.5.x.

There are two things to notice. First, the jump from 16.x.x at llvmlite 0.44.0 to 20.x.x at 0.45.0 skips three LLVM majors in one llvmlite release, so the mapping is not one-to-one across versions and you cannot assume adjacent llvmlite releases sit on adjacent LLVM releases. Second, the table overlaps: 0.17.0 appears both in the row for 0.16.0 through 0.17.0 on LLVM 3.9.x and in the row for 0.17.0 through 0.20.0 on LLVM 4.0.x. If you are pinning an old version, that overlap means the table alone does not settle it.

A third gap matters more in practice. The table's top row is 0.48.0, and the newest published release is 0.49.0 from 2026-08-11. So the LLVM requirement for the current release is not stated in the table. The 0.48.0 release notes and the 0.49.0 release notes are the places to check it, and both are on the project's Read the Docs site.

Python support, and where the README stops being precise

The README states that llvmlite has been tested with Python 3.10 through 3.15 and is likely to work with greater versions. The packaging enforces only half of that.

`setup.py` defines `min_python_version = (3, 10)` and calls a guard function before anything else, which raises a RuntimeError naming the current and minimum versions if the interpreter is older. There is no upper bound in that check. So the tested range and the enforced range genuinely differ: 3.10 is a hard floor, and 3.16 would install without complaint despite being outside what the README says was tested. That is a deliberate-looking choice for a library that ships prebuilt wheels, and it is also a reason to prefer a pinned environment.

The build script is where the toolchain requirement becomes concrete. `build_library_files()` runs `ffi/build.py` as a subprocess with `check=True`, so a failure to compile the shim aborts the install rather than producing a broken package. On Linux, BSD, macOS and GNU platforms the script appends `-fPIC` to `CXXFLAGS` before doing so.

The rest of the packaging is versioneer, with the version file at `llvmlite/_version.py`, a tag prefix of `v` and a parent directory prefix of `llvmlite-`. There is also a `LICENSE.thirdparty` file in the tree, which is worth a look given the project links against LLVM.

Installing: conda first, everything else second

The README's recommendation is unambiguous. Use the binaries provided by the Numba team through the Conda package manager, from Numba's anaconda.org channel:

bash
conda install --channel=numba llvmlite

It also notes that the official llvmlite package in the Anaconda distribution works. The reason for the recommendation is structural rather than a matter of taste: llvmlite is not a pure Python wheel, so a source install means compiling the C shim against a matching LLVM, which means your system LLVM development package has to be the right major version.

For everyone else, the README points to the installation section of the documentation at llvmlite.pydata.org and says it will teach you how to compile and install llvmlite yourself. That is where the wheel-building instructions live, and they are also the answer to the most common failure people hit with this package.

The examples directory is the other thing to look at before building anything. `examples/lljit.py` is the LLVM ORC JIT example, `examples/llvmir.py` shows IR handling, `examples/llvmir_iter.py` iteration, `examples/parseasm.py` assembly parsing, `examples/ir_fpadd.py` building IR in Python, `examples/ll_fpadd.py` running the result, and `examples/test.ll` is a hand-written IR file to parse. There is also a `examples/opaque_pointers/` directory and a `examples/notebooks/` directory.

Materialising IR through the parser instead of the API

One design choice deserves isolating because it explains why llvmlite is easier to debug than a direct binding.

Materialising an LLVM module calls LLVM's IR parser, rather than building the module step by step through the C++ API. The README states the benefit plainly: better error messages than step-by-step IR building, and no more segfaults or process aborts.

That is a large practical difference. With a direct API, a mistake in your construction order produces a crash inside the C++ library with no useful context. With llvmlite, the same mistake produces a parse error on the textual IR you generated, which points at the thing you got wrong. For a project that builds IR programmatically from another language's type system, which is exactly what Numba does, that difference is the difference between a debuggable error and an intermittent abort.

The examples `ir_fpadd.py` and `ll_fpadd.py` together illustrate the intended workflow: build IR in Python, then hand it to the JIT and call it. The `examples/llvmir_iter.py` file suggests the other common need, walking a module once it exists.

Editorial conclusion

llvmlite exists because binding LLVM's C++ API to Python at full fidelity is a mistake, and everything in its design follows from that decision. If you are writing a JIT compiler, the pure Python IR builder is the part you will actually use, and the fact that materialising a module goes through LLVM's own IR parser rather than incremental C++ calls is what turns segfaults into readable errors. If you only want to call LLVM from Python for something small, this is still more than you need. Check the compatibility table against the LLVM version you have before anything else, because llvmlite pins one exactly and refuses to run against the wrong one.

Frequently asked questions

What does the error "error failed building wheel for llvmlite" mean and how can I fix it?

It means pip fell back to a source build and compiling the bundled C wrapper failed. llvmlite is not a pure Python package, so the install needs a working LLVM development install matching the version that release of llvmlite requires. The README's fix is to avoid the source build: install with conda from the numba channel, which ships prebuilt binaries.

What does LLVM stand for?

LLVM is the Low Level Virtual Machine, a compiler infrastructure project that provides an intermediate representation, an optimizer and a JIT compiler used by languages including C, Rust, Clang and, through llvmlite, Python JIT compilers. llvmlite does not implement LLVM; it binds to an existing LLVM installation.

How can I use LLVM in Python?

Install llvmlite rather than trying to bind LLVM yourself. It gives you a pure Python IR builder, a ctypes wrapper over the LLVM C API and a JIT interface, so you can create a module, add functions to it, materialise it and execute it without writing C++. The README warns that the older llvmpy binding exposed far more of the LLVM C++ API and was error prone to use.

Is LLVM written in C or C++?

LLVM's core is written in C++, which is part of why binding its C++ API to another language is awkward. The stable, small surface intended for other languages is the C API, and that is the API llvmlite mostly uses, adding a small C shim only for the parts the C API does not expose. Its IR builder layer is pure Python.

Official sources

  1. License: BSD-2-Clause
  2. numba/llvmlite on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/numba-llvmlite.svg)](https://hysenlabs.com/projects/numba-llvmlite)