kcpp - the Kamranga C/C++ compiler and toolchain

Copyright (c) 2026 Muhammad Anisur Rahman. All rights reserved.

Version 1.0.0

kcpp compiles C and C++ to machine code for small targets, and comes with the whole chain around it: an assembler, a linker, a librarian, a disassembler and the tools that turn a linked image into something a board or a simulator can load.

The same binary also runs C as a script, without producing any object code at all - see icpp-manual.md.

The short version

kcpp -cpu32 hello.c          # -> hello.asm, hello.o
miskasm hello.asm            # assemble (and single-file link)
klink -o hello.kx hello.o    # link
kdis hello.kx                # read back what you built

Compiling

kcpp [options] <sourcefile.c>

Output is written next to the source, not to a name you choose:

FileIs
<source>.asmassembly for the target
<source>.oobject file
<source>.errorerrors and warnings

-o is an optimisation LEVEL, not an output name. -o0 is the default and -o1 reuses values already in registers; higher numbers clamp to -o1 with a warning, because nothing above it exists yet.

Machine shape

Register width and address width are independent, which is not a convenience - it is a real machine shape:

OptionMeans
-cpu32 / -cpu64data register width. 64 is the default
-addr32 / -addr64address bus and pointer width

-cpu32 implies -addr32 unless you also say -addr64. An explicit -addr32/-addr64 always wins, whatever the order.

64-bit registers on a 32-bit bus is a shape real hardware has - RV32D, ARMv7 with NEON, MIPS64 in 32-bit addressing mode - so the compiler models the two separately rather than tying them together.

Output container

exe=native | kx | elf | coff | pe

native (the .kx) is the default and is what bare-metal targets and TUWA-RTOS link against. The container is independent of the CPU: the same code ships as .kx or as ELF. It is stamped into the object header, so every later tool reads it from the file rather than being told again.

-exe=FMT, exeformat=FMT and -exeformat=FMT all mean the same thing.

Other options

OptionDoes
-Ipathadditional include directory (repeatable)
-Dname[=value]define a macro. -DNAME, -DNAME=VALUE, -D NAME all work
-Werrwarnings become errors (-Werror also accepted)
-debug / -nodebugkeep or strip debug symbols. Saying neither leaves current behaviour alone
-core=rv32emit RV32I through the retarget back end
-rtltranslate integer functions to synthesizable Verilog instead of running

-core=rv32 writes <source>.rv32.lst and prints a coverage summary naming every three-address opcode not yet implemented - so an incomplete back end tells you exactly what is missing instead of emitting something that looks finished.

Position-independent code and modules

kcpp -cpu32 -pic mod.c
miskasm -nolink mod.asm
klink -pic -dll -import TuwaPrintConsole -export modmain -o mod.kx mod.obj
#   -> also writes mod.twa

-pic makes the compiler reach globals through a base register instead of at absolute addresses, so the code runs wherever it is loaded.

klink -pic plus one of -exe / -dll / -drv writes a .twa module next to the .kx. The .kx is still written, because that is what kdis, kmap and ksym read and losing it makes a bad module much harder to diagnose.

The extension is .twa and not .tuwa because a FAT 8.3 name allows a three-character extension. A four-character one cannot be created on a FAT volume at all - the filesystem refuses it rather than truncating - so a module could not be copied onto a target under the name the linker gave it.

The tools

ToolDoes
miskasm <file.asm>assemble. -nolink gives an object only, skipping the automatic single-file link
klink [-o out.kx] [-e entry] files...link objects and libraries. Entry defaults to _start
kliblibrarian - build and manage .lib archives
`kmake <project.tpj \makefile>`build driver. Takes the IDE's native project file or a legacy makefile
kdis <file.kx>disassemble to readable .dis
kmap <file.kx>memory map: sections, symbols, source layout
ksym <file.kx>symbol address table
knosym <file.kx>strip debug symbols, writing a smaller .kx
kxtobin <file.kx>flat .bin of the raw image
khex16, khex32, khex16withaddr, khex32withaddrIntel-hex style output at 16 or 32 bits, with or without addresses
kice <file.kx>in-circuit-emulator load file
kverilogsram <file.kx>ICE file plus a Verilog SRAM initialisation file, for loading a design in simulation

Every tool that takes a .kx accepts an optional output filename and picks a sensible default otherwise.

Targets

The native target is the RBT instruction set, 32- and 64-bit. -core=rv32 emits RV32I through the retarget back end, and RETARGET_PLAN.md describes how further targets are added.

For what a compiled program runs on, see the TUWA-RTOS documentation: TUWA-RTOS is the real-time operating system that loads and runs what this toolchain builds.

Diagnostics

Errors and warnings go to <source>.error as well as to the console, so a build driven from a script leaves a record.

Check the exit code, not the output. A run can print Total errors:0 and still fail - the exit status is what a build script should test.