1
0
mirror of https://github.com/arduino/Arduino.git synced 2025-03-15 12:29:26 +01:00

Compilation speed-up patch (only compile modify files). (Paul Stoffregen)

http://code.google.com/p/arduino/issues/detail?id=638
This commit is contained in:
David A. Mellis 2011-12-16 18:20:22 -05:00
parent b8fbffeac4
commit b0ae6e764d
3 changed files with 110 additions and 6 deletions

View File

@ -1010,6 +1010,7 @@ public class Base {
Preferences.set("target", (String) getValue("target")); Preferences.set("target", (String) getValue("target"));
Preferences.set("board", (String) getValue("board")); Preferences.set("board", (String) getValue("board"));
onBoardOrPortChange(); onBoardOrPortChange();
Sketch.buildSettingChanged();
} }
}; };
action.putValue("target", target.getName()); action.putValue("target", target.getName());

View File

@ -1246,6 +1246,12 @@ public class Sketch {
*/ */
//protected String compile() throws RunnerException { //protected String compile() throws RunnerException {
// called when any setting changes that requires all files to be recompiled
public static void buildSettingChanged() {
deleteFilesOnNextBuild = true;
}
private static boolean deleteFilesOnNextBuild = true;
/** /**
* When running from the editor, take care of preparations before running * When running from the editor, take care of preparations before running
@ -1620,9 +1626,29 @@ public class Sketch {
} }
File appletFolder = new File(appletPath); File appletFolder = new File(appletPath);
// Nuke the old applet folder because it can cause trouble String use_dep = Base.getBoardPreferences().get("build.dependency");
if (Preferences.getBoolean("export.delete_target_folder")) { if (use_dep == null || use_dep.compareToIgnoreCase("true") != 0 || deleteFilesOnNextBuild) {
// 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(appletFolder); Base.removeDir(appletFolder);
deleteFilesOnNextBuild = false;
} 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 (appletFolder.exists()) {
String files[] = appletFolder.list();
for (String file : files) {
if (file.endsWith(".c") || file.endsWith(".cpp") || file.endsWith(".s")) {
File deleteMe = new File(appletFolder, file);
if (!deleteMe.delete()) {
System.err.println("Could not delete " + deleteMe);
}
}
}
}
} }
// Create a fresh applet folder (needed before preproc is run below) // Create a fresh applet folder (needed before preproc is run below)
appletFolder.mkdirs(); appletFolder.mkdirs();

View File

@ -269,7 +269,11 @@ public class Compiler implements MessageConsumer {
for (File file : cSources) { for (File file : cSources) {
String objectPath = buildPath + File.separator + file.getName() + ".o"; String objectPath = buildPath + File.separator + file.getName() + ".o";
objectPaths.add(new File(objectPath)); String dependPath = buildPath + File.separator + file.getName() + ".d";
File objectFile = new File(objectPath);
File dependFile = new File(dependPath);
objectPaths.add(objectFile);
if (is_already_compiled(file, objectFile, dependFile, boardPreferences)) continue;
execAsynchronously(getCommandCompilerC(avrBasePath, includePaths, execAsynchronously(getCommandCompilerC(avrBasePath, includePaths,
file.getAbsolutePath(), file.getAbsolutePath(),
objectPath, objectPath,
@ -278,7 +282,11 @@ public class Compiler implements MessageConsumer {
for (File file : cppSources) { for (File file : cppSources) {
String objectPath = buildPath + File.separator + file.getName() + ".o"; String objectPath = buildPath + File.separator + file.getName() + ".o";
objectPaths.add(new File(objectPath)); String dependPath = buildPath + File.separator + file.getName() + ".d";
File objectFile = new File(objectPath);
File dependFile = new File(dependPath);
objectPaths.add(objectFile);
if (is_already_compiled(file, objectFile, dependFile, boardPreferences)) continue;
execAsynchronously(getCommandCompilerCPP(avrBasePath, includePaths, execAsynchronously(getCommandCompilerCPP(avrBasePath, includePaths,
file.getAbsolutePath(), file.getAbsolutePath(),
objectPath, objectPath,
@ -288,6 +296,71 @@ public class Compiler implements MessageConsumer {
return objectPaths; return objectPaths;
} }
private boolean is_already_compiled(File src, File obj, File dep, Map<String, String> prefs) {
String build_dep = prefs.get("build.dependency");
if (build_dep == null) return false;
if (build_dep.compareToIgnoreCase("true") != 0) return false;
boolean ret=true;
try {
//System.out.println("\n is_already_compiled: begin checks: " + obj.getPath());
if (!obj.exists()) return false; // object file (.o) does not exist
if (!dep.exists()) return false; // dep file (.d) does not exist
long src_modified = src.lastModified();
long obj_modified = obj.lastModified();
if (src_modified >= obj_modified) return false; // source modified since object compiled
if (src_modified >= dep.lastModified()) return false; // src modified since dep compiled
BufferedReader reader = new BufferedReader(new FileReader(dep.getPath()));
String line;
boolean need_obj_parse = true;
while ((line = reader.readLine()) != null) {
if (line.endsWith("\\")) {
line = line.substring(0, line.length() - 1);
}
line = line.trim();
if (line.length() == 0) continue; // ignore blank lines
if (need_obj_parse) {
// line is supposed to be the object file - make sure it really is!
if (line.endsWith(":")) {
line = line.substring(0, line.length() - 1);
String objpath = obj.getCanonicalPath();
File linefile = new File(line);
String linepath = linefile.getCanonicalPath();
//System.out.println(" is_already_compiled: obj = " + objpath);
//System.out.println(" is_already_compiled: line = " + linepath);
if (objpath.compareTo(linepath) == 0) {
need_obj_parse = false;
continue;
} else {
ret = false; // object named inside .d file is not the correct file!
break;
}
} else {
ret = false; // object file supposed to end with ':', but didn't
break;
}
} else {
// line is a prerequisite file
File prereq = new File(line);
if (!prereq.exists()) {
ret = false; // prerequisite file did not exist
break;
}
if (prereq.lastModified() >= obj_modified) {
ret = false; // prerequisite modified since object was compiled
break;
}
//System.out.println(" is_already_compiled: prerequisite ok");
}
}
reader.close();
} catch (Exception e) {
return false; // any error reading dep file = recompile it
}
if (ret && (verbose || Preferences.getBoolean("build.verbose"))) {
System.out.println(" Using previously compiled: " + obj.getPath());
}
return ret;
}
boolean firstErrorFound; boolean firstErrorFound;
boolean secondErrorFound; boolean secondErrorFound;
@ -490,6 +563,7 @@ public class Compiler implements MessageConsumer {
"-fdata-sections", "-fdata-sections",
"-mmcu=" + boardPreferences.get("build.mcu"), "-mmcu=" + boardPreferences.get("build.mcu"),
"-DF_CPU=" + boardPreferences.get("build.f_cpu"), "-DF_CPU=" + boardPreferences.get("build.f_cpu"),
"-MMD", // output dependancy info
"-DARDUINO=" + Base.REVISION, "-DARDUINO=" + Base.REVISION,
})); }));
@ -498,7 +572,8 @@ public class Compiler implements MessageConsumer {
} }
baseCommandCompiler.add(sourceName); baseCommandCompiler.add(sourceName);
baseCommandCompiler.add("-o"+ objectName); baseCommandCompiler.add("-o");
baseCommandCompiler.add(objectName);
return baseCommandCompiler; return baseCommandCompiler;
} }
@ -519,6 +594,7 @@ public class Compiler implements MessageConsumer {
"-fdata-sections", "-fdata-sections",
"-mmcu=" + boardPreferences.get("build.mcu"), "-mmcu=" + boardPreferences.get("build.mcu"),
"-DF_CPU=" + boardPreferences.get("build.f_cpu"), "-DF_CPU=" + boardPreferences.get("build.f_cpu"),
"-MMD", // output dependancy info
"-DARDUINO=" + Base.REVISION, "-DARDUINO=" + Base.REVISION,
})); }));
@ -527,7 +603,8 @@ public class Compiler implements MessageConsumer {
} }
baseCommandCompilerCPP.add(sourceName); baseCommandCompilerCPP.add(sourceName);
baseCommandCompilerCPP.add("-o"+ objectName); baseCommandCompilerCPP.add("-o");
baseCommandCompilerCPP.add(objectName);
return baseCommandCompilerCPP; return baseCommandCompilerCPP;
} }