# CIRCT builds inside an LLVM checkout, so cloning it means cloning LLVM as a submodule

> CIRCT applies MLIR and the LLVM development methodology to hardware design tools. This review covers the recursive clone, the cmake call that builds CIRCT as an external LLVM project, the narrower ninja targets, and why the README calls the project experimental.

**llvm/circt** — Circuit IR Compilers and Tools

- Repository: https://github.com/llvm/circt
- Website: https://circt.org
- Stars: 2,270 · Forks: 547
- Language: C++
- License: NOASSERTION
- Published: 2026-10-11 · Updated: 2026-10-30 · Language: en
- Canonical page: https://hysenlabs.com/projects/llvm-circt

## The LLVM submodule is the version CIRCT was tested against

CIRCT contains LLVM as a git submodule, and the checkout under llvm/ is not just a convenience. The README says that copy includes staged changes to MLIR which may be necessary to support CIRCT, and that it represents the version of LLVM that has been tested. MLIR is still changing relatively rapidly, so using a different LLVM is allowed but APIs may have changed.

This is why the first command is a recursive clone:

```sh
# Clone the repository and its submodules
git clone git@github.com:llvm/circt.git --recursive
cd circt
```

The URL is an SSH one, so an account with a GitHub SSH key is assumed. Whenever you check out a CIRCT branch that points to a different LLVM commit, run git submodule update to bring the submodule along.

The submodule is cloned shallow, with just enough history to check out the pinned commit. For work that needs the full LLVM history, cd llvm and run git fetch --unshallow.

## One cmake call builds CIRCT as an external project of LLVM

The quick start configures from the llvm/llvm directory and tells LLVM to treat CIRCT as an external project. Each flag does something specific:

```sh
# Configure the build
cmake -G Ninja llvm/llvm -B build \
    -DCMAKE_BUILD_TYPE=RelWithDebInfo \
    -DLLVM_ENABLE_ASSERTIONS=ON \
    -DLLVM_TARGETS_TO_BUILD=host \
    -DLLVM_ENABLE_PROJECTS=mlir \
    -DLLVM_EXTERNAL_PROJECTS=circt \
    -DLLVM_EXTERNAL_CIRCT_SOURCE_DIR=$PWD \
    -DLLVM_ENABLE_LLD=ON
```

LLVM_ENABLE_PROJECTS=mlir pulls in MLIR, LLVM_EXTERNAL_PROJECTS=circt registers CIRCT, and LLVM_EXTERNAL_CIRCT_SOURCE_DIR=$PWD points at the checkout. LLVM_TARGETS_TO_BUILD=host limits code generation to the host architecture, and LLVM_ENABLE_LLD=ON makes the build use the lld linker, which makes lld a build requirement.

The build tool is Ninja, and the README lists git, ninja, python3, cmake and a C++ toolchain as the dependencies. Fuller requirements are deferred to the MLIR and LLVM getting started pages.

## Building only circt-opt or firtool avoids compiling everything

The full build is also the test run: ninja -C build check-circt builds all CIRCT tools and libraries and runs all tests. That is the slow path.

For a single tool, name its target:

```sh
ninja -C build bin/circt-opt
```

```sh
ninja -C build bin/firtool
```

The README says this builds only the necessary parts of LLVM, MLIR and CIRCT, which can be a lot quicker than building everything. The recent release tags are named after firtool, the latest being firtool-1.162.0 on 2026-10-15, after firtool-1.161.0 on 2026-10-01 and firtool-1.160.0 on 2026-09-25.

The release list in the repository carries firtool versions only, so firtool is the one tool with a numbered release stream.

## circt-verilog needs a separate cmake switch

The Verilog frontend is not in the default build. To include circt-verilog, the README says to add -DCIRCT_SLANG_FRONTEND_ENABLED=ON to the cmake call. The flag name points to the slang frontend as the parser behind it, but the README text shown does not describe slang further, so check docs/ before assuming how it handles a given Verilog construct.

This matters for anyone who arrives wanting to feed Verilog into CIRCT. A build from the quick start commands as written will not contain circt-verilog. The switch has to be present at configure time, and changing it later means reconfiguring the build directory.

The repository layout shows where related pieces live: frontends/ for input languages, tools/ for the executables, lib/ and include/ for the libraries, integration_test/ and test/ for tests, and examples/circt-standalone/ as the sample of an external project that links against CIRCT.

## Build type decides whether you can step into MLIR

The quick start uses RelWithDebInfo, which the README describes as a release build with debug info: faster than a debug build and still easy to debug. The other choices are spelled out.

DCMAKE_BUILD_TYPE=Debug enables debug information and makes the whole tree compile slower, but lets you step through code into the LLVM and MLIR frameworks. DCMAKE_BUILD_TYPE=Release gives a build that runs very fast, and the README states that release mode makes a very large difference in performance. DCMAKE_EXPORT_COMPILE_COMMANDS=ON generates compile_commands.json for editors and language servers.

Because LLVM_ENABLE_ASSERTIONS=ON appears in the recommended call, even the fast configuration keeps assertions on. A tool built that way is for development. Anything you time for a decision should come from a build you configured yourself with Release.

Splitting the build is the way around a single compromise. The README describes building LLVM and MLIR first in isolation, then CIRCT against that build, which allows CIRCT in debug mode and LLVM and MLIR in release mode.

## Building LLVM and MLIR first costs a second build directory

The separate-build route starts inside the submodule. You configure LLVM with cmake -G Ninja llvm -B build and the options RelWithDebInfo, LLVM_ENABLE_ASSERTIONS=ON, LLVM_ENABLE_PROJECTS=mlir and LLVM_TARGETS_TO_BUILD=host, then run ninja -C build followed by ninja -C build check-mlir.

CIRCT is then configured from the repository root with cmake -G Ninja . -B build, with MLIR_DIR=$PWD/llvm/build/lib/cmake/mlir and LLVM_DIR=$PWD/llvm/build/lib/cmake/llvm pointing at the first build. The README text is cut off after that, so the final ninja and test commands are not visible in what was provided.

There are now two build directories named build, one under llvm/ and one at the root. The root one depends on the other by path, so deleting or moving the LLVM build breaks the CIRCT configuration. The upside is that you rebuild CIRCT without recompiling LLVM each time you change a CIRCT option.

## An experimental project whose participation rules follow LLVM

The README calls CIRCT an (experimental!) effort. Its motivation is that EDA tools are inconsistent, have usability concerns and were not designed together, and that they generally exchange Verilog or VHDL, with Verilog suffering from issues such as poor location tracking support. The project wants reusable, modular, library-based infrastructure built on compiler design practice.

Contributions follow the LLVM policies. You open pull requests against the CIRCT repository and gain commit access through the standard LLVM process. docs/DeveloperPolicy.md and docs/AIToolPolicy.md add project-specific rules, and an AGENTS.md sits at the repository root. Discussion happens on the LLVM Discourse server, a CIRCT channel on the LLVM Discord server and a weekly video chat.

A Python route exists, through the docs/PythonBindings.md page. The repository's last push was on 2026-10-25, and the charter in docs/Charter.md has the longer statement of goals. The root contains a LICENSE file, and you should read it directly, because no license is stated in the README text.

## Conclusion

Pick CIRCT if you write compilers or hardware tooling and already work with MLIR and a CMake and Ninja build of LLVM. Do not pick it for a quick install, since the README documents only a source build. Before committing, build just circt-opt or firtool with the narrow ninja target and see how long that takes on your machine, then check the license file in the repository root.

## FAQ

### What does CIRCT stand for?

CIRCT stands for Circuit Intermediate Representations (IR) Compilers and Tools. The README adds that the T can be expanded as Tool, Translator, Team, Technology and other words.

### How do I build CIRCT from source?

Run git clone git@github.com:llvm/circt.git --recursive, configure with the cmake -G Ninja llvm/llvm -B build call from the README, then build with ninja. ninja -C build check-circt builds everything and runs the tests.

### How do I build only the firtool or circt-opt binary?

Run ninja -C build bin/firtool or ninja -C build bin/circt-opt after configuring. That builds only the necessary parts of LLVM, MLIR and CIRCT.

## Sources

- [Issues](https://github.com/llvm/circt/issues)
- [llvm/circt on GitHub](https://github.com/llvm/circt)
- [Project website](https://circt.org)
- [README](https://github.com/llvm/circt/blob/main/README.md)
- [Releases](https://github.com/llvm/circt/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/llvm-circt
