The main complexity here is that the Python frontend generates MLIR, runs some HEIR pipeline, and then may get as output language-specific source code (C++ code, Go code, Python code etc.), which then must be integrated back into the frontend. For compiled languages, this requires a system-wide dependency on the particular compiler toolchain and any installed library dependencies as shared object files.
Bazel avoids these issues, with the exception of having a C++ compiler and the C++ standard libraries available on you system.
System requirements:
- A C compiler, such as
clang++org++. - C/c++ standard libraries that come with the compiler, but may be in a
nonstandard location. Ensure they can be discovered by a call to
clangwithout any special flags. (clang -vwill show you which paths it considers). - Python development headers (e.g.,
python3.11-devor similar).
- Use the macros in
testing.bzlto createpy_testrules that exercise the frontend, and run them withbazel test. - Create
py_binaryrules depending on@heir//frontendto create executables, and run then withbazel run.
- Ensure
bazel build //tools:allhas been run to buildheir-optandheir-translate. - Create a virtualenv:
python3.11 -m venv venv. It should also work with Python 3.12 and 3.13. - Install the frontend:
pip install -e .(if this fails, add-v). In this case, the installed package will autodetect paths to relevant resources from the bazel build.
- Install:
pip install .. This will run the bazel build, copy relevant files, and install the package just like a wheel installed from PyPI.
The Python frontend uses the following environment variables as overrides for auto-detected resources.
-
HEIR_OPT_PATHandHEIR_TRANSLATE_PATH: to the location of theheir-optandheir-translatebinaries on your system.- Uses
shutil.whichto find the binary on your path if not set. - Defaults to
bazel-bin/tools/heir-{opt,translate}. - Cf.
heir/backends/openfhe/config.pyfor more details.
- Uses
-
OpenFHE installation locations (default to where
cmakeinstalls them in the OpenFHE development repo).OPENFHE_LIB_DIR: a string containing the directory containing the OpenFHE .so files. Usually/usr/local/libOPENFHE_INCLUDE_DIR: a colon-separated string of directories containing OpenFHE headers. Note this usually requires four different paths due to how OpenFHE organizes its imports, one for each of the three main subdirectories of the project./usr/local/include/openfhe/usr/local/include/openfhe/binfhe/usr/local/include/openfhe/core/usr/local/include/openfhe/pke
OPENFHE_LINK_LIBS: a colon-separated string of libraries to link against (withoutlibor.so). E.g.,"OPENFHEbinfhe:OPENFHEcore:OPENFHEpke".OPENFHE_INCLUDE_TYPE: a string indicating the include path type to use (see options onheir-translate --emit-openfhe). Should beinstall-relativefor a system-wide OpenFHE installation.
This uses pyink for autoformatting, which is a fork of the more commonly used black formatter with some patches to support Google's internal style guide. The configuration in pyproject.toml corresponds to the options making pyink consistent with Google's internal style guide.
The pyink repo has instructions for setting up pyink with VSCode. The
pre-commit configuration for this repo will automatically run pyink, and to
run a one-time format of the entire project, use pre-commit run --all-files.
The HEIR Python package is built using cibuildwheel, which is also what CI uses to produce PyPI releases. To test wheel builds locally:
- Install docker or podman (required for containerized linux builds). If using
podman, set the environment variable
CIBW_CONTAINER_ENGINE=podman. - Install
cibuildwheel(pip install cibuildwheel). - macOS only: cibuildwheel requires the official
python.org framework installers (not
Homebrew or uv-managed Pythons). Download and install the
.pkgfor each Python version you want to build (3.12, 3.13, etc.).
Build a single wheel (recommended for local testing):
cibuildwheel --only cp312-macosx_arm64 # macOS Apple Silicon
cibuildwheel --only cp312-macosx_x86_64 # macOS Intel
cibuildwheel --only cp312-manylinux_x86_64 # Linux x86_64
cibuildwheel --only cp312-manylinux_aarch64 # Linux arm64The built wheel will be in ./wheelhouse/. Note that building wheels for
non-native architectures will require emulation and therefore be significantly
slower.
The GitHub Actions workflow (.github/workflows/wheels.yml) builds wheels for
both Linux and macOS and uploads them to PyPI on release. It can also be
triggered manually via workflow_dispatch.