API Reference
First Principle
gerc is the Rust lowering and emission layer of the toolchain.
The safest downstream posture is:
- prefer crate-root APIs first
- provide
gerc’s own source/evidence inputs directly - keep upstream artifact translation outside
gerc/src/** - treat emitted Rust and build artifacts as the product boundary
API Tiers
gerc organizes its public API into two tiers:
- Tier 1:
generate(),generate_from_source(),GercConfig,GercInput,GercOutput,GercOutputMeta,SCHEMA_VERSION - Tier 2: the individual modules (
lower,gate,emit,typemap,linkgen,crategen,consumer,c)
The crate root also re-exports the common emission entrypoints so downstream
code does not need to import emit or crategen directly for routine use:
emit_source, emit_type, emit_crate, emit_build_rs, emit_rustc_args,
emit_rustc_link_args, OutputMode, OverwritePolicy, CrateManifest, and
EmittedCrate.
For explicit staged workflows, the crate root also re-exports:
EvidenceInputsGateDecisionoutput_meta,meta_to_json,meta_from_json,projection_to_json, andprojection_from_jsonGercConsumer,ConsumerReport,ConsumerFinding,FindingKind,PassthroughConsumer,FolConsumer,build_sidecar,sidecar_to_json,sidecar_from_json,extern_function_names,record_names, andtype_alias_names
For staged inspection, import the modules explicitly:
gerc::gate::gate_package(...)gerc::lower::lower_package(...)
The root also re-exports many gerc::c::* types directly, because the crate
still supports staged and compatibility-style workflows over its own binding
model.
Preferred Public Surface
These are the main consumer-facing entrypoints:
generate()andgenerate_from_source()GercInput,GercConfig, andGercOutputemit_source(),emit_crate(),emit_build_rs(), andemit_rustc_args()- JSON metadata and projection helpers
- consumer-sidecar helpers
Primary Workflow
generate_from_source() is the preferred entrypoint when the caller already
has a SourcePackage. Use GercInput directly when attaching optional
translated evidence in parallel with source.
#![allow(unused)]
fn main() {
use gerc::{
emit_crate, emit_rustc_args, emit_source, generate, generate_from_source, GercConfig,
GercInput, OutputMode, OverwritePolicy,
};
let input = GercInput::from_source_package(source.clone())
.with_analysis(analysis)
.with_validation(validation)
.with_link_plan(plan);
let output = generate_from_source(source, &GercConfig::new("mylib_sys")).unwrap();
let config = GercConfig::new("mylib_sys");
let output = generate(&input, &config).unwrap();
let source = emit_source(&output.projection);
let rustc_args = emit_rustc_args(&output.projection);
let emitted = emit_crate(
&output.projection,
&config,
std::path::Path::new("/tmp/mylib_sys"),
OutputMode::Crate,
OverwritePolicy::Overwrite,
).unwrap();
}
GercInput also exposes from_source_json(...) for explicit JSON intake.
When validation evidence is attached, generate() filters out declarations
that fail validation gating instead of emitting speculative Rust bindings.
For lower-level staged work, the public API still supports:
BindingPackageBindingItemBindingTypegate::gate_package(...)lower::lower_package(...)
The emitted crate path supports both:
- Cargo build-script rendering via
build.rs - direct
rustcargument rendering viarustc-link-args.txtandemit_rustc_args(...)
Downstream Posture
If you are integrating gerc into another tool, prefer:
- root-level generation APIs
- explicit
GercInputconstruction when evidence is available - emitted Rust/build outputs rather than internal lowering modules
- tests/examples/harnesses for any
parcorlincartifact translation
Integration Coverage
The current suite exercises realistic split-pipeline paths, not only hand-constructed packages:
parc -> gercsource-only generation for zlib and libpng fixturesparc -> linc -> gercgeneration with declared link surfacesparc -> linc -> gercgeneration with resolved link-plan evidence
Those paths are proved in tests and examples. They are not library-level crate dependencies.
Configuration
GercConfig controls what gets generated:
| Field | Default | Description |
|---|---|---|
crate_name | "gerc_output" | Name for the generated crate |
crate_version | "0.1.0" | Version string |
emit_functions | true | Emit extern "C" function declarations |
emit_records | true | Emit #[repr(C)] struct/union types |
emit_enums | true | Emit enum types |
emit_type_aliases | true | Emit type aliases |
emit_variables | true | Emit static variable declarations |
emit_constants | true | Emit constant definitions |
emit_build_script | true | Emit build.rs with link metadata |
Explicit Non-Goals
The current contract does not promise:
- parsing or preprocessing C
- binary inspection inside
gerc - automatic invention of missing ABI facts
- library-level dependencies on upstream pipeline crates
Error Handling
All fallible operations return GercResult<T>, which is Result<T, GercError>.
JSON Contract
Output metadata can be serialized for downstream tooling:
#![allow(unused)]
fn main() {
use gerc::contract::{output_meta, meta_to_json};
let meta = output_meta(&config, &output);
let json = meta_to_json(&meta).unwrap();
}
The JSON includes schema_version as an artifact-shape gate.
meta_from_json() rejects metadata with a schema version newer than the
current build supports rather than guessing.
Consumer Contract
Downstream tools implement the GercConsumer trait:
#![allow(unused)]
fn main() {
use gerc::consumer::{GercConsumer, ConsumerReport};
use gerc::ir::RustProjection;
struct MyConsumer;
impl GercConsumer for MyConsumer {
fn inspect(&self, proj: &RustProjection) -> ConsumerReport {
ConsumerReport::default()
}
}
}
A MetadataSidecar (JSON) can be generated alongside the crate for tools that
do not need to parse Rust source:
#![allow(unused)]
fn main() {
use gerc::consumer::{build_sidecar, sidecar_to_json};
let sidecar = build_sidecar("mylib_sys", &output.projection);
let json = sidecar_to_json(&sidecar).unwrap();
}
Generated crate metadata and crate-level src/lib.rs markers identify the
emitter as GERC.