updated Compiler

updated Compiler Editor and Downloader classes
so that now compilation works and error messages are
parsed (altough very crudely)
dist.sh now creates a dmg file on mac os x

mbanzi
This commit is contained in:
Massimo Banzi 2005-08-29 18:36:10 +00:00
parent 6417eff01b
commit e58e88111c
4 changed files with 188 additions and 112 deletions

View File

@ -1,9 +1,9 @@
/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/* /*
Compiler - default compiler class that connects to jikes Compiler - default compiler class that connects to the external compiler
Part of the Processing project - http://processing.org
Part of the Arduino project - http://arduino.berlios.de
Derived from the Processing project - http://processing.org
Copyleft 2005 Massimo Banzi (arduino modifications) Copyleft 2005 Massimo Banzi (arduino modifications)
Copyright (c) 2004-05 Ben Fry and Casey Reas Copyright (c) 2004-05 Ben Fry and Casey Reas
@ -26,8 +26,6 @@
package processing.app; package processing.app;
//import processing.core.*;
import java.io.*; import java.io.*;
import java.util.*; import java.util.*;
import java.util.zip.*; import java.util.zip.*;
@ -74,11 +72,14 @@ public class Compiler implements MessageConsumer {
System.out.println("Compiling Arduino program"); System.out.println("Compiling Arduino program");
Process process; Process process;
String commandLine = userdir + "tools/gnumake -C " + userdir + "lib compile";
//TODO test this in windows
if (Base.isWindows()) commandLine.replace('/','\\');
int result = 0; int result = 0;
try { try {
process = Runtime.getRuntime().exec(userdir + "tools/gnumake -s -C " + userdir + "lib compile"); // System.out.println(commandLine);
process = Runtime.getRuntime().exec(commandLine);
// System.err.println(userdir + "lib/wiringlite/bin/gnumake -s -C " + userdir + "lib compile");
new MessageSiphon(process.getInputStream(), this); new MessageSiphon(process.getInputStream(), this);
new MessageSiphon(process.getErrorStream(), this); new MessageSiphon(process.getErrorStream(), this);
@ -112,11 +113,40 @@ public class Compiler implements MessageConsumer {
* whenever a piece (usually a line) of error message is spewed * whenever a piece (usually a line) of error message is spewed
* out from the compiler. The errors are parsed for their contents * out from the compiler. The errors are parsed for their contents
* and line number, which is then reported back to Editor. * and line number, which is then reported back to Editor.
* In Arduino v1 this is very very crude
*/ */
public void message(String s) { public void message(String s) {
// This receives messages as full lines, so a newline needs // This receives messages as full lines, so a newline needs
// to be added as they're printed to the console. // to be added as they're printed to the console.
System.err.println(s); //System.out.print(s);
//if ((s.indexOf("warning:") != -1) && (s.indexOf("prog.c:") != -1) ) {
// String[] result = s.split(":");
// for (int x=0; x<result.length; x++)
// System.out.println(x + " " +result[x]);
// //System.out.print(s);
// //totalErrors++;
//}
if (((s.indexOf("error:") != -1) || (s.indexOf("warning:") != -1)) && (s.indexOf("prog.c:") != -1) ) {
String[] result = s.split(":");
// 0 = prog.c
// 1 = line number
// 2 = error or warning
// 3 = message
// TODO put the length of the header file into a Preference!!!
//if ((s.indexOf("(Each undeclared") == 0) && (s.indexOf("for each function it appears in") == 0)) {
int lineNum = Integer.parseInt(result[1]) - 15;
System.out.print( result[2] + " at line " + lineNum + " " + result[3]);
//}
}
}
public void processing_message(String s) {
// ignore cautions // ignore cautions
if (s.indexOf("Caution") != -1) return; if (s.indexOf("Caution") != -1) return;
@ -255,7 +285,7 @@ public class Compiler implements MessageConsumer {
} }
} }
/*
static String bootClassPath; static String bootClassPath;
static public String calcBootClassPath() { static public String calcBootClassPath() {
@ -270,7 +300,7 @@ public class Compiler implements MessageConsumer {
return bootClassPath; return bootClassPath;
} }
*/
/// ///

View File

@ -60,32 +60,30 @@ public class Downloader implements MessageConsumer {
private int serial_databits = 8; private int serial_databits = 8;
private float serial_stopbits = 1; private float serial_stopbits = 1;
public void serialPreferences() {
// System.out.println("setting serial properties");
serial_port = Preferences.get("serial.port");
//serial_rate = 9600; //Preferences.getInteger("serial.download_rate");
//serial_parity = Preferences.get("serial.parity").charAt(0);
//serial_databits = Preferences.getInteger("serial.databits");
//serial_stopbits = new Float(Preferences.get("serial.stopbits")).floatValue();
}
public Downloader() { public Downloader() {
serial_port = Preferences.get("serial.port");
} }
// Calls the makefile with the "program" option
// TODO Windows paths!
private boolean downloadMake(String userdir) { private boolean downloadMake(String userdir) {
System.out.println("Downloading - makefile"); System.out.println("Downloading - makefile");
Process process; Process process;
int result = 0; int result = 0;
try { try {
serialPreferences(); serial_port = Preferences.get("serial.port");
String command = userdir + "tools/gnumake SERIAL=" + serial_port + " -C " + userdir + "lib program"; String command = userdir + "lib/wiringlite/bin/gnumake SERIAL=" + serial_port + " -C " + userdir + "lib/wiringlite program";
System.out.println(command); System.out.println(command);
process = Runtime.getRuntime().exec(command); process = Runtime.getRuntime().exec(command);
new MessageSiphon(process.getInputStream(), this); new MessageSiphon(process.getInputStream(), this);
new MessageSiphon(process.getErrorStream(), this); new MessageSiphon(process.getErrorStream(), this);
boolean compiling = true; boolean compiling = true;
while (compiling) { while (compiling) {
try { try {
@ -110,19 +108,22 @@ public class Downloader implements MessageConsumer {
String userdir = System.getProperty("user.dir") + File.separator; String userdir = System.getProperty("user.dir") + File.separator;
return downloadMake(userdir); return downloadNative(userdir);
} }
// Calls UISP directly, skipping the makefile
//
// TODO Windows paths!!
public boolean downloadNative(String userdir) { public boolean downloadNative(String userdir) {
System.out.println("Downloading - native"); System.out.println("Downloading code");
buildPath = userdir + "lib/tmp";
String commandDownloader[] = new String[] { String commandDownloader[] = new String[] {
(( Base.isMacOS()) ? "tools/avr/bin/uisp" : userdir + "tools/avr/bin/uisp",
userdir + "tools/avr/bin/uisp"),
//[2] Serial port //[2] Serial port
//[6] hex class file //[6] hex class file
"-dprog=stk500", "-dprog=stk500",
@ -139,15 +140,18 @@ public class Downloader implements MessageConsumer {
int result=0; // pre-initialized to quiet a bogus warning from gcc int result=0; // pre-initialized to quiet a bogus warning from gcc
try { try {
serialPreferences(); serial_port = Preferences.get("serial.port");
commandDownloader[2] = ((Base.isMacOS()) ? "-dserial=" + serial_port.toLowerCase() : "-dserial=" + serial_port ); commandDownloader[2] = "-dserial=" + serial_port;
commandDownloader[6] = "if=" + buildPath + File.separator + className + ".hex"; commandDownloader[6] = "if=" + buildPath + File.separator + "prog.hex";
// for(int i = 0; i < commandDownloader.length; i++) { // for(int i = 0; i < commandDownloader.length; i++) {
// System.out.println(commandDownloader[i]); // System.out.print(commandDownloader[i] + " ");
// } //}
Process process = Runtime.getRuntime().exec(commandDownloader); Process process = Runtime.getRuntime().exec(commandDownloader);
new MessageSiphon(process.getInputStream(), this); new processing.app.MessageSiphon(process.getInputStream(), this);
new MessageSiphon(process.getErrorStream(), this); new processing.app.MessageSiphon(process.getErrorStream(), this);
// wait for the process to finish. if interrupted // wait for the process to finish. if interrupted
// before waitFor returns, continue waiting // before waitFor returns, continue waiting
@ -192,77 +196,113 @@ public class Downloader implements MessageConsumer {
boolean firstErrorFound; boolean firstErrorFound;
boolean secondErrorFound; boolean secondErrorFound;
// part of the PdeMessageConsumer interface // part of the MessageConsumer interface
// //
// at the moment we are pretty happy just to see the error messages coming back
public void message(String s) { public void message(String s) {
//System.err.println("MSG: " + s); //System.err.println("MSG: " + s);
//System.err.print(s); System.err.print(s);
// ignore cautions
if (s.indexOf("Caution") != -1) return;
// gcc always uses a forward slash character as its separator, so
// we need to replace any platform-specific separator characters before
// attemping to compare
//
String partialTempPath = buildPath.replace(File.separatorChar, '/')
+ "/" + className + ".c";
// if the partial temp path appears in the error message...
//
int partialStartIndex = s.indexOf(partialTempPath);
//System.out.println(partialStartIndex);
if (partialStartIndex != -1) {
// skip past the path and parse the int after the first colon
//
String s1 = s.substring(partialStartIndex + partialTempPath.length()
+ 1);
int colon = s1.indexOf(':');
int lineNumber = Integer.parseInt(s1.substring(0, colon));
//System.out.println("pde / line number: " + lineNumber);
//String s2 = s1.substring(colon + 2);
int err = s1.indexOf("Error:");
if (err != -1) {
// if the first error has already been found, then this must be
// (at least) the second error found
if (firstErrorFound) {
secondErrorFound = true;
return;
}
// if we're here at all, this is at least the first error
firstErrorFound = true;
//err += "error:".length();
String description = s1.substring(err + "Error:".length());
description = description.trim();
//System.out.println("description = " + description);
exception = new RunnerException(description, lineNumber-1);
//editor.error(exception);
} else {
System.err.println("i suck: " + s);
}
} else {
// this isn't the start of an error line, so don't attempt to parse
// a line number out of it.
// if we're not yet at the second error, these lines are probably
// associated with the first error message, which is already in the
// status bar, and are likely to be of interest to the user, so
// spit them to the console.
//
if (!secondErrorFound) {
System.err.println(s);
}
}
} }
public boolean downloadNew(String userdir) {
serial_port = Preferences.get("serial.port");
// TODO must manage this flag from the editor
boolean alreadyCompiled = true;
// TODO must manage this flag from global prefs
boolean debug = true;
String verbose = " ";
if (alreadyCompiled) {
if (serial_port == "") {
System.out.println("The serial port is not set!");
System.out.println("Use the Options -> Serial menu to select");
System.out.println("where you have connected your arduino board");
return false;
};
String commandLine = "";
if (debug) System.out.println("userdir is "+userdir);
int result = -1;
String ext = "";
// TODO make this code more portable using File.separator
if (Base.isMacOS()) {
ext = "";
commandLine = userdir + "tools/avr/bin/uisp ";
commandLine += " -dprog=stk500 -dspeed=9600 ";
commandLine += " -dserial=" + serial_port;
commandLine += " -dpart=ATmega8";
commandLine += " if=" +userdir + "lib/wiringlite/tmp/prog.hex --upload";
} else {
ext = ".exe";
commandLine = userdir + "lib\\wiringlite\\bin\\gnumake" + ext + " SERIAL=" + serial_port + verbose + " -C " + userdir + "lib\\wiringlite program";
}
if (debug) System.out.println(commandLine);
// Launch the command as a thread (this way we can kill it
// in the case it times out)
Command command = new Command(commandLine, true);
command.setName("theDownloader");
command.start();
// TODO move this to Preferences
// Default timeout when calling a command (in seconds)
final int maxTimeOut = 30; // 10 secs
// Start timer to monitor buffer timeout ==> deadlock in process
int timeCount = 0;
while ((timeCount <= maxTimeOut) && (result == -1) && command.isAlive()) {
try {
result = command.waitResult;
Thread.currentThread().sleep(1000);
} catch (InterruptedException ie) {
}
timeCount++;
}
result = command.waitResult;
if ((result != 0) && (command.errorResult == -1)) {
// result = 94;
System.out.println("Time out error when trying to upload the program");
System.out.println("Board not present, bootloader not installed or processor's failure");
System.out.println("Arduino download unsuccessful (error: " + result + ")");
} else if (result == 0) {
System.out.println(command.errorMsg);
System.out.println("OK - Arduino download successful");
} else if ((result != 0) && (49 == command.errorResult)) {
System.out.println(command.errorMsg);
System.out.println("Bootloader not responding");
System.out.println("Arduino download unsuccessful (error: " + result + ")");
} else {
System.out.println(command.errorMsg);
System.out.println("Arduino download unsuccessful (error: " + result + ")");
}
if (command.isAlive()) command.process.destroy();
} else {
System.out.println("You have to compile the code first");
System.out.println("Arduino download unsuccessful");
}
return true;
}
} }

View File

@ -632,7 +632,7 @@ public class Editor extends JFrame
item.addActionListener(new ActionListener() { item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
new AutoFormat(Editor.this).show(); new AutoFormat(Editor.this).show();
//handleBeautify();
} }
}); });
menu.add(item); menu.add(item);
@ -1140,17 +1140,16 @@ public class Editor extends JFrame
for (int i = 0; i < 10; i++) System.out.println(); for (int i = 0; i < 10; i++) System.out.println();
// clear the console on each run, unless the user doesn't want to // clear the console on each run, unless the user doesn't want to
//if (Base.getBoolean("console.auto_clear", true)) {
//if (Preferences.getBoolean("console.auto_clear", true)) { //if (Preferences.getBoolean("console.auto_clear", true)) {
if (Preferences.getBoolean("console.auto_clear")) { if (Preferences.getBoolean("console.auto_clear")) {
console.clear(); console.clear();
} }
presenting = present; presenting = present;
console.message("Arduino compiling\n", false,true); // console.message("Arduino compiling\n", false,true);
String cfilename = System.getProperty("user.dir") + File.separator + "lib/build/arduino.c"; String cfilename = System.getProperty("user.dir") + File.separator + "lib/build/arduino.c";
// console.message(" file = " + cfilename, false,true); //console.message(" file = " + cfilename, false,true);
try { try {
Writer out = new FileWriter(cfilename); Writer out = new FileWriter(cfilename);
out.write(textarea.getText()); out.write(textarea.getText());
@ -1164,12 +1163,12 @@ public class Editor extends JFrame
Compiler compiler = new Compiler(); Compiler compiler = new Compiler();
String buildPath = Preferences.get("build.path"); String buildPath = Preferences.get("build.path");
// console.message(" buildpath = " + buildPath, false,true); //console.message(" buildpath = " + buildPath, false,true);
try { try {
boolean success = compiler.compile(sketch, buildPath); boolean success = compiler.compile(sketch, buildPath);
} catch (RunnerException e) { } catch (RunnerException e) {
error(e); error(e);
} }
buttons.clear(); buttons.clear();
@ -1287,6 +1286,7 @@ public class Editor extends JFrame
* mode, this will always be called instead of doStop(). * mode, this will always be called instead of doStop().
*/ */
public void doClose() { public void doClose() {
/*
//if (presenting) { //if (presenting) {
//presentationWindow.hide(); //presentationWindow.hide();
//} else { //} else {
@ -1295,7 +1295,7 @@ public class Editor extends JFrame
// externally. so don't even try setting if window is null // externally. so don't even try setting if window is null
// since Runner will set the appletLocation when an // since Runner will set the appletLocation when an
// external process is in use. // external process is in use.
if (runtime.window != null) { //if (runtime.window != null) {
appletLocation = runtime.window.getLocation(); appletLocation = runtime.window.getLocation();
} }
} catch (NullPointerException e) { } } catch (NullPointerException e) { }
@ -1311,7 +1311,7 @@ public class Editor extends JFrame
} }
} catch (Exception e) { } } catch (Exception e) { }
//buttons.clear(); // done by doStop //buttons.clear(); // done by doStop
*/
sketch.cleanup(); sketch.cleanup();
// [toxi 030903] // [toxi 030903]

View File

@ -51,7 +51,13 @@ find arduino -name ".svn" -exec rm -rf {} ';' 2> /dev/null
mv arduino/Arduino.app "arduino/Arduino $SHORT_REVISION.app" mv arduino/Arduino.app "arduino/Arduino $SHORT_REVISION.app"
mv arduino arduino-$REVISION mv arduino arduino-$REVISION
zip -r arduino-$REVISION.zip arduino-$REVISION #zip -r arduino-$REVISION.zip arduino-$REVISION
rm -Rf tmp
mkdir tmp
mv arduino-$REVISION/ tmp/
hdiutil create -fs HFS+ -srcfolder "./tmp/" -volname "arduino-$REVISION" "arduino-$REVISION.dmg"
#` don't have deluxe on my laptop right now #` don't have deluxe on my laptop right now
#stuff -f sitx arduino-$REVISION #stuff -f sitx arduino-$REVISION