{"id":31049020,"url":"https://github.com/serd223/bookkeeper","last_synced_at":"2025-09-14T21:26:52.290Z","repository":{"id":306649323,"uuid":"1026407750","full_name":"serd223/bookkeeper","owner":"serd223","description":"Serialization/Deserialization automation for C","archived":false,"fork":false,"pushed_at":"2025-08-25T02:06:45.000Z","size":301,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-08-25T04:21:57.686Z","etag":null,"topics":["automation","boilerplate","c","codegen","codegeneration","codegenerator","deserialization","serde","serialization"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/serd223.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE-MIT","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-07-25T20:47:36.000Z","updated_at":"2025-08-25T02:06:48.000Z","dependencies_parsed_at":"2025-07-26T23:08:44.680Z","dependency_job_id":"51c85ecb-b99b-45f5-b777-31c2e46797e3","html_url":"https://github.com/serd223/bookkeeper","commit_stats":null,"previous_names":["serd223/bookkeeper"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/serd223/bookkeeper","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/serd223%2Fbookkeeper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/serd223%2Fbookkeeper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/serd223%2Fbookkeeper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/serd223%2Fbookkeeper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/serd223","download_url":"https://codeload.github.com/serd223/bookkeeper/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/serd223%2Fbookkeeper/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275170148,"owners_count":25417426,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-14T02:00:10.474Z","response_time":75,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["automation","boilerplate","c","codegen","codegeneration","codegenerator","deserialization","serde","serialization"],"created_at":"2025-09-14T21:26:47.020Z","updated_at":"2025-09-14T21:26:52.253Z","avatar_url":"https://github.com/serd223.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# bookkeeper\n`bookkeeper` is a single source file C code generation tool that generates boilerplate serialization/deserialization code for your user defined structures.\n\n`bookkeeper` is heavily inspired by the Rust [`serde`](https://serde.rs/) crate and [this Tsoding stream](https://youtu.be/hnM6aSpWJ8c?si=7WqJW0dy8oaJtdmm).\n\n# Quick Start\nHere is a simple example that outputs both JSON and Debug output: ([quick.c](./examples/quick.c))\n```c\n#include \u003cstdio.h\u003e\n\n#define BK_IMPLEMENTATION\n#define BK_DISABLE_json_PARSE\n\n#include \"people.h\" // Example file\n#include \"people.h.bk.h\" // Generated file\n\ntypedef struct {\n    Person friend_info; tag(\"info\")\n    int years_known;\n} Friend derive_json() derive_debug();\n#include \"quick.c.bk.h\" // Generated file\n\nint main(void) {\n    Person p = {.name = \"Alice\", .age = 30, .married = false};\n    Friend f = {.friend_info = p,.years_known = 5};\n    printf(\"JSON:\\n\");\n    dump_json_Friend(\u0026f, stdout);\n    printf(\"\\n\\nDebug:\\n\");\n    dump_debug_Friend(\u0026f, stdout);\n    return 0;\n}\n```\nHere is its output:\n```\nJSON:\n{\"info\":{\"name\":\"Alice\",\"age\":30,\"married\":false},\"years_known\":5}\n\nDebug:\nFriend {\n    friend_info: Person {\n        (string) name: Alice\n        (int) age: 30\n        (bool) married: false\n    }\n    (int) years_known: 5\n}\n```\nAnd this is how you can build it:\n```console\n    $ git clone https://github.com/serd223/bookkeeper.git \u0026\u0026 cd bookkeeper\n    $ mkdir build \u0026\u0026 mkdir gen\n    $ # Uses `clang` by default, set `CC` in the `Makefile` if you prefer another compiler.\n    $ make quick\n    $ ./build/quick\n```\n\n# But why?\nAs C programmers we find ourselves constantly writing boilerplate code for parsing some config struct, or just simply printing any struct. C lacks the necessary metaprogramming tools to automate the generation of this kind of boilerplate code (unlike more modern languages where you can do `#derive(Debug)` or `deriving Show`). So we either write it by hand every single time (too much work), ask LLMs to write the code for us (unreliable and requires code review), or use code generation tools like `bookkeeper`. `bookkeeper` aims to be an easy to use, extendible, user friendly, embedded friendly and portable solution to this problem.\n\n\u003e[!WARNING]\n\u003e Although bookkeeper aims to be all of those things, it is still somewhat early in development and the tool itself only supports Linux. The generated code is mostly embedded friendly and portable, though.\n\n# Overview\nThe `bk` tool requires an output directory and (optional) input file(s). The output directory can be specified with `-o`. Then you can either supply files one by one with the `-i` flag (like `-i file1 -i file`), or you can supply an input directory with `-I` and the tool will scan that directory for any `.c` or `.h` files. `bk` analyzes the included files and collects all `typedef struct { field_type field; } StructName` style struct definitions. Each struct can 'derive' functionalities that will be included in the generated code. For instance, if you want your struct to support JSON parsing/dumping you would write:\n\n```c\ntypedef struct {\n    int some_field; tag(\"SomeField\")\n    const char* some_other_field;\n    /* fields */\n} MyStruct derive_json();\n```\n(See [people.h](./examples/people.h))\n\nBy default, `bk` places generated files next to their source files (mirroring the original file structure). These generated files have the following naming schema: `original_file_name.bk.h`.\n\nFor further explanation regarding the provided example, check out the [Usage section of User Documentation](./docs/usage.md).\n\n# Documentation\n## User Documentation\nYou can access User Documentation via the [`docs/index.md`](./docs/index.md) file in this repository, this file contains links to other sections of User Documentation.\n\nThis documentation contains information about [the general usage of `bookkeeper`](./docs/usage.md), [configuration](./docs/config.md) and [writing extensions for `bookkeeper`](./docs/extensions.md).\n\n## `bookkeeper` Documentation\n`bookkeeper` Documentation is generated via [`doxygen`](https://doxygen.nl/). After installing it if you haven't, you can run:\n```console\n    $ make docs\n```\nin the root of the repository to generate the documentation. The generated files are placed inside `docs/doxygen` and you can open the `docs/doxygen/html/index.html` file inside your browser to browse the documentation.\n\nThis documentation is the general documentation of the internals of `bookkeeper`. It is meant for those who want to modify `bookkeeper`, extension authors or those who are just curious.\n\n# Build Instructions\n## Prerequisites\n - [git](https://git-scm.com/)\n - [gnu make](https://www.gnu.org/software/make/)\n - A C compiler (defaults to `clang`, change `CC` in [Makefile](./Makefile) if you prefer `gcc` or another)\n\n## Instructions\nFirst, you will need to clone this repository and `cd` into the repository's root directory:\n```console\n    $ git clone https://github.com/serd223/bookkeeper.git\n    $ cd bookkeeper\n```\n\nThen create `build` and `gen` folders:\n```console\n    $ mkdir build\n    $ mkdir gen\n```\n\nYou can build `bk` by running:\n```console\n    $ make\n    $ ./build/bk\n```\n\n## Building Examples\nIn order to build the `dump_people` example, run: (auto-generates necessary files)\n```console\n    $ make dump\n    $ ./build/dump_people\n```\n\nIn order to build the `parse_people` example, run: (auto-generates necessary files)\n```console\n    $ make parse\n    $ ./build/parse_people\n```\nIn order to build and test the provided extension example, you can run: (auto-generates necessary files)\n```console\n    $ make schema_ext\n    $ ./build/bk_ext -I ./examples -o ./gen -om dir\n```\nYou can then inspect the generated files inside the `gen` folder to see the generated example schema functions.\n\nCheck out [Usage](./docs/usage.md) or the [examples folder](./examples/)!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fserd223%2Fbookkeeper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fserd223%2Fbookkeeper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fserd223%2Fbookkeeper/lists"}