0xKiire Systems Programming Blog
website·Indexed 32 days ago
https://0xkiire.comA technical resource focused on low-level programming, systems design, and performance optimization. The site features comprehensive guides on graphics programming with SDL2 and Vulkan, Linux kernel interfaces like io_uring and futexes, memory management, build systems, and architectural deep dives into building web frameworks, text editors, and Git from scratch.
What's inside 0xKiire
- Zypher is an open-source web framework written in the Zig programming language, designed for maximum performance and minimum overhead.
Overview of the cg GUI library architecture
The
cglibrary is a production-quality, retained-mode GUI toolkit written in C with SDL2 as its sole dependency. Unlike immediate mode (IMGUI) where the UI is re-specified every frame,cguses a retained-mode widget tree. This allows layout to be computed only when the tree changes, simplifies animations via property interpolation, and enables persistent widget state (e.g., focus, hover, scroll position).The architecture consists of four primary layers:
- Application Code: Manages widgets, callbacks, and properties.
- Core Library (cg): Handles the widget tree, box-model layout engine (inspired by CSS flexbox), event system (bubbling/capturing), theme system, and tweening animation engine.
- Rendering Abstraction (cg_draw.c): Provides primitives for rectangles, rounded rectangles, borders, text, images, and clipping.
- Backend: SDL2 and SDL_ttf for low-level rendering and font management.
Overview of the GUI Event System
The event system is responsible for routing SDL2 input events to the appropriate widgets. It is built on three core mechanisms:
- Hit testing: Determining which widget is currently under the user's cursor.
- Event bubbling: Propagating events from the leaf widget (the most specific target) up to the root widget.
- Capture: Allowing a specific widget to capture all mouse events, which is essential for implementing operations like drag-and-drop.
Overview of Zig for WebAssembly development
Zig is suitable for WebAssembly (WASM) because it has no garbage collector, no hidden allocator, and no required runtime. Using thewasm32-freestandingtarget in Zig 0.16.0 produces minimal modules containing only the code written by the developer. Unlike other languages, Zig does not provide automatic marshalling (likewasm-bindgen); developers must manually handle the movement of strings, arrays, and structs across the ABI boundary using linear memory.Overview of Zypher Web Framework
Zypher is an open-source web framework written in the Zig programming language. It is designed for maximum performance and minimum overhead.# View Zypher on GitHub git clone https://github.com/zypher-org/zypherIntroduction to Build Systems
A build system automates the transformation of source code into executable programs. It is essential for managing projects that grow across multiple files, languages, platforms, and dependencies. Key benefits include incremental builds (rebuilding only changed files), dependency management, cross-platform support, reproducible builds, parallel compilation, and automated testing/packaging.Overview of zypher development approaches
zypher provides two distinct ways to build web applications:
- The Package Approach (Manual Wiring): zypher is added as a Zig dependency in
build.zig.zon. The developer manually configuresbuild.zigand writes all source files. This offers maximum control over the project structure and dependencies. - The CLI Approach: Uses a standalone
zypherbinary to scaffold projects (zypher new), manage migrations, create superusers, and run the development server. This approach automates repetitive setup tasks.
Note on CLI Approach: Currently,
zypher newgenerates a project that expects the zypher source tree to be located two directories above the project root (via azypher-rootbuild option), as it is not yet published to a package registry.- The Package Approach (Manual Wiring): zypher is added as a Zig dependency in
List available zypher scaffold templates
Usezypher templatesto see available project structures. Embedded templates includesingle-file(prototypes),mvc(Model-View-Controller),mvp(Model-View-Presenter), andclean-arch(Clean Architecture), with corresponding-apiversions for JSON-only REST APIs.# List embedded templates zypher templates # List templates in a custom directory zypher templates --template-dir ./my-templatesImplement an npm postinstall script for Zig binaries
Use apostinstallscript (install.js) to detect the current platform and architecture, locate the corresponding platform-specific package, and copy the Zig binary into the root package'sbinfolder with executable permissions.const { execSync } = require("child_process"); const path = require("path"); const fs = require("fs"); const PLATFORMS = { "linux-x64": "my-tool-linux-x64", "linux-arm64": "my-tool-linux-arm64", "darwin-x64": "my-tool-darwin-x64", "darwin-arm64": "my-tool-darwin-arm64", "win32-x64": "my-tool-win32-x64", "win32-arm64": "my-tool-win32-arm64", }; const key = `${process.platform}-${process.arch}`; const pkgName = PLATFORMS[key]; if (!pkgName) { console.error(`my-tool: unsupported platform ${key}`); process.exit(1); } let pkgDir; try { pkgDir = path.dirname(require.resolve(`${pkgName}/package.json`)); } catch { console.error(`my-tool: could not find platform package ${pkgName}.`); process.exit(1); } const ext = process.platform === "win32" ? ".exe" : ""; const src = path.join(pkgDir, `my-tool${ext}`); const binDir = path.join(__dirname, "bin"); const dest = path.join(binDir, `my-tool${ext}`); fs.mkdirSync(binDir, { recursive: true }); fs.copyFileSync(src, dest); fs.chmodSync(dest, 0o755);Understand the CPU cache hierarchy and memory movement
Modern CPUs use a multi-tiered cache hierarchy to bridge the speed gap between the processor and DRAM. A cache miss can cost tens to hundreds of cycles, making data layout critical for performance. Memory is moved in cache lines (typically 64 bytes); accessing a single byte triggers the CPU to fetch the entire line containing that byte.
Hierarchy Levels:
- L1: Smallest and fastest, dedicated per core.
- L2: Larger and slightly slower, dedicated per core.
- L3: Much larger, shared among all cores.
- DRAM: Largest capacity but slowest access time.
Understand frame buffers and double buffering
A frame buffer is a region of memory containing pixel data for a single complete frame. To prevent screen flickering, double buffering is used: a 'Front buffer' is currently displayed to the user, while a 'Back buffer' is used for drawing the next frame. Once the frame is complete, the buffers are swapped.Inspect inode numbers and link counts in C
Uselstatto retrieve metadata about a file or symlink. Usinglstatinstead ofstatensures you get information about the symlink itself rather than the target it points to. Thestruct statcontainsst_ino(inode number),st_nlink(hard link count), andst_mode(file type).#include <errno.h> #include <stdio.h> #include <string.h> #include <sys/stat.h> #include <unistd.h> int main(int argc, char **argv) { if (argc != 2) { fprintf(stderr, "usage: %s <path>\n", argv[0]); return 2; } struct stat st; if (lstat(argv[1], &st) != 0) { fprintf(stderr, "lstat: %s\n", strerror(errno)); return 1; } printf("inode: %lu\n", (unsigned long)st.st_ino); printf("links: %lu\n", (unsigned long)st.st_nlink); printf("size: %lu\n", (unsigned long)st.st_size); if (S_ISLNK(st.st_mode)) { printf("type: symlink\n"); } else if (S_ISDIR(st.st_mode)) { printf("type: directory\n"); } else if (S_ISREG(st.st_mode)) { printf("type: regular\n"); } else { printf("type: other\n"); } return 0; }