Install pyc

pyc is built from source. It needs clang, LLVM, the Boehm garbage collector and DParser. A full build takes a few minutes.

Requirements

  • clang / clang++ with C++23 support, and llvm-ar
  • LLVM development libraries, with llvm-config on your PATH. The LLVM backend is always built.
  • Boehm GC (libgc, libgccpp)
  • PCRE (libpcre)
  • DParser, built with GC support and installed
Ubuntu / Debian
$ sudo apt-get install clang-20 llvm-20-dev libgc-dev libpcre3-dev
Fedora / RHEL
$ sudo dnf install clang llvm-devel gc-devel pcre-devel
Use LLVM 20.

CI runs clang/LLVM 20 on Ubuntu 24.04. The unversioned packages there are LLVM 18, whose coroutine ABI breaks the generator and async tests.

Build from source

The IFA analysis library ships inside the repository under ifa/ and is built automatically. Install DParser first:

# 1. DParser, with garbage-collector support
$ git clone https://github.com/jplevyak/dparser.git
$ cd dparser && sudo make install D_USE_GC=1 && cd ..

# 2. pyc
$ git clone https://github.com/jplevyak/pyc.git
$ cd pyc
$ make

make builds ifa/libifa_gc.a, the runtime, and the pyc binary. pyc itself is built at -O3 -march=native by default. For a debuggable compiler, use make clean && make OPTIMIZE=.

After changing a header or a build flag, run make clean.

The Makefiles track neither, and stale objects produce failures that look like real bugs.

Put pyc on your PATH

pyc finds its builtin library (__pyc__/, pyc_lib/ and the runtime) next to its own executable, following symlinks. A symlink from the checkout is enough:

$ ln -s "$PWD/pyc" ~/.local/bin/pyc

You can also name the directory explicitly with -D <dir> or $PYC_SYSTEM_DIRECTORY.

Your first program

hello.py
def fib(n):
    return n if n < 2 else fib(n - 1) + fib(n - 2)

print(fib(35))
$ pyc hello.py          # writes ./hello (and keeps hello.py.c)
$ ./hello
9227465

pyc reads the file and everything it imports, analyzes the whole program, and writes an executable named after the input. Use -o to choose the name. Imports resolve against the current directory, then pyc_lib/, then $PYTHONPATH.

Run scripts with #!

-x compiles once, caches the binary under ~/.cache/pyc, and runs it. A later run whose sources are all unchanged starts the cached executable in a few milliseconds.

greet.py
#!/usr/bin/env -S pyc -x
import sys
print("hello", sys.argv[1:])
$ chmod +x greet.py
$ ./greet.py a b
hello ['a', 'b']

JIT and REPL

$ pyc -j program.py     # compile with LLVM and run in-process
$ pyc --repl            # interactive, backed by the JIT

Verify the build

make test runs everything CI runs, on both backends, in about four minutes. When it passes, every end-to-end test matched both its expected output and CPython.

$ make test

Next: take the tour.