mirror of
https://github.com/arduino/Arduino.git
synced 2025-02-18 12:54:25 +01:00
Moved the sketch building code from Sketch to Compiler.
This commit is contained in:
parent
b7d1846eb9
commit
afbbe77752
@ -26,13 +26,12 @@ package processing.app;
|
||||
import cc.arduino.packages.BoardPort;
|
||||
import cc.arduino.packages.UploaderAndMonitorFactory;
|
||||
import cc.arduino.packages.Uploader;
|
||||
import processing.app.debug.*;
|
||||
import processing.app.debug.Compiler;
|
||||
import processing.app.debug.Compiler.ProgressListener;
|
||||
import processing.app.debug.RunnerException;
|
||||
import processing.app.debug.TargetPlatform;
|
||||
import processing.app.forms.PasswordAuthorizationDialog;
|
||||
import processing.app.helpers.OSUtils;
|
||||
import processing.app.helpers.PreferencesMap;
|
||||
import processing.app.helpers.FileUtils;
|
||||
import processing.app.packages.Library;
|
||||
import static processing.app.I18n._;
|
||||
|
||||
@ -61,12 +60,6 @@ public class Sketch {
|
||||
/** Class name for the PApplet, as determined by the preprocessor. */
|
||||
private String appletClassName;
|
||||
|
||||
/**
|
||||
* File inside the build directory that contains the build options
|
||||
* used for the last build.
|
||||
*/
|
||||
static final String BUILD_PREFS_FILE = "buildprefs.txt";
|
||||
|
||||
/**
|
||||
* path is location of the main .pde file, because this is also
|
||||
* simplest to use when opening the file from the finder/explorer.
|
||||
@ -1017,48 +1010,6 @@ public class Sketch {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Cleanup temporary files used during a build/run.
|
||||
*/
|
||||
protected void cleanup(boolean force) {
|
||||
// if the java runtime is holding onto any files in the build dir, we
|
||||
// won't be able to delete them, so we need to force a gc here
|
||||
System.gc();
|
||||
|
||||
if (force) {
|
||||
// delete the entire directory and all contents
|
||||
// when we know something changed and all objects
|
||||
// need to be recompiled, or if the board does not
|
||||
// use setting build.dependency
|
||||
//Base.removeDir(tempBuildFolder);
|
||||
|
||||
// note that we can't remove the builddir itself, otherwise
|
||||
// the next time we start up, internal runs using Runner won't
|
||||
// work because the build dir won't exist at startup, so the classloader
|
||||
// will ignore the fact that that dir is in the CLASSPATH in run.sh
|
||||
Base.removeDescendants(tempBuildFolder);
|
||||
} else {
|
||||
// delete only stale source files, from the previously
|
||||
// compiled sketch. This allows multiple windows to be
|
||||
// used. Keep everything else, which might be reusable
|
||||
if (tempBuildFolder.exists()) {
|
||||
String files[] = tempBuildFolder.list();
|
||||
for (String file : files) {
|
||||
if (file.endsWith(".c") || file.endsWith(".cpp") || file.endsWith(".s")) {
|
||||
File deleteMe = new File(tempBuildFolder, file);
|
||||
if (!deleteMe.delete()) {
|
||||
System.err.println("Could not delete " + deleteMe);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create a fresh applet folder (needed before preproc is run below)
|
||||
//tempBuildFolder.mkdirs();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Preprocess, Compile, and Run the current code.
|
||||
* <P>
|
||||
@ -1180,47 +1131,6 @@ public class Sketch {
|
||||
return build(tempBuildFolder.getAbsolutePath(), verbose);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the build preferences used on the previous build in
|
||||
* buildPath match the ones given.
|
||||
*/
|
||||
protected boolean buildPreferencesChanged(File buildPrefsFile, String newBuildPrefs) {
|
||||
// No previous build, so no match
|
||||
if (!buildPrefsFile.exists())
|
||||
return true;
|
||||
|
||||
String previousPrefs;
|
||||
try {
|
||||
previousPrefs = FileUtils.readFileToString(buildPrefsFile);
|
||||
} catch (IOException e) {
|
||||
System.err.println(_("Could not read prevous build preferences file, rebuilding all"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!previousPrefs.equals(newBuildPrefs)) {
|
||||
System.out.println(_("Build options changed, rebuilding all"));
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the build preferences of the given compiler as a string.
|
||||
* Only includes build-specific preferences, to make sure unrelated
|
||||
* preferences don't cause a rebuild (in particular preferences that
|
||||
* change on every start, like last.ide.xxx.daterun). */
|
||||
protected String buildPrefsString(Compiler compiler) {
|
||||
PreferencesMap buildPrefs = compiler.getBuildPreferences();
|
||||
String res = "";
|
||||
SortedSet<String> treeSet = new TreeSet<String>(buildPrefs.keySet());
|
||||
for (String k : treeSet) {
|
||||
if (k.startsWith("build.") || k.startsWith("compiler.") || k.startsWith("recipes."))
|
||||
res += k + " = " + buildPrefs.get(k) + "\n";
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Preprocess and compile all the code for this sketch.
|
||||
*
|
||||
@ -1231,45 +1141,19 @@ public class Sketch {
|
||||
* @return null if compilation failed, main class name if not
|
||||
*/
|
||||
public String build(String buildPath, boolean verbose) throws RunnerException {
|
||||
String primaryClassName = data.getName() + ".cpp";
|
||||
Compiler compiler = new Compiler(data, buildPath, primaryClassName);
|
||||
File buildPrefsFile = new File(buildPath, BUILD_PREFS_FILE);
|
||||
String newBuildPrefs = buildPrefsString(compiler);
|
||||
|
||||
// Do a forced cleanup (throw everything away) if the previous
|
||||
// build settings do not match the previous ones
|
||||
boolean prefsChanged = buildPreferencesChanged(buildPrefsFile, newBuildPrefs);
|
||||
cleanup(prefsChanged);
|
||||
|
||||
if (prefsChanged) {
|
||||
try {
|
||||
PrintWriter out = new PrintWriter(buildPrefsFile);
|
||||
out.print(newBuildPrefs);
|
||||
out.close();
|
||||
} catch (IOException e) {
|
||||
System.err.println(_("Could not write build preferences file"));
|
||||
}
|
||||
}
|
||||
|
||||
// run the preprocessor
|
||||
editor.status.progressUpdate(20);
|
||||
|
||||
ensureExistence();
|
||||
|
||||
compiler.setProgressListener(new ProgressListener() {
|
||||
ProgressListener pl = new ProgressListener() {
|
||||
@Override
|
||||
public void progress(int percent) {
|
||||
editor.status.progressUpdate(percent);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// compile the program. errors will happen as a RunnerException
|
||||
// that will bubble up to whomever called build().
|
||||
if (compiler.compile(verbose)) {
|
||||
size(compiler.getBuildPreferences());
|
||||
return primaryClassName;
|
||||
}
|
||||
return null;
|
||||
return Compiler.build(data, buildPath, tempBuildFolder, pl, verbose);
|
||||
}
|
||||
|
||||
protected boolean exportApplet(boolean usingProgrammer) throws Exception {
|
||||
@ -1307,58 +1191,6 @@ public class Sketch {
|
||||
}
|
||||
|
||||
|
||||
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(_("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(_("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(
|
||||
_("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(_("Global variables use {0} bytes of dynamic memory."), dataSize));
|
||||
}
|
||||
}
|
||||
|
||||
if (textSize > maxTextSize)
|
||||
throw new RunnerException(
|
||||
_("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(
|
||||
_("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(_("Low memory available, stability problems may occur."));
|
||||
}
|
||||
|
||||
protected boolean upload(String buildPath, String suggestedClassName, boolean usingProgrammer) throws Exception {
|
||||
|
||||
TargetPlatform target = Base.getTargetPlatform();
|
||||
|
@ -31,10 +31,13 @@ import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import processing.app.Base;
|
||||
import processing.app.BaseNoGui;
|
||||
@ -54,6 +57,12 @@ import processing.app.legacy.PApplet;
|
||||
|
||||
public class Compiler implements MessageConsumer {
|
||||
|
||||
/**
|
||||
* File inside the build directory that contains the build options
|
||||
* used for the last build.
|
||||
*/
|
||||
static final public String BUILD_PREFS_FILE = "buildprefs.txt";
|
||||
|
||||
private SketchData sketch;
|
||||
private PreferencesMap prefs;
|
||||
private boolean verbose;
|
||||
@ -73,6 +82,38 @@ public class Compiler implements MessageConsumer {
|
||||
|
||||
private ProgressListener progressListener;
|
||||
|
||||
static public String build(SketchData data, String buildPath, File tempBuildFolder, ProgressListener progListener, boolean verbose) throws RunnerException {
|
||||
String primaryClassName = data.getName() + ".cpp";
|
||||
Compiler compiler = new Compiler(data, buildPath, primaryClassName);
|
||||
File buildPrefsFile = new File(buildPath, BUILD_PREFS_FILE);
|
||||
String newBuildPrefs = compiler.buildPrefsString();
|
||||
|
||||
// Do a forced cleanup (throw everything away) if the previous
|
||||
// build settings do not match the previous ones
|
||||
boolean prefsChanged = compiler.buildPreferencesChanged(buildPrefsFile, newBuildPrefs);
|
||||
compiler.cleanup(prefsChanged, tempBuildFolder);
|
||||
|
||||
if (prefsChanged) {
|
||||
try {
|
||||
PrintWriter out = new PrintWriter(buildPrefsFile);
|
||||
out.print(newBuildPrefs);
|
||||
out.close();
|
||||
} catch (IOException e) {
|
||||
System.err.println(_("Could not write build preferences file"));
|
||||
}
|
||||
}
|
||||
|
||||
compiler.setProgressListener(progListener);
|
||||
|
||||
// compile the program. errors will happen as a RunnerException
|
||||
// that will bubble up to whomever called build().
|
||||
if (compiler.compile(verbose)) {
|
||||
compiler.size(compiler.getBuildPreferences());
|
||||
return primaryClassName;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Compiler
|
||||
* @param _sketch Sketch object to be compiled.
|
||||
@ -92,10 +133,144 @@ public class Compiler implements MessageConsumer {
|
||||
};
|
||||
}
|
||||
|
||||
public void setProgressListener(ProgressListener _progressListener) {
|
||||
/**
|
||||
* Check if the build preferences used on the previous build in
|
||||
* buildPath match the ones given.
|
||||
*/
|
||||
protected boolean buildPreferencesChanged(File buildPrefsFile, String newBuildPrefs) {
|
||||
// No previous build, so no match
|
||||
if (!buildPrefsFile.exists())
|
||||
return true;
|
||||
|
||||
String previousPrefs;
|
||||
try {
|
||||
previousPrefs = FileUtils.readFileToString(buildPrefsFile);
|
||||
} catch (IOException e) {
|
||||
System.err.println(_("Could not read prevous build preferences file, rebuilding all"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!previousPrefs.equals(newBuildPrefs)) {
|
||||
System.out.println(_("Build options changed, rebuilding all"));
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the build preferences of the given compiler as a string.
|
||||
* Only includes build-specific preferences, to make sure unrelated
|
||||
* preferences don't cause a rebuild (in particular preferences that
|
||||
* change on every start, like last.ide.xxx.daterun). */
|
||||
protected String buildPrefsString() {
|
||||
PreferencesMap buildPrefs = getBuildPreferences();
|
||||
String res = "";
|
||||
SortedSet<String> treeSet = new TreeSet<String>(buildPrefs.keySet());
|
||||
for (String k : treeSet) {
|
||||
if (k.startsWith("build.") || k.startsWith("compiler.") || k.startsWith("recipes."))
|
||||
res += k + " = " + buildPrefs.get(k) + "\n";
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
protected void setProgressListener(ProgressListener _progressListener) {
|
||||
progressListener = _progressListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup temporary files used during a build/run.
|
||||
*/
|
||||
protected void cleanup(boolean force, File tempBuildFolder) {
|
||||
// if the java runtime is holding onto any files in the build dir, we
|
||||
// won't be able to delete them, so we need to force a gc here
|
||||
System.gc();
|
||||
|
||||
if (force) {
|
||||
// delete the entire directory and all contents
|
||||
// when we know something changed and all objects
|
||||
// need to be recompiled, or if the board does not
|
||||
// use setting build.dependency
|
||||
//Base.removeDir(tempBuildFolder);
|
||||
|
||||
// note that we can't remove the builddir itself, otherwise
|
||||
// the next time we start up, internal runs using Runner won't
|
||||
// work because the build dir won't exist at startup, so the classloader
|
||||
// will ignore the fact that that dir is in the CLASSPATH in run.sh
|
||||
Base.removeDescendants(tempBuildFolder);
|
||||
} else {
|
||||
// delete only stale source files, from the previously
|
||||
// compiled sketch. This allows multiple windows to be
|
||||
// used. Keep everything else, which might be reusable
|
||||
if (tempBuildFolder.exists()) {
|
||||
String files[] = tempBuildFolder.list();
|
||||
for (String file : files) {
|
||||
if (file.endsWith(".c") || file.endsWith(".cpp") || file.endsWith(".s")) {
|
||||
File deleteMe = new File(tempBuildFolder, file);
|
||||
if (!deleteMe.delete()) {
|
||||
System.err.println("Could not delete " + deleteMe);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create a fresh applet folder (needed before preproc is run below)
|
||||
//tempBuildFolder.mkdirs();
|
||||
}
|
||||
|
||||
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(_("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(_("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(
|
||||
_("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(_("Global variables use {0} bytes of dynamic memory."), dataSize));
|
||||
}
|
||||
}
|
||||
|
||||
if (textSize > maxTextSize)
|
||||
throw new RunnerException(
|
||||
_("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(
|
||||
_("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(_("Low memory available, stability problems may occur."));
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile sketch.
|
||||
* @param buildPath
|
||||
|
Loading…
x
Reference in New Issue
Block a user