diff --git a/packages/cli/src/cli/link.rs b/packages/cli/src/cli/link.rs index 08539718a..005aad3d4 100644 --- a/packages/cli/src/cli/link.rs +++ b/packages/cli/src/cli/link.rs @@ -1,7 +1,7 @@ use crate::Result; -use anyhow::Context; +use anyhow::{bail, Context}; use serde::{Deserialize, Serialize}; -use std::{borrow::Cow, ffi::OsString, path::PathBuf}; +use std::{borrow::Cow, ffi::OsString, path::PathBuf, process::ExitCode}; use target_lexicon::Triple; /// `dx` can act as a linker in a few scenarios. Note that we don't *actually* implement the linker logic, @@ -106,16 +106,20 @@ impl LinkAction { Ok(()) } - pub(crate) fn run_link(self) { + pub(crate) fn run_link(self) -> ExitCode { let link_err_file = self.link_err_file.clone(); - let res = self.run_link_inner(); + if let Err(err) = self.run_link_inner() { + eprintln!("Linker error: {err}"); - if let Err(err) = res { // If we failed to run the linker, we need to write the error to the file // so that the main process can read it. _ = std::fs::create_dir_all(link_err_file.parent().unwrap()); _ = std::fs::write(link_err_file, format!("Linker error: {err}")); + + return ExitCode::FAILURE; } + + ExitCode::SUCCESS } /// Write the incoming linker args to a file @@ -149,12 +153,20 @@ impl LinkAction { }; let res = cmd.output().expect("Failed to run linker"); + if !res.status.success() { + bail!( + "{}\n{}", + String::from_utf8_lossy(&res.stdout), + String::from_utf8_lossy(&res.stderr) + ); + } if !res.stderr.is_empty() || !res.stdout.is_empty() { + // Write linker warnings to file so that the main process can read them. _ = std::fs::create_dir_all(self.link_err_file.parent().unwrap()); _ = std::fs::write( self.link_err_file, format!( - "Linker error: {}\n{}", + "Linker warnings: {}\n{}", String::from_utf8_lossy(&res.stdout), String::from_utf8_lossy(&res.stderr) ), diff --git a/packages/cli/src/main.rs b/packages/cli/src/main.rs index aadc1c100..fbca1aec3 100644 --- a/packages/cli/src/main.rs +++ b/packages/cli/src/main.rs @@ -24,6 +24,8 @@ mod wasm_bindgen; mod wasm_opt; mod workspace; +use std::process::ExitCode; + pub(crate) use build::*; pub(crate) use cli::*; pub(crate) use config::*; @@ -39,7 +41,7 @@ pub(crate) use wasm_bindgen::*; pub(crate) use workspace::*; #[tokio::main] -async fn main() { +async fn main() -> ExitCode { // The CLI uses dx as a rustcwrapper in some instances (like binary patching) if rustcwrapper::is_wrapping_rustc() { return rustcwrapper::run_rustc(); @@ -81,4 +83,6 @@ async fn main() { output => tracing::info!(json = %output), } + + ExitCode::SUCCESS } diff --git a/packages/cli/src/rustcwrapper.rs b/packages/cli/src/rustcwrapper.rs index b5835badc..41252481f 100644 --- a/packages/cli/src/rustcwrapper.rs +++ b/packages/cli/src/rustcwrapper.rs @@ -2,6 +2,7 @@ use serde::{Deserialize, Serialize}; use std::{ env::{args, vars}, path::PathBuf, + process::ExitCode, }; /// The environment variable indicating where the args file is located. @@ -65,7 +66,7 @@ fn has_linking_args() -> bool { /// Run rustc directly, but output the result to a file. /// /// -pub fn run_rustc() { +pub fn run_rustc() -> ExitCode { // If we are being asked to link, delegate to the linker action. if has_linking_args() { return crate::link::LinkAction::from_env()