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.
Object files
Executables
Shared libraries
# 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.
Library linking order example
# 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
TCC supports multiple output formats through linker options.
ELF variants
ELF 32-bit (default on i386)
Binary image
COFF format
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
Library paths and linking
# 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:
Static/dynamic control
Dynamic linking options
Runtime library paths
Symbol control
# 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 )
OUTPUT_FORMAT and TARGET (ignored)
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
Simple executable
Static library creation
Shared library creation
Cross-compilation
# Single file
tcc -o hello hello.c
# Multiple files
tcc -o app main.c utils.c parser.c -lm
Advanced linking scenarios
Plugin system with dlopen
// 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().
Linker capabilities by platform:
Platform Object Files Executables Shared Libs Notes Linux i386 ELF32 Yes Yes Full support Linux x86_64 ELF64 Yes Yes Full support Windows i386 PE EXE/DLL DLL Full support Windows x86_64 PE+ EXE/DLL DLL Full support ARM ELF32 Yes Yes Supported ARM64 ELF64 Yes Yes Supported RISC-V ELF64 Yes Yes Supported
For best cross-platform compatibility, stick to standard library linking and avoid platform-specific linker scripts when possible.