From 7686ee00f04e68e9bfde619724b6fdf049b5695d Mon Sep 17 00:00:00 2001 From: guipublic Date: Tue, 1 Jul 2025 12:58:40 +0000 Subject: [PATCH 1/3] graceful handling of SIGPIPE --- tooling/artifact_cli/src/execution.rs | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/tooling/artifact_cli/src/execution.rs b/tooling/artifact_cli/src/execution.rs index cbe9f4754ea..65dd68c6db9 100644 --- a/tooling/artifact_cli/src/execution.rs +++ b/tooling/artifact_cli/src/execution.rs @@ -6,6 +6,7 @@ use nargo::{NargoError, foreign_calls::ForeignCallExecutor}; use noirc_abi::input_parser::InputValue; use noirc_artifacts::debug::DebugArtifact; use noirc_driver::CompiledProgram; +use std::io::Write; use crate::{ errors::CliError, @@ -75,6 +76,20 @@ pub fn show_diagnostic(circuit: &CompiledProgram, err: &NargoError } } +/// Print the input to stdout, and exit gracefully if `SIGPIPE` is received. +/// Rust ignores `SIGPIPE` by default, converting pipe errors into `ErrorKind::BrokenPipe` +fn print_to_stdout(args: std::fmt::Arguments) { + let mut stdout = std::io::stdout(); + if let Err(e) = stdout.write_fmt(args) { + if e.kind() == std::io::ErrorKind::BrokenPipe { + // Gracefully exit on broken pipe + std::process::exit(0); + } else { + panic!("Unexpected error: {e}"); + } + } +} + /// Print some information and save the witness if an output directory is specified, /// then checks if the expected return values were the ones we expected. pub fn save_and_check_witness( @@ -84,13 +99,13 @@ pub fn save_and_check_witness( witness_dir: Option<&Path>, witness_name: Option<&str>, ) -> Result<(), CliError> { - println!("[{}] Circuit witness successfully solved", circuit_name); + print_to_stdout(format_args!("[{}] Circuit witness successfully solved\n", circuit_name)); // Save first, so that we can potentially look at the output if the expectations fail. if let Some(witness_dir) = witness_dir { save_witness(&results.witness_stack, circuit_name, witness_dir, witness_name)?; } if let Some(ref return_value) = results.return_values.actual_return { - println!("[{}] Circuit output: {return_value:?}", circuit_name); + print_to_stdout(format_args!("[{}] Circuit output: {return_value:?}\n", circuit_name)); } check_witness(circuit, results.return_values) } @@ -112,7 +127,11 @@ pub fn save_witness( } } - println!("[{}] Witness saved to {}", circuit_name, witness_path.display()); + print_to_stdout(format_args!( + "[{}] Witness saved to {}\n", + circuit_name, + witness_path.display() + )); Ok(()) } From faf5f2d3ccd6dd71bf3e992b2d6f5ec3e7a4a247 Mon Sep 17 00:00:00 2001 From: guipublic Date: Tue, 1 Jul 2025 14:51:58 +0000 Subject: [PATCH 2/3] replace println with noirc_errors::print_to_stdout for 'nargo compile' --- compiler/noirc_driver/src/lib.rs | 4 ++-- compiler/noirc_errors/src/lib.rs | 15 +++++++++++++++ compiler/noirc_evaluator/src/ssa.rs | 5 ++++- tooling/artifact_cli/src/execution.rs | 27 +++++++++------------------ 4 files changed, 30 insertions(+), 21 deletions(-) diff --git a/compiler/noirc_driver/src/lib.rs b/compiler/noirc_driver/src/lib.rs index 1e917452215..248d2b5935c 100644 --- a/compiler/noirc_driver/src/lib.rs +++ b/compiler/noirc_driver/src/lib.rs @@ -440,8 +440,8 @@ pub fn compile_main( } if options.print_acir { - println!("Compiled ACIR for main (unoptimized):"); - println!("{}", compiled_program.program); + noirc_errors::print_to_stdout(format_args!("Compiled ACIR for main (unoptimized):\n")); + noirc_errors::print_to_stdout(format_args!("{}\n", compiled_program.program)); } Ok((compiled_program, warnings)) diff --git a/compiler/noirc_errors/src/lib.rs b/compiler/noirc_errors/src/lib.rs index 29f4e6213ed..d95f8948013 100644 --- a/compiler/noirc_errors/src/lib.rs +++ b/compiler/noirc_errors/src/lib.rs @@ -7,3 +7,18 @@ mod position; pub mod reporter; pub use position::{Located, Location, Position, Span, Spanned}; pub use reporter::{CustomDiagnostic, DiagnosticKind}; +use std::io::Write; + +/// Print the input to stdout, and exit gracefully if `SIGPIPE` is received. +/// Rust ignores `SIGPIPE` by default, converting pipe errors into `ErrorKind::BrokenPipe` +pub fn print_to_stdout(args: std::fmt::Arguments) { + let mut stdout = std::io::stdout(); + if let Err(e) = stdout.write_fmt(args) { + if e.kind() == std::io::ErrorKind::BrokenPipe { + // Gracefully exit on broken pipe + std::process::exit(0); + } else { + panic!("Unexpected error: {e}"); + } + } +} diff --git a/compiler/noirc_evaluator/src/ssa.rs b/compiler/noirc_evaluator/src/ssa.rs index eae0928efb6..51ce88e39bd 100644 --- a/compiler/noirc_evaluator/src/ssa.rs +++ b/compiler/noirc_evaluator/src/ssa.rs @@ -790,7 +790,10 @@ impl<'local> SsaBuilder<'local> { }; if print_ssa_pass { - println!("After {msg}:\n{}", self.ssa.print_with(self.files)); + noirc_errors::print_to_stdout(format_args!( + "After {msg}:\n{}", + self.ssa.print_with(self.files) + )); } self } diff --git a/tooling/artifact_cli/src/execution.rs b/tooling/artifact_cli/src/execution.rs index 65dd68c6db9..ecf9dde3b13 100644 --- a/tooling/artifact_cli/src/execution.rs +++ b/tooling/artifact_cli/src/execution.rs @@ -6,7 +6,6 @@ use nargo::{NargoError, foreign_calls::ForeignCallExecutor}; use noirc_abi::input_parser::InputValue; use noirc_artifacts::debug::DebugArtifact; use noirc_driver::CompiledProgram; -use std::io::Write; use crate::{ errors::CliError, @@ -76,20 +75,6 @@ pub fn show_diagnostic(circuit: &CompiledProgram, err: &NargoError } } -/// Print the input to stdout, and exit gracefully if `SIGPIPE` is received. -/// Rust ignores `SIGPIPE` by default, converting pipe errors into `ErrorKind::BrokenPipe` -fn print_to_stdout(args: std::fmt::Arguments) { - let mut stdout = std::io::stdout(); - if let Err(e) = stdout.write_fmt(args) { - if e.kind() == std::io::ErrorKind::BrokenPipe { - // Gracefully exit on broken pipe - std::process::exit(0); - } else { - panic!("Unexpected error: {e}"); - } - } -} - /// Print some information and save the witness if an output directory is specified, /// then checks if the expected return values were the ones we expected. pub fn save_and_check_witness( @@ -99,13 +84,19 @@ pub fn save_and_check_witness( witness_dir: Option<&Path>, witness_name: Option<&str>, ) -> Result<(), CliError> { - print_to_stdout(format_args!("[{}] Circuit witness successfully solved\n", circuit_name)); + noirc_errors::print_to_stdout(format_args!( + "[{}] Circuit witness successfully solved\n", + circuit_name + )); // Save first, so that we can potentially look at the output if the expectations fail. if let Some(witness_dir) = witness_dir { save_witness(&results.witness_stack, circuit_name, witness_dir, witness_name)?; } if let Some(ref return_value) = results.return_values.actual_return { - print_to_stdout(format_args!("[{}] Circuit output: {return_value:?}\n", circuit_name)); + noirc_errors::print_to_stdout(format_args!( + "[{}] Circuit output: {return_value:?}\n", + circuit_name + )); } check_witness(circuit, results.return_values) } @@ -127,7 +118,7 @@ pub fn save_witness( } } - print_to_stdout(format_args!( + noirc_errors::print_to_stdout(format_args!( "[{}] Witness saved to {}\n", circuit_name, witness_path.display() From 80e29b1fa69c7ca397e4fd2fb831fcec16e657bf Mon Sep 17 00:00:00 2001 From: guipublic Date: Thu, 17 Jul 2025 11:58:02 +0200 Subject: [PATCH 3/3] code review: use a macro for print to stdout --- compiler/noirc_driver/src/lib.rs | 4 ++-- compiler/noirc_errors/src/lib.rs | 15 +++++++++++++++ compiler/noirc_evaluator/src/ssa/builder.rs | 5 +++-- tooling/artifact_cli/src/execution.rs | 14 +++++--------- 4 files changed, 25 insertions(+), 13 deletions(-) diff --git a/compiler/noirc_driver/src/lib.rs b/compiler/noirc_driver/src/lib.rs index be3222d25b0..1619497f539 100644 --- a/compiler/noirc_driver/src/lib.rs +++ b/compiler/noirc_driver/src/lib.rs @@ -479,8 +479,8 @@ pub fn compile_main( } if options.print_acir { - noirc_errors::print_to_stdout(format_args!("Compiled ACIR for main (unoptimized):\n")); - noirc_errors::print_to_stdout(format_args!("{}\n", compiled_program.program)); + noirc_errors::println_to_stdout!("Compiled ACIR for main (unoptimized):"); + noirc_errors::println_to_stdout!("{}", compiled_program.program); } Ok((compiled_program, warnings)) diff --git a/compiler/noirc_errors/src/lib.rs b/compiler/noirc_errors/src/lib.rs index d95f8948013..a775bbf2e8b 100644 --- a/compiler/noirc_errors/src/lib.rs +++ b/compiler/noirc_errors/src/lib.rs @@ -22,3 +22,18 @@ pub fn print_to_stdout(args: std::fmt::Arguments) { } } } + +/// Macro to print formatted output to stdout +#[macro_export] +macro_rules! print_to_stdout { + ($($arg:tt)*) => { + noirc_errors::print_to_stdout(format_args!($($arg)*)) + }; +} + +#[macro_export] +macro_rules! println_to_stdout { + ($($arg:tt)*) => { + noirc_errors::print_to_stdout(format_args!("{}\n", format!($($arg)*))) + }; +} diff --git a/compiler/noirc_evaluator/src/ssa/builder.rs b/compiler/noirc_evaluator/src/ssa/builder.rs index 35053f3c3ac..ed562d514c9 100644 --- a/compiler/noirc_evaluator/src/ssa/builder.rs +++ b/compiler/noirc_evaluator/src/ssa/builder.rs @@ -3,6 +3,7 @@ use std::io::Write; use std::path::Path; use std::{collections::HashMap, path::PathBuf}; +use noirc_errors::println_to_stdout; use noirc_frontend::monomorphization::ast::Program; use crate::errors::RuntimeError; @@ -201,7 +202,7 @@ impl<'local> SsaBuilder<'local> { }; if print_ssa_pass { - println!("After {msg}:\n{}", self.ssa.print_with(self.files)); + println_to_stdout!("After {msg}:\n{}", self.ssa.print_with(self.files)); } self } @@ -214,7 +215,7 @@ pub(super) fn time(name: &str, print_timings: bool, f: impl FnOnce() -> T) -> if print_timings { let end_time = chrono::Utc::now().time(); - println!("{name}: {} ms", (end_time - start_time).num_milliseconds()); + println_to_stdout!("{name}: {} ms", (end_time - start_time).num_milliseconds()); } result diff --git a/tooling/artifact_cli/src/execution.rs b/tooling/artifact_cli/src/execution.rs index d77635a890f..69ea6f3837a 100644 --- a/tooling/artifact_cli/src/execution.rs +++ b/tooling/artifact_cli/src/execution.rs @@ -84,17 +84,13 @@ pub fn save_and_check_witness( witness_dir: Option<&Path>, witness_name: Option<&str>, ) -> Result<(), CliError> { - noirc_errors::print_to_stdout(format_args!( - "[{circuit_name}] Circuit witness successfully solved\n" - )); + noirc_errors::println_to_stdout!("[{circuit_name}] Circuit witness successfully solved"); // Save first, so that we can potentially look at the output if the expectations fail. if let Some(witness_dir) = witness_dir { save_witness(&results.witness_stack, circuit_name, witness_dir, witness_name)?; } if let Some(ref return_value) = results.return_values.actual_return { - noirc_errors::print_to_stdout(format_args!( - "[{circuit_name}] Circuit output: {return_value:?}\n" - )); + noirc_errors::println_to_stdout!("[{circuit_name}] Circuit output: {return_value:?}"); } check_witness(circuit, results.return_values) } @@ -116,11 +112,11 @@ pub fn save_witness( } } - noirc_errors::print_to_stdout(format_args!( - "[{}] Witness saved to {}\n", + noirc_errors::println_to_stdout!( + "[{}] Witness saved to {}", circuit_name, witness_path.display() - )); + ); Ok(()) }