Bazel tips
BUILD file formatting
The buildifier
tool can be used to format BUILD files. You can download the
latest Buildifier release from the
Bazel Release Page.
See IDE configuration for tips on integrating this
with your IDE.
Avoiding rebuilds
Bazel is notoriously fickle when it comes to deciding whether a full rebuild is
necessary, which is bad for HEIR because rebuilding LLVM from scratch takes 15
minutes or more. We try to avoid this as much as possible by setting default
options in the project root’s .bazelrc
.
The main things that cause a rebuild are:
- A change to the
.bazelrc
that implicitly causes a flag change. Note HEIR has its own project-specific.bazelrc
in the root directory. - A change to the command-line flags passed to bazel, e.g.,
-c opt
vs-c dbg
for optimization level and debug symbols. The default is-c dbg
, and you may want to override this to optimize performance of generated code. For example, the OpenFHE backend generates much faster code when compiled with-c opt
. - A change to relevant command-line variables, such as
PATH
, which is avoided by theincompatible_strict_action_env
flag. Note activating a python virtualenv triggers aPATH
change. The default isincompatible_strict_action_env=true
, and you would override this in the event that you want your shell’s environment variables to change and be inherited by bazel.
Pointing HEIR to a local clone of llvm-project
Occasionally changes in HEIR will need to be made in tandem with upstream
changes in MLIR. In particular, we occasionally find upstream bugs that only
occur with HEIR passes, and we are the primary owners/users of the upstream
polynomial
dialect.
To tell bazel
to use a local clone of llvm-project
instead of a pinned
commit hash, replace bazel/import_llvm.bzl
with the following file:
cat > bazel/import_llvm.bzl << EOF
"""Provides the repository macro to import LLVM."""
def import_llvm(name):
"""Imports LLVM."""
native.new_local_repository(
name = name,
# this BUILD file is intentionally empty, because the LLVM project
# internally contains a set of bazel BUILD files overlaying the project.
build_file_content = "# empty",
path = "/path/to/llvm-project",
)
EOF
The next bazel build
will require a full rebuild if the checked-out LLVM
commit differs from the pinned commit hash in bazel/import_llvm.bzl
.
Note that you cannot reuse the LLVM CMake build artifacts in the bazel build. Based on what you’re trying to do, this may require some extra steps.
- If you just want to run existing MLIR and HEIR tests against local
llvm-project
changes, you can run the tests from HEIR usingbazel test @llvm-project//mlir/...:all
. Newlit
tests can be added inllvm-project
’s existing directories and tested this way without a rebuild. - If you add new CMake targets in
llvm-project
, then to incorporate them into HEIR you need to add new bazel targets inllvm-project/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel
. This is required if, for example, a new dialect or pass is added in MLIR upstream.
Send any upstream changes to HEIR-relevant MLIR files to @j2kun (Jeremy Kun) who has LLVM commit access and can also suggest additional MLIR reviewers.
Finding the right dependency targets
Whenever a new dependency is added in C++ or Tablegen, a new bazel BUILD
dependency is required, which requires finding the path to the relevant target
that provides the file you want. In HEIR the BUILD target should be defined in
the same directory as the file you want to depend on (e.g., the targets that
provide foo.h
are in BUILD
in the same directory), but upstream MLIR’s bazel
layout is different.
LLVM’s bazel overlay for MLIR is contained in a single file, and so you can manually look there to find the right target. With bazel, if you know the filepath of interested you can also run:
bazel query --keep_going 'same_pkg_direct_rdeps(@llvm-project//mlir:<path>)'
where <path>
is the path relative to mlir/
in the llvm-project
project
root. For example, to find the target that provides
mlir/include/mlir/Pass/PassBase.td
, run
bazel query --keep_going 'same_pkg_direct_rdeps(@llvm-project//mlir:include/mlir/Pass/PassBase.td)'
And the output will be something like
@llvm-project//mlir:PassBaseTdFiles
You can find more examples and alternative queries at the Bazel query docs.