diff --git a/content/news/20250925-migration-to-c++.md b/content/news/20250925-migration-to-c++.md new file mode 100644 index 0000000..fc311fe --- /dev/null +++ b/content/news/20250925-migration-to-c++.md @@ -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 project’s 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.