diff --git a/main.go b/main.go index a854a75073..c8955780ac 100644 --- a/main.go +++ b/main.go @@ -339,8 +339,17 @@ func dirsToModuleRootAbs(maindir, modroot string) []string { return dirs } +// validateOutputFormat checks if the output file extension matches the expected format +func validateOutputFormat(outpath, expectedExt string) error { + actualExt := filepath.Ext(outpath) + if actualExt != expectedExt { + return fmt.Errorf("output format %s does not match target format %s", actualExt, expectedExt) + } + return nil +} + // Flash builds and flashes the built binary to the given serial port. -func Flash(pkgName, port string, options *compileopts.Options) error { +func Flash(pkgName, port, outpath string, options *compileopts.Options) error { config, err := builder.NewConfig(options) if err != nil { return err @@ -389,13 +398,24 @@ func Flash(pkgName, port string, options *compileopts.Options) error { if !options.Work { defer os.RemoveAll(tmpdir) } - + // Validate output format before building + if outpath != "" { + if err := validateOutputFormat(outpath, fileExt); err != nil { + return err + } + } // Build the binary. result, err := builder.Build(pkgName, fileExt, tmpdir, config) if err != nil { return err } + // Save output file if specified (after build, before flashing) + if outpath != "" { + if err := copyFile(result.Binary, outpath); err != nil { + return fmt.Errorf("failed to save output file: %v", err) + } + } // do we need port reset to put MCU into bootloader mode? if config.Target.PortReset == "true" && flashMethod != "openocd" { port, err := getDefaultPort(port, config.Target.SerialPort) @@ -1297,6 +1317,11 @@ extension at all.` (https://tinygo.org/docs/reference/microcontrollers/). Examples: "arduino-nano", "d1mini", "xiao". + -o={filename}: + Save the built binary to the specified output file. The file + format must match the target's expected format (e.g., .hex, + .uf2). Both flashing and saving will be performed. + -monitor: Start the serial monitor (see below) immediately after flashing. However, some microcontrollers need a split second @@ -1627,7 +1652,7 @@ func main() { flag.BoolVar(&flagTest, "test", false, "supply -test flag to go list") } var outpath string - if command == "help" || command == "build" || command == "test" { + if command == "help" || command == "build" || command == "test" || command == "flash" { flag.StringVar(&outpath, "o", "", "output filename") } @@ -1778,7 +1803,7 @@ func main() { case "flash", "gdb", "lldb": pkgName := filepath.ToSlash(flag.Arg(0)) if command == "flash" { - err := Flash(pkgName, *port, options) + err := Flash(pkgName, *port, outpath, options) printBuildOutput(err, *flagJSON) } else { if !options.Debug {