blob: 078251177d51b9a27f469d133d5ebc439aa3fa8c [file] [log] [blame] [view]
# Using IREE with a Custom LLVM via Bzlmod
This document explains how projects that depend on IREE can provide their own LLVM
instead of using IREE's bundled version.
## Terminology
### Bzlmod
Bazel's module system (introduced in Bazel 6.0, default in Bazel 7.0+). It replaces
the legacy WORKSPACE file with `MODULE.bazel` for managing external dependencies.
### Root Module
The top-level project being built. In bzlmod, only the root module's `MODULE.bazel`
is fully evaluated - dependency modules have limited control over the build graph.
### Module Extension
A mechanism for creating repositories dynamically in bzlmod. Extensions are defined
in `.bzl` files and invoked via `use_extension()` in MODULE.bazel.
### `use_extension()`
Runs a module extension's implementation function, which typically creates repositories.
Returns an extension proxy that can be passed to `use_repo()`.
### `use_repo()`
Imports repositories created by a module extension into the current module's visibility
scope. Without `use_repo()`, repos created by an extension exist but aren't accessible
to your BUILD files.
```python
# Extension creates repos internally
ext = use_extension("@some_module//:extensions.bzl", "some_extension")
# use_repo makes specific repos visible as @repo_a, @repo_b, etc.
use_repo(ext, "repo_a", "repo_b")
```
### `use_repo_rule()`
Imports a repository rule from another module so it can be called directly in
MODULE.bazel to create a repository.
### `llvm-raw`
A repository containing the raw LLVM source code. This is the input to the LLVM
build configuration.
### `llvm-project`
The configured LLVM repository created by `llvm_configure`. It overlays Bazel BUILD
files onto the `llvm-raw` source and extracts CMake configuration variables.
### `llvm-project-overlay`
The bzlmod module name for LLVM's Bazel integration (located at
`llvm-project/utils/bazel/`). It provides the `llvm_repos_extension` and
`llvm_configure` rule.
## How It Works
IREE's module extension (`iree_extension`) creates the `llvm-raw` repository
**only when IREE is the root module**:
```python
# In build_tools/bazel/extensions.bzl
def _iree_extension_impl(module_ctx):
if any([m.is_root and m.name == "iree_core" for m in module_ctx.modules]):
new_local_repository(
name = "llvm-raw",
build_file_content = "# empty",
path = "third_party/llvm-project",
)
# ... other repos
```
When your project depends on IREE, IREE is **not** the root module - your project is.
Therefore, IREE's extension will not create `llvm-raw`, and you must provide it yourself.
## MODULE.bazel Ordering
The order of statements in MODULE.bazel matters:
1. `module()` - must be first
2. `bazel_dep()` - declare module dependencies
3. `local_path_override()` - must come after the `bazel_dep()` it overrides
4. `use_extension()` - must come after the `bazel_dep()` that provides the extension
5. `use_repo()` - must come after its corresponding `use_extension()`
6. `use_repo_rule()` + invocation - can reference repos created by earlier extensions
## Example: Using Your Own LLVM
```python
# my_project/MODULE.bazel
module(
name = "my_project",
version = "1.0.0",
)
# Standard bazel dependencies (must match or be compatible with IREE's versions)
bazel_dep(name = "bazel_skylib", version = "1.8.2")
bazel_dep(name = "platforms", version = "1.0.0")
bazel_dep(name = "rules_cc", version = "0.2.11")
# ... other deps as needed
# Depend on IREE
bazel_dep(name = "iree_core", version = "0.0.1")
# Override IREE to use your local checkout (optional, for development)
local_path_override(
module_name = "iree_core",
path = "third_party/iree",
)
# Depend on LLVM overlay module
bazel_dep(name = "llvm-project-overlay", version = "main")
local_path_override(
module_name = "llvm-project-overlay",
path = "my/custom/llvm-project/utils/bazel",
)
# Create your own llvm-raw repository pointing to your LLVM
new_local_repository = use_repo_rule(
"@bazel_tools//tools/build_defs/repo:local.bzl",
"new_local_repository",
)
new_local_repository(
name = "llvm-raw",
path = "my/custom/llvm-project",
build_file_content = "# empty",
)
# Use LLVM's extension for third-party deps (gmp, mpfr, etc.)
llvm_repos_ext = use_extension(
"@llvm-project-overlay//:extensions.bzl",
"llvm_repos_extension",
)
use_repo(
llvm_repos_ext,
"gmp",
"mpc",
"mpfr",
"nanobind",
"pfm",
"pybind11",
"vulkan_sdk",
)
# Use IREE's extension (won't create llvm-raw since you're the root module)
iree_ext = use_extension(
"@iree_core//build_tools/bazel:extensions.bzl",
"iree_extension",
)
use_repo(
iree_ext,
"com_github_dvidelabs_flatcc",
"com_google_benchmark",
"com_google_googletest",
"stablehlo",
# ... other IREE repos you need
)
# Configure LLVM (creates llvm-project from your llvm-raw)
llvm_configure = use_repo_rule(
"@llvm-raw//utils/bazel:configure.bzl",
"llvm_configure",
)
llvm_configure(name = "llvm-project")
```
## Using LLVM from an HTTP Archive
If you want to fetch LLVM from a release tarball instead of a local path:
```python
# my_project/MODULE.bazel
http_archive = use_repo_rule(
"@bazel_tools//tools/build_defs/repo:http.bzl",
"http_archive",
)
LLVM_COMMIT = "abc123..." # Your desired commit
LLVM_SHA256 = "..." # SHA256 of the tarball
http_archive(
name = "llvm-raw",
build_file_content = "# empty",
sha256 = LLVM_SHA256,
strip_prefix = "llvm-project-" + LLVM_COMMIT,
urls = ["https://github.com/llvm/llvm-project/archive/{}.tar.gz".format(LLVM_COMMIT)],
)
```
## Version Compatibility
When providing your own LLVM, ensure compatibility with IREE:
1. **LLVM Version**: IREE targets a specific LLVM commit. Check IREE's
`third_party/llvm-project` submodule for the expected version.
2. **Bazel Dependencies**: Your LLVM's `utils/bazel/MODULE.bazel` declares
dependency versions. These should be compatible with IREE's dependencies.
3. **API Compatibility**: LLVM APIs change between versions. Your LLVM must
be API-compatible with what IREE expects.
## Troubleshooting
### "repository 'llvm-raw' is not defined"
You haven't created the `llvm-raw` repository. As the root module, you must
define it yourself (see examples above).
### Build errors in LLVM code
Your LLVM version may be incompatible with IREE. Check that your LLVM commit
is close to IREE's expected version.
### Duplicate repository errors
Multiple modules may be trying to create the same repository. Ensure only
one source defines each repository name.