use crate::{BuildArgs, HELPER_TARGET_SUBDIR, ZISK_TARGET};
use anyhow::{Context, Result};
use cargo_metadata::camino::Utf8PathBuf;
use std::{path::PathBuf, process::Command};
pub(crate) fn create_command(
args: &BuildArgs,
program_dir: &Utf8PathBuf,
program_metadata: &cargo_metadata::Metadata,
) -> Result<Command> {
let mut command = Command::new("cargo");
command.args(["+zisk", "build"]);
if let Some(features) = &args.features {
command.arg("--features").arg(features);
}
if args.all_features {
command.arg("--all-features");
}
if args.no_default_features {
command.arg("--no-default-features");
}
if args.release {
command.arg("--release");
}
for package in &args.packages {
command.args(["--package", package]);
}
for bin in &args.binaries {
command.args(["--bin", bin]);
}
command.args(["--target", ZISK_TARGET]);
let rustc_bin = zisk_rustc()?;
command.env("RUSTC", rustc_bin.display().to_string()).env_remove("RUSTC_WORKSPACE_WRAPPER");
let canonicalized_program_dir =
program_dir.canonicalize().context("Failed to canonicalize program directory")?;
command.current_dir(canonicalized_program_dir);
command.env("CARGO_TARGET_DIR", program_metadata.target_directory.join(HELPER_TARGET_SUBDIR));
Ok(command)
}
pub(crate) fn zisk_rustc() -> Result<PathBuf> {
static ZISK_RUSTC: std::sync::OnceLock<std::result::Result<PathBuf, String>> =
std::sync::OnceLock::new();
ZISK_RUSTC
.get_or_init(|| zisk_rustc_lookup().map_err(|err| format!("{err:#}")))
.clone()
.map_err(|err| anyhow::anyhow!(err))
}
fn zisk_rustc_lookup() -> Result<PathBuf> {
let output = Command::new("rustc")
.env("RUSTUP_TOOLCHAIN", crate::RUSTUP_TOOLCHAIN_NAME)
.arg("--print")
.arg("sysroot")
.output()
.map_err(|_| {
anyhow::anyhow!(
"ZisK toolchain '{}' is not installed or rustup is not available.\n\
Run `cargo zisk toolchain install` to install it.",
crate::RUSTUP_TOOLCHAIN_NAME
)
})?;
if !output.status.success() {
anyhow::bail!(
"ZisK toolchain '{}' is not installed.\n\
Run `cargo zisk toolchain install` to install it.",
crate::RUSTUP_TOOLCHAIN_NAME
);
}
let stdout_string =
String::from_utf8(output.stdout).context("Can't parse rustc --print sysroot stdout")?;
Ok(PathBuf::from(stdout_string.trim()).join("bin/rustc"))
}