use super::*;
pub(super) fn link_aot_binary_msvc(
bytecode_obj: &Path,
cmain_obj: &Path,
traces_obj: Option<&Path>,
staticlib: &Path,
out_path: &Path,
target: &TargetSpec,
) -> Result<(), AotError> {
let Some(mut cmd) = target.msvc_link_command() else {
return Err(AotError::Link(format!(
"MSVC linker (lld-link / link.exe) not on PATH for target {} — \
install one of: (a) LLVM (`brew install llvm` on macOS; \
`apt install lld` on Linux) which ships `lld-link`, or \
(b) Visual Studio Build Tools 2022 (`link.exe`, Windows host \
only — invoke luna-aot from a Developer Command Prompt so \
`PATH` + `LIB` are set). Override with `LD=...` to point at \
a custom linker.",
target.triple
)));
};
cmd.arg("/NOLOGO");
cmd.arg("/SUBSYSTEM:CONSOLE");
let machine = match target.arch {
Architecture::X86_64 => "X64",
Architecture::I386 => "X86",
Architecture::Aarch64 => "ARM64",
_ => {
return Err(AotError::Link(format!(
"MSVC link: unsupported arch {:?} for target {} (supported: \
x86_64, i686, aarch64)",
target.arch, target.triple
)));
}
};
cmd.arg(format!("/MACHINE:{machine}"));
cmd.arg(format!("/OUT:{}", out_path.display()));
cmd.arg(cmain_obj).arg(bytecode_obj);
if let Some(traces) = traces_obj {
cmd.arg(traces);
}
cmd.arg(staticlib);
for lib in &[
"bcrypt.lib",
"userenv.lib",
"ws2_32.lib",
"advapi32.lib",
"ntdll.lib",
"kernel32.lib",
"legacy_stdio_definitions.lib",
"ucrt.lib",
"vcruntime.lib",
"msvcrt.lib",
] {
cmd.arg(lib);
}
let output = cmd.output().map_err(|e| {
AotError::Link(format!(
"spawn MSVC linker for target {}: {e}",
target.triple
))
})?;
if !output.status.success() {
return Err(AotError::Link(format!(
"MSVC link failed (target {}, exit {:?}):\ncommand: {:?}\n\
stdout:\n{}\nstderr:\n{}",
target.triple,
output.status.code(),
cmd,
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr),
)));
}
Ok(())
}