Skip to main content

lean_toolchain/
lib.rs

1//! Lean 4 toolchain discovery, fingerprinting, allowlist re-export, and build-script helpers.
2//!
3//! Sits one layer above [`lean_rs_abi`], which owns link-free ABI/toolchain metadata. This crate
4//! composes on top: a typed [`ToolchainFingerprint`], the workspace-only Lake [`LAKE_FIXTURE_DIGEST`], a layered
5//! [`LinkDiagnostics`] error type, and reusable build-script helpers
6//! ([`emit_lean_link_directives_checked`], [`build_lake_target`],
7//! [`build_lake_target_quiet`]) that downstream embedders and higher layers can use to get
8//! consistent link/rerun directives and Lake dylib paths without duplicating policy.
9//!
10//! ## Single typed entry point
11//!
12//! [`LEAN_VERSION`], [`LEAN_HEADER_PATH`], and [`LEAN_HEADER_DIGEST`] are re-exported from
13//! [`lean_rs_abi`] so embedders that depend on this crate need only one import for build
14//! metadata. The allowlist comes through [`required_symbols`] (no copy).
15//!
16//! ## Layering
17//!
18//! `lean-rs-abi → lean-toolchain` for link-free metadata, and `lean-rs-sys → lean-rs`
19//! for raw runtime FFI. Raw `lean_*` symbols never appear in this crate's public surface.
20
21#![forbid(unsafe_code)]
22
23mod build_helpers;
24mod built_capability;
25mod diagnostics;
26mod discover;
27mod fingerprint;
28mod lakefile_toml;
29mod limits;
30mod loader;
31pub mod manifest_validation;
32mod modules;
33
34pub use build_helpers::{
35    BuiltLeanCapability, CAPABILITY_MANIFEST_SCHEMA_VERSION, CargoLeanCapability, build_lake_target,
36    build_lake_target_quiet, capability_env_var, capability_manifest_env_var, emit_lean_link_directives,
37    emit_lean_link_directives_checked,
38};
39pub use built_capability::{BuiltCapabilityArtifact, LeanBuiltCapability, LeanBuiltCapabilityError};
40pub use diagnostics::LinkDiagnostics;
41pub use discover::{DiscoverOptions, DiscoverySource, ToolchainInfo, discover_toolchain};
42pub use fingerprint::{HOST_TRIPLE, LAKE_FIXTURE_DIGEST, ToolchainFingerprint};
43pub use lean_rs_abi::{LEAN_HEADER_DIGEST, LEAN_HEADER_PATH, LEAN_RESOLVED_VERSION, LEAN_VERSION};
44pub use lean_rs_abi::{SUPPORTED_TOOLCHAINS, SupportedToolchain, supported_by_digest, supported_for};
45pub use limits::{
46    LEAN_DIAGNOSTIC_BYTE_LIMIT_DEFAULT, LEAN_DIAGNOSTIC_BYTE_LIMIT_MAX, LEAN_HEARTBEAT_LIMIT_DEFAULT,
47    LEAN_HEARTBEAT_LIMIT_MAX,
48};
49pub use loader::{
50    LOADER_DIAGNOSTIC_TEXT_LIMIT, LeanExportAbiRepr, LeanExportArgAbi, LeanExportOwnership, LeanExportResultConvention,
51    LeanExportReturnAbi, LeanExportSignature, LeanExportSymbolKind, LeanLibraryDependency, LeanLoaderCheck,
52    LeanLoaderDiagnosticCode, LeanLoaderReport, LeanLoaderSeverity, LeanModuleInitializer, bound_loader_text,
53};
54pub use manifest_validation::CapabilityManifest;
55pub use modules::{
56    LeanLakeProjectModules, LeanModuleDescriptor, LeanModuleDiscoveryDiagnostic, LeanModuleDiscoveryOptions,
57    LeanModuleSetFingerprint, discover_lake_modules,
58};
59
60/// Version of the `lean-toolchain` crate, matching `Cargo.toml`.
61pub const VERSION: &str = env!("CARGO_PKG_VERSION");
62
63/// Curated allowlist of `LEAN_EXPORT` symbols the workspace relies on.
64///
65/// Returns [`lean_rs_abi::REQUIRED_SYMBOLS`] directly—the allowlist lives in
66/// exactly one place. Use this through `lean-toolchain` so consumer crates do
67/// not also need a direct raw-FFI dependency just to enumerate symbol
68/// names.
69#[must_use]
70pub fn required_symbols() -> &'static [&'static str] {
71    lean_rs_abi::REQUIRED_SYMBOLS
72}
73
74#[cfg(test)]
75mod tests {
76    use super::{LEAN_HEADER_DIGEST, LEAN_VERSION, VERSION, required_symbols};
77
78    #[test]
79    fn version_constant_matches_package() {
80        assert_eq!(VERSION, env!("CARGO_PKG_VERSION"));
81    }
82
83    #[test]
84    fn required_symbols_is_nonempty() {
85        assert!(!required_symbols().is_empty());
86    }
87
88    #[test]
89    fn lean_metadata_is_baked() {
90        assert!(!LEAN_VERSION.is_empty());
91        assert_eq!(LEAN_HEADER_DIGEST.len(), 64);
92        assert!(LEAN_HEADER_DIGEST.chars().all(|c| c.is_ascii_hexdigit()));
93    }
94}