autozig_build/
lib.rs

1//! Build script support for autozig
2//!
3//! This crate provides helper functions for use in build.rs scripts
4
5#![forbid(unsafe_code)]
6
7use std::{
8    env,
9    path::PathBuf,
10};
11
12use anyhow::Result;
13use autozig_engine::{
14    AutoZigEngine,
15    BuildOutput,
16};
17
18pub mod simd;
19
20pub use simd::{
21    detect_and_report,
22    SimdConfig,
23};
24
25/// Builder for autozig in build.rs
26pub struct Builder {
27    src_dir: PathBuf,
28}
29
30impl Builder {
31    /// Create a new builder
32    ///
33    /// # Arguments
34    /// * `src_dir` - The source directory to scan for autozig! macros (usually
35    ///   "src")
36    pub fn new(src_dir: impl Into<PathBuf>) -> Self {
37        Self { src_dir: src_dir.into() }
38    }
39
40    /// Run the build process
41    ///
42    /// This will:
43    /// 1. Scan source files for autozig! macros
44    /// 2. Extract and compile Zig code
45    /// 3. Generate FFI bindings
46    /// 4. Configure cargo to link the generated library
47    pub fn build(&self) -> Result<BuildOutput> {
48        // Get OUT_DIR from environment
49        let out_dir = env::var("OUT_DIR")
50            .map(PathBuf::from)
51            .unwrap_or_else(|_| PathBuf::from("target/debug/build"));
52
53        // Create and run engine
54        let engine = AutoZigEngine::new(&self.src_dir, &out_dir);
55        engine.build()
56    }
57}
58
59/// Convenience function for simple build scripts
60///
61/// # Example
62///
63/// ```rust,no_run
64/// // In build.rs:
65/// fn main() -> anyhow::Result<()> {
66///     autozig_build::build("src")?;
67///     Ok(())
68/// }
69/// ```
70pub fn build(src_dir: impl Into<PathBuf>) -> Result<BuildOutput> {
71    Builder::new(src_dir).build()
72}
73
74/// Compile Zig test executables from .zig files in a directory
75///
76/// This will find all .zig files in the specified directory and compile their
77/// tests. Test executables will be placed in OUT_DIR with the naming pattern:
78/// test_{filename}
79///
80/// # Arguments
81/// * `zig_dir` - Directory containing .zig files with test blocks
82///
83/// # Example
84///
85/// ```rust,no_run
86/// // In build.rs:
87/// fn main() -> anyhow::Result<()> {
88///     autozig_build::build("src")?;
89///     autozig_build::build_tests("zig")?; // Compile tests from zig/ directory
90///     Ok(())
91/// }
92/// ```
93pub fn build_tests(zig_dir: impl Into<PathBuf>) -> Result<Vec<PathBuf>> {
94    use std::fs;
95
96    use autozig_engine::ZigCompiler;
97
98    let zig_dir = zig_dir.into();
99    let out_dir = env::var("OUT_DIR")
100        .map(PathBuf::from)
101        .unwrap_or_else(|_| PathBuf::from("target/debug/build"));
102
103    let compiler = ZigCompiler::new();
104    let mut test_executables = Vec::new();
105
106    // Find all .zig files
107    if !zig_dir.exists() {
108        println!("cargo:warning=Zig directory not found: {}", zig_dir.display());
109        return Ok(test_executables);
110    }
111
112    for entry in fs::read_dir(&zig_dir)? {
113        let entry = entry?;
114        let path = entry.path();
115
116        if path.extension().and_then(|s| s.to_str()) == Some("zig") {
117            let file_stem = path.file_stem().unwrap().to_str().unwrap();
118            let test_exe = out_dir.join(format!("test_{}", file_stem));
119
120            println!("cargo:warning=Building Zig tests for: {}", path.display());
121
122            // Compile tests
123            compiler.compile_tests(&path, &test_exe, "native")?;
124
125            test_executables.push(test_exe);
126
127            println!("cargo:rerun-if-changed={}", path.display());
128        }
129    }
130
131    println!("cargo:warning=Built {} Zig test executables", test_executables.len());
132
133    Ok(test_executables)
134}
135
136#[cfg(test)]
137mod tests {
138    use super::*;
139
140    #[test]
141    fn test_builder_creation() {
142        let builder = Builder::new("src");
143        assert_eq!(builder.src_dir, PathBuf::from("src"));
144    }
145}