Skip to content

Run bindgen when updating llama.cpp instead of at build time - #1111

Draft
madsmtm wants to merge 4 commits into
utilityai:mainfrom
nobodywho-ooo:bindgen
Draft

madsmtm wants to merge 4 commits into
utilityai:mainfrom
nobodywho-ooo:bindgen

Conversation

@madsmtm

@madsmtm madsmtm commented Aug 27, 2026 •

Copy link
Copy Markdown
Contributor

This has several benefits:

  • It makes users builds faster, as they don't have to build bindgen and all of its dependencies.
  • It means that users don't need to have libclang installed, only maintainers do.
  • It makes it easier for maintainers to see and track changes to the llama-cpp-sys-2 API.

And a few downsides:

  • You have to manually update the bindings if you've made a local change to e.g. include/llama.h.
    • Mitigated by: the process for doing so should be fairly simple (just run cargo run --bin generate-bindings).
  • If llama.cpp ever adds #ifdef-gated APIs, this will be a bit more work to maintain (we'd probably need to blacklist those, and add their definitions manually).
  • In theory, llama.cpp could add #ifdef ANDROID int foo() #else char foo() #endif, and that'd be unsound. They haven't done crazy things like that so far though, so this probably isn't going to be an issue.

I've manually verified that the bindings are the same across both Android and macOS, and CI should continually verify that they're the same across the major desktop targets.

@MarcusDunn

Copy link
Copy Markdown
Contributor

I like this change a lot.

I originally selected build-time bindgen because it seemed to be what the community did in general. Can you point to other projects who do something like this?

@madsmtm

madsmtm commented Aug 27, 2026 •

Copy link
Copy Markdown
Contributor Author

I'm aware of a few, though it's not a very widely used pattern (to my great disappointment):

I've been thinking about for years to work on bindgen to make this pattern easier (or to at least document it), though I haven't gotten around to it yet.

@madsmtm

madsmtm commented Aug 27, 2026

Copy link
Copy Markdown
Contributor Author

I guess in some sense, this is also an experiment, to get a feel for how much is needed for bindgen to support this properly.

This actually currently fails on Windows, for two reasons:

First, enums with no zero members default to being int instead of unsigned int. I think this has effects on the ABI, so we can't just willy-nilly this. One solution would be to use #[repr(C)] enum RustEnum { ... }, but that can be unsound. I think the better solution here would be to file a PR to llama.cpp where I explicitly mark their enums with a type (possible since C23). Might also be possible to improve in bindgen (though really needs rust-lang/rfcs#3894).

And second, this definition of GGML_NORETURN is parsed differently:

#ifdef __cplusplus
#   define GGML_NORETURN [[noreturn]]
#elif defined(_MSC_VER)
#   define GGML_NORETURN __declspec(noreturn)
#else
#   define GGML_NORETURN _Noreturn
#endif

Bindgen successfully picks up the __declspec(noreturn) on Windows, but not the _Noreturn elsewhere. It has Builder::enable_function_attribute_detection, though that seems completely broken with GGML_DEPRECATED.

@madsmtm

madsmtm commented Aug 28, 2026 •

Copy link
Copy Markdown
Contributor Author

So I'm going to mark this as a draft, and continue it after fixing stuff in bindgen.

@madsmtm
madsmtm marked this pull request as draft August 28, 2026 08:15
Currently, the sys APIs include the entire definition of `FILE`, which
is platform-dependent and introduces a lot of extra types to declare.

Instead, we define `FILE` as `c_void`, and exclude the extra
definitions.
This makes users builds faster, as they don't have to build bindgen and
all of its dependencies, and makes it easier for maintainers to see and
track changes to the sys API.

One downside is that you have to manually update the bindings if you've
made a local change to e.g. llama.h, but the process for doing so should
be fairly simple (just run `cargo run --bin generate-bindings`).

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants