New compiler

This commit is contained in:
Federico Fissore 2015-08-31 16:05:23 +02:00
parent 81c7156edb
commit e5ddd0be3b
30 changed files with 1334 additions and 97 deletions

1
.gitignore vendored
View File

@ -14,6 +14,7 @@ hardware/arduino/bootloaders/caterina_LUFA/Caterina.elf
hardware/arduino/bootloaders/caterina_LUFA/Caterina.eep
hardware/arduino/bootloaders/caterina_LUFA/.dep/
build/*.zip
build/*.tar.bz2
build/windows/work/
build/windows/*.zip
build/windows/*.tgz

View File

@ -116,9 +116,9 @@ public class ConsoleOutputStream extends ByteArrayOutputStream {
if (document != null) {
SwingUtilities.invokeLater(() -> {
try {
String lineWithoutSlashR = line.replace("\r\n", "\n").replace("\r", "\n");
String lineWithoutCR = line.replace("\r\n", "\n").replace("\r", "\n");
int offset = document.getLength();
document.insertString(offset, lineWithoutSlashR, attributes);
document.insertString(offset, lineWithoutCR, attributes);
} catch (BadLocationException ble) {
//ignore
}

View File

@ -1,5 +1,3 @@
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
* This file is part of Arduino.
*

View File

@ -750,6 +750,10 @@ public class Editor extends JFrame implements RunnerListener {
item = newJMenuItemAlt(tr("Export compiled Binary"), 'S');
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (new ShouldSaveReadOnly().test(sketch) && !handleSave(true)) {
System.out.println(tr("Export canceled, changes must first be saved."));
return;
}
handleRun(false, new ShouldSaveReadOnly(), Editor.this.presentAndSaveHandler, Editor.this.runAndSaveHandler);
}
});

View File

@ -23,11 +23,14 @@
package processing.app;
import cc.arduino.Compiler;
import cc.arduino.CompilerProgressListener;
import cc.arduino.UploaderUtils;
import cc.arduino.files.DeleteFilesOnShutdown;
import cc.arduino.packages.Uploader;
import processing.app.debug.Compiler;
import processing.app.debug.Compiler.ProgressListener;
import processing.app.debug.RunnerException;
import processing.app.forms.PasswordAuthorizationDialog;
import processing.app.helpers.FileUtils;
import processing.app.helpers.OSUtils;
import processing.app.helpers.PreferencesMapException;
import processing.app.packages.LibraryList;
@ -37,10 +40,14 @@ import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static processing.app.I18n.tr;
@ -60,7 +67,7 @@ public class Sketch {
private int currentIndex;
private final SketchData data;
/**
* path is location of the main .pde file, because this is also
* simplest to use when opening the file from the finder/explorer.
@ -1093,7 +1100,7 @@ public class Sketch {
* @return null if compilation failed, main class name if not
* @throws RunnerException
*/
public String build(boolean verbose, boolean save) throws RunnerException, PreferencesMapException {
public String build(boolean verbose, boolean save) throws RunnerException, PreferencesMapException, IOException {
return build(tempBuildFolder.getAbsolutePath(), verbose, save);
}
@ -1106,15 +1113,32 @@ public class Sketch {
*
* @return null if compilation failed, main class name if not
*/
private String build(String buildPath, boolean verbose, boolean save) throws RunnerException, PreferencesMapException {
private String build(String buildPath, boolean verbose, boolean save) throws RunnerException, PreferencesMapException, IOException {
// run the preprocessor
editor.status.progressUpdate(20);
ensureExistence();
ProgressListener pl = editor.status::progressUpdate;
return Compiler.build(data, buildPath, tempBuildFolder, pl, verbose, save);
CompilerProgressListener progressListener = editor.status::progressUpdate;
String pathToSketch = data.getMainFilePath();
if (isModified()) {
pathToSketch = saveSketchInTempFolder();
}
return new Compiler(pathToSketch, data, buildPath).build(progressListener, save);
}
private String saveSketchInTempFolder() throws IOException {
File tempFolder = FileUtils.createTempFolder();
DeleteFilesOnShutdown.add(tempFolder);
FileUtils.copy(getFolder(), tempFolder);
for (SketchCode sc : Stream.of(data.getCodes()).filter(SketchCode::isModified).collect(Collectors.toList())) {
Files.write(Paths.get(tempFolder.getAbsolutePath(), sc.getFileName()), sc.getProgram().getBytes());
}
return Paths.get(tempFolder.getAbsolutePath(), data.getPrimaryFile().getName()).toString();
}
protected boolean exportApplet(boolean usingProgrammer) throws Exception {
@ -1153,7 +1177,7 @@ public class Sketch {
private boolean upload(String buildPath, String suggestedClassName, boolean usingProgrammer) throws Exception {
Uploader uploader = Compiler.getUploaderByPreferences(false);
Uploader uploader = new UploaderUtils().getUploaderByPreferences(false);
boolean success = false;
do {
@ -1172,7 +1196,7 @@ public class Sketch {
List<String> warningsAccumulator = new LinkedList<>();
try {
success = Compiler.upload(data, uploader, buildPath, suggestedClassName, usingProgrammer, false, warningsAccumulator);
success = new UploaderUtils().upload(data, uploader, buildPath, suggestedClassName, usingProgrammer, false, warningsAccumulator);
} finally {
if (uploader.requiresAuthorization() && !success) {
PreferencesData.remove(uploader.getAuthorizationKey());

View File

@ -1,62 +0,0 @@
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
Part of the Processing project - http://processing.org
Copyright (c) 2004-08 Ben Fry and Casey Reas
Copyright (c) 2001-04 Massachusetts Institute of Technology
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package processing.app.debug;
import java.io.*;
/**
* OutputStream to handle stdout/stderr messages.
* <P>
* This is used by Editor, System.err is set to
* new PrintStream(new MessageStream()).
* It's also used by Compiler.
*/
class MessageStream extends OutputStream {
MessageConsumer messageConsumer;
public MessageStream(MessageConsumer messageConsumer) {
this.messageConsumer = messageConsumer;
}
public void close() { }
public void flush() { }
public void write(byte b[]) {
// this never seems to get called
System.out.println("leech1: " + new String(b));
}
public void write(byte b[], int offset, int length) {
//System.out.println("leech2: " + new String(b));
this.messageConsumer.message(new String(b, offset, length));
}
public void write(int b) {
// this never seems to get called
System.out.println("leech3: '" + ((char)b) + "'");
}
}

View File

@ -0,0 +1,95 @@
/*
* This file is part of Arduino.
*
* Copyright 2015 Arduino LLC (http://www.arduino.cc/)
*
* Arduino is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* As a special exception, you may use this file as part of a free software
* library without restriction. Specifically, if other files instantiate
* templates or use macros or inline functions from this file, or you compile
* this file and link it with other files to produce an executable, this
* file does not by itself cause the resulting executable to be covered by
* the GNU General Public License. This exception does not however
* invalidate any other reasons why the executable file might be covered by
* the GNU General Public License.
*/
package cc.arduino.i18n;
import org.junit.Test;
import java.util.Map;
import static org.junit.Assert.assertEquals;
public class ExternalProcessOutputParserTest {
@Test
public void testParser1() throws Exception {
Map<String, Object> output = new ExternalProcessOutputParser().parse("===WARNING: Category '{0}' in library {1} is not valid. Setting to '{2}' ||| [ Wire Uncategorized]");
assertEquals("WARNING: Category '{0}' in library {1} is not valid. Setting to '{2}'", output.get("msg"));
Object[] args = (Object[]) output.get("args");
assertEquals(3, args.length);
assertEquals("", args[0]);
assertEquals("Wire", args[1]);
assertEquals("Uncategorized", args[2]);
}
@Test
public void testParser2() throws Exception {
Map<String, Object> output = new ExternalProcessOutputParser().parse("===Using previously compiled file: {0} ||| [%2Ftmp%2Farduino-sketch-456612873D8321DA02916066CB8B2FE6%2Flibraries%2FBridge%2FBridge.cpp.o]");
assertEquals("Using previously compiled file: {0}", output.get("msg"));
Object[] args = (Object[]) output.get("args");
assertEquals(1, args.length);
assertEquals("/tmp/arduino-sketch-456612873D8321DA02916066CB8B2FE6/libraries/Bridge/Bridge.cpp.o", args[0]);
}
@Test
public void testParser3() throws Exception {
Map<String, Object> output = new ExternalProcessOutputParser().parse("===Using library {0} at version {1} in folder: {2} {3} {4} ||| [Stepper 1.1.1 %2Fhome%2Ffederico%2Fmateriale%2Fworks_Arduino%2FArduino%2Fbuild%2Flinux%2Fwork%2Flibraries%2FStepper ]");
assertEquals("Using library {0} at version {1} in folder: {2} {3} {4}", output.get("msg"));
Object[] args = (Object[]) output.get("args");
assertEquals(5, args.length);
assertEquals("Stepper", args[0]);
assertEquals("1.1.1", args[1]);
assertEquals("/home/federico/materiale/works_Arduino/Arduino/build/linux/work/libraries/Stepper", args[2]);
assertEquals("", args[3]);
assertEquals("", args[4]);
}
@Test
public void testParser4() throws Exception {
Map<String, Object> output = new ExternalProcessOutputParser().parse("==={0} ||| []");
assertEquals("{0}", output.get("msg"));
Object[] args = (Object[]) output.get("args");
assertEquals(0, args.length);
}
@Test
public void testParser5() throws Exception {
Map<String, Object> output = new ExternalProcessOutputParser().parse("==={0} ||| [ ]");
assertEquals("{0}", output.get("msg"));
Object[] args = (Object[]) output.get("args");
assertEquals(1, args.length);
assertEquals("", args[0]);
}
}

View File

@ -0,0 +1,56 @@
/*
* This file is part of Arduino.
*
* Copyright 2015 Arduino LLC (http://www.arduino.cc/)
*
* Arduino is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* As a special exception, you may use this file as part of a free software
* library without restriction. Specifically, if other files instantiate
* templates or use macros or inline functions from this file, or you compile
* this file and link it with other files to produce an executable, this
* file does not by itself cause the resulting executable to be covered by
* the GNU General Public License. This exception does not however
* invalidate any other reasons why the executable file might be covered by
* the GNU General Public License.
*/
package cc.arduino.i18n;
import org.junit.Test;
import processing.app.AbstractWithPreferencesTest;
import processing.app.I18n;
import java.util.Map;
import static org.junit.Assert.assertEquals;
public class I18NTest extends AbstractWithPreferencesTest {
@Test
public void testMessageFormat() throws Exception {
Object[] args = new Object[]{"a", "b", "c"};
String actual = I18n.format("WARNING: Category '{0}' in library {1} is not valid. Setting to '{2}'", args);
assertEquals("WARNING: Category 'a' in library b is not valid. Setting to 'c'", actual);
}
@Test
public void testMessageFormatFromExternalProcess() throws Exception {
Map<String, Object> output = new ExternalProcessOutputParser().parse("===WARNING: Category '{0}' in library {1} is not valid. Setting to '{2}' ||| [ Wire Uncategorized]");
String actual = I18n.format((String) output.get("msg"), (Object[])output.get("args"));
assertEquals("WARNING: Category '' in library Wire is not valid. Setting to 'Uncategorized'", actual);
}
}

View File

@ -30,13 +30,13 @@
package processing.app.debug;
import static org.junit.Assert.assertEquals;
import static processing.app.debug.Compiler.unescapeDepFile;
import static processing.app.debug.OldCompiler.unescapeDepFile;
import org.junit.Test;
import processing.app.AbstractWithPreferencesTest;
public class CompilerTest extends AbstractWithPreferencesTest {
public class OldCompilerTest extends AbstractWithPreferencesTest {
@Test
public void makeDepUnescapeTest() throws Exception {

View File

@ -0,0 +1,584 @@
/*
* This file is part of Arduino.
*
* Copyright 2015 Arduino LLC (http://www.arduino.cc/)
*
* Arduino is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* As a special exception, you may use this file as part of a free software
* library without restriction. Specifically, if other files instantiate
* templates or use macros or inline functions from this file, or you compile
* this file and link it with other files to produce an executable, this
* file does not by itself cause the resulting executable to be covered by
* the GNU General Public License. This exception does not however
* invalidate any other reasons why the executable file might be covered by
* the GNU General Public License.
*/
package cc.arduino;
import cc.arduino.i18n.I18NAwareMessageConsumer;
import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecutor;
import org.apache.commons.exec.PumpStreamHandler;
import processing.app.*;
import processing.app.debug.*;
import processing.app.helpers.PreferencesMap;
import processing.app.helpers.PreferencesMapException;
import processing.app.helpers.StringReplacer;
import processing.app.legacy.PApplet;
import processing.app.tools.DoubleQuotedArgumentsOnWindowsCommandLine;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static processing.app.I18n.tr;
public class Compiler implements MessageConsumer {
//used by transifex integration
static {
tr("'arch' folder is no longer supported! See http://goo.gl/gfFJzU for more information");
tr("Board {0} (platform {1}, package {2}) is unknown");
tr("Bootloader file specified but missing: {0}");
tr("Build options changed, rebuilding all");
tr("Unable to find {0} in {1}");
tr("Invalid quoting: no closing [{0}] char found.");
tr("(legacy)");
tr("Multiple libraries were found for \"{0}\"");
tr(" Not used: {0}");
tr(" Used: {0}");
tr("Library can't use both 'src' and 'utility' folders.");
tr("WARNING: library {0} claims to run on {1} architecture(s) and may be incompatible with your current board which runs on {2} architecture(s).");
tr("Looking for recipes like {0}*{1}");
tr("Board {0}:{1}:{2} doesn''t define a ''build.board'' preference. Auto-set to: {3}");
tr("Third-party platform.txt does not define compiler.path. Please report this to the third-party hardware maintainer.");
tr("Selected board depends on '{0}' core (not installed).");
tr("{0} must be a folder");
tr("{0}: Unknown package");
tr("{0} pattern is missing");
tr("Platform {0} (package {1}) is unknown");
tr("Progress {0}");
tr("Missing '{0}' from library in {1}");
tr("Running: {0}");
tr("Running recipe: {0}");
tr("Setting build path to {0}");
tr("Unhandled type {0} in context {1} key");
tr("Unknown sketch file extension: {0}");
tr("Using library {0} at version {1} in folder: {2} {3}");
tr("Using library {0} in folder: {1} {2}");
tr("Using previously compiled file: {0}");
tr("WARNING: Category '{0}' in library {1} is not valid. Setting to '{2}'");
tr("Warning: platform.txt from core '{0}' misses property '{1}', using default value '{2}'. Consider upgrading this core.");
tr("Warning: platform.txt from core '{0}' contains deprecated {1}, automatically converted to {2}. Consider upgrading this core.");
tr("WARNING: Spurious {0} folder in '{1}' library");
}
enum BuilderAction {
COMPILE("-compile"), DUMP_PREFS("-dump-prefs");
private final String value;
BuilderAction(String value) {
this.value = value;
}
}
private final String pathToSketch;
private final SketchData sketch;
private final String buildPath;
private boolean verbose;
private RunnerException exception;
public Compiler(SketchData data, String buildPath) {
this(data.getMainFilePath(), data, buildPath);
}
public Compiler(String pathToSketch, SketchData sketch, String buildPath) {
this.pathToSketch = pathToSketch;
this.sketch = sketch;
this.buildPath = buildPath;
this.verbose = PreferencesData.getBoolean("build.verbose");
}
public String build(CompilerProgressListener progListener, boolean exportHex) throws RunnerException, PreferencesMapException, IOException {
TargetBoard board = BaseNoGui.getTargetBoard();
if (board == null) {
throw new RunnerException("Board is not selected");
}
TargetPlatform platform = board.getContainerPlatform();
TargetPackage aPackage = platform.getContainerPackage();
PreferencesMap prefs = loadPreferences(board, platform, aPackage);
MessageConsumerOutputStream out = new MessageConsumerOutputStream(new ProgressAwareMessageConsumer(new I18NAwareMessageConsumer(System.out), progListener), "\n");
MessageConsumerOutputStream err = new MessageConsumerOutputStream(new I18NAwareMessageConsumer(System.err, Compiler.this), "\n");
callArduinoBuilder(board, platform, aPackage, BuilderAction.COMPILE, new PumpStreamHandler(out, err));
out.flush();
err.flush();
if (exportHex) {
runActions("hooks.savehex.presavehex", prefs);
saveHex(prefs);
runActions("hooks.savehex.postsavehex", prefs);
}
size(prefs);
return sketch.getName() + ".ino";
}
private PreferencesMap loadPreferences(TargetBoard board, TargetPlatform platform, TargetPackage aPackage) throws RunnerException, IOException {
ByteArrayOutputStream stdout = new ByteArrayOutputStream();
ByteArrayOutputStream stderr = new ByteArrayOutputStream();
MessageConsumerOutputStream err = new MessageConsumerOutputStream(new I18NAwareMessageConsumer(new PrintStream(stderr), Compiler.this), "\n");
try {
callArduinoBuilder(board, platform, aPackage, BuilderAction.DUMP_PREFS, new PumpStreamHandler(stdout, err));
} catch (RunnerException e) {
System.err.println(new String(stderr.toByteArray()));
throw e;
}
PreferencesMap prefs = new PreferencesMap();
prefs.load(new ByteArrayInputStream(stdout.toByteArray()));
return prefs;
}
private void callArduinoBuilder(TargetBoard board, TargetPlatform platform, TargetPackage aPackage, BuilderAction action, PumpStreamHandler streamHandler) throws RunnerException {
File executable = BaseNoGui.getContentFile("arduino-builder");
CommandLine commandLine = new CommandLine(executable);
commandLine.addArgument(action.value, false);
commandLine.addArgument("-logger=machine", false);
Stream.of(BaseNoGui.getHardwarePath(), new File(BaseNoGui.getSettingsFolder(), "packages").getAbsolutePath(), BaseNoGui.getSketchbookHardwareFolder().getAbsolutePath())
.forEach(p -> {
if (Files.exists(Paths.get(p))) {
commandLine.addArgument("-hardware=\"" + p + "\"", false);
}
});
Stream.of(BaseNoGui.getContentFile("tools-builder").getAbsolutePath(), Paths.get(BaseNoGui.getHardwarePath(), "tools", "avr").toAbsolutePath().toString(), new File(BaseNoGui.getSettingsFolder(), "packages").getAbsolutePath())
.forEach(p -> {
if (Files.exists(Paths.get(p))) {
commandLine.addArgument("-tools=\"" + p + "\"", false);
}
});
commandLine.addArgument("-libraries=\"" + BaseNoGui.getSketchbookLibrariesFolder().getAbsolutePath() + "\"", false);
commandLine.addArgument("-libraries=\"" + BaseNoGui.getContentFile("libraries").getAbsolutePath() + "\"", false);
String fqbn = Stream.of(aPackage.getId(), platform.getId(), board.getId(), boardOptions(board)).filter(s -> !s.isEmpty()).collect(Collectors.joining(":"));
commandLine.addArgument("-fqbn=" + fqbn, false);
commandLine.addArgument("-ide-version=" + BaseNoGui.REVISION, false);
commandLine.addArgument("-build-path=\"" + buildPath + "\"", false);
commandLine.addArgument("-warnings=" + PreferencesData.get("compiler.warning_level"), false);
PreferencesData.getMap()
.subTree("build_properties_custom")
.entrySet()
.stream()
.forEach(kv -> commandLine.addArgument("-prefs=\"" + kv.getKey() + "=" + kv.getValue() + "\"", false));
commandLine.addArgument("-prefs=build.warn_data_percentage=" + PreferencesData.get("build.warn_data_percentage"));
//commandLine.addArgument("-debug-level=10", false);
if (verbose) {
commandLine.addArgument("-verbose", false);
}
commandLine.addArgument("\"" + pathToSketch + "\"", false);
if (verbose) {
System.out.println(commandLine);
}
DefaultExecutor executor = new DefaultExecutor();
executor.setStreamHandler(streamHandler);
int result;
executor.setExitValues(null);
try {
result = executor.execute(commandLine);
} catch (IOException e) {
RunnerException re = new RunnerException(e.getMessage());
re.hideStackTrace();
throw re;
}
executor.setExitValues(new int[0]);
if (exception != null)
throw exception;
if (result > 1) {
System.err.println(I18n.format(tr("{0} returned {1}"), executable.getName(), result));
}
if (result != 0) {
RunnerException re = new RunnerException(tr("Error compiling."));
re.hideStackTrace();
throw re;
}
}
protected void size(PreferencesMap prefs) throws RunnerException {
String maxTextSizeString = prefs.get("upload.maximum_size");
String maxDataSizeString = prefs.get("upload.maximum_data_size");
if (maxTextSizeString == null) {
return;
}
long maxTextSize = Integer.parseInt(maxTextSizeString);
long maxDataSize = -1;
if (maxDataSizeString != null) {
maxDataSize = Integer.parseInt(maxDataSizeString);
}
Sizer sizer = new Sizer(prefs);
long[] sizes;
try {
sizes = sizer.computeSize();
} catch (RunnerException e) {
System.err.println(I18n.format(tr("Couldn't determine program size: {0}"), e.getMessage()));
return;
}
long textSize = sizes[0];
long dataSize = sizes[1];
System.out.println();
System.out.println(I18n.format(tr("Sketch uses {0} bytes ({2}%%) of program storage space. Maximum is {1} bytes."), textSize, maxTextSize, textSize * 100 / maxTextSize));
if (dataSize >= 0) {
if (maxDataSize > 0) {
System.out.println(I18n.format(tr("Global variables use {0} bytes ({2}%%) of dynamic memory, leaving {3} bytes for local variables. Maximum is {1} bytes."), dataSize, maxDataSize, dataSize * 100 / maxDataSize, maxDataSize - dataSize));
} else {
System.out.println(I18n.format(tr("Global variables use {0} bytes of dynamic memory."), dataSize));
}
}
if (textSize > maxTextSize) {
throw new RunnerException(tr("Sketch too big; see http://www.arduino.cc/en/Guide/Troubleshooting#size for tips on reducing it."));
}
if (maxDataSize > 0 && dataSize > maxDataSize) {
throw new RunnerException(tr("Not enough memory; see http://www.arduino.cc/en/Guide/Troubleshooting#size for tips on reducing your footprint."));
}
int warnDataPercentage = Integer.parseInt(prefs.get("build.warn_data_percentage"));
if (maxDataSize > 0 && dataSize > maxDataSize * warnDataPercentage / 100) {
System.err.println(tr("Low memory available, stability problems may occur."));
}
}
void saveHex(PreferencesMap prefs) throws RunnerException {
List<String> compiledSketches = new ArrayList<>(prefs.subTree("recipe.output.tmp_file", 1).values());
List<String> copyOfCompiledSketches = new ArrayList<>(prefs.subTree("recipe.output.save_file", 1).values());
if (isExportCompiledSketchSupported(compiledSketches, copyOfCompiledSketches, prefs)) {
System.err.println(tr("Warning: This core does not support exporting sketches. Please consider upgrading it or contacting its author"));
return;
}
PreferencesMap dict = new PreferencesMap(prefs);
dict.put("ide_version", "" + BaseNoGui.REVISION);
PreferencesMap withBootloaderDict = new PreferencesMap(dict);
dict.put("build.project_name", dict.get("build.project_name") + ".with_bootloader");
if (!compiledSketches.isEmpty()) {
for (int i = 0; i < compiledSketches.size(); i++) {
saveHex(compiledSketches.get(i), copyOfCompiledSketches.get(i), dict);
saveHex(compiledSketches.get(i), copyOfCompiledSketches.get(i), withBootloaderDict);
}
} else {
try {
saveHex(prefs.getOrExcept("recipe.output.tmp_file"), prefs.getOrExcept("recipe.output.save_file"), dict);
saveHex(prefs.getOrExcept("recipe.output.tmp_file"), prefs.getOrExcept("recipe.output.save_file"), withBootloaderDict);
} catch (PreferencesMapException e) {
throw new RunnerException(e);
}
}
}
private void saveHex(String compiledSketch, String copyOfCompiledSketch, PreferencesMap prefs) throws RunnerException {
try {
compiledSketch = StringReplacer.replaceFromMapping(compiledSketch, prefs);
copyOfCompiledSketch = StringReplacer.replaceFromMapping(copyOfCompiledSketch, prefs);
Path compiledSketchPath;
Path compiledSketchPathInSubfolder = Paths.get(prefs.get("build.path"), "sketch", compiledSketch);
Path compiledSketchPathInBuildPath = Paths.get(prefs.get("build.path"), compiledSketch);
if (Files.exists(compiledSketchPathInSubfolder)) {
compiledSketchPath = compiledSketchPathInSubfolder;
} else {
compiledSketchPath = compiledSketchPathInBuildPath;
}
Path copyOfCompiledSketchFilePath = Paths.get(this.sketch.getFolder().getAbsolutePath(), copyOfCompiledSketch);
Files.copy(compiledSketchPath, copyOfCompiledSketchFilePath, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
throw new RunnerException(e);
}
}
private boolean isExportCompiledSketchSupported(List<String> compiledSketches, List<String> copyOfCompiledSketches, PreferencesMap prefs) {
return (compiledSketches.isEmpty() || copyOfCompiledSketches.isEmpty() || copyOfCompiledSketches.size() < compiledSketches.size()) && (!prefs.containsKey("recipe.output.tmp_file") || !prefs.containsKey("recipe.output.save_file"));
}
void runActions(String recipeClass, PreferencesMap prefs) throws RunnerException, PreferencesMapException {
List<String> patterns = new ArrayList<>();
for (String key : prefs.keySet()) {
if (key.startsWith("recipe." + recipeClass) && key.endsWith(".pattern"))
patterns.add(key);
}
Collections.sort(patterns);
for (String recipe : patterns) {
runRecipe(recipe, prefs);
}
}
void runRecipe(String recipe, PreferencesMap prefs) throws RunnerException, PreferencesMapException {
PreferencesMap dict = new PreferencesMap(prefs);
dict.put("ide_version", "" + BaseNoGui.REVISION);
dict.put("sketch_path", sketch.getFolder().getAbsolutePath());
String[] cmdArray;
String cmd = prefs.getOrExcept(recipe);
try {
cmdArray = StringReplacer.formatAndSplit(cmd, dict, true);
} catch (Exception e) {
throw new RunnerException(e);
}
exec(cmdArray);
}
private void exec(String[] command) throws RunnerException {
// eliminate any empty array entries
List<String> stringList = new ArrayList<String>();
for (String string : command) {
string = string.trim();
if (string.length() != 0)
stringList.add(string);
}
command = stringList.toArray(new String[stringList.size()]);
if (command.length == 0)
return;
if (verbose) {
for (String c : command)
System.out.print(c + " ");
System.out.println();
}
DefaultExecutor executor = new DefaultExecutor();
executor.setStreamHandler(new PumpStreamHandler() {
@Override
protected Thread createPump(InputStream is, OutputStream os, boolean closeWhenExhausted) {
final Thread result = new Thread(new MyStreamPumper(is, Compiler.this));
result.setDaemon(true);
return result;
}
});
CommandLine commandLine = new DoubleQuotedArgumentsOnWindowsCommandLine(command[0]);
for (int i = 1; i < command.length; i++) {
commandLine.addArgument(command[i], false);
}
int result;
executor.setExitValues(null);
try {
result = executor.execute(commandLine);
} catch (IOException e) {
RunnerException re = new RunnerException(e.getMessage());
re.hideStackTrace();
throw re;
}
executor.setExitValues(new int[0]);
// an error was queued up by message(), barf this back to compile(),
// which will barf it back to Editor. if you're having trouble
// discerning the imagery, consider how cows regurgitate their food
// to digest it, and the fact that they have five stomaches.
//
//System.out.println("throwing up " + exception);
if (exception != null)
throw exception;
if (result > 1) {
// a failure in the tool (e.g. unable to locate a sub-executable)
System.err
.println(I18n.format(tr("{0} returned {1}"), command[0], result));
}
if (result != 0) {
RunnerException re = new RunnerException(tr("Error compiling."));
re.hideStackTrace();
throw re;
}
}
private String boardOptions(TargetBoard board) {
return board.getMenuIds().stream()
.filter(board::hasMenu)
.filter(menuId -> {
String entry = PreferencesData.get("custom_" + menuId);
return entry != null && entry.startsWith(board.getId());
})
.map(menuId -> {
String entry = PreferencesData.get("custom_" + menuId);
String selectionId = entry.substring(board.getId().length() + 1);
return menuId + "=" + selectionId;
})
.collect(Collectors.joining(","));
}
/**
* Part of the MessageConsumer interface, this is called
* whenever a piece (usually a line) of error message is spewed
* out from the compiler. The errors are parsed for their contents
* and line number, which is then reported back to Editor.
*/
public void message(String s) {
int i;
if (!verbose) {
while ((i = s.indexOf(buildPath + File.separator)) != -1) {
s = s.substring(0, i) + s.substring(i + (buildPath + File.separator).length());
}
}
String errorFormat = "(.+\\.\\w+):(\\d+)(:\\d+)*:\\s*error:\\s*(.*)\\s*";
String[] pieces = PApplet.match(s, errorFormat);
if (pieces != null) {
String error = pieces[pieces.length - 1], msg = "";
if (error.trim().equals("SPI.h: No such file or directory")) {
error = tr("Please import the SPI library from the Sketch > Import Library menu.");
msg = tr("\nAs of Arduino 0019, the Ethernet library depends on the SPI library." +
"\nYou appear to be using it or another library that depends on the SPI library.\n\n");
}
if (error.trim().equals("'BYTE' was not declared in this scope")) {
error = tr("The 'BYTE' keyword is no longer supported.");
msg = tr("\nAs of Arduino 1.0, the 'BYTE' keyword is no longer supported." +
"\nPlease use Serial.write() instead.\n\n");
}
if (error.trim().equals("no matching function for call to 'Server::Server(int)'")) {
error = tr("The Server class has been renamed EthernetServer.");
msg = tr("\nAs of Arduino 1.0, the Server class in the Ethernet library " +
"has been renamed to EthernetServer.\n\n");
}
if (error.trim().equals("no matching function for call to 'Client::Client(byte [4], int)'")) {
error = tr("The Client class has been renamed EthernetClient.");
msg = tr("\nAs of Arduino 1.0, the Client class in the Ethernet library " +
"has been renamed to EthernetClient.\n\n");
}
if (error.trim().equals("'Udp' was not declared in this scope")) {
error = tr("The Udp class has been renamed EthernetUdp.");
msg = tr("\nAs of Arduino 1.0, the Udp class in the Ethernet library " +
"has been renamed to EthernetUdp.\n\n");
}
if (error.trim().equals("'class TwoWire' has no member named 'send'")) {
error = tr("Wire.send() has been renamed Wire.write().");
msg = tr("\nAs of Arduino 1.0, the Wire.send() function was renamed " +
"to Wire.write() for consistency with other libraries.\n\n");
}
if (error.trim().equals("'class TwoWire' has no member named 'receive'")) {
error = tr("Wire.receive() has been renamed Wire.read().");
msg = tr("\nAs of Arduino 1.0, the Wire.receive() function was renamed " +
"to Wire.read() for consistency with other libraries.\n\n");
}
if (error.trim().equals("'Mouse' was not declared in this scope")) {
error = tr("'Mouse' only supported on the Arduino Leonardo");
//msg = _("\nThe 'Mouse' class is only supported on the Arduino Leonardo.\n\n");
}
if (error.trim().equals("'Keyboard' was not declared in this scope")) {
error = tr("'Keyboard' only supported on the Arduino Leonardo");
//msg = _("\nThe 'Keyboard' class is only supported on the Arduino Leonardo.\n\n");
}
RunnerException exception = placeException(error, pieces[1], PApplet.parseInt(pieces[2]) - 1);
// replace full file path with the name of the sketch tab (unless we're
// in verbose mode, in which case don't modify the compiler output)
if (exception != null && !verbose) {
SketchCode code = sketch.getCode(exception.getCodeIndex());
String fileName = (code.isExtension("ino") || code.isExtension("pde")) ? code.getPrettyName() : code.getFileName();
int lineNum = exception.getCodeLine() + 1;
s = fileName + ":" + lineNum + ": error: " + error + msg;
}
if (exception != null) {
if (this.exception == null || this.exception.getMessage().equals(exception.getMessage())) {
this.exception = exception;
this.exception.hideStackTrace();
}
}
}
if (s.contains("undefined reference to `SPIClass::begin()'") &&
s.contains("libraries/Robot_Control")) {
String error = tr("Please import the SPI library from the Sketch > Import Library menu.");
exception = new RunnerException(error);
}
if (s.contains("undefined reference to `Wire'") &&
s.contains("libraries/Robot_Control")) {
String error = tr("Please import the Wire library from the Sketch > Import Library menu.");
exception = new RunnerException(error);
}
System.err.println(s);
}
public RunnerException placeException(String message,
String dotJavaFilename,
int dotJavaLine) {
// Placing errors is simple, because we inserted #line directives
// into the preprocessed source. The compiler gives us correct
// the file name and line number. :-)
for (SketchCode code : sketch.getCodes()) {
if (dotJavaFilename.equals(code.getFileName())) {
return new RunnerException(message, sketch.indexOfCode(code), dotJavaLine);
}
}
return null;
}
}

View File

@ -0,0 +1,36 @@
/*
* This file is part of Arduino.
*
* Copyright 2015 Arduino LLC (http://www.arduino.cc/)
*
* Arduino is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* As a special exception, you may use this file as part of a free software
* library without restriction. Specifically, if other files instantiate
* templates or use macros or inline functions from this file, or you compile
* this file and link it with other files to produce an executable, this
* file does not by itself cause the resulting executable to be covered by
* the GNU General Public License. This exception does not however
* invalidate any other reasons why the executable file might be covered by
* the GNU General Public License.
*/
package cc.arduino;
public interface CompilerProgressListener {
void progress(int value);
}

View File

@ -0,0 +1,62 @@
/*
* This file is part of Arduino.
*
* Arduino is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* As a special exception, you may use this file as part of a free software
* library without restriction. Specifically, if other files instantiate
* templates or use macros or inline functions from this file, or you compile
* this file and link it with other files to produce an executable, this
* file does not by itself cause the resulting executable to be covered by
* the GNU General Public License. This exception does not however
* invalidate any other reasons why the executable file might be covered by
* the GNU General Public License.
*
* Copyright 2015 Arduino LLC (http://www.arduino.cc/)
*/
package cc.arduino;
import processing.app.helpers.PreferencesMap;
import processing.app.helpers.PreferencesMapException;
import processing.app.helpers.StringReplacer;
import java.io.File;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import static processing.app.I18n.tr;
public class CompilerUtils {
public File findCompiledSketch(PreferencesMap prefs) throws PreferencesMapException {
List<String> paths = Arrays.asList(
"{build.path}/sketch/{build.project_name}.with_bootloader.hex",
"{build.path}/sketch/{build.project_name}.hex",
"{build.path}/{build.project_name}.with_bootloader.hex",
"{build.path}/{build.project_name}.hex",
"{build.path}/sketch/{build.project_name}.bin",
"{build.path}/{build.project_name}.bin"
);
Optional<File> sketch = paths.stream().
map(path -> StringReplacer.replaceFromMapping(path, prefs)).
map(File::new).
filter(File::exists).
findFirst();
return sketch.orElseThrow(() -> new IllegalStateException(tr("No compiled sketch found")));
}
}

View File

@ -0,0 +1,46 @@
package cc.arduino;
import processing.app.debug.MessageConsumer;
import java.io.ByteArrayOutputStream;
public class MessageConsumerOutputStream extends ByteArrayOutputStream {
private final MessageConsumer consumer;
private final String lineSeparator;
public MessageConsumerOutputStream(MessageConsumer consumer) {
this(consumer, System.getProperty("line.separator"));
}
public MessageConsumerOutputStream(MessageConsumer consumer, String lineSeparator) {
this.consumer = consumer;
this.lineSeparator = lineSeparator;
}
@Override
public void write(byte[] b, int off, int len) {
super.write(b, off, len);
flush();
}
@Override
public void flush() {
String asString = toString();
if (!asString.contains(lineSeparator)) {
return;
}
while (asString.contains(lineSeparator)) {
String line = asString.substring(0, asString.indexOf(lineSeparator));
reset();
byte[] bytes = asString.substring(asString.indexOf(lineSeparator) + lineSeparator.length()).getBytes();
super.write(bytes, 0, bytes.length);
asString = toString();
consumer.message(line);
}
}
}

View File

@ -73,7 +73,7 @@ public class MyStreamPumper implements Runnable {
try {
String line;
while ((line = reader.readLine()) != null) {
messageConsumer.message(line + "\n");
messageConsumer.message(line);
}
} catch (Exception e) {
// nothing to do - happens quite often with watchdog

View File

@ -0,0 +1,62 @@
/*
* This file is part of Arduino.
*
* Copyright 2015 Arduino LLC (http://www.arduino.cc/)
*
* Arduino is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* As a special exception, you may use this file as part of a free software
* library without restriction. Specifically, if other files instantiate
* templates or use macros or inline functions from this file, or you compile
* this file and link it with other files to produce an executable, this
* file does not by itself cause the resulting executable to be covered by
* the GNU General Public License. This exception does not however
* invalidate any other reasons why the executable file might be covered by
* the GNU General Public License.
*/
package cc.arduino;
import cc.arduino.i18n.ExternalProcessOutputParser;
import processing.app.debug.MessageConsumer;
import java.util.Map;
public class ProgressAwareMessageConsumer implements MessageConsumer {
private final MessageConsumer parent;
private final CompilerProgressListener progressListener;
private final ExternalProcessOutputParser parser;
public ProgressAwareMessageConsumer(MessageConsumer parent, CompilerProgressListener progressListener) {
this.parent = parent;
this.progressListener = progressListener;
this.parser = new ExternalProcessOutputParser();
}
@Override
public void message(String s) {
if (s.startsWith("===Progress")) {
Map<String, Object> parsedMessage = parser.parse(s);
Object[] args = (Object[]) parsedMessage.get("args");
progressListener.progress(Double.valueOf(args[0].toString()).intValue());
return;
}
if (parent != null) {
parent.message(s);
}
}
}

View File

@ -0,0 +1,97 @@
/*
* This file is part of Arduino.
*
* Arduino is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* As a special exception, you may use this file as part of a free software
* library without restriction. Specifically, if other files instantiate
* templates or use macros or inline functions from this file, or you compile
* this file and link it with other files to produce an executable, this
* file does not by itself cause the resulting executable to be covered by
* the GNU General Public License. This exception does not however
* invalidate any other reasons why the executable file might be covered by
* the GNU General Public License.
*
* Copyright 2015 Arduino LLC (http://www.arduino.cc/)
*/
package cc.arduino;
import cc.arduino.packages.BoardPort;
import cc.arduino.packages.Uploader;
import cc.arduino.packages.UploaderFactory;
import processing.app.BaseNoGui;
import processing.app.PreferencesData;
import processing.app.SketchData;
import processing.app.debug.TargetPlatform;
import java.util.LinkedList;
import java.util.List;
import static processing.app.I18n.tr;
public class UploaderUtils {
public Uploader getUploaderByPreferences(boolean noUploadPort) {
TargetPlatform target = BaseNoGui.getTargetPlatform();
String board = PreferencesData.get("board");
BoardPort boardPort = null;
if (!noUploadPort) {
boardPort = BaseNoGui.getDiscoveryManager().find(PreferencesData.get("serial.port"));
}
return new UploaderFactory().newUploader(target.getBoards().get(board), boardPort, noUploadPort);
}
public boolean upload(SketchData data, Uploader uploader, String buildPath, String suggestedClassName, boolean usingProgrammer, boolean noUploadPort, List<String> warningsAccumulator) throws Exception {
if (uploader == null)
uploader = getUploaderByPreferences(noUploadPort);
boolean success = false;
if (uploader.requiresAuthorization() && !PreferencesData.has(uploader.getAuthorizationKey())) {
BaseNoGui.showError(tr("Authorization required"),
tr("No authorization data found"), null);
}
boolean useNewWarningsAccumulator = false;
if (warningsAccumulator == null) {
warningsAccumulator = new LinkedList<String>();
useNewWarningsAccumulator = true;
}
try {
success = uploader.uploadUsingPreferences(data.getFolder(), buildPath, suggestedClassName, usingProgrammer, warningsAccumulator);
} finally {
if (uploader.requiresAuthorization() && !success) {
PreferencesData.remove(uploader.getAuthorizationKey());
}
}
if (useNewWarningsAccumulator) {
for (String warning : warningsAccumulator) {
System.out.print(tr("Warning"));
System.out.print(": ");
System.out.println(warning);
}
}
return success;
}
}

View File

@ -0,0 +1,94 @@
/*
* This file is part of Arduino.
*
* Copyright 2015 Arduino LLC (http://www.arduino.cc/)
*
* Arduino is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* As a special exception, you may use this file as part of a free software
* library without restriction. Specifically, if other files instantiate
* templates or use macros or inline functions from this file, or you compile
* this file and link it with other files to produce an executable, this
* file does not by itself cause the resulting executable to be covered by
* the GNU General Public License. This exception does not however
* invalidate any other reasons why the executable file might be covered by
* the GNU General Public License.
*/
package cc.arduino.i18n;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.*;
import java.util.stream.Collectors;
public class ExternalProcessOutputParser {
public Map<String, Object> parse(String s) {
if (!s.startsWith("===")) {
throw new IllegalArgumentException(s);
}
s = s.substring(3);
Map<String, Object> output = new HashMap<>();
String[] parts = s.split(" \\|\\|\\| ");
output.put("msg", parts[0]);
output.put("args", parseArgs(parts[1]));
return output;
}
private Object[] parseArgs(String argsAsString) {
if (!argsAsString.startsWith("[") || !argsAsString.endsWith("]")) {
throw new IllegalArgumentException(argsAsString);
}
argsAsString = argsAsString.substring(1, argsAsString.length() - 1);
if (argsAsString.isEmpty()) {
return new Object[0];
}
List<String> args = new ArrayList<>(Arrays.asList(argsAsString.split(" ")));
List<String> additionalArgs = addAsManyEmptyArgsAsEndingSpaces(argsAsString, args);
for (int i = 0; i < args.size(); i++) {
try {
args.set(i, URLDecoder.decode(args.get(i), "UTF-8"));
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
args.addAll(additionalArgs);
return args.toArray();
}
private List<String> addAsManyEmptyArgsAsEndingSpaces(String argsAsString, List<String> args) {
List<String> additionalArgs = new LinkedList<>();
if (argsAsString.charAt(argsAsString.length() - 1) == ' ') {
String allArgsButEndingSpacesAsString = args.stream().collect(Collectors.joining(" "));
String endingSpacesOnly = argsAsString.replace(allArgsButEndingSpacesAsString, "");
for (int i = 0; i < endingSpacesOnly.length(); i++) {
additionalArgs.add("");
}
}
return additionalArgs;
}
}

View File

@ -0,0 +1,70 @@
/*
* This file is part of Arduino.
*
* Copyright 2015 Arduino LLC (http://www.arduino.cc/)
*
* Arduino is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* As a special exception, you may use this file as part of a free software
* library without restriction. Specifically, if other files instantiate
* templates or use macros or inline functions from this file, or you compile
* this file and link it with other files to produce an executable, this
* file does not by itself cause the resulting executable to be covered by
* the GNU General Public License. This exception does not however
* invalidate any other reasons why the executable file might be covered by
* the GNU General Public License.
*/
package cc.arduino.i18n;
import processing.app.I18n;
import processing.app.debug.MessageConsumer;
import java.io.PrintStream;
import java.util.Map;
import static processing.app.I18n.tr;
public class I18NAwareMessageConsumer implements MessageConsumer {
private final PrintStream ps;
private final MessageConsumer parent;
private final ExternalProcessOutputParser parser;
public I18NAwareMessageConsumer(PrintStream ps) {
this(ps, null);
}
public I18NAwareMessageConsumer(PrintStream ps, MessageConsumer parent) {
this.ps = ps;
this.parent = parent;
this.parser = new ExternalProcessOutputParser();
}
@Override
public void message(String s) {
if (s.startsWith("===")) {
Map<String, Object> parsedMessage = parser.parse(s);
ps.println(I18n.format(tr((String) parsedMessage.get("msg")), (Object[]) parsedMessage.get("args")));
return;
}
if (parent != null) {
parent.message(s);
} else {
ps.println(s);
}
}
}

View File

@ -1,5 +1,3 @@
/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
Uploader - abstract uploading baseclass (common to both uisp and avrdude)
Part of the Arduino project - http://www.arduino.cc/

View File

@ -29,6 +29,8 @@
package cc.arduino.packages.uploaders;
import cc.arduino.Compiler;
import cc.arduino.CompilerUtils;
import cc.arduino.packages.BoardPort;
import cc.arduino.packages.Uploader;
import cc.arduino.packages.ssh.*;
@ -117,7 +119,7 @@ public class SSHUploader extends Uploader {
if (!coreMissesRemoteUploadTool && mergedSketch.exists()) {
sketchToCopy = mergedSketch;
} else {
sketchToCopy = processing.app.debug.Compiler.findCompiledSketch(prefs);
sketchToCopy = new CompilerUtils().findCompiledSketch(prefs);
}
scpFiles(scp, ssh, sourcePath, sketchToCopy, warningsAccumulator);

View File

@ -1,5 +1,3 @@
/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
BasicUploader - generic command line uploader implementation
Part of the Arduino project - http://www.arduino.cc/

View File

@ -1,6 +1,8 @@
package processing.app;
import cc.arduino.Compiler;
import cc.arduino.Constants;
import cc.arduino.UploaderUtils;
import cc.arduino.contributions.GPGDetachedSignatureVerifier;
import cc.arduino.contributions.SignatureVerificationFailedException;
import cc.arduino.contributions.libraries.LibrariesIndexer;
@ -13,7 +15,6 @@ import com.fasterxml.jackson.core.JsonProcessingException;
import org.apache.commons.compress.utils.IOUtils;
import org.apache.commons.logging.impl.LogFactoryImpl;
import org.apache.commons.logging.impl.NoOpLog;
import processing.app.debug.Compiler;
import processing.app.debug.*;
import processing.app.helpers.*;
import processing.app.helpers.filefilters.OnlyDirs;
@ -504,16 +505,16 @@ public class BaseNoGui {
if (!data.getFolder().exists()) {
showError(tr("No sketch"), tr("Can't find the sketch in the specified path"), null);
}
String suggestedClassName = Compiler.build(data, tempBuildFolder.getAbsolutePath(), tempBuildFolder, null, parser.isDoVerboseBuild(), false);
String suggestedClassName = new Compiler(data, tempBuildFolder.getAbsolutePath()).build(null, false);
if (suggestedClassName == null) {
showError(tr("Error while verifying"), tr("An error occurred while verifying the sketch"), null);
}
showMessage(tr("Done compiling"), tr("Done compiling"));
Uploader uploader = Compiler.getUploaderByPreferences(parser.isNoUploadPort());
Uploader uploader = new UploaderUtils().getUploaderByPreferences(parser.isNoUploadPort());
if (uploader.requiresAuthorization() && !PreferencesData.has(uploader.getAuthorizationKey())) showError("...", "...", null);
try {
success = Compiler.upload(data, uploader, tempBuildFolder.getAbsolutePath(), suggestedClassName, parser.isDoUseProgrammer(), parser.isNoUploadPort(), warningsAccumulator);
success = new UploaderUtils().upload(data, uploader, tempBuildFolder.getAbsolutePath(), suggestedClassName, parser.isDoUseProgrammer(), parser.isNoUploadPort(), warningsAccumulator);
showMessage(tr("Done uploading"), tr("Done uploading"));
} finally {
if (uploader.requiresAuthorization() && !success) {
@ -550,7 +551,7 @@ public class BaseNoGui {
// if (!data.getFolder().exists()) showError(...);
// String ... = Compiler.build(data, tempBuildFolder.getAbsolutePath(), tempBuildFolder, null, verbose);
if (!data.getFolder().exists()) showError(tr("No sketch"), tr("Can't find the sketch in the specified path"), null);
String suggestedClassName = Compiler.build(data, tempBuildFolder.getAbsolutePath(), tempBuildFolder, null, parser.isDoVerboseBuild(), false);
String suggestedClassName = new Compiler(data, tempBuildFolder.getAbsolutePath()).build(null, false);
if (suggestedClassName == null) showError(tr("Error while verifying"), tr("An error occurred while verifying the sketch"), null);
showMessage(tr("Done compiling"), tr("Done compiling"));
} catch (Exception e) {

View File

@ -26,17 +26,17 @@ package processing.app.debug;
/**
* Interface for dealing with parser/compiler output.
* <P>
* <p>
* Different instances of MessageStream need to do different things with
* messages. In particular, a stream instance used for parsing output from
* the compiler compiler has to interpret its messages differently than one
* parsing output from the runtime.
* <P>
* <p>
* Classes which consume messages and do something with them
* should implement this interface.
*/
public interface MessageConsumer {
public void message(String s);
void message(String s);
}

View File

@ -61,7 +61,8 @@ import java.util.stream.Stream;
import static processing.app.I18n.tr;
public class Compiler implements MessageConsumer {
@Deprecated
public class OldCompiler implements MessageConsumer {
/**
* File inside the build directory that contains the build options
@ -96,7 +97,7 @@ public class Compiler implements MessageConsumer {
tr("Bad sketch primary file or bad sketch directory structure"), null);
String primaryClassName = data.getName() + ".cpp";
Compiler compiler = new Compiler(data, buildPath, primaryClassName);
OldCompiler compiler = new OldCompiler(data, buildPath, primaryClassName);
File buildPrefsFile = new File(buildPath, BUILD_PREFS_FILE);
String newBuildPrefs = compiler.buildPrefsString();
@ -208,7 +209,7 @@ public class Compiler implements MessageConsumer {
* @param _buildPath Where the temporary files live and will be built from.
* @param _primaryClassName the name of the combined sketch file w/ extension
*/
public Compiler(SketchData _sketch, String _buildPath, String _primaryClassName)
public OldCompiler(SketchData _sketch, String _buildPath, String _primaryClassName)
throws RunnerException {
sketch = _sketch;
prefs = createBuildPreferences(_buildPath, _primaryClassName);
@ -808,7 +809,7 @@ public class Compiler implements MessageConsumer {
@Override
protected Thread createPump(InputStream is, OutputStream os, boolean closeWhenExhausted) {
final Thread result = new Thread(new MyStreamPumper(is, Compiler.this));
final Thread result = new Thread(new MyStreamPumper(is, OldCompiler.this));
result.setDaemon(true);
return result;

View File

@ -277,6 +277,7 @@ public class CommandlineParser {
BaseNoGui.showError(null, I18n.format(tr("{0}: Invalid argument to --pref, should be of the form \"pref=value\""), arg), 3);
PreferencesData.set(split[0], split[1]);
PreferencesData.set("build_properties_custom." + split[0], split[1]);
}
public boolean isDoVerboseBuild() {

View File

@ -0,0 +1 @@
4b72651bf25dc056c430c9160e7c6a4aa9909214

View File

@ -0,0 +1 @@
68d07baf4cb12f270ca1fe6c669018695614a304

View File

@ -0,0 +1 @@
15c8230a431669e629e9cbb635df6d90731cf144

View File

@ -0,0 +1 @@
5979a9ea20c7b982433a1119875aa6518b859bb6

View File

@ -71,6 +71,8 @@
</or>
</condition>
<property name="ARDUINO-BUILDER-VERSION" value="1.0.0-beta3" />
<!-- Libraries required for running arduino -->
<fileset dir=".." id="runtime.jars">
<include name="arduino-core/arduino-core.jar" />
@ -372,6 +374,21 @@
<copy file="macosx/libastylej-2.05.1/libastylej.jnilib" tofile="macosx/work/${staging_hardware_folder}/../lib/libastylej.dylib" />
<chmod perm="755" file="macosx/work/${staging_hardware_folder}/../lib/libastylej.dylib" />
<mkdir dir="${staging_folder}/arduino-builder-macosx"/>
<antcall target="untar">
<param name="archive_file" value="./arduino-builder-macosx-${ARDUINO-BUILDER-VERSION}.tar.bz2" />
<param name="archive_url" value="http://downloads.arduino.cc/tools/arduino-builder-macosx-${ARDUINO-BUILDER-VERSION}.tar.bz2" />
<param name="final_folder" value="${staging_folder}/arduino-builder-macosx/arduino-builder" />
<param name="dest_folder" value="${staging_folder}/arduino-builder-macosx" />
</antcall>
<copy file="${staging_folder}/arduino-builder-macosx/arduino-builder" tofile="macosx/work/${staging_hardware_folder}/../arduino-builder" />
<chmod perm="755" file="macosx/work/${staging_hardware_folder}/../arduino-builder" />
<move file="${staging_folder}/arduino-builder-macosx/tools" tofile="macosx/work/${staging_hardware_folder}/../tools-builder"/>
<copy todir="macosx/work/${staging_hardware_folder}" overwrite="true">
<fileset dir="${staging_folder}/arduino-builder-macosx/hardware" includes="*.txt"/>
</copy>
<delete dir="${staging_folder}/arduino-builder-macosx" includeemptydirs="true"/>
</target>
<!-- Unzip AVR tools -->
@ -483,6 +500,9 @@
<delete>
<fileset dir="linux" includes="arduino-*linux*.tar.xz"/>
</delete>
<delete>
<fileset dir="linux" includes="arduino-*linux*.tar.xz"/>
</delete>
</target>
<target name="linux-checkos" unless="linux">
@ -541,6 +561,21 @@
<param name="JVM" value="${LINUX32_BUNDLED_JVM}"/>
</antcall>
<mkdir dir="${staging_folder}/arduino-builder-linux32"/>
<antcall target="untar">
<param name="archive_file" value="./arduino-builder-linux32-${ARDUINO-BUILDER-VERSION}.tar.bz2" />
<param name="archive_url" value="http://downloads.arduino.cc/tools/arduino-builder-linux32-${ARDUINO-BUILDER-VERSION}.tar.bz2" />
<param name="final_folder" value="${staging_folder}/arduino-builder-linux32/arduino-builder" />
<param name="dest_folder" value="${staging_folder}/arduino-builder-linux32" />
</antcall>
<copy file="${staging_folder}/arduino-builder-linux32/arduino-builder" tofile="linux/work/arduino-builder" />
<chmod perm="755" file="linux/work/arduino-builder" />
<move file="${staging_folder}/arduino-builder-linux32/tools" tofile="linux/work/tools-builder"/>
<copy todir="linux/work/hardware" overwrite="true">
<fileset dir="${staging_folder}/arduino-builder-linux32/hardware" includes="*.txt"/>
</copy>
<delete dir="${staging_folder}/arduino-builder-linux32" includeemptydirs="true"/>
<antcall target="avr-toolchain-bundle">
<param name="unpack_target" value="untar"/>
<param name="gcc_archive_file" value="avr-gcc-4.8.1-arduino5-i686-pc-linux-gnu.tar.bz2"/>
@ -557,6 +592,21 @@
<param name="JVM" value="${LINUX64_BUNDLED_JVM}"/>
</antcall>
<mkdir dir="${staging_folder}/arduino-builder-linux64"/>
<antcall target="untar">
<param name="archive_file" value="./arduino-builder-linux64-${ARDUINO-BUILDER-VERSION}.tar.bz2" />
<param name="archive_url" value="http://downloads.arduino.cc/tools/arduino-builder-linux64-${ARDUINO-BUILDER-VERSION}.tar.bz2" />
<param name="final_folder" value="${staging_folder}/arduino-builder-linux64/arduino-builder" />
<param name="dest_folder" value="${staging_folder}/arduino-builder-linux64" />
</antcall>
<copy file="${staging_folder}/arduino-builder-linux64/arduino-builder" tofile="linux/work/arduino-builder" />
<chmod perm="755" file="linux/work/arduino-builder" />
<move file="${staging_folder}/arduino-builder-linux64/tools" tofile="linux/work/tools-builder"/>
<copy todir="linux/work/hardware" overwrite="true">
<fileset dir="${staging_folder}/arduino-builder-linux64/hardware" includes="*.txt"/>
</copy>
<delete dir="${staging_folder}/arduino-builder-linux64" includeemptydirs="true"/>
<antcall target="avr-toolchain-bundle">
<param name="unpack_target" value="untar"/>
<param name="gcc_archive_file" value="avr-gcc-4.8.1-arduino5-x86_64-pc-linux-gnu.tar.bz2"/>
@ -762,6 +812,21 @@
<fileset file="windows/work/hardware/tools/listComPorts.exe" />
</chmod>
<mkdir dir="${staging_folder}/arduino-builder-windows"/>
<antcall target="unzip">
<param name="archive_file" value="./arduino-builder-windows-${ARDUINO-BUILDER-VERSION}.zip" />
<param name="archive_url" value="http://downloads.arduino.cc/tools/arduino-builder-windows-${ARDUINO-BUILDER-VERSION}.zip" />
<param name="final_folder" value="${staging_folder}/arduino-builder-windows/arduino-builder.exe" />
<param name="dest_folder" value="${staging_folder}/arduino-builder-windows" />
</antcall>
<copy file="${staging_folder}/arduino-builder-windows/arduino-builder.exe" tofile="windows/work/arduino-builder.exe" />
<chmod perm="755" file="windows/work/arduino-builder.exe" />
<move file="${staging_folder}/arduino-builder-windows/tools" tofile="windows/work/tools-builder"/>
<copy todir="windows/work/hardware" overwrite="true">
<fileset dir="${staging_folder}/arduino-builder-windows/hardware" includes="*.txt"/>
</copy>
<delete dir="${staging_folder}/arduino-builder-windows" includeemptydirs="true"/>
<antcall target="assemble">
<param name="target.path" value="windows/work" />
</antcall>