Migration to C++
All checks were successful
Builds / ExectOS WebSite (push) Successful in 16s

This commit is contained in:
2025-09-28 20:08:12 +02:00
parent 99cb326e9b
commit 1c6574ec42

View File

@@ -0,0 +1,64 @@
+++
title = 'Migration of the Project to C++ with Maintained C Compatibility'
author = 'Aiken Harris'
date = '2025-09-28T17:12:45+01:00'
+++
The projects kernel, bootloader, and all associated modules have been migrated to C++. This transition was a complex
and time-consuming effort that we deliberately prioritized over adding new features. Because the codebase was still
relatively compact, undertaking this migration at this stage was significantly easier than it would have been later.
In total, the migration involved modifications across **297 files**, with *16,671* lines of code added and *13,312*
lines removed. The process culminated in the merge of **67 commits**. Despite these internal changes, the public
interface exposed through XTDK remains fully compatible with C. As a result, developers can write drivers in either C
or C++.
## Benefits of the Migration
Although certain C++ features such as global constructors, destructors, runtime type information and exceptions are not
suitable for use in the kernel, a large subset of the language can be used safely and effectively. Adopting C++
internally allows us to benefit from:
- **Stronger static type checking** templates, references and stricter type rules help eliminate entire classes of
low-level bugs before they reach runtime.
- **Lightweight classes and structs** we can define clear interfaces and encapsulate data without relying on heavy
runtime mechanisms. Member functions and inline methods provide better organisation than scattered C functions.
- **Namespaces for isolation** by grouping related functionality into namespaces we avoid symbol collisions, keep the
global namespace clean and make it easier to navigate the codebase.
- **Inline and template-based utilities** compile-time polymorphism and generic programming allow common patterns to
be written once and reused without runtime overhead.
- **Clearer modular boundaries** internal implementation details can be hidden behind class interfaces, improving
encapsulation and making each subsystem easier to reason about and maintain.
This approach preserves the deterministic behaviour and performance required by kernel code while still providing
a modern, well-structured environment for development. It enables a codebase that is easier to extend, review and
maintain, without introducing mechanisms that are unsafe or impractical at the system level.
## Preserving C Compatibility
Full C compatibility has been retained through the use of **C wrappers** around the underlying C++ components. This
design choice means that the migration does not affect how external code interacts with the system.
Although the project is still in its initial phase and no drivers have been released yet, the architecture is prepared
so that drivers can be written in **both C and C++** without restriction.
The SDK remains accessible to developers who prefer C, while at the same time opening the door for developers writing in
C++ to integrate with the system using native language features. This approach ensures a stable and predictable API
over time and provides flexibility for future contributors regardless of their chosen language.
## C Wrappers and Linker Optimisations
The C wrappers are implemented as lightweight functions declared with `extern "C"` forwarding calls to the C++
implementation. When building with **clang-cl**, linker flags help ensure these wrappers have negligible impact on
performance and binary size:
- **`/OPT:REF`** (Remove Unreferenced Functions and Data) directs the linker to eliminate functions and data sections
that are not referenced anywhere in the binary. This reduces the size of the resulting kernel and modules by
discarding unused wrappers or internal routines.
- **`/OPT:ICF`** (Identical COMDAT Folding) merges byte-for-byte identical functions or sections into a single instance.
In practice, thin C wrappers calling the same C++ routine can be folded together, removing redundancy and avoiding
unnecessary call layers.
With these optimisations, the system delivers the advantages of a C++ implementation while maintaining a stable,
efficient C interface for developers.