diff --git a/app/src/processing/app/Sketch.java b/app/src/processing/app/Sketch.java index aa1d375e4..11068a2a7 100644 --- a/app/src/processing/app/Sketch.java +++ b/app/src/processing/app/Sketch.java @@ -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. *

@@ -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 treeSet = new TreeSet(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(); diff --git a/app/src/processing/app/debug/Compiler.java b/app/src/processing/app/debug/Compiler.java index d515f9545..5a7f3329e 100644 --- a/app/src/processing/app/debug/Compiler.java +++ b/app/src/processing/app/debug/Compiler.java @@ -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 treeSet = new TreeSet(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