date: 2018-05-29 layout: post title: Embedding files in C programs with koio
tags: [C, announcement]
Quick blog post today to introduce a new tool I wrote: koio. This is a small tool which takes a list of files and embeds them in a C file. A library provides an fopen shim which checks the list of embedded files before resorting to the real filesystem.
I made this tool for chopsui, where I eventually want to be able to bundle up sui markup, stylesheets, images, and so on in a statically linked chopsui program. Many projects have small tools which serve a similar purpose, but it was simple enough and useful enough that I chose to make something generic so it could be used on several projects.
The usage is pretty simple. I can embed ko_fopen.c
in a C file with this
command:
sh
$ koio -o bundle.c ko_fopen.c://ko_fopen.c
I can compile and link with bundle.c
and do something like this:
```c
include <koio.h>
void koio_load_assets(void); void koio_unload_assets(void);
int main(int argc, char *argv) { koio_load_assets(); FILE src = ko_fopen(“//ko_fopen.c”, “r”); int c; while ((c = fgetc(src)) != EOF) { putchar©; } fclose(src); koio_unload_assets(); return 0; } ```
The generated bundle.c
looks like this:
```c
include <koio.h>
static struct { const char path; size_t len; char data; } files[] = { { .path = “//ko_fopen.c”, .len = 408, .data = “#define _POSIX_C_SOURCE 200809L\n#include <errno.h>\n#include <stdlib.h>\n#inc” “lude <stdio.h>\n#include \"koio_private.h\”\n\nFILE ko_fopen(const char path" “, const char mode) {\n\tstruct file_entry entry = hashtable_get(&koio_vfs, p” “ath);\n\tif (entry) {\n\t\tif (mode[0] != ‘r’ || mode[1] != ‘\0’) {\n\t\t\ter” “rno = ENOTSUP;\n\t\t\treturn NULL;\n\t\t}\n\t\treturn fmemopen(entry->data, en” “try->len, \"r\”);\n\t}\n\treturn fopen(path, mode);\n}\n", }, };
void koio_load_assets(void) { ko_add_file(files[0].path, files[0].data, files[0].len); }
void koio_unload_assets(void) { ko_del_file(files[0].path); } ```
A very simple tool, but one that I hope people will find useful. It’s very lightweight:
- 312 lines of C
- /bin/koio is ~40 KiB statically linked to musl
- libkoio.a is ~18 KiB
- Only mandatory dependencies are POSIX 2008 and a C99 compiler
- Only optional dependency is scdoc for the manual, which is similarly lightweight
Enjoy!