use crate::cli::ExecContext;
use crate::error::Result;
use crate::executor::{check_tool, exec, exec_commands, exec_ignore_error, print_status};
use std::path::Path;
const BUILD_DIR_PREFIX: &str = "/tmp/rsbuild-cython";
pub fn run(package: &str, ctx: &ExecContext) -> Result<()> {
check_tool("cythonize")?;
check_tool("rsync")?;
check_tool("pip")?;
if !Path::new(package).is_dir() {
return Err(crate::error::RsbuildError::PathNotFound {
path: package.into(),
});
}
let build_dir = format!("{}-{}", BUILD_DIR_PREFIX, package);
print_status(&format!("Compiling Cython package: {}", package), ctx);
setup_build_dir(&build_dir, ctx)?;
compile_cython(package, &build_dir, ctx)?;
finalize_build(package, &build_dir, ctx)?;
print_status(&format!("Cython package '{}' built successfully", package), ctx);
Ok(())
}
fn setup_build_dir(build_dir: &str, ctx: &ExecContext) -> Result<()> {
exec_ignore_error(&format!("rm -rf {}", build_dir), ctx);
exec(&format!("mkdir -p {}/dist/legacy", build_dir), ctx)?;
for file in &["requirements.txt", "setup.cfg", "setup.py", "pyproject.toml"] {
if Path::new(file).exists() {
exec_ignore_error(&format!("cp {} {}", file, build_dir), ctx);
}
}
Ok(())
}
fn compile_cython(package: &str, build_dir: &str, ctx: &ExecContext) -> Result<()> {
exec_commands(
&[
&format!("cythonize -a -i {}", package),
"rsbuild clean",
&format!("find ./{} -type f -name '*.c' -delete 2>/dev/null || true", package),
&format!("find {} -type f -name '*.so' > /tmp/rsbuild_so_files", package),
&format!("rsync -av --files-from=/tmp/rsbuild_so_files ./ {}", build_dir),
&format!("find ./{} -type f -name '*.so' -delete 2>/dev/null || true", package),
],
ctx,
)
}
fn finalize_build(_package: &str, build_dir: &str, ctx: &ExecContext) -> Result<()> {
exec(&format!("cd {} && rsbuild build wheel", build_dir), ctx)?;
exec_commands(&["rsbuild clean", "rm -f /tmp/rsbuild_so_files"], ctx)?;
exec_ignore_error("find . -type f -name '*.html' -delete 2>/dev/null", ctx);
exec(&format!("mkdir -p dist && mv {}/dist/*.whl dist/", build_dir), ctx)?;
exec_ignore_error(&format!("rm -rf {}", build_dir), ctx);
Ok(())
}