Skip to content

Add save hex option and update Sketch menu #2458

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 93 additions & 27 deletions app/src/processing/app/Editor.java
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@ public class Editor extends JFrame implements RunnerListener {

Runnable runHandler;
Runnable presentHandler;
Runnable runAndSaveHandler;
Runnable presentAndSaveHandler;
Runnable stopHandler;
Runnable exportHandler;
Runnable exportAppHandler;
Expand Down Expand Up @@ -557,21 +559,6 @@ public void actionPerformed(ActionEvent e) {
});
fileMenu.add(saveAsMenuItem);

item = newJMenuItem(_("Upload"), 'U');
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
handleExport(false);
}
});
fileMenu.add(item);

item = newJMenuItemShift(_("Upload Using Programmer"), 'U');
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
handleExport(true);
}
});
fileMenu.add(item);

fileMenu.addSeparator();

Expand Down Expand Up @@ -620,7 +607,7 @@ public void actionPerformed(ActionEvent e) {
protected JMenu buildSketchMenu() {
JMenuItem item;
sketchMenu = new JMenu(_("Sketch"));

item = newJMenuItem(_("Verify / Compile"), 'R');
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Expand All @@ -629,13 +616,29 @@ public void actionPerformed(ActionEvent e) {
});
sketchMenu.add(item);

// item = newJMenuItemShift("Verify / Compile (verbose)", 'R');
// item.addActionListener(new ActionListener() {
// public void actionPerformed(ActionEvent e) {
// handleRun(true);
// }
// });
// sketchMenu.add(item);
item = newJMenuItemShift("Compile and Save Hex", 'R');
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
handleRunAndSave(false);
}
});
sketchMenu.add(item);

item = newJMenuItem(_("Upload"), 'U');
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
handleExport(false);
}
});
sketchMenu.add(item);

item = newJMenuItemShift(_("Upload Using Programmer"), 'U');
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
handleExport(true);
}
});
sketchMenu.add(item);

// item = new JMenuItem("Stop");
// item.addActionListener(new ActionListener() {
Expand Down Expand Up @@ -1414,11 +1417,17 @@ protected void updateRedoState() {
// abstract from the editor in this fashion.


public void setHandlers(Runnable runHandler, Runnable presentHandler,
public void setHandlers(Runnable runHandler,
Runnable presentHandler,
Runnable runAndSaveHandler,
Runnable presentAndSaveHandler,
Runnable stopHandler,
Runnable exportHandler, Runnable exportAppHandler) {
Runnable exportHandler,
Runnable exportAppHandler) {
this.runHandler = runHandler;
this.presentHandler = presentHandler;
this.runAndSaveHandler = runHandler;
this.presentAndSaveHandler = presentHandler;
this.stopHandler = stopHandler;
this.exportHandler = exportHandler;
this.exportAppHandler = exportAppHandler;
Expand All @@ -1428,6 +1437,8 @@ public void setHandlers(Runnable runHandler, Runnable presentHandler,
public void resetHandlers() {
runHandler = new DefaultRunHandler();
presentHandler = new DefaultPresentHandler();
runAndSaveHandler = new DefaultRunAndSaveHandler();
presentAndSaveHandler = new DefaultPresentAndSaveHandler();
stopHandler = new DefaultStopHandler();
exportHandler = new DefaultExportHandler();
exportAppHandler = new DefaultExportAppHandler();
Expand Down Expand Up @@ -1916,13 +1927,35 @@ public void handleRun(final boolean verbose) {
// placed on the event thread and causes a hang--bad idea all around.
new Thread(verbose ? presentHandler : runHandler).start();
}
/**
* Implements Sketch → Run and Save Hex.
* @param verbose Set true to run with verbose output.
*/
public void handleRunAndSave(final boolean verbose) {
internalCloseRunner();
running = true;
toolbar.activate(EditorToolbar.RUN);
status.progress(_("Compiling sketch..."));

// do this to advance/clear the terminal window / dos prompt / etc
for (int i = 0; i < 10; i++) System.out.println();

// clear the console on each run, unless the user doesn't want to
if (Preferences.getBoolean("console.auto_clear")) {
console.clear();
}

// Cannot use invokeLater() here, otherwise it gets
// placed on the event thread and causes a hang--bad idea all around.
new Thread(verbose ? presentAndSaveHandler : runAndSaveHandler).start();
}

// DAM: in Arduino, this is compile
class DefaultRunHandler implements Runnable {
public void run() {
try {
sketch.prepare();
sketch.build(false);
sketch.build(false, false);
statusNotice(_("Done compiling."));
} catch (Exception e) {
status.unprogress();
Expand All @@ -1939,7 +1972,7 @@ class DefaultPresentHandler implements Runnable {
public void run() {
try {
sketch.prepare();
sketch.build(true);
sketch.build(true, false);
statusNotice(_("Done compiling."));
} catch (Exception e) {
status.unprogress();
Expand All @@ -1950,6 +1983,39 @@ public void run() {
toolbar.deactivate(EditorToolbar.RUN);
}
}
//DAM: in Arduino, this is compile
class DefaultRunAndSaveHandler implements Runnable {
public void run() {
try {
sketch.prepare();
sketch.build(false, true);
statusNotice(_("Done compiling."));
} catch (Exception e) {
status.unprogress();
statusError(e);
}

status.unprogress();
toolbar.deactivate(EditorToolbar.RUN);
}
}

// DAM: in Arduino, this is compile (with verbose output)
class DefaultPresentAndSaveHandler implements Runnable {
public void run() {
try {
sketch.prepare();
sketch.build(true, true);
statusNotice(_("Done compiling."));
} catch (Exception e) {
status.unprogress();
statusError(e);
}

status.unprogress();
toolbar.deactivate(EditorToolbar.RUN);
}
}

class DefaultStopHandler implements Runnable {
public void run() {
Expand Down
10 changes: 5 additions & 5 deletions app/src/processing/app/Sketch.java
Original file line number Diff line number Diff line change
Expand Up @@ -1129,8 +1129,8 @@ public void prepare() throws IOException {
* @return null if compilation failed, main class name if not
* @throws RunnerException
*/
public String build(boolean verbose) throws RunnerException {
return build(tempBuildFolder.getAbsolutePath(), verbose);
public String build(boolean verbose, boolean save) throws RunnerException {
return build(tempBuildFolder.getAbsolutePath(), verbose, save);
}

/**
Expand All @@ -1142,7 +1142,7 @@ public String build(boolean verbose) throws RunnerException {
*
* @return null if compilation failed, main class name if not
*/
public String build(String buildPath, boolean verbose) throws RunnerException {
public String build(String buildPath, boolean verbose, boolean save) throws RunnerException {
// run the preprocessor
editor.status.progressUpdate(20);

Expand All @@ -1155,7 +1155,7 @@ public void progress(int percent) {
}
};

return Compiler.build(data, buildPath, tempBuildFolder, pl, verbose);
return Compiler.build(data, buildPath, tempBuildFolder, pl, verbose, save);
}

protected boolean exportApplet(boolean usingProgrammer) throws Exception {
Expand All @@ -1173,7 +1173,7 @@ public boolean exportApplet(String appletPath, boolean usingProgrammer)

// build the sketch
editor.status.progressNotice(_("Compiling sketch..."));
String foundName = build(appletPath, false);
String foundName = build(appletPath, false, false);
// (already reported) error during export, exit this function
if (foundName == null) return false;

Expand Down
31 changes: 28 additions & 3 deletions arduino-core/src/processing/app/debug/Compiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ public class Compiler implements MessageConsumer {
private SketchData sketch;
private PreferencesMap prefs;
private boolean verbose;
private boolean saveHex;

private List<File> objectFiles;

Expand All @@ -86,7 +87,7 @@ public interface ProgressListener {

private ProgressListener progressListener;

static public String build(SketchData data, String buildPath, File tempBuildFolder, ProgressListener progListener, boolean verbose) throws RunnerException {
static public String build(SketchData data, String buildPath, File tempBuildFolder, ProgressListener progListener, boolean verbose, boolean save) throws RunnerException {
if (SketchData.checkSketchFile(data.getPrimaryFile()) == null)
BaseNoGui.showError(_("Bad file selected"),
_("Bad sketch primary file or bad sketck directory structure"), null);
Expand Down Expand Up @@ -115,7 +116,7 @@ static public String build(SketchData data, String buildPath, File tempBuildFold

// compile the program. errors will happen as a RunnerException
// that will bubble up to whomever called build().
if (compiler.compile(verbose)) {
if (compiler.compile(verbose, save)) {
compiler.size(compiler.getBuildPreferences());
return primaryClassName;
}
Expand Down Expand Up @@ -343,10 +344,11 @@ protected void size(PreferencesMap prefs) throws RunnerException {
* @return true if successful.
* @throws RunnerException Only if there's a problem. Only then.
*/
public boolean compile(boolean _verbose) throws RunnerException {
public boolean compile(boolean _verbose, boolean _save) throws RunnerException {
preprocess(prefs.get("build.path"));

verbose = _verbose || PreferencesData.getBoolean("build.verbose");
saveHex = _save;
sketchIsCompiled = false;
objectFiles = new ArrayList<File>();

Expand Down Expand Up @@ -409,6 +411,12 @@ public boolean compile(boolean _verbose) throws RunnerException {
// 6. build the .hex file
progressListener.progress(80);
compileHex();

// 7. Save the .hex file
if (saveHex) {
progressListener.progress(85);
saveHex();
}

progressListener.progress(90);
return true;
Expand Down Expand Up @@ -1101,6 +1109,23 @@ void compileHex() throws RunnerException {
}
execAsynchronously(cmdArray);
}

// 7. Save the .hex file
void saveHex() throws RunnerException {
PreferencesMap dict = new PreferencesMap(prefs);
dict.put("ide_version", "" + BaseNoGui.REVISION);

String[] cmdArray;
try {
String hexPattern = prefs.get("recipe.hex.pattern");
String savePath = sketch.getFolder().getAbsolutePath() + "/" + hexPattern;
String cmd = hexPattern + " " + savePath;
cmdArray = StringReplacer.formatAndSplit(cmd, dict, true);
} catch (Exception e) {
throw new RunnerException(e);
}
execAsynchronously(cmdArray);
}

private static String prepareIncludes(List<File> includeFolders) {
String res = "";
Expand Down
4 changes: 4 additions & 0 deletions hardware/arduino/avr/platform.txt
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ recipe.objcopy.eep.pattern="{compiler.path}{compiler.objcopy.cmd}" {compiler.obj
## Create hex
recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.flags} {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.hex"

## Save hex
recipe.hex.pattern=cp -f "{build.path}/{build.project_name}.hex"
recipe.hex.pattern.windows=copy /y "{build.path}/{build.project_name}.hex"

## Compute size
recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf"
recipe.size.regex=^(?:\.text|\.data|\.bootloader)\s+([0-9]+).*
Expand Down
4 changes: 4 additions & 0 deletions hardware/arduino/sam/platform.txt
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ recipe.objcopy.eep.pattern=
## Create hex
recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.flags} {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.bin"

## Save hex
recipe.hex.pattern=cp -f "{build.path}/{build.project_name}.bin"
recipe.hex.pattern.windows=copy /y "{build.path}/{build.project_name}.bin"

## Compute size
recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf"
recipe.size.regex=\.text\s+([0-9]+).*
Expand Down