An open API service indexing awesome lists of open source software.

https://github.com/tinybiggames/delphic

Runtime C compilation for Delphi
https://github.com/tinybiggames/delphic

c-backend c-runtime c99 delphi embedded-c win64 windows-10 windows-11

Last synced: 4 months ago
JSON representation

Runtime C compilation for Delphi

Awesome Lists containing this project

README

          

![DelphiC](media/delphic.png)
[![Chat on Discord](https://img.shields.io/discord/754884471324672040?style=for-the-badge)](https://discord.gg/tinyBigGAMES) [![Follow on Bluesky](https://img.shields.io/badge/Bluesky-tinyBigGAMES-blue?style=for-the-badge&logo=bluesky)](https://bsky.app/profile/tinybiggames.com)

## โšก Runtime C compilation for Delphi

**DelphiC** is a comprehensive Delphi wrapper for the Tiny C Compiler (TCC), enabling runtime C code compilation, execution, and bidirectional symbol exchange between Delphi and C code. Compile C code to memory, executables, DLLs, or object files directly from your Delphi applications.

[![License](https://img.shields.io/badge/license-BSD--3--Clause-blue.svg)](#)
[![Platform](https://img.shields.io/badge/platform-Win64-lightgrey.svg)](#)
[![Delphi](https://img.shields.io/badge/Delphi-10.4+-red.svg)](#)

## โœจ Features

- ๐Ÿ’พ **In-Memory Compilation** - Compile and execute C code at runtime without temporary files
- ๐Ÿ“ฆ **Multiple Output Types** - Generate EXE, DLL, OBJ files, or preprocess-only mode
- ๐Ÿ”„ **Bidirectional Symbols** - Call Delphi functions from C and vice versa
- ๐Ÿ›ก๏ธ **Comprehensive Error Handling** - Structured error capture with filename, line numbers, and severity
- ๐Ÿ” **Workflow Enforcement** - State management prevents API misuse and crashes
- โš™๏ธ **Full TCC Options** - Direct access to all TCC compiler flags and settings
- ๐Ÿ”— **Multi-Unit Support** - Compile and link multiple C source files and object files
- ๐ŸŽฏ **Zero Dependencies** - Self-contained with embedded TCC, no external tools required

## ๐Ÿ’ก Use Cases

- ๐ŸŽฎ JIT compilation for scripting engines
- ๐Ÿ”Œ Dynamic plugin systems with C-based extensions
- ๐Ÿ—๏ธ Runtime code generation for DSLs
- ๐Ÿ“š Embedding C libraries without separate compilation
- ๐ŸŽ“ Educational tools demonstrating compilation concepts
- ๐Ÿ”€ Language transpilers targeting C as intermediate representation

## ๐Ÿ“‹ Requirements

- **OS**: Windows 64-bit
- **Delphi**: Tested on 12.3
- **Target**: x86_64 only

## ๐Ÿ“ฅ Installation

### From Source

1. Clone the repository:
```bash
git clone https://github.com/tinyBigGAMES/DelphiC.git
```

2. Add the `src` folder to your Delphi library path or project search path

3. Add `DelphiC` to your uses clause:
```delphi
uses
DelphiC;
```

## ๐Ÿš€ Quick Start

### ๐Ÿ‘‹ Hello World - Memory Execution

```delphi
uses
DelphiC;

procedure HelloWorld;
type
THelloFunc = function(): Integer; cdecl;
var
LCompiler: TDelphiC;
LHello: THelloFunc;
begin
LCompiler := TDelphiC.Create();
try
// Configure for in-memory execution
LCompiler.SetOuput(opMemory);

// Compile C code
LCompiler.CompileString(
'#include ' + #10 +
'int hello() {' + #10 +
' printf("Hello from C!\n");' + #10 +
' return 42;' + #10 +
'}'
);

// Relocate and get function pointer
if LCompiler.Relocate() then
begin
LHello := LCompiler.GetSymbol('hello');
if Assigned(LHello) then
WriteLn('Result: ', LHello());
end;
finally
LCompiler.Free();
end;
end;
```

### ๐Ÿ”„ Calling Delphi from C

```delphi
// Delphi callback function
function DelphiAdd(A, B: Integer): Integer; cdecl;
begin
Result := A + B;
WriteLn('Delphi says: ', A, ' + ', B, ' = ', Result);
end;

procedure CallbackExample;
type
TTestFunc = function(): Integer; cdecl;
const
CCode =
'int delphi_add(int a, int b);' + #10 +
'int test() {' + #10 +
' return delphi_add(10, 20);' + #10 +
'}';
var
LCompiler: TDelphiC;
LTest: TTestFunc;
begin
LCompiler := TDelphiC.Create();
try
LCompiler.SetOuput(opMemory);

// Inject Delphi function into C
LCompiler.AddSymbol('delphi_add', @DelphiAdd);

LCompiler.CompileString(CCode);

if LCompiler.Relocate() then
begin
LTest := LCompiler.GetSymbol('test');
if Assigned(LTest) then
WriteLn('C called Delphi, result: ', LTest());
end;
finally
LCompiler.Free();
end;
end;
```

### ๐ŸŽฏ Generating Executables

```delphi
procedure CreateExecutable;
var
LCompiler: TDelphiC;
begin
LCompiler := TDelphiC.Create();
try
LCompiler.SetOuput(opEXE);
LCompiler.SetSubsystem(ssConsole);

LCompiler.CompileString(
'#include ' + #10 +
'int main() {' + #10 +
' printf("Standalone executable!\n");' + #10 +
' return 0;' + #10 +
'}'
);

LCompiler.OutputFile('myapp.exe');
WriteLn('Created myapp.exe');
finally
LCompiler.Free();
end;
end;
```

### ๐Ÿ“š Multi-File Compilation

```delphi
procedure MultiFileProject;
var
LCompiler: TDelphiC;
begin
LCompiler := TDelphiC.Create();
try
// Compile unit1 to object file
LCompiler.SetOuput(opOBJ);
LCompiler.CompileString('int add(int a, int b) { return a + b; }');
LCompiler.OutputFile('unit1.o');

// Reset and link everything
LCompiler.Reset();
LCompiler.SetOuput(opEXE);
LCompiler.AddFile('unit1.o'); // Link compiled object
LCompiler.CompileString('int add(int, int); int main() { return add(2, 3); }');
LCompiler.OutputFile('program.exe');
finally
LCompiler.Free();
end;
end;
```

## ๐Ÿ“– API Overview

### ๐Ÿ”ง Core Methods

| Method | Description |
|--------|-------------|
| `Create()` | Initialize TCC compilation context |
| `Reset()` | Reset compiler for reuse |
| `SetOuput(TDCOutput)` | Set output type (Memory/EXE/DLL/OBJ/Preprocess) |
| `CompileString(code, filename)` | Compile C source from string |
| `AddFile(filename)` | Add C source, object file, or library |
| `Relocate()` | Prepare for in-memory execution |
| `GetSymbol(name)` | Retrieve function/variable pointer |
| `AddSymbol(name, ptr)` | Inject Delphi symbols into C |
| `OutputFile(filename)` | Generate output file |
| `Run(argc, argv)` | Execute compiled program |

### โš™๏ธ Configuration

| Method | Description |
|--------|-------------|
| `SetOption(option)` | Set any TCC command-line option |
| `SetDebugInfo(enabled)` | Enable debug information (-g) |
| `DisableWarnings()` | Suppress all warnings (-w) |
| `SetWarningsAsErrors()` | Treat warnings as errors (-Werror) |
| `SetSubsystem(TDCSubsystem)` | Set Windows subsystem (Console/GUI) |
| `DefineSymbol(sym, val)` | Define preprocessor symbol |
| `AddIncludePath(path)` | Add include directory |
| `AddLibraryPath(path)` | Add library search path |
| `AddLibrary(name)` | Link against library |

### ๐Ÿšจ Error Handling

| Method | Description |
|--------|-------------|
| `SetPrintCallback(handler)` | Register error/warning callback |
| `GetErrors()` | Retrieve structured error list |
| `ClearErrors()` | Clear accumulated errors |

## ๐Ÿ› ๏ธ Compiler Options

DelphiC supports all TCC Win64 options via `SetOption()`:

**๐Ÿ“ Preprocessor**: `-I`, `-D`, `-U`, `-E`
**โšก Compilation**: `-funsigned-char`, `-fsigned-char`, `-fms-extensions`
**โš ๏ธ Warnings**: `-w`, `-Wall`, `-Werror`, `-Wimplicit-function-declaration`
**๐Ÿ”— Linking**: `-L`, `-l`, `-Wl,-subsystem=`, `-Wl,-stack=`
**๐Ÿ› Debug**: `-g` (bounds checking `-b` not supported on Win64)
**๐ŸŽฏ Target**: `-mms-bitfields`, `-mno-sse`

See full documentation in source code XML comments.

## ๐Ÿ”„ Workflows

### ๐Ÿ’พ Memory Output (for JIT/Scripting)
```
SetOutput(opMemory) โ†’ CompileString โ†’ [AddSymbol] โ†’ Relocate โ†’ GetSymbol
```

### ๐Ÿ“ฆ File Output (EXE/DLL/OBJ)
```
SetOutput(opEXE/DLL/OBJ) โ†’ CompileString โ†’ [AddSymbol] โ†’ OutputFile
```

### โ–ถ๏ธ Direct Execution
```
SetOutput(opEXE) โ†’ CompileString โ†’ Run(argc, argv)
```

## ๐Ÿšจ Error Handling

```delphi
LCompiler.SetPrintCallback(
nil,
procedure(const AError: string; const AUserData: Pointer)
begin
WriteLn('[TCC] ', AError);
end
);

if not LCompiler.CompileString(CCode) then
begin
var LErrors := LCompiler.GetErrors();
for var LError in LErrors do
WriteLn(LError.Filename, ':', LError.Line, ': ', LError.Message);
end;
```

## ๐Ÿ“š Examples

See the `examples/` directory for:
- โœ… Basic compilation and execution
- ๐Ÿ”„ Callback integration
- ๐Ÿ“ฆ Multi-unit projects
- ๐Ÿšจ Error handling patterns
- ๐Ÿ“– Dynamic library creation

## โš ๏ธ Limitations

- ๐ŸชŸ **Win64 only** - No 32-bit or other platform support
- ๐Ÿšซ **No bounds checking** - The `-b` flag causes crashes on Win64
- ๐Ÿ”ง **No optimization flags** - TCC ignores `-O` options (single-pass compiler)
- ๐Ÿ“œ **C99 standard** - Some C11/C23 features may not be supported
- ๐Ÿšท **No C++** - Pure C compilation only

## ๐Ÿ—๏ธ Architecture

DelphiC uses a state machine to enforce correct TCC API usage:

```
๐Ÿ†• New โ†’ โš™๏ธ Configured โ†’ โœ… Compiled โ†’ ๐Ÿš€ Relocated/Finalized
```

Invalid state transitions return `False` and prevent crashes from TCC API misuse.

## ๐Ÿ”จ Building from Source

1. Open `DelphiC - Runtime C compilation for Delphi.groupproj` in `src` folder
2. in `UTestbed.pas`, set `LNum` to test number to run
3. Build an run

No external dependencies required - TCC is embedded as a compiled object.

## ๐Ÿค Contributing

Contributions are welcome! Please:

1. ๐Ÿด Fork the repository
2. ๐ŸŒฟ Create a feature branch
3. ๐Ÿ“ Follow existing code style
4. โœ… Add tests for new features
5. ๐Ÿ’พ Commit changes
6. ๐Ÿ“ค Push to branch
7. ๐Ÿ”€ Open a Pull Request

## ๐Ÿ“„ License

DelphiC is released under the **BSD 3-Clause License**.

Copyright ยฉ 2025-present tinyBigGAMESโ„ข LLC. All Rights Reserved.

See [LICENSE](https://github.com/tinyBigGAMES/DelphiC#BSD-3-Clause-1-ov-file) for full license text.

### ๐Ÿ“ฆ Third-Party Components

This library uses:
- **TCC (Tiny C Compiler)** - https://github.com/TinyCC/tinycc

## ๐Ÿ’ฌ Support

- ๐Ÿ› **Issues**: [GitHub Issues](https://github.com/tinyBigGAMES/DelphiC/issues)
- ๐Ÿ’ญ **Discussions**: [GitHub Discussions](https://github.com/tinyBigGAMES/DelphiC/discussions)

## ๐Ÿ™ Acknowledgments

- **Fabrice Bellard** - Original TCC author
- **TCC Contributors** - Ongoing TCC development
- **Delphi Community** - Testing and feedback

---

**Made with โค๏ธ by tinyBigGAMESโ„ข**

*"Bridging Delphi and C at runtime"*