Skip to content

Usage

The codon command includes several subcommands for compiling and executing code.

codon run

codon run will compile and execute the provided program:

codon run file.py           # compile and run (defaults to debug mode)
codon run -debug file.py    # compile and run in debug mode
codon run -release file.py  # compile and run with optimizations

If the file is given as -, then the program is read from standard input:

echo 'print("hello")' | codon run -release -
# hello

Program arguments can be provided after the file, as in:

codon run -release file.py arg1 arg2 arg3

For example:

echo 'import sys; print(sys.argv)' | codon run -release - arg1 arg2 arg3
# ['-', 'arg1', 'arg2', 'arg3']

codon build

codon build will compile to a desired output type, be it an executable, object file, shared library, LLVM IR or Python extension. The -release and -debug flags also apply to codon build in the same way as described from codon run above.

The optional -o <file> parameter can be used to specify the output file. If no output type is specified, the output type is determined from the file name provided to -o. If no output file name is specified, the output file name is derived from the input file name, in combination with the output type (e.g. compiling foo.py to an object file results in output file foo.o).

Compile to executable

The -exe flag can be used to generate an executable:

# compile 'program.py' to executable 'program'
codon build -exe program.py

# compile 'program.py' to executable 'hello'
codon build -exe -o hello program.py

# compile 'program.py' to executable 'hello' with optimizations
codon build -exe -o hello -release program.py

# compile 'program.py' to executable 'hello' with optimizations
# '-exe' is inferred from `-o` argument
codon build -o hello -release program.py

Codon uses a C++ compiler to link the actual executable after compilation. Extra linker flags can be passed with the -linker-flags argument. For example:

# includes /foo/bar in the executable's rpath
codon build -release -linker-flags '-Wl,-rpath,/foo/bar' program.py

Multiple linker flags can be passed by separating them with a space in the argument to -linker-flags.

Compile to shared library

The -lib flag can be used to generate a shared library:

# compile 'program.py' to shared library 'program.so'
codon build -lib program.py

# compile 'program.py' to shared library 'hello.so'
codon build -lib -o hello.so program.py

# compile 'program.py' to shared library 'hello.so' with optimizations
codon build -lib -o hello.so -release program.py

# compile 'program.py' to shared library 'hello.so' with optimizations
# '-lib' is inferred from `-o` argument
codon build -o hello.so -release program.py

The -linker-flags flag described above also applies when compiling to a shared library.

Info

When compiling to a shared library, the program's main code will be included and executed when the library is loaded as a constructor. This allows you to include any necessary initialization code in the main program.

Info

If you intend to call a Codon-generated shared library from C or C++, be sure to mark relevant functions with @export to ensure they are made visible by the linker. Exported functions can be called as regular C functions (i.e. they follow the C ABI). Learn more →

Compile to object file

The -obj flag can be used to generate an object file:

# compile 'program.py' to object file 'program.o'
codon build -obj program.py

# compile 'program.py' to object file 'hello.o'
codon build -obj -o hello.o program.py

# compile 'program.py' to object file 'hello.o' with optimizations
codon build -obj -o hello.o -release program.py

# compile 'program.py' to object file 'hello.o' with optimizations
# '-obj' is inferred from `-o` argument
codon build -o hello.o -release program.py

Compile to LLVM IR

The -llvm flag can be used to generate LLVM IR:

# compile 'program.py' to LLVM IR file 'program.ll'
codon build -llvm program.py

# compile 'program.py' to LLVM IR file 'hello.ll'
codon build -llvm -o hello.ll program.py

# compile 'program.py' to LLVM IR file 'hello.ll' with optimizations
codon build -llvm -o hello.ll -release program.py

# compile 'program.py' to LLVM IR file 'hello.ll' with optimizations
# '-llvm' is inferred from `-o` argument
codon build -o hello.ll -release program.py

Compile to Python extension

The -pyext flag can be used to generate a Python extension:

# compile 'program.py' to Python extension 'program.o'
codon build -pyext program.py

# compile 'program.py' to Python extension 'hello.o'
codon build -pyext -o hello.o program.py

# compile 'program.py' to Python extension 'hello.o' with optimizations
codon build -pyext -o hello.o -release program.py

# compile 'program.py' to Python extension 'hello.o' with module
# name 'mymodule' and optimizations enabled
codon build -pyext -o hello.o -release -module mymodule program.py

Info

When using -pyext, you will also often want to use the --relocation-model=pic flag to generate position-independent code.

codon jit

Codon provides a debugging interface for its JIT compilation capabilities through the codon jit subcommand. This subcommand uses the same JIT engine internally as used by Codon's Python JIT decorator and Jupyter kernel. However, it is intended to be used as a debugging utility rather than as a general usage mode.

Warning

codon jit is intended to be used as a debugging utility for Codon's JIT compilation capabilities. The interface may change between Codon versions.

codon jit can be passed a file name to read from, or - to read from standard input. For example:

echo 'print("hello world")' | codon jit -
# >>> Codon JIT v0.19.0 <<<
# hello world
# [done]

It can also be used as a REPL if no file is provided. JIT inputs can be separated with the string #%%.

Using Codon in an existing Python codebase

Codon provides a Python package called codon-jit that can be installed with pip. This package supports JIT compilation on a per-function basis within an existing Python codebase.

Learn more in the Python JIT docs.

Additional options

Disabling exceptions

By default, Codon does exception handling to match Python's semantics and behavior. If you know your program does not raise or catch exceptions, they can be disabled altogether with the -disable-exceptions flag.

-disable-exceptions can lead to (sometimes substantial) performance improvements by enabling the compiler to deduce additional information about the semantics of the program. For example, if the compiler can deduce that there will be no index errors in a loop that iterates over an array, it can potentially use that information to perform vectorization or other optimizations.

In some contexts, exceptions are disabled automatically by Codon, such as when compiling for GPU execution.

Numerical semantics

For performance reasons, certain numerical operations in Codon follow C semantics by default. For example, integer division rounds towards zero in Codon whereas it rounds down in Python:

print((-3) // 2)
# Codon: -1
# Python: -2

Similarly, floating-point division by zero returns inf in Codon whereas it raises an exception in Python:

print(1.0 / 0.0)
# Codon: inf
# Python: 'ZeroDivisionError: float division by zero'

The -numerics=<mode> flag can be used to control this behavior:

  • -numerics=c (default): C semantics, as above
  • -numerics=py: Python semantics, matching Python behavior at the cost of performance

Fast-math

Fast-math optimizations can be enabled with the -fast-math flag. Note that this flag makes various assumptions about nan and inf values, so it is best to use it with caution.

Disabling optimization passes

The -disable-opt <pass> flag can be used to disable specific optimization passes. For example:

# compile & run with optimizations, but don't perform NumPy fusion optimization
codon run -release -disable-opt core-numpy-fusion program.py

Compile-time definitions

Literal variables can be passed on the command-line via the -D flag. These variables are treated as compile-time constants and can be used for compile-time metaprogramming.

For example, the following code:

n = Int[N](42)
print(n * n)

can be executed with:

codon run -DN=16 program.py

to use a 16-bit integer as the type of variable n.

Logging

Codon can display logging information and also output intermediate compilation results via the -log <streams> command. The argument to -log can contain any of the following characters:

  • t (time): Displays timings for various stages of the compilation process.
  • T (typecheck): Enables logging during type checking
  • i (IR): Enables logging during Codon IR passes
  • l (dump): Dumps intermediate compilation results, including AST, Codon IR and LLVM IR