Skip to main content
TinyCC includes an integrated linker that can directly output relocatable ELF files, executable files, and dynamic libraries without relying on an external linker. This self-contained approach makes TCC uniquely portable and fast.

Output file generation

TCC can directly generate multiple output formats without external tools.

ELF file generation

TCC can directly output relocatable ELF files (object files), executable ELF files, and dynamic ELF libraries without an external linker.
# Generate relocatable object file
tcc -c file.c              # Creates file.o

# Combine multiple files into one object
tcc -r -o combined.o a.c b.c

PE-i386 file generation (Windows)

TCC for Windows supports native Win32 executable formats:
# Console executable
tcc -o program.exe main.c

# GUI executable
tcc -Wl,-subsystem=gui -o program.exe gui_app.c

# DLL (Dynamic Link Library)
tcc -shared -o mylib.dll mylib.c
For detailed Windows usage information, see tcc-win32.txt in the TCC distribution.

Linking behavior

Library linking

TCC linker eliminates unreferenced object code in libraries:
# Link with libraries
tcc -o program main.c -lm -lpthread

# Specify library search paths
tcc -o program main.c -L/opt/libs -lmylib

# Link object files and libraries
tcc -o program main.o utils.o -lm
Important limitation: The linker does a single pass on object and library lists. Order matters! Libraries should come after the object files that use them. Grouping options (--start-group and --end-group) are not supported.
# Correct order (library after objects that need it)
tcc -o program main.o utils.o -lmath

# Wrong order (may have undefined references)
tcc -o program -lmath main.o utils.o

# Multiple libraries (specify in dependency order)
tcc -o program main.o -lhighlevel -llowlevel -lc

File types

TCC can load multiple input formats:
  • ELF object files (.o)
  • Archives (.a files) - static libraries
  • Dynamic libraries (.so files on Unix, .dll on Windows)
  • Assembly files (.s and .S)
  • C source files (.c)
# Mix different input types
tcc -o program main.c utils.o libhelper.a -ldynamic

Output format options

TCC supports multiple output formats through linker options.

ELF variants

tcc -Wl,--oformat=elf32-i386 -o program main.c
The binary output format is useful for embedded systems, bootloaders, and firmware where you need a raw binary image without ELF headers.

Linker options

Basic options

# Specify output file
tcc -o myprogram main.c

# Generate shared library
tcc -shared -o libtest.so test.c

# Generate relocatable object combining inputs
tcc -r -o combined.o file1.c file2.c
# Add library search path
tcc -L/usr/local/lib -lmylib main.c

# Link with specific library
tcc -lm -lpthread main.c

# Set TCC internal library path
tcc -B/opt/tcc/lib main.c

Advanced linker options

These options are passed to the linker with -Wl, prefix:
# Don't link with standard libraries
tcc -nostdlib -o bare.elf bare.c

# Don't search default library paths
tcc -Wl,-nostdlib main.c

# Static linking
tcc -static -o program main.c

Windows-specific options

# Set Windows subsystem
tcc -Wl,-subsystem=console -o app.exe main.c
tcc -Wl,-subsystem=gui -o winapp.exe gui.c
tcc -Wl,-subsystem=wince -o ceapp.exe ce.c

# Modify executable layout
tcc -Wl,-Ttext=0x400000 -o program.exe main.c
tcc -Wl,-section-alignment=4096 -o program.exe main.c
tcc -Wl,-file-alignment=512 -o program.exe main.c
tcc -Wl,-image-base=0x10000000 -o dll.dll lib.c
tcc -Wl,-stack=0x100000 -o program.exe main.c

GNU Linker Scripts

TCC’s linker supports a subset of GNU ld scripts. This is necessary because many Linux systems use linker scripts for dynamic libraries (like /usr/lib/libc.so).

Supported commands

Group multiple libraries together:
/* GNU ld script example from /usr/lib/libc.so */
GROUP ( /lib/libc.so.6 /usr/lib/libc_nonshared.a )
This allows using both shared and static libraries together.
Specify individual files:
FILE ( /lib/x86_64-linux-gnu/libc.so.6 )
These commands are recognized but ignored:
OUTPUT_FORMAT(elf64-x86-64)
TARGET(elf64-x86-64)

Position Independent Code (PIC)

Current limitation: TCC does not generate position independent code (PIC) for dynamic libraries. This means:
  • Dynamic library code generated by TCC cannot be shared among processes
  • Each process gets its own copy of the library code in memory
  • This may increase memory usage when multiple processes use the same TCC-compiled shared library
# This creates a shared library, but without PIC
tcc -shared -o libtest.so test.c

Practical examples

Building a complete application

# Single file
tcc -o hello hello.c

# Multiple files
tcc -o app main.c utils.c parser.c -lm

Advanced linking scenarios

// Build main program with exported symbols
tcc -rdynamic -o app main.c -ldl

// Build plugin as shared library
tcc -shared -o plugin.so plugin.c
The -rdynamic flag exports symbols so plugins can access them via dlopen().
# Create raw binary for embedded system
tcc -nostdlib -Wl,--oformat=binary -Wl,-Ttext=0x8000 \
    -o firmware.bin startup.S main.c

# Custom linker script (partial support)
tcc -nostdlib -o firmware.elf -Wl,-T,custom.ld main.c

Platform support

Linker capabilities by platform:
PlatformObject FilesExecutablesShared LibsNotes
Linux i386ELF32YesYesFull support
Linux x86_64ELF64YesYesFull support
Windows i386PEEXE/DLLDLLFull support
Windows x86_64PE+EXE/DLLDLLFull support
ARMELF32YesYesSupported
ARM64ELF64YesYesSupported
RISC-VELF64YesYesSupported
For best cross-platform compatibility, stick to standard library linking and avoid platform-specific linker scripts when possible.

Build docs developers (and LLMs) love