use crate::cli::Args;
use crate::color;
use crate::config::{Arch, HostPlatform, Libc, TargetConfig};
use crate::env::{set_gcc_lib_paths, setup_sysroot_env, CrossEnv};
use crate::error::{CrossError, Result};
use crate::platform::{setup_cmake, setup_cross_compile_prefix, setup_generic_cmake_toolchain};
use crate::runner;
pub async fn setup(
target_config: &TargetConfig,
args: &Args,
host: &HostPlatform,
) -> Result<CrossEnv> {
let rust_target = target_config.target;
if target_config.libc == Some(Libc::Msvc) {
if host.is_windows() {
color::log_success(&format!(
"Using native MSVC toolchain for {}",
color::yellow(rust_target)
));
return Ok(CrossEnv::new());
}
return Err(CrossError::CrossCompilationNotSupported {
target_os: "windows-msvc".to_string(),
host_os: host.os.to_string(),
});
}
setup_mingw(target_config, args, host).await
}
async fn setup_mingw(
target_config: &TargetConfig,
args: &Args,
host: &HostPlatform,
) -> Result<CrossEnv> {
let arch = target_config.arch;
let rust_target = target_config.target;
if !matches!(arch, Arch::I686 | Arch::X86_64) {
return Err(CrossError::UnsupportedArchitecture {
arch: arch.as_str().to_string(),
os: "windows-gnu".to_string(),
});
}
let bin_prefix = format!("{}-w64-mingw32", arch.as_str());
let cross_compiler_name = format!("{bin_prefix}-cross");
let compiler_dir = args.cross_compiler_dir.join(format!(
"{}-{}",
cross_compiler_name, args.cross_make_version
));
let exe_ext = if host.is_windows() { ".exe" } else { "" };
let gcc_name = format!("{bin_prefix}-gcc{exe_ext}");
let gcc_path = compiler_dir.join("bin").join(&gcc_name);
if !gcc_path.exists() {
let host_platform = host.download_platform();
let (extension, format_hint) = if host.is_windows() {
(".zip", Some(crate::download::ArchiveFormat::Zip))
} else {
(".tgz", Some(crate::download::ArchiveFormat::TarGz))
};
let download_url = format!(
"https://github.com/zijiren233/cross-make/releases/download/{}-{}/{}{}",
args.cross_make_version, host_platform, cross_compiler_name, extension
);
crate::download::download_and_extract(
&download_url,
&compiler_dir,
format_hint,
args.github_proxy.as_deref(),
)
.await?;
}
let mut env = CrossEnv::new();
let bin_dir = compiler_dir.join("bin");
env.set_cc(&gcc_name);
env.set_cxx(format!("{bin_prefix}-g++{exe_ext}"));
env.set_ar(format!("{bin_prefix}-ar{exe_ext}"));
env.set_linker(&gcc_name);
env.add_path(&bin_dir);
set_gcc_lib_paths(&mut env, &compiler_dir, &bin_prefix);
setup_sysroot_env(&mut env, &compiler_dir, &bin_prefix, rust_target);
setup_cross_compile_prefix(&mut env, &bin_prefix);
setup_cmake(&mut env, args.cmake_generator.as_deref(), host.is_windows());
setup_generic_cmake_toolchain(&mut env);
if !host.is_windows() && args.command.needs_runner() {
runner::setup_wine_runner(&mut env, rust_target);
}
color::log_success(&format!(
"Configured MinGW-w64 toolchain for {}",
color::yellow(rust_target)
));
Ok(env)
}