diff --git a/src/commands/devices.rs b/src/commands/devices.rs index 53f121b..4095a46 100644 --- a/src/commands/devices.rs +++ b/src/commands/devices.rs @@ -60,8 +60,14 @@ pub fn scan_devices() -> Result<()> { println!(" - Check kernel log: dmesg | tail -20"); println!(" - Check USB bus: lsusb | grep -i -E 'ch34|arduino|1a86|2341'"); } + #[cfg(target_os = "windows")] + { + println!(" - Open Device Manager and check Ports (COM & LPT)"); + println!(" - Install CH340 driver if needed: https://www.wch-ic.com/downloads/CH341SER_EXE.html"); + println!(" - Check if the board appears under \"Other devices\" with a warning icon"); + } println!(); } Ok(()) -} +} \ No newline at end of file diff --git a/src/commands/doctor.rs b/src/commands/doctor.rs index f25aa12..0e93039 100644 --- a/src/commands/doctor.rs +++ b/src/commands/doctor.rs @@ -43,10 +43,12 @@ pub fn run_diagnostics() -> Result<()> { } else { println!( "{}", - "Issues found. Run 'anvil setup' to fix." + "Issues found. See instructions below." .bright_yellow() .bold() ); + println!(); + print_fix_instructions(&health); } println!(); @@ -78,7 +80,7 @@ pub fn check_system_health() -> SystemHealth { let cmake_ok = which::which("cmake").is_ok(); // C++ compiler (optional -- for host tests) - let cpp_compiler_ok = which::which("g++").is_ok() || which::which("clang++").is_ok(); + let cpp_compiler_ok = has_cpp_compiler(); // git let git_ok = which::which("git").is_ok(); @@ -99,6 +101,20 @@ pub fn check_system_health() -> SystemHealth { } } +/// Check for a C++ compiler on any platform. +fn has_cpp_compiler() -> bool { + if which::which("g++").is_ok() || which::which("clang++").is_ok() { + return true; + } + #[cfg(windows)] + { + if which::which("cl").is_ok() { + return true; + } + } + false +} + fn print_diagnostics(health: &SystemHealth) { println!("{}", "Required:".bright_yellow().bold()); println!(); @@ -139,14 +155,23 @@ fn print_diagnostics(health: &SystemHealth) { println!("{}", "Optional:".bright_yellow().bold()); println!(); - // avr-size + // avr-size -- installed as part of the avr core, not a separate step if health.avr_size_ok { println!(" {} avr-size (binary size reporting)", "ok".green()); - } else { + } else if !health.avr_core_ok { println!( " {} avr-size {}", "--".bright_black(), - "install: sudo apt install gcc-avr".bright_black() + "included with arduino:avr core (no separate install)".bright_black() + ); + } else { + // Core is installed but avr-size is not on PATH -- + // this can happen on Windows where the tool is buried + // inside the Arduino15 packages directory. + println!( + " {} avr-size {}", + "--".bright_black(), + hint_avr_size_not_on_path().bright_black() ); } @@ -171,18 +196,18 @@ fn print_diagnostics(health: &SystemHealth) { println!( " {} cmake {}", "--".bright_black(), - "install: sudo apt install cmake".bright_black() + hint_cmake().bright_black() ); } // C++ compiler if health.cpp_compiler_ok { - println!(" {} C++ compiler (g++/clang++)", "ok".green()); + println!(" {} C++ compiler", "ok".green()); } else { println!( " {} C++ compiler {}", "--".bright_black(), - "install: sudo apt install g++".bright_black() + hint_cpp_compiler().bright_black() ); } @@ -193,7 +218,7 @@ fn print_diagnostics(health: &SystemHealth) { println!( " {} git {}", "--".bright_black(), - "install: sudo apt install git".bright_black() + hint_git().bright_black() ); } @@ -216,6 +241,160 @@ fn print_diagnostics(health: &SystemHealth) { } } +/// Print step-by-step fix instructions when required items are missing. +fn print_fix_instructions(health: &SystemHealth) { + println!("{}", "How to fix:".bright_cyan().bold()); + println!(); + + let mut step = 1u32; + + if !health.arduino_cli_ok { + println!( + " {}. {}", + step, + "Install arduino-cli:".bright_white().bold() + ); + if cfg!(target_os = "windows") { + println!(); + println!(" Option A -- WinGet (recommended):"); + println!(" {}", "winget install ArduinoSA.CLI".bright_cyan()); + println!(); + println!(" Option B -- Chocolatey:"); + println!(" {}", "choco install arduino-cli".bright_cyan()); + println!(); + println!(" Option C -- Direct download:"); + println!( + " {}", + "https://arduino.github.io/arduino-cli/installation/" + .bright_cyan() + ); + } else if cfg!(target_os = "macos") { + println!(" {}", "brew install arduino-cli".bright_cyan()); + } else { + println!(); + println!(" Option A -- Install script:"); + println!( + " {}", + "curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | sh" + .bright_cyan() + ); + println!( + " {}", + "sudo mv bin/arduino-cli /usr/local/bin/".bright_cyan() + ); + println!(); + println!(" Option B -- Package manager:"); + println!( + " {} {}", + "sudo apt install arduino-cli".bright_cyan(), + "(Debian/Ubuntu)".bright_black() + ); + println!( + " {} {}", + "yay -S arduino-cli".bright_cyan(), + "(Arch)".bright_black() + ); + } + println!(); + step += 1; + } + + if !health.arduino_cli_ok { + // They need to open a new terminal after installing arduino-cli + println!( + " {}. {}", + step, + "Close and reopen your terminal".bright_white().bold() + ); + println!( + " {}", + "(so the new PATH takes effect)".bright_black() + ); + println!(); + step += 1; + } + + if !health.avr_core_ok { + println!( + " {}. {}", + step, + "Install the AVR core and verify everything:" + .bright_white() + .bold() + ); + println!(" {}", "anvil setup".bright_cyan()); + println!(); + // step += 1; + } + + if !health.git_ok { + println!( + " {}", + "Tip: git is optional but recommended for version control." + .bright_black() + ); + if cfg!(target_os = "windows") { + println!( + " {}", + "winget install Git.Git".bright_black() + ); + } else if cfg!(target_os = "macos") { + println!( + " {}", + "xcode-select --install".bright_black() + ); + } else { + println!( + " {}", + "sudo apt install git".bright_black() + ); + } + println!(); + } +} + +// --------------------------------------------------------------------------- +// Platform-aware install hints (one-liners for the diagnostics table) +// --------------------------------------------------------------------------- + +fn hint_avr_size_not_on_path() -> &'static str { + if cfg!(target_os = "windows") { + "installed but not on PATH (binary size reports will be skipped)" + } else { + "installed but not on PATH" + } +} + +fn hint_cmake() -> &'static str { + if cfg!(target_os = "windows") { + "install: winget install Kitware.CMake (or choco install cmake)" + } else if cfg!(target_os = "macos") { + "install: brew install cmake" + } else { + "install: sudo apt install cmake" + } +} + +fn hint_cpp_compiler() -> &'static str { + if cfg!(target_os = "windows") { + "install: winget install Microsoft.VisualStudio.2022.BuildTools (or MinGW g++)" + } else if cfg!(target_os = "macos") { + "install: xcode-select --install" + } else { + "install: sudo apt install g++" + } +} + +fn hint_git() -> &'static str { + if cfg!(target_os = "windows") { + "install: winget install Git.Git (or https://git-scm.com)" + } else if cfg!(target_os = "macos") { + "install: xcode-select --install (or brew install git)" + } else { + "install: sudo apt install git" + } +} + fn check_dialout() -> bool { #[cfg(unix)] { @@ -234,4 +413,4 @@ fn check_dialout() -> bool { { true // Not applicable on Windows } -} +} \ No newline at end of file diff --git a/src/commands/setup.rs b/src/commands/setup.rs index 26cfd3b..1f07359 100644 --- a/src/commands/setup.rs +++ b/src/commands/setup.rs @@ -78,11 +78,22 @@ pub fn run_setup() -> Result<()> { if which::which("avr-size").is_ok() { println!(" {} avr-size (binary size reporting)", "ok".green()); } else { - println!( - " {} avr-size not found. Install for binary size details:", - "info".bright_black() - ); - println!(" sudo apt install gcc-avr"); + print_optional_hint("avr-size", hint_avr_size()); + } + + if which::which("cmake").is_ok() { + println!(" {} cmake (for host-side tests)", "ok".green()); + } else { + print_optional_hint("cmake", hint_cmake()); + } + + if which::which("g++").is_ok() + || which::which("clang++").is_ok() + || cfg!(windows) && which::which("cl").is_ok() + { + println!(" {} C++ compiler", "ok".green()); + } else { + print_optional_hint("C++ compiler", hint_cpp_compiler()); } #[cfg(unix)] @@ -137,6 +148,15 @@ pub fn run_setup() -> Result<()> { Ok(()) } +fn print_optional_hint(name: &str, hint: &str) { + println!( + " {} {} not found. Install for full functionality:", + "info".bright_black(), + name + ); + println!(" {}", hint); +} + fn print_install_instructions() { println!("{}", "Install arduino-cli:".bright_yellow().bold()); println!(); @@ -161,3 +181,37 @@ fn print_install_instructions() { println!(); println!(" Then re-run: anvil setup"); } + +// --------------------------------------------------------------------------- +// Platform-aware install hints +// --------------------------------------------------------------------------- + +fn hint_avr_size() -> &'static str { + if cfg!(target_os = "windows") { + "bundled with arduino:avr core (avr-size.exe in Arduino15 packages)" + } else if cfg!(target_os = "macos") { + "brew install avr-gcc" + } else { + "sudo apt install gcc-avr" + } +} + +fn hint_cmake() -> &'static str { + if cfg!(target_os = "windows") { + "winget install Kitware.CMake (or choco install cmake)" + } else if cfg!(target_os = "macos") { + "brew install cmake" + } else { + "sudo apt install cmake" + } +} + +fn hint_cpp_compiler() -> &'static str { + if cfg!(target_os = "windows") { + "winget install Microsoft.VisualStudio.2022.BuildTools (or MinGW g++)" + } else if cfg!(target_os = "macos") { + "xcode-select --install" + } else { + "sudo apt install g++" + } +} \ No newline at end of file