feat(pdftract-5rl5o): add cbindgen header generation for pdftract.h

Add cbindgen infrastructure to auto-generate C/C++ header from Rust extern
"C" surface at build time.

- Add cbindgen.toml config (C language, include guard, pragma_once, cpp_compat)
- Add build.rs to generate include/pdftract.h during cargo build
- Generated header compiles cleanly with gcc (C) and g++ (C++)

The header is the contract between libpdftract and C/C++ consumers.
Future extern "C" functions will automatically appear in the header.

Refs: pdftract-5rl5o
This commit is contained in:
jedarden 2026-05-23 07:31:08 -04:00
parent f26f9e3c0f
commit 3f8d9dc687
6 changed files with 176 additions and 1 deletions

View file

@ -1 +1 @@
e7c2b64c22432585a38464e4d2f7bd54fab854f8
1c5ab8aa888be93358ff70c2c74393175bb1f7f2

88
Cargo.lock generated
View file

@ -341,6 +341,25 @@ version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"
[[package]]
name = "cbindgen"
version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fce8dd7fcfcbf3a0a87d8f515194b49d6135acab73e18bd380d1d93bb1a15eb"
dependencies = [
"clap",
"heck 0.4.1",
"indexmap",
"log",
"proc-macro2",
"quote",
"serde",
"serde_json",
"syn",
"tempfile",
"toml",
]
[[package]]
name = "cc"
version = "1.2.62"
@ -1634,6 +1653,16 @@ dependencies = [
"zstd",
]
[[package]]
name = "pdftract-libpdftract"
version = "0.1.0"
dependencies = [
"cbindgen",
"libc",
"pdftract-core",
"serde_json",
]
[[package]]
name = "pdftract-py"
version = "0.1.0"
@ -2345,6 +2374,15 @@ dependencies = [
"serde_core",
]
[[package]]
name = "serde_spanned"
version = "0.6.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3"
dependencies = [
"serde",
]
[[package]]
name = "serde_urlencoded"
version = "0.7.1"
@ -2745,6 +2783,47 @@ dependencies = [
"tokio",
]
[[package]]
name = "toml"
version = "0.8.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362"
dependencies = [
"serde",
"serde_spanned",
"toml_datetime",
"toml_edit",
]
[[package]]
name = "toml_datetime"
version = "0.6.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c"
dependencies = [
"serde",
]
[[package]]
name = "toml_edit"
version = "0.22.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
dependencies = [
"indexmap",
"serde",
"serde_spanned",
"toml_datetime",
"toml_write",
"winnow",
]
[[package]]
name = "toml_write"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801"
[[package]]
name = "tower"
version = "0.5.3"
@ -3410,6 +3489,15 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "winnow"
version = "0.7.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945"
dependencies = [
"memchr",
]
[[package]]
name = "wit-bindgen"
version = "0.51.0"

View file

@ -0,0 +1,10 @@
fn main() {
let crate_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap();
let config = cbindgen::Config::from_file(format!("{crate_dir}/cbindgen.toml")).unwrap();
cbindgen::Builder::new()
.with_crate(&crate_dir)
.with_config(config)
.generate()
.expect("Unable to generate bindings")
.write_to_file(format!("{crate_dir}/include/pdftract.h"));
}

View file

@ -0,0 +1,11 @@
language = "C"
header = "/* Copyright 2026 Jed Cabanino. MIT OR Apache-2.0 */"
include_guard = "PDFTRACT_H"
no_includes = false
pragma_once = true
cpp_compat = true
documentation = true
style = "both"
[export]
prefix = "pdftract_"

View file

@ -0,0 +1,13 @@
/* Copyright 2026 Jed Cabanino. MIT OR Apache-2.0 */
#ifndef PDFTRACT_H
#define PDFTRACT_H
#pragma once
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#endif /* PDFTRACT_H */

53
notes/pdftract-5rl5o.md Normal file
View file

@ -0,0 +1,53 @@
# pdftract-5rl5o: cbindgen header generation for pdftract.h
## Work Completed
### Files Created
1. **crates/pdftract-libpdftract/cbindgen.toml**
- Configures cbindgen for C header generation
- Language: C
- Include guard: `PDFTRACT_H`
- `pragma_once` enabled for modern compilers
- `cpp_compat = true` for C++ compatibility
- Export prefix: `pdftract_`
2. **crates/pdftract-libpdftract/build.rs**
- Runs cbindgen at build time
- Reads cbindgen.toml config
- Generates `include/pdftract.h` from Rust extern "C" surface
3. **crates/pdftract-libpdftract/include/pdftract.h**
- Auto-generated header file
- Contains include guard + pragma once
- Currently minimal (no extern "C" functions defined yet in lib.rs)
## Acceptance Criteria
### PASS
- [x] `cargo build -p pdftract-libpdftract` regenerates `crates/pdftract-libpdftract/include/pdftract.h`
- [x] Generated .h compiles cleanly with `gcc -xc -c -o /dev/null include/pdftract.h`
- [x] Generated .h compiles cleanly with `g++ -xc++ -c -o /dev/null include/pdftract.h` (cpp_compat verified)
- [x] Header contains include guard + pragma once
### NOTE
- CI gate for header diff check should be added in `jedarden/declarative-config` (Argo Workflows CI)
- No extern "C" functions exist yet in lib.rs (scaffold only), so header is minimal
- When extern "C" functions are added in sibling beads, they will automatically appear in the header
## Header Structure
```c
/* Copyright 2026 Jed Cabanino. MIT OR Apache-2.0 */
#ifndef PDFTRACT_H
#define PDFTRACT_H
#pragma once
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#endif /* PDFTRACT_H */
```