Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,29 @@ jobs:
CC_riscv64gc_unknown_linux_gnu: riscv64-linux-gnu-gcc
run: cargo build --release --target riscv64gc-unknown-linux-gnu

cbindgen-header:
name: cbindgen header up to date
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Install Rust
uses: dtolnay/rust-toolchain@stable

- name: Install cbindgen
run: cargo install cbindgen --version 0.29.2 --locked

# Regenerate include/sandlock.h in place and fail if it differs from the
# committed copy, so the C ABI header can never drift from the crate's
# #[no_mangle] definitions.
- name: Regenerate header and check it is up to date
run: |
cbindgen --config crates/sandlock-ffi/cbindgen.toml \
--crate sandlock-ffi \
--output crates/sandlock-ffi/include/sandlock.h
git diff --exit-code crates/sandlock-ffi/include/sandlock.h \
|| { echo "::error::sandlock.h is stale; regenerate it with cbindgen (see crates/sandlock-ffi/cbindgen.toml)"; exit 1; }

python:
name: Python tests (${{ matrix.runner }}, py${{ matrix.python-version }})
runs-on: ${{ matrix.runner }}
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/target/
crates/sandlock-ffi/include/
crates/sandlock-ffi/include/*
!crates/sandlock-ffi/include/sandlock.h
__pycache__/
*.pyc
*.pyo
Expand Down
6 changes: 5 additions & 1 deletion crates/sandlock-ffi/build.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
fn main() {
// Header is hand-maintained — no auto-generation.
// include/sandlock.h is generated from this crate's #[no_mangle] exports
// by cbindgen, not produced here: the build does not run cbindgen so a
// plain `cargo build` needs no extra tooling. Regenerate the header with
// the command in cbindgen.toml after changing the C ABI; CI checks that the
// committed header matches a fresh generation.
// Run `cargo build -p sandlock-ffi` then find the .so in target/release/.
}
75 changes: 75 additions & 0 deletions crates/sandlock-ffi/cbindgen.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Configuration for generating include/sandlock.h with cbindgen.
#
# Regenerate the header with:
# cbindgen --config crates/sandlock-ffi/cbindgen.toml \
# --crate sandlock-ffi --output crates/sandlock-ffi/include/sandlock.h
#
# CI verifies the committed header matches a fresh generation, so the C ABI
# contract can never drift from the #[no_mangle] definitions in src/.

language = "C"
style = "type"
include_guard = "SANDLOCK_H"
cpp_compat = true
documentation = true
documentation_style = "doxy"

no_includes = true
sys_includes = ["stdint.h", "stddef.h", "stdbool.h"]

header = """/*
* sandlock C API — opaque handle bindings to sandlock-core.
*
* GENERATED BY cbindgen. DO NOT EDIT THIS FILE BY HAND.
* See crates/sandlock-ffi/cbindgen.toml for the regeneration command.
*
* All pointer types are opaque handles; free each with its _free().
* Builder functions consume and return the builder (move semantics).
*/"""

# Opaque handle types forward-declared by hand:
# - sandlock_builder_t / sandlock_t (renamed below from the sandlock-core
# types SandboxBuilder / Sandbox) are foreign; cbindgen does not parse the
# dependency crate (parse_deps = false), so it cannot emit them itself, yet
# they appear behind pointers in this ABI.
# - sandlock_sandbox_t / sandlock_result_t / sandlock_handler_t are #[repr(C)]
# wrappers around non-C inner types; they are opaque to C (only ever used
# behind pointers), so their bodies are excluded below and forward-declared
# here instead.
after_includes = """

typedef struct sandlock_builder_t sandlock_builder_t;
typedef struct sandlock_t sandlock_t;
typedef struct sandlock_sandbox_t sandlock_sandbox_t;
typedef struct sandlock_result_t sandlock_result_t;
typedef struct sandlock_handler_t sandlock_handler_t;
"""

[parse]
parse_deps = false

[export]
# Force-emit the two action/exception enums: they are referenced from Rust only
# via `... as u32` casts, never as a typed field or parameter, so cbindgen would
# otherwise drop them as unreferenced even though their constants are public ABI.
include = ["sandlock_action_kind_t", "sandlock_exception_policy_t"]
exclude = [
"SandboxBuilder",
"Sandbox",
"sandlock_sandbox_t",
"sandlock_result_t",
"sandlock_handler_t",
]

[export.rename]
"SandboxBuilder" = "sandlock_builder_t"
"Sandbox" = "sandlock_t"
# Rename the enum *types* so prefix_with_name yields the established C constant
# names (SANDLOCK_EXCEPTION_KILL, SANDLOCK_ACTION_INJECT_FD_SEND, ...) rather
# than the verbose SANDLOCK_EXCEPTION_POLICY_T_* / SANDLOCK_ACTION_KIND_T_*.
"sandlock_exception_policy_t" = "sandlock_exception"
"sandlock_action_kind_t" = "sandlock_action"

[enum]
rename_variants = "ScreamingSnakeCase"
prefix_with_name = true
Loading
Loading