Cwerg: a C-like language with a compiler small enough to read
The best C-like language that can be implemented in 10kLOC.
At a glance
- What is it?
- Cwerg is a from-scratch compiler for a C-like language with a Python flavoured syntax, split into a frontend, an intermediate representation and a multi-target backend, and it is deliberately small, with hard line count targets of ten thousand for the frontend and ten thousand plus five thousand per backend target. Two implementations of most components, one in Python and one in C++, are the mechanism for keeping it that way.
- Who is it for?
- Cwerg suits a systems programmer who wants to understand a compiler end to end, or anyone looking for a small, readable C-like language implementation to fork, extend or use as a JIT backend. It does not suit a production build where generated code quality matters, because the project explicitly de-emphasises it, and it does not suit someone who needs a mature toolchain today.
- Can I use it commercially?
- Yes. Apache-2.0 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 127 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 October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Three components with an interface between them
Cwerg aims to be a complete, compact and fast from-scratch compiler for a C-like language, and it has no dependencies. The description of the components is short enough to quote in structure.
The frontend is a low-level C-like language with a Python inspired concrete syntax, and it is marked as still under active development. The intermediate representation defines an IR that serves as the interface between the frontend and the backend, which is the architectural decision that gives the project its shape: everything the backend knows about the language, it learns through the IR, and everything the frontend produces, it produces in the IR.
The backend is multi-target, currently X86-64, Aarch64 and Arm32. The readme also says it is suitable for other compilers and as a JIT, which is a claim about the IR being a clean enough interface to be reused rather than only consumed by this project's own backends.
The topics attached to the repository match that description: assembler, compiler, elf, ir-optimizer, low-level-programming, x86-64, arm and arm64. The presence of an IR optimizer in the topic list suggests the IR is not merely a serialisation format but a level where optimisation happens.
The top-level directory layout matches the three components exactly, with FE/, IR/ and BE/ directories, plus Util/ for shared code, a TestHostSetup/ directory for the test environment, a docker/ directory, a CMakeLists.txt for the C++ build, a cwerg.py entry point, a cloc.sh script for counting lines, and the documentation files quick_start_user.md, quick_start_developer.md and why_python.md.
Line count budgets are the feature, not a side effect
The most distinctive thing about Cwerg is that its size constraints are stated as hard targets with numbers attached, and the repository publishes the current counts.
The philosophy section says most components are implemented twice. There is a specification and reference implementation in Python 3.10, and a high performance implementation in C++20 with limited STL usage. Re-implementations in other languages are explicitly encouraged, and a lot of the code is table driven to make that possible.
The size targets are explicit. The frontend target is 10kLOC. The backend target is 10kLOC of target independent code plus 5kLOC per target, with the note that they cheat a little and do not include various tables in those numbers. The current counts are published in FE/CLOC.md and BE/CLOC.md.
The reason for the budget is stated as well: to prevent feature creep. Cwerg de-emphasises the quality of the generated code, with the hope of coming within 50% of state of the art compilers, in favour of a small code base that can be understood by a single developer and very fast translation times. The translation speed target is 1000k LOC per second using at most four cores on a 2020 era midrange desktop or high end laptop.
That is a coherent trade and a deliberately narrow one. The compiler is optimised for reading and for speed of translation, not for the output it produces. Anyone evaluating Cwerg for a production build has to accept that trade, because it is the stated goal rather than an accident.
Two implementations means the tests can cross-check each other
The dual implementation scheme has an obvious purpose beyond speed, and the repository layout supports it.
The Makefile runs the tests in two passes, one for Python and one for C++, and the coverage is thorough enough to be worth reading. The tests target runs the backend and the frontend Python tests, then the backend, Util and frontend C++ tests. There is a separate build_compiler target that builds the C++ versions of the frontend and the code generation tools for each of the three architectures, naming them x64_codegen_tool.exe, a64_codegen_tool.exe and a32_codegen_tool.exe.
The presence of two implementations of the same component means the two can be compared against each other on the same input, and a divergence is a bug in one of them. That is a much stronger test than either implementation alone, and it is the standard technique for compilers of this size.
The Makefile also shows the build environment assumptions. It sets PYTHONPATH to the current directory, forces LC_ALL to C so that make sorts sanely, and puts the local bin directory on the PATH. The C++ build links against the unwind and lzma libraries with the CWERG_ENABLE_UNWIND flag, and the cmake_setup target creates a build directory and runs cmake with those flags and libraries passed in. The C++ components are optional in the sense that the Python implementation can serve as the reference, but the fast path uses the C++ one.
A separate show_versions target delegates to the TestHostSetup directory, which is where the hosted test environment keeps its tooling.
The build is driven from a Makefile with a Python entry point
There is a CMakeLists.txt at the root and a Makefile at the root, and they do different jobs. CMake configures and builds the C++ frontend and backends, and the Makefile orchestrates.
The Makefile is unusual in that most of it is documentation. It sets MAKEFLAGS to warn about undefined variables, and then a long comment block explains the optional configuration: the CC variable for a C compiler such as clang, PYPY as a prefix for invoking Python programs, and the QEMU_A32, QEMU_A64 and QEMU_X64 prefixes for running programs compiled for those architectures under emulation. That last part tells you the test suite runs cross-architecture binaries under QEMU, which is how a single machine tests all three targets.
The environment defaults are also set in the Makefile rather than left to the shell, with COLOR on, VERBOSE off, and the local bin directory appended to the PATH:
export PYTHONPATH := $(shell pwd)
export COLOR := ON
export VERBOSE := FALSE
export PATH := $(PATH):$(HOME)/.local/binThe Cwerg flags and libraries are set as variables, CWERG_FLAGS with the unwind option and CWERG_LIBS with the two libraries, and passed to cmake by the cmake_setup target.
The entry point named in the top level is cwerg.py, and the repository also ships a docker/ directory, so there is a containerised path for people who would rather not install the toolchain locally.
The documentation split is clear about who should read what. To try out Cwerg, the readme points you at quick_start_user.md, and to start hacking on it, at quick_start_developer.md. The why_python.md file is the rationale document for the two-implementation scheme.
A hobby compiler with an Apache licence and no releases
The maintenance facts are modest, and the project is transparent about what it is.
The repository is not archived, the default branch is master, and the last push was on 2026-06-19, four months before the current date. There are no GitHub releases, which is consistent with a compiler that people build from source rather than install from a package index. The licence is Apache 2.0, with the LICENSE file at the root.
The stated identity is deliberately playful. The description calls it the best C-like language that can be implemented in 10kLOC, and the readme heading repeats the phrase. The aspiration, though, is the serious part: a complete, compact and fast from-scratch compiler with no dependencies, which is a real achievement rather than a slogan.
The inspiration list is a good indicator of the design lineage and worth reading for anyone interested in small compilers. It names LLVM, QBE with a link comparing it to LLVM, the Mir JIT project, Wirth's A Plea for Lean Software together with Oberon and its compiler implementation, Delphi's compilation speed, and gcc code size. The Wirth and Oberon references are the clearest signal, since Wirth's argument is that small systems are a design discipline rather than an accident, and the line count budget is that argument applied to a compiler.
The project has a Discord channel and a test status badge, which suggests a small active community around a tool that a single developer maintains.
The realistic use cases are learning, research and embedding. Read it to understand how a compiler is put together, extend it to add a language feature or a target, or use the IR and backend as a JIT for something else, which is the reuse the readme explicitly points at.
Editorial conclusion
Cwerg suits a systems programmer who wants to understand a compiler end to end, or anyone looking for a small, readable C-like language implementation to fork, extend or use as a JIT backend. It does not suit a production build where generated code quality matters, because the project explicitly de-emphasises it, and it does not suit someone who needs a mature toolchain today. Before evaluating it, follow quick_start_user.md, then read why_python.md for the rationale behind the dual implementation, and check the current line counts in FE/CLOC.md and BE/CLOC.md to see how much headroom the budget has left.
Frequently asked questions
What is Cwerg?
Cwerg is a complete, compact and fast from-scratch compiler for a C-like language with a Python inspired concrete syntax, with no dependencies. It is split into a frontend, an intermediate representation that acts as the interface between them, and a multi-target backend for X86-64, Aarch64 and Arm32.
Why is most of Cwerg implemented twice?
Most components have a specification and reference implementation in Python 3.10 and a high performance implementation in C++20 with limited STL usage. Re-implementations in other languages are explicitly encouraged, and much of the code is table driven to make that possible.
What are the line count targets for Cwerg?
The frontend target is 10kLOC and the backend target is 10kLOC of target independent code plus 5kLOC per target, and the targets exist to prevent feature creep. The current counts are published in FE/CLOC.md and BE/CLOC.md.
How good is the code Cwerg generates?
The project de-emphasises generated code quality, with the hope of coming within 50% of state of the art compilers, in favour of a small code base and very fast translation times. The stated translation speed target is 1000k LOC per second on at most four cores.
Which architectures does the Cwerg backend target?
Currently X86-64, Aarch64 and Arm32, with the Makefile providing QEMU_A32, QEMU_A64 and QEMU_X64 prefixes so cross-architecture binaries can be run under emulation during testing. The backend is also described as suitable for other compilers and as a JIT.
Official sources
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.
[](https://hysenlabs.com/projects/robertmuth-cwerg)Was this useful?