Skip to content

Commit 17f74a5

Browse files
update Sketch menu, add Save hex option
* Moving Upload options from "File" menu to "Sketch" menu as those are sketch actions more than file actions. Signed-off-by: Arnav Gupta <[email protected]>
1 parent 6d7751c commit 17f74a5

File tree

6 files changed

+157
-42
lines changed

6 files changed

+157
-42
lines changed

app/src/processing/app/Editor.java

Lines changed: 93 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,8 @@ public class Editor extends JFrame implements RunnerListener {
153153

154154
Runnable runHandler;
155155
Runnable presentHandler;
156+
Runnable runAndSaveHandler;
157+
Runnable presentAndSaveHandler;
156158
Runnable stopHandler;
157159
Runnable exportHandler;
158160
Runnable exportAppHandler;
@@ -557,22 +559,6 @@ public void actionPerformed(ActionEvent e) {
557559
});
558560
fileMenu.add(saveAsMenuItem);
559561

560-
item = newJMenuItem(_("Upload"), 'U');
561-
item.addActionListener(new ActionListener() {
562-
public void actionPerformed(ActionEvent e) {
563-
handleExport(false);
564-
}
565-
});
566-
fileMenu.add(item);
567-
568-
item = newJMenuItemShift(_("Upload Using Programmer"), 'U');
569-
item.addActionListener(new ActionListener() {
570-
public void actionPerformed(ActionEvent e) {
571-
handleExport(true);
572-
}
573-
});
574-
fileMenu.add(item);
575-
576562
fileMenu.addSeparator();
577563

578564
item = newJMenuItemShift(_("Page Setup"), 'P');
@@ -620,6 +606,7 @@ public void actionPerformed(ActionEvent e) {
620606
protected JMenu buildSketchMenu() {
621607
JMenuItem item;
622608
sketchMenu = new JMenu(_("Sketch"));
609+
623610

624611
item = newJMenuItem(_("Verify / Compile"), 'R');
625612
item.addActionListener(new ActionListener() {
@@ -628,14 +615,31 @@ public void actionPerformed(ActionEvent e) {
628615
}
629616
});
630617
sketchMenu.add(item);
618+
619+
item = newJMenuItem(_("Upload"), 'U');
620+
item.addActionListener(new ActionListener() {
621+
public void actionPerformed(ActionEvent e) {
622+
handleExport(false);
623+
}
624+
});
625+
sketchMenu.add(item);
631626

632-
// item = newJMenuItemShift("Verify / Compile (verbose)", 'R');
633-
// item.addActionListener(new ActionListener() {
634-
// public void actionPerformed(ActionEvent e) {
635-
// handleRun(true);
636-
// }
637-
// });
638-
// sketchMenu.add(item);
627+
item = newJMenuItemShift(_("Upload Using Programmer"), 'U');
628+
item.addActionListener(new ActionListener() {
629+
public void actionPerformed(ActionEvent e) {
630+
handleExport(true);
631+
}
632+
});
633+
sketchMenu.add(item);
634+
635+
636+
item = newJMenuItemAlt("Export compiled Binary", 'S');
637+
item.addActionListener(new ActionListener() {
638+
public void actionPerformed(ActionEvent e) {
639+
handleRunAndSave(true);
640+
}
641+
});
642+
sketchMenu.add(item);
639643

640644
// item = new JMenuItem("Stop");
641645
// item.addActionListener(new ActionListener() {
@@ -1414,11 +1418,17 @@ protected void updateRedoState() {
14141418
// abstract from the editor in this fashion.
14151419

14161420

1417-
public void setHandlers(Runnable runHandler, Runnable presentHandler,
1421+
public void setHandlers(Runnable runHandler,
1422+
Runnable presentHandler,
1423+
Runnable runAndSaveHandler,
1424+
Runnable presentAndSaveHandler,
14181425
Runnable stopHandler,
1419-
Runnable exportHandler, Runnable exportAppHandler) {
1426+
Runnable exportHandler,
1427+
Runnable exportAppHandler) {
14201428
this.runHandler = runHandler;
14211429
this.presentHandler = presentHandler;
1430+
this.runAndSaveHandler = runAndSaveHandler;
1431+
this.presentAndSaveHandler = presentAndSaveHandler;
14221432
this.stopHandler = stopHandler;
14231433
this.exportHandler = exportHandler;
14241434
this.exportAppHandler = exportAppHandler;
@@ -1428,6 +1438,8 @@ public void setHandlers(Runnable runHandler, Runnable presentHandler,
14281438
public void resetHandlers() {
14291439
runHandler = new BuildHandler();
14301440
presentHandler = new BuildHandler(true);
1441+
runAndSaveHandler = new BuildAndSaveHandler();
1442+
presentAndSaveHandler = new BuildAndSaveHandler(true);
14311443
stopHandler = new DefaultStopHandler();
14321444
exportHandler = new DefaultExportHandler();
14331445
exportAppHandler = new DefaultExportAppHandler();
@@ -1916,6 +1928,29 @@ public void handleRun(final boolean verbose) {
19161928
// placed on the event thread and causes a hang--bad idea all around.
19171929
new Thread(verbose ? presentHandler : runHandler).start();
19181930
}
1931+
1932+
/**
1933+
* Implements Sketch &rarr; Run and Save.
1934+
* @param verbose Set true to run with verbose output.
1935+
*/
1936+
public void handleRunAndSave(final boolean verbose) {
1937+
internalCloseRunner();
1938+
running = true;
1939+
toolbar.activate(EditorToolbar.RUN);
1940+
status.progress(_("Compiling sketch..."));
1941+
1942+
// do this to advance/clear the terminal window / dos prompt / etc
1943+
for (int i = 0; i < 10; i++) System.out.println();
1944+
1945+
// clear the console on each run, unless the user doesn't want to
1946+
if (Preferences.getBoolean("console.auto_clear")) {
1947+
console.clear();
1948+
}
1949+
1950+
// Cannot use invokeLater() here, otherwise it gets
1951+
// placed on the event thread and causes a hang--bad idea all around.
1952+
new Thread(verbose ? presentAndSaveHandler : runAndSaveHandler).start();
1953+
}
19191954

19201955
class BuildHandler implements Runnable {
19211956

@@ -1933,7 +1968,7 @@ public BuildHandler(boolean verbose) {
19331968
public void run() {
19341969
try {
19351970
sketch.prepare();
1936-
sketch.build(verbose);
1971+
sketch.build(verbose, false);
19371972
statusNotice(_("Done compiling."));
19381973
} catch (PreferencesMapException e) {
19391974
statusError(I18n.format(
@@ -1948,6 +1983,38 @@ public void run() {
19481983
toolbar.deactivate(EditorToolbar.RUN);
19491984
}
19501985
}
1986+
1987+
class BuildAndSaveHandler implements Runnable {
1988+
1989+
private final boolean verbose;
1990+
1991+
public BuildAndSaveHandler() {
1992+
this(false);
1993+
}
1994+
1995+
public BuildAndSaveHandler(boolean verbose) {
1996+
this.verbose = verbose;
1997+
}
1998+
1999+
@Override
2000+
public void run() {
2001+
try {
2002+
sketch.prepare();
2003+
sketch.build(verbose, true);
2004+
statusNotice(_("Done compiling."));
2005+
} catch (PreferencesMapException e) {
2006+
statusError(I18n.format(
2007+
_("Error while compiling: missing '{0}' configuration parameter"),
2008+
e.getMessage()));
2009+
} catch (Exception e) {
2010+
status.unprogress();
2011+
statusError(e);
2012+
}
2013+
2014+
status.unprogress();
2015+
toolbar.deactivate(EditorToolbar.RUN);
2016+
}
2017+
}
19512018

19522019
class DefaultStopHandler implements Runnable {
19532020
public void run() {

app/src/processing/app/Sketch.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1130,8 +1130,8 @@ public void prepare() throws IOException {
11301130
* @return null if compilation failed, main class name if not
11311131
* @throws RunnerException
11321132
*/
1133-
public String build(boolean verbose) throws RunnerException, PreferencesMapException {
1134-
return build(tempBuildFolder.getAbsolutePath(), verbose);
1133+
public String build(boolean verbose, boolean save) throws RunnerException, PreferencesMapException {
1134+
return build(tempBuildFolder.getAbsolutePath(), verbose, save);
11351135
}
11361136

11371137
/**
@@ -1143,7 +1143,7 @@ public String build(boolean verbose) throws RunnerException, PreferencesMapExcep
11431143
*
11441144
* @return null if compilation failed, main class name if not
11451145
*/
1146-
public String build(String buildPath, boolean verbose) throws RunnerException, PreferencesMapException {
1146+
public String build(String buildPath, boolean verbose, boolean save) throws RunnerException, PreferencesMapException {
11471147
// run the preprocessor
11481148
editor.status.progressUpdate(20);
11491149

@@ -1156,7 +1156,7 @@ public void progress(int percent) {
11561156
}
11571157
};
11581158

1159-
return Compiler.build(data, buildPath, tempBuildFolder, pl, verbose);
1159+
return Compiler.build(data, buildPath, tempBuildFolder, pl, verbose, save);
11601160
}
11611161

11621162
protected boolean exportApplet(boolean usingProgrammer) throws Exception {
@@ -1174,7 +1174,7 @@ public boolean exportApplet(String appletPath, boolean usingProgrammer)
11741174

11751175
// build the sketch
11761176
editor.status.progressNotice(_("Compiling sketch..."));
1177-
String foundName = build(appletPath, false);
1177+
String foundName = build(appletPath, false, false);
11781178
// (already reported) error during export, exit this function
11791179
if (foundName == null) return false;
11801180

arduino-core/src/processing/app/BaseNoGui.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,7 @@ static public void init(String[] args) {
502502
// - calls Sketch.build(verbose=false) that calls Sketch.ensureExistence(), set progressListener and calls Compiler.build()
503503
// - calls Sketch.upload() (see later...)
504504
if (!data.getFolder().exists()) showError(_("No sketch"), _("Can't find the sketch in the specified path"), null);
505-
String suggestedClassName = Compiler.build(data, tempBuildFolder.getAbsolutePath(), tempBuildFolder, null, parser.isDoVerboseBuild());
505+
String suggestedClassName = Compiler.build(data, tempBuildFolder.getAbsolutePath(), tempBuildFolder, null, parser.isDoVerboseBuild(), false);
506506
if (suggestedClassName == null) showError(_("Error while verifying"), _("An error occurred while verifying the sketch"), null);
507507
showMessage(_("Done compiling"), _("Done compiling"));
508508

@@ -547,7 +547,7 @@ static public void init(String[] args) {
547547
// if (!data.getFolder().exists()) showError(...);
548548
// String ... = Compiler.build(data, tempBuildFolder.getAbsolutePath(), tempBuildFolder, null, verbose);
549549
if (!data.getFolder().exists()) showError(_("No sketch"), _("Can't find the sketch in the specified path"), null);
550-
String suggestedClassName = Compiler.build(data, tempBuildFolder.getAbsolutePath(), tempBuildFolder, null, parser.isDoVerboseBuild());
550+
String suggestedClassName = Compiler.build(data, tempBuildFolder.getAbsolutePath(), tempBuildFolder, null, parser.isDoVerboseBuild(), false);
551551
if (suggestedClassName == null) showError(_("Error while verifying"), _("An error occurred while verifying the sketch"), null);
552552
showMessage(_("Done compiling"), _("Done compiling"));
553553
} catch (Exception e) {

arduino-core/src/processing/app/debug/Compiler.java

Lines changed: 49 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import java.io.FileNotFoundException;
3131
import java.io.FileOutputStream;
3232
import java.io.FileReader;
33+
import java.io.FileWriter;
3334
import java.io.IOException;
3435
import java.io.PrintWriter;
3536
import java.util.ArrayList;
@@ -67,6 +68,7 @@ public class Compiler implements MessageConsumer {
6768
private SketchData sketch;
6869
private PreferencesMap prefs;
6970
private boolean verbose;
71+
private boolean saveHex;
7072

7173
private List<File> objectFiles;
7274

@@ -83,7 +85,7 @@ public interface ProgressListener {
8385

8486
private ProgressListener progressListener;
8587

86-
static public String build(SketchData data, String buildPath, File tempBuildFolder, ProgressListener progListener, boolean verbose) throws RunnerException, PreferencesMapException {
88+
static public String build(SketchData data, String buildPath, File tempBuildFolder, ProgressListener progListener, boolean verbose, boolean save) throws RunnerException, PreferencesMapException {
8789
if (SketchData.checkSketchFile(data.getPrimaryFile()) == null)
8890
BaseNoGui.showError(_("Bad file selected"),
8991
_("Bad sketch primary file or bad sketch directory structure"), null);
@@ -112,7 +114,7 @@ static public String build(SketchData data, String buildPath, File tempBuildFold
112114

113115
// compile the program. errors will happen as a RunnerException
114116
// that will bubble up to whomever called build().
115-
if (compiler.compile(verbose)) {
117+
if (compiler.compile(verbose, save)) {
116118
compiler.size(compiler.getBuildPreferences());
117119
return primaryClassName;
118120
}
@@ -340,10 +342,11 @@ protected void size(PreferencesMap prefs) throws RunnerException {
340342
* @return true if successful.
341343
* @throws RunnerException Only if there's a problem. Only then.
342344
*/
343-
public boolean compile(boolean _verbose) throws RunnerException, PreferencesMapException {
345+
public boolean compile(boolean _verbose, boolean _save) throws RunnerException, PreferencesMapException {
344346
preprocess(prefs.get("build.path"));
345347

346348
verbose = _verbose || PreferencesData.getBoolean("build.verbose");
349+
saveHex = _save;
347350
sketchIsCompiled = false;
348351
objectFiles = new ArrayList<File>();
349352

@@ -381,31 +384,37 @@ public boolean compile(boolean _verbose) throws RunnerException, PreferencesMapE
381384
}
382385

383386
// 1. compile the sketch (already in the buildPath)
384-
progressListener.progress(30);
387+
progressListener.progress(20);
385388
compileSketch(includeFolders);
386389
sketchIsCompiled = true;
387390

388391
// 2. compile the libraries, outputting .o files to: <buildPath>/<library>/
389392
// Doesn't really use configPreferences
390-
progressListener.progress(40);
393+
progressListener.progress(30);
391394
compileLibraries(includeFolders);
392395

393396
// 3. compile the core, outputting .o files to <buildPath> and then
394397
// collecting them into the core.a library file.
395-
progressListener.progress(50);
398+
progressListener.progress(40);
396399
compileCore();
397400

398401
// 4. link it all together into the .elf file
399-
progressListener.progress(60);
402+
progressListener.progress(50);
400403
compileLink();
401404

402405
// 5. extract EEPROM data (from EEMEM directive) to .eep file.
403-
progressListener.progress(70);
406+
progressListener.progress(60);
404407
runRecipe("recipe.objcopy.eep.pattern");
405408

406409
// 6. build the .hex file
407-
progressListener.progress(80);
410+
progressListener.progress(70);
408411
runRecipe("recipe.objcopy.hex.pattern");
412+
413+
// 7. save the hex file
414+
if (saveHex) {
415+
progressListener.progress(80);
416+
saveHex();
417+
}
409418

410419
progressListener.progress(90);
411420
return true;
@@ -1042,6 +1051,37 @@ void runRecipe(String recipe) throws RunnerException, PreferencesMapException {
10421051
}
10431052
execAsynchronously(cmdArray);
10441053
}
1054+
1055+
//7. Save the .hex file
1056+
void saveHex() throws RunnerException {
1057+
PreferencesMap dict = new PreferencesMap(prefs);
1058+
dict.put("ide_version", "" + BaseNoGui.REVISION);
1059+
1060+
String[] cmdArray;
1061+
try {
1062+
String tmp_file = prefs.getOrExcept("recipe.hex.tmp_file");
1063+
tmp_file = StringReplacer.replaceFromMapping(tmp_file, dict);
1064+
String save_file = prefs.getOrExcept("recipe.hex.save_file");
1065+
save_file = StringReplacer.replaceFromMapping(save_file, dict);
1066+
1067+
File hexFile = new File(prefs.get("build.path") + "/" + tmp_file);
1068+
File saveFile = new File(sketch.getFolder().getAbsolutePath() + "/" + save_file);
1069+
1070+
FileReader in = new FileReader(hexFile);
1071+
FileWriter out = new FileWriter(saveFile);
1072+
1073+
int c;
1074+
while ((c = in.read()) != -1)
1075+
out.write(c);
1076+
1077+
in.close();
1078+
out.close();
1079+
1080+
} catch (Exception e) {
1081+
throw new RunnerException(e);
1082+
}
1083+
}
1084+
10451085

10461086
private static String prepareIncludes(List<File> includeFolders) {
10471087
String res = "";

hardware/arduino/avr/platform.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ recipe.objcopy.eep.pattern="{compiler.path}{compiler.objcopy.cmd}" {compiler.obj
6767
## Create hex
6868
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"
6969

70+
## Save hex
71+
recipe.hex.tmp_file={build.project_name}.hex
72+
recipe.hex.save_file={build.project_name}.{build.variant}.hex
73+
7074
## Compute size
7175
recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf"
7276
recipe.size.regex=^(?:\.text|\.data|\.bootloader)\s+([0-9]+).*

hardware/arduino/sam/platform.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ recipe.objcopy.eep.pattern=
7171
## Create hex
7272
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"
7373

74+
## Save hex
75+
recipe.hex.tmp_file={build.project_name}.bin
76+
recipe.hex.save_file={build.project_name}.{build.variant}.bin
77+
7478
## Compute size
7579
recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf"
7680
recipe.size.regex=\.text\s+([0-9]+).*

0 commit comments

Comments
 (0)