Library / SDK
c2lang/c2compiler avatar
c2lang/c2compiler

C2Compiler is a self hosted compiler written in its own language

the c2 programming language

841 stars56 forksCApache-2.0

At a glance

What is it?
C2Compiler is the C2 programming language compiler, written in C2 itself, so building it requires a bootstrap stage before it can compile other C2 projects. The build system is where the interesting engineering lives, with plugin generated code, sanitiser targets and a self hosted tester.
Who is it for?
C2Compiler suits a C programmer who wants to read a real compiler written in a small systems language, and who is prepared to accept a self hosting build with a bootstrap stage before anything else works. It is not a drop in C compiler for production use, since there are no GitHub releases, the build expects a Unix shell environment and the plugin path setup, and the language is described as an evolution of C rather than C itself.
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 received new commits within the last day.
What is it written in?
Mainly C, 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

A compiler written in the language it compiles

C2Compiler is the compiler for the C2 programming language, and the striking detail is that it is written in C2 itself. The README is explicit: the C2 compiler written in C2 itself. The first version was written in C++, and that earlier implementation can still be found in the history of the archive.

C2 is described as an evolution of C, with more information at c2lang.org, and the repository topics list c, c2, compiler and programming-language. The primary language of the repository is C, which is the natural consequence of a compiler whose own output is C.

Self hosting has a specific practical meaning here. You cannot build the compiler from a clean checkout without first producing a working compiler, which is what the bootstrap stage is for. Everything else about the project follows from that: the build is driven by a Makefile that knows how to build a bootstrap binary and then use it to build the real one, and the documentation tells you to source a shell script before you do anything.

The licence is Apache-2.0, and the homepage is c2lang.org. There are no GitHub releases, so the repository is where the artefact comes from.

The bootstrap build, step by step

The build instructions are short, and the environment script is the first thing you run:

bash
. ./env.sh
make -C bootstrap
./install_plugins.sh

That produces a bootstrap version of c2c and then uses it to build the actual compiler, with the output landing in the output/ directory. Once that is done you can run the compiler to build other C2 projects:

bash
./output/c2c/c2c

The README suggests a symlink in your own bin directory as a nicer arrangement:

bash
ln -s <path_to_c2compiler>/output/c2c/c2c ~/bin/c2c

and reminds you to make sure that directory is on your PATH. The install_plugins.sh script in the third command is not optional decoration, because the compiler loads plugins during the build, and the plugin directory is one of the two environment variables the tool needs.

Two environment variables are required. C2_LIBDIR points at where the library headers live, and it should point to the libs directory inside your checkout. C2_PLUGINDIR points at where the compiled plugins live, it can be anywhere, and it is the one the install_plugins.sh script uses. Both may contain multiple paths separated by colons.

The installation document in the repository, INSTALL.md, covers installation on Linux or OSX. The README itself does not restate the system requirements, so that file is the reference.

The Makefile builds the compiler twice, with and without plugins

The top level Makefile is where the self hosting cycle is spelled out, and it is worth reading closely.

The default target depends on the compiler binary, and that binary is produced by a rule with two stages. First the bootstrap binary compiles c2c with no plugins, using the fast and quiet flags, and the result is moved into the bootstrap directory. Then the freshly built compiler compiles c2c again, this time with the plugin set, and the fast binary is moved aside before the plugin build runs. The plugin set is listed explicitly as deps_generator, refs_generator, git_version, unit_test and shell_cmd.

The output of that second pass is therefore a compiler that knows about plugins, and the plugins are installed twice, once after each stage. The plugins that run during the build are not decoration either: deps_generator and refs_generator appear to produce parts of the compiler's own source, which is why a plugin free compiler cannot bootstrap the final one.

The flags are controlled by make variables. ASAN, MSAN and UBSAN each add the corresponding sanitizer flag, and there are convenience targets that set them, including a combined san target that enables ASAN and UBSAN. DEBUG adds a fast flag, and CONFIG_32BIT passes a configuration down to the sub make. Those are the kinds of targets a compiler project needs and a weekend project does not have.

Plugins can rewrite the AST during compilation

The plugin system is described as allowing plugins to be loaded during compilation with the AST modified by them. That is a stronger contract than a build hook or a code generator, because the plugin operates on the tree the compiler is working with, not on the source text before it.

The compiler looks for plugins in the environment variable C2_PLUGINDIR, which is set by the env.sh script, and the path can also be set in the build file. Running install_plugins.sh creates a directory under the user's home and copies all plugins there.

To run the compiler without plugins at all, there is a --noplugins option, and the Makefile uses that flag for the bootstrap stages.

The practical consequence for anyone extending the compiler is that a plugin can change the meaning of a program, not just its output format. That is a lot of power, and it means a plugin is part of your build's trusted surface. The example set includes a dedicated plugin example directory under examples/, which is the place to start if you want to see what a plugin's interface looks like.

A self hosted tester and the example programs

The unit tests run through a binary the project builds for itself:

bash
./output/tester/tester test

The Makefile rule for it depends on the tester sources, the compiler dependencies and the compiler itself, and it invokes the compiler with the tester target. So the test suite is compiled by the compiler under test, which is the arrangement you want in a self hosted project.

The examples directory is substantial and tells you what the language and its library can already do. There are programs for base64 encoding, a JSON parser, a directory walker, file operations, a logger, list handling, longjmp, optional types, plugins, pthreads, signals, sockets, load_file, inline assembly, an event loop, a cstrip tool, multicast, and an embedded Lua. There are also build recipes, with build_arm.yaml and build_generic.yaml next to a recipe.txt, and a common directory of shared code.

The presence of a Lua binding, socket and pthread examples and an inline assembly example says more about the state of the standard library than any feature list would. The libs directory holds the library sources that C2_LIBDIR points at, and the ir and ir_examples directories indicate an intermediate representation layer with its own examples.

Repository layout and the tools around it

The tree at the root is a compiler's tree, and the directory names describe the pipeline. There is a parser directory, an ast directory and an ast_utils directory, an analyser directory, an ir directory for the intermediate representation, a generator directory that presumably emits the target code, a common directory for shared code, a compiler directory, and a libs directory for the standard library.

Alongside those sit the supporting pieces: a bootstrap directory holding the bootstrap compiler, a plugins directory, a tools directory, a test directory, docs, examples, and a recipe.txt that lists the source files in dependency order. There is a man page, c2c.1, in the repository, which is a small sign that the project is meant to be installed properly rather than run from a checkout.

A CLAUDE.md file sits at the root, which suggests the project is developed with the help of an AI assistant, and there is a.github directory for the workflows.

The Makefile also has a target for building a bootstrap compiler with an explicit output name, and another for regenerating the bootstrap files for various systems and architectures, moving the generated C into place. That last target is how a bootstrap binary is produced for a platform you are not currently on.

Where the project stands

The repository is not archived and the last push was on 2026-10-22, so work is landing on the master branch. There are no GitHub releases, which means there is no versioned artefact to download and no changelog to consult for a specific release, only the repository state itself.

That combination, active development with no tagged releases, is normal for a language project in its early phase. It also means there is no stability promise in the usual sense, and no way to pin a known good version other than pinning a commit.

The licence is Apache-2.0, which is permissive and includes an express patent grant, and it is the kind of licence a language and compiler project often chooses for exactly that reason. Any specific question about what it means for your use belongs with your own counsel.

The realistic assessment is that this is a compiler in progress. The pipeline, the plugin system, the tester and a broad example set are all there, and the build is genuinely self hosting. What is not there is a release cadence, a compatibility promise for the language, or documentation in the repository beyond the install file, the man page and the docs directory.

Editorial conclusion

C2Compiler suits a C programmer who wants to read a real compiler written in a small systems language, and who is prepared to accept a self hosting build with a bootstrap stage before anything else works. It is not a drop in C compiler for production use, since there are no GitHub releases, the build expects a Unix shell environment and the plugin path setup, and the language is described as an evolution of C rather than C itself. Before trying it, read INSTALL.md, source env.sh so C2_LIBDIR and C2_PLUGINDIR are set, run the bootstrap make target, and check the examples directory to see how much of the standard library is already in place.

Frequently asked questions

How do I build the C2 compiler from source?

Source the environment script, then build the bootstrap compiler and install the plugins with . ./env.sh, make -C bootstrap and ./install_plugins.sh. The resulting compiler binary is at ./output/c2c/c2c and can be run to compile other C2 projects.

What do C2_LIBDIR and C2_PLUGINDIR do?

C2_LIBDIR points at where the library headers are found and should point to the libs directory of the checkout. C2_PLUGINDIR points at where the compiled c2c plugins live, is used by install_plugins.sh, and both variables may hold multiple paths separated by colons.

What can a C2 compiler plugin do?

The plugin system allows plugins to be loaded during compilation with the AST modified by them. The compiler looks for them in the environment variable C2_PLUGINDIR or in the build file, and the --noplugins option runs the compiler without them.

Official sources

  1. c2lang/c2compiler on GitHub
  2. Issues
  3. License: Apache-2.0
  4. README
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/c2lang-c2compiler.svg)](https://hysenlabs.com/projects/c2lang-c2compiler)

Was this useful?