Skip to content

update Sketch menu, add Save hex option #2567

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
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
119 changes: 93 additions & 26 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,22 +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();

item = newJMenuItemShift(_("Page Setup"), 'P');
Expand Down Expand Up @@ -620,6 +606,7 @@ public void actionPerformed(ActionEvent e) {
protected JMenu buildSketchMenu() {
JMenuItem item;
sketchMenu = new JMenu(_("Sketch"));


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

item = newJMenuItem(_("Upload"), 'U');
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
handleExport(false);
}
});
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(_("Upload Using Programmer"), 'U');
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
handleExport(true);
}
});
sketchMenu.add(item);


item = newJMenuItemAlt(_("Export compiled Binary"), 'S');
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
handleRunAndSave(true);
}
});
sketchMenu.add(item);

// item = new JMenuItem("Stop");
// item.addActionListener(new ActionListener() {
Expand Down Expand Up @@ -1414,11 +1418,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 = runAndSaveHandler;
this.presentAndSaveHandler = presentAndSaveHandler;
this.stopHandler = stopHandler;
this.exportHandler = exportHandler;
this.exportAppHandler = exportAppHandler;
Expand All @@ -1428,6 +1438,8 @@ public void setHandlers(Runnable runHandler, Runnable presentHandler,
public void resetHandlers() {
runHandler = new BuildHandler();
presentHandler = new BuildHandler(true);
runAndSaveHandler = new BuildAndSaveHandler();
presentAndSaveHandler = new BuildAndSaveHandler(true);
stopHandler = new DefaultStopHandler();
exportHandler = new DefaultExportHandler();
exportAppHandler = new DefaultExportAppHandler();
Expand Down Expand Up @@ -1916,6 +1928,29 @@ 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.
* @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();
}

class BuildHandler implements Runnable {

Expand All @@ -1933,7 +1968,7 @@ public BuildHandler(boolean verbose) {
public void run() {
try {
sketch.prepare();
sketch.build(verbose);
sketch.build(verbose, false);
statusNotice(_("Done compiling."));
} catch (PreferencesMapException e) {
statusError(I18n.format(
Expand All @@ -1948,6 +1983,38 @@ public void run() {
toolbar.deactivate(EditorToolbar.RUN);
}
}

class BuildAndSaveHandler implements Runnable {

private final boolean verbose;

public BuildAndSaveHandler() {
this(false);
}

public BuildAndSaveHandler(boolean verbose) {
this.verbose = verbose;
}

@Override
public void run() {
try {
sketch.prepare();
sketch.build(verbose, true);
statusNotice(_("Done compiling."));
} catch (PreferencesMapException e) {
statusError(I18n.format(
_("Error while compiling: missing '{0}' configuration parameter"),
e.getMessage()));
} 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 @@ -1130,8 +1130,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, PreferencesMapException {
return build(tempBuildFolder.getAbsolutePath(), verbose);
public String build(boolean verbose, boolean save) throws RunnerException, PreferencesMapException {
return build(tempBuildFolder.getAbsolutePath(), verbose, save);
}

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

Expand All @@ -1156,7 +1156,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 @@ -1174,7 +1174,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
4 changes: 2 additions & 2 deletions arduino-core/src/processing/app/BaseNoGui.java
Original file line number Diff line number Diff line change
Expand Up @@ -499,7 +499,7 @@ static public void init(String[] args) {
// - calls Sketch.build(verbose=false) that calls Sketch.ensureExistence(), set progressListener and calls Compiler.build()
// - calls Sketch.upload() (see later...)
if (!data.getFolder().exists()) showError(_("No sketch"), _("Can't find the sketch in the specified path"), null);
String suggestedClassName = Compiler.build(data, tempBuildFolder.getAbsolutePath(), tempBuildFolder, null, parser.isDoVerboseBuild());
String suggestedClassName = Compiler.build(data, tempBuildFolder.getAbsolutePath(), tempBuildFolder, null, parser.isDoVerboseBuild(), false);
if (suggestedClassName == null) showError(_("Error while verifying"), _("An error occurred while verifying the sketch"), null);
showMessage(_("Done compiling"), _("Done compiling"));

Expand Down Expand Up @@ -544,7 +544,7 @@ static public void init(String[] args) {
// if (!data.getFolder().exists()) showError(...);
// String ... = Compiler.build(data, tempBuildFolder.getAbsolutePath(), tempBuildFolder, null, verbose);
if (!data.getFolder().exists()) showError(_("No sketch"), _("Can't find the sketch in the specified path"), null);
String suggestedClassName = Compiler.build(data, tempBuildFolder.getAbsolutePath(), tempBuildFolder, null, parser.isDoVerboseBuild());
String suggestedClassName = Compiler.build(data, tempBuildFolder.getAbsolutePath(), tempBuildFolder, null, parser.isDoVerboseBuild(), false);
if (suggestedClassName == null) showError(_("Error while verifying"), _("An error occurred while verifying the sketch"), null);
showMessage(_("Done compiling"), _("Done compiling"));
} catch (Exception e) {
Expand Down
58 changes: 49 additions & 9 deletions arduino-core/src/processing/app/debug/Compiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
Expand Down Expand Up @@ -67,6 +68,7 @@ public class Compiler implements MessageConsumer {
private SketchData sketch;
private PreferencesMap prefs;
private boolean verbose;
private boolean saveHex;

private List<File> objectFiles;

Expand All @@ -83,7 +85,7 @@ public interface ProgressListener {

private ProgressListener progressListener;

static public String build(SketchData data, String buildPath, File tempBuildFolder, ProgressListener progListener, boolean verbose) throws RunnerException, PreferencesMapException {
static public String build(SketchData data, String buildPath, File tempBuildFolder, ProgressListener progListener, boolean verbose, boolean save) throws RunnerException, PreferencesMapException {
if (SketchData.checkSketchFile(data.getPrimaryFile()) == null)
BaseNoGui.showError(_("Bad file selected"),
_("Bad sketch primary file or bad sketch directory structure"), null);
Expand Down Expand Up @@ -112,7 +114,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 @@ -340,10 +342,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, PreferencesMapException {
public boolean compile(boolean _verbose, boolean _save) throws RunnerException, PreferencesMapException {
preprocess(prefs.get("build.path"));

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

Expand Down Expand Up @@ -381,31 +384,37 @@ public boolean compile(boolean _verbose) throws RunnerException, PreferencesMapE
}

// 1. compile the sketch (already in the buildPath)
progressListener.progress(30);
progressListener.progress(20);
compileSketch(includeFolders);
sketchIsCompiled = true;

// 2. compile the libraries, outputting .o files to: <buildPath>/<library>/
// Doesn't really use configPreferences
progressListener.progress(40);
progressListener.progress(30);
compileLibraries(includeFolders);

// 3. compile the core, outputting .o files to <buildPath> and then
// collecting them into the core.a library file.
progressListener.progress(50);
progressListener.progress(40);
compileCore();

// 4. link it all together into the .elf file
progressListener.progress(60);
progressListener.progress(50);
compileLink();

// 5. extract EEPROM data (from EEMEM directive) to .eep file.
progressListener.progress(70);
progressListener.progress(60);
runRecipe("recipe.objcopy.eep.pattern");

// 6. build the .hex file
progressListener.progress(80);
progressListener.progress(70);
runRecipe("recipe.objcopy.hex.pattern");

// 7. save the hex file
if (saveHex) {
progressListener.progress(80);
saveHex();
}

progressListener.progress(90);
return true;
Expand Down Expand Up @@ -1042,6 +1051,37 @@ void runRecipe(String recipe) throws RunnerException, PreferencesMapException {
}
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 tmp_file = prefs.getOrExcept("recipe.output.tmp_file");
tmp_file = StringReplacer.replaceFromMapping(tmp_file, dict);
String save_file = prefs.getOrExcept("recipe.output.save_file");
save_file = StringReplacer.replaceFromMapping(save_file, dict);

File hexFile = new File(prefs.get("build.path") + "/" + tmp_file);
File saveFile = new File(sketch.getFolder().getAbsolutePath() + "/" + save_file);

FileReader in = new FileReader(hexFile);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FileUtils.copyFile may be used here.

FileWriter out = new FileWriter(saveFile);

int c;
while ((c = in.read()) != -1)
out.write(c);

in.close();
out.close();

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May you add a message for verbose compile? Something like:

Copying output file xxxxxx.hex to /xxx/yyy/zzz

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also for AVR we would like to save the .eep ??

Arnav Gupta (championswimmer)
LinkedIn http://in.linkedin.com/in/arnavgupta/ | Web
http://championswimmer.in | Blog http://blog.championswimmer.in |
Twitter http://twitter.com/championswimmer | Facebook
http://facebook.com/championswimmer | Github
http://github.com/championswimmer

On 18 February 2015 at 16:08, Cristian Maglie notifications@github.com
wrote:

In arduino-core/src/processing/app/debug/Compiler.java
#2567 (comment):

  •  String save_file = prefs.getOrExcept("recipe.output.save_file");
    
  •  save_file = StringReplacer.replaceFromMapping(save_file, dict);
    
  •  File hexFile = new File(prefs.get("build.path") + "/" + tmp_file);
    
  •  File saveFile = new File(sketch.getFolder().getAbsolutePath() + "/" + save_file);
    
  •  FileReader in = new FileReader(hexFile);
    
  •  FileWriter out = new FileWriter(saveFile);
    
  •  int c;
    
  •  while ((c = in.read()) != -1)
    
  •    out.write(c);
    
  •  in.close();
    
  •  out.close();
    

May you add a message for verbose compile? Something like:

Copying output file xxxxxx.hex to /xxx/yyy/zzz

Reply to this email directly or view it on GitHub
https://github.com/arduino/Arduino/pull/2567/files#r24892263.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, maybe we would like to list the files as a comma separated list?

} catch (Exception e) {
throw new RunnerException(e);
}
}


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.output.tmp_file={build.project_name}.hex
recipe.output.save_file={build.project_name}.{build.variant}.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.output.tmp_file={build.project_name}.bin
recipe.output.save_file={build.project_name}.{build.variant}.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