1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-06-20 21:01:25 +03:00

platforms.txt recipes now have symbolic variables instead of indexes ({0},{1},etc.)

Recipes arguments are splitted with spaces instead of |. Single argument containing spaces
should be placed between "double quotes".
Refactored and formatted Compiler class, removed all unused code in comments.
This commit is contained in:
Cristian Maglie
2011-12-31 14:32:48 +01:00
parent 1b3ae5fa63
commit abe41d805d
5 changed files with 500 additions and 656 deletions

View File

@ -41,6 +41,7 @@ import processing.app.Preferences;
import processing.app.Sketch; import processing.app.Sketch;
import processing.app.SketchCode; import processing.app.SketchCode;
import processing.app.helpers.PreferencesMap; import processing.app.helpers.PreferencesMap;
import processing.app.helpers.StringReplacer;
import processing.core.PApplet; import processing.core.PApplet;
public class Compiler implements MessageConsumer { public class Compiler implements MessageConsumer {
@ -61,7 +62,7 @@ public class Compiler implements MessageConsumer {
List<File> objectFiles; List<File> objectFiles;
/** /**
* Compile with avr-gcc. * Compile sketch.
* *
* @param _sketch Sketch object to be compiled. * @param _sketch Sketch object to be compiled.
* @param _buildPath Where the temporary files live and will be built from. * @param _buildPath Where the temporary files live and will be built from.
@ -69,10 +70,9 @@ public class Compiler implements MessageConsumer {
* @return true if successful. * @return true if successful.
* @throws RunnerException Only if there's a problem. Only then. * @throws RunnerException Only if there's a problem. Only then.
*/ */
public boolean compile(Sketch _sketch, public boolean compile(Sketch _sketch, String _buildPath,
String _buildPath, String _primaryClassName, boolean _verbose)
String _primaryClassName, throws RunnerException {
boolean _verbose) throws RunnerException {
sketch = _sketch; sketch = _sketch;
buildPath = _buildPath; buildPath = _buildPath;
primaryClassName = _primaryClassName; primaryClassName = _primaryClassName;
@ -89,17 +89,17 @@ public class Compiler implements MessageConsumer {
else else
platformPreferences = Base.getPlatformPreferences(platform); platformPreferences = Base.getPlatformPreferences(platform);
// Merge all the global preference configuration // Merge all the global preference configuration in order of priority
PreferencesMap configPreferences = new PreferencesMap(); PreferencesMap prefs = new PreferencesMap();
configPreferences.putAll(Preferences.getMap()); prefs.putAll(Preferences.getMap());
configPreferences.putAll(platformPreferences); prefs.putAll(platformPreferences);
configPreferences.putAll(boardPreferences); prefs.putAll(boardPreferences);
for (String k : configPreferences.keySet()) { for (String k : prefs.keySet()) {
if (configPreferences.get(k) == null) if (prefs.get(k) == null)
configPreferences.put(k, ""); prefs.put(k, "");
} }
String avrBasePath = configPreferences.get("compiler.path"); String avrBasePath = prefs.get("compiler.path");
if (avrBasePath == null) { if (avrBasePath == null) {
avrBasePath = Base.getAvrBasePath(); avrBasePath = Base.getAvrBasePath();
System.out.println("avrBasePath: " + avrBasePath); System.out.println("avrBasePath: " + avrBasePath);
@ -109,19 +109,17 @@ public class Compiler implements MessageConsumer {
// Put in the system path in the compiler path if available // Put in the system path in the compiler path if available
MessageFormat compileFormat = new MessageFormat(avrBasePath); MessageFormat compileFormat = new MessageFormat(avrBasePath);
String basePath = System.getProperty("user.dir"); String basePath = System.getProperty("user.dir");
if (Base.isMacOS()) { if (Base.isMacOS())
// logger.debug("basePath: " + basePath);
basePath += "/Arduino.app/Contents/Resources/Java"; basePath += "/Arduino.app/Contents/Resources/Java";
}
Object[] Args = { basePath }; Object[] Args = { basePath };
avrBasePath = compileFormat.format(Args); avrBasePath = compileFormat.format(Args);
System.out.println("avrBasePath:new: " + avrBasePath); System.out.println("avrBasePath:new: " + avrBasePath);
} }
board = configPreferences.get("board"); board = prefs.get("board");
if (board == "") if (board == "")
board = "_UNKNOWN"; board = "_UNKNOWN";
String core = configPreferences.get("build.core"); String core = prefs.get("build.core");
if (core == null) { if (core == null) {
RunnerException re = new RunnerException( RunnerException re = new RunnerException(
_("No board selected; please choose a board from the Tools > Board menu.")); _("No board selected; please choose a board from the Tools > Board menu."));
@ -169,150 +167,42 @@ public class Compiler implements MessageConsumer {
includePaths.add(file.getPath()); includePaths.add(file.getPath());
// 1. compile the sketch (already in the buildPath) // 1. compile the sketch (already in the buildPath)
System.out.println("1. compileSketch");
sketch.setCompilingProgress(30); sketch.setCompilingProgress(30);
compileSketch(avrBasePath, _buildPath, includePaths, configPreferences); compileSketch(avrBasePath, _buildPath, includePaths, prefs);
// 2. compile the libraries, outputting .o files to: <buildPath>/<library>/ // 2. compile the libraries, outputting .o files to: <buildPath>/<library>/
// Doesn't really use configPreferences // Doesn't really use configPreferences
System.out.println("2. compileLibraries");
sketch.setCompilingProgress(40); sketch.setCompilingProgress(40);
compileLibraries(avrBasePath, _buildPath, includePaths, configPreferences); compileLibraries(avrBasePath, _buildPath, includePaths, prefs);
/*
for (File libraryFolder : sketch.getImportedLibraries()) {
File outputFolder = new File(buildPath, libraryFolder.getName());
File utilityFolder = new File(libraryFolder, "utility");
createFolder(outputFolder);
// this library can use includes in its utility/ folder
includePaths.add(utilityFolder.getAbsolutePath());
objectFiles.addAll(
compileFiles(avrBasePath, outputFolder.getAbsolutePath(), includePaths,
findFilesInFolder(libraryFolder, "S", false),
findFilesInFolder(libraryFolder, "c", false),
findFilesInFolder(libraryFolder, "cpp", false),
boardPreferences));
outputFolder = new File(outputFolder, "utility");
createFolder(outputFolder);
objectFiles.addAll(
compileFiles(avrBasePath, outputFolder.getAbsolutePath(), includePaths,
findFilesInFolder(utilityFolder, "S", false),
findFilesInFolder(utilityFolder, "c", false),
findFilesInFolder(utilityFolder, "cpp", false),
boardPreferences));
// other libraries should not see this library's utility/ folder
includePaths.remove(includePaths.size() - 1);
}
*/
// 3. compile the core, outputting .o files to <buildPath> and then // 3. compile the core, outputting .o files to <buildPath> and then
// collecting them into the core.a library file. // collecting them into the core.a library file.
System.out.println("3. compileCore");
System.out.println("corePath: " + corePath);
sketch.setCompilingProgress(50); sketch.setCompilingProgress(50);
compileCore(avrBasePath, _buildPath, corePath, variant, variantPath, compileCore(avrBasePath, _buildPath, corePath, variant, variantPath, prefs);
configPreferences);
/*
includePaths.clear();
includePaths.add(corePath); // include path for core only
if (variantPath != null) includePaths.add(variantPath);
List<File> coreObjectFiles =
compileFiles(avrBasePath, buildPath, includePaths,
findFilesInPath(corePath, "S", true),
findFilesInPath(corePath, "c", true),
findFilesInPath(corePath, "cpp", true),
boardPreferences);
String runtimeLibraryName = buildPath + File.separator + "core.a";
List baseCommandAR = new ArrayList(Arrays.asList(new String[] {
avrBasePath + "avr-ar",
"rcs",
runtimeLibraryName
}));
for(File file : coreObjectFiles) {
List commandAR = new ArrayList(baseCommandAR);
commandAR.add(file.getAbsolutePath());
execAsynchronously(commandAR);
}
*/
// 4. link it all together into the .elf file // 4. link it all together into the .elf file
sketch.setCompilingProgress(60); sketch.setCompilingProgress(60);
System.out.println("4. compileLink"); compileLink(avrBasePath, _buildPath, corePath, includePaths, prefs);
compileLink(avrBasePath, _buildPath, corePath, includePaths,
configPreferences);
/*
List baseCommandLinker = new ArrayList(Arrays.asList(new String[] {
avrBasePath + "avr-gcc",
"-Os",
"-Wl,--gc-sections"+optRelax,
"-mmcu=" + boardPreferences.get("build.mcu"),
"-o",
buildPath + File.separator + primaryClassName + ".elf"
}));
for (File file : objectFiles) {
baseCommandLinker.add(file.getAbsolutePath());
}
baseCommandLinker.add(runtimeLibraryName);
baseCommandLinker.add("-L" + buildPath);
baseCommandLinker.add("-lm");
execAsynchronously(baseCommandLinker);
List baseCommandObjcopy = new ArrayList(Arrays.asList(new String[] {
avrBasePath + "avr-objcopy",
"-O",
"-R",
}));
List commandObjcopy;
*/
// 5. extract EEPROM data (from EEMEM directive) to .eep file. // 5. extract EEPROM data (from EEMEM directive) to .eep file.
sketch.setCompilingProgress(70); sketch.setCompilingProgress(70);
/* compileEep(avrBasePath, _buildPath, includePaths, prefs);
commandObjcopy = new ArrayList(baseCommandObjcopy);
commandObjcopy.add(2, "ihex");
commandObjcopy.set(3, "-j");
commandObjcopy.add(".eeprom");
commandObjcopy.add("--set-section-flags=.eeprom=alloc,load");
commandObjcopy.add("--no-change-warnings");
commandObjcopy.add("--change-section-lma");
commandObjcopy.add(".eeprom=0");
commandObjcopy.add(buildPath + File.separator + primaryClassName + ".elf");
commandObjcopy.add(buildPath + File.separator + primaryClassName + ".eep");
execAsynchronously(commandObjcopy);
*/
System.out.println("5. compileEep");
compileEep(avrBasePath, _buildPath, includePaths, configPreferences);
// 6. build the .hex file // 6. build the .hex file
sketch.setCompilingProgress(80); sketch.setCompilingProgress(80);
/* compileHex(avrBasePath, _buildPath, includePaths, prefs);
commandObjcopy = new ArrayList(baseCommandObjcopy);
commandObjcopy.add(2, "ihex");
commandObjcopy.add(".eeprom"); // remove eeprom data
commandObjcopy.add(buildPath + File.separator + primaryClassName + ".elf");
commandObjcopy.add(buildPath + File.separator + primaryClassName + ".hex");
execAsynchronously(commandObjcopy);
*/
System.out.println("6. compileHex");
compileHex(avrBasePath, _buildPath, includePaths, configPreferences);
sketch.setCompilingProgress(90); sketch.setCompilingProgress(90);
return true; return true;
} }
private List<File> compileFiles(String avrBasePath, private List<File> compileFiles(String avrBasePath, String buildPath,
String buildPath, List<String> includePaths, File sourcePath, boolean recurse,
List<File> sSources, List<String> includePaths,
List<File> cSources, List<File> cppSources, PreferencesMap prefs) throws RunnerException {
PreferencesMap prefs) List<File> sSources = findFilesInFolder(sourcePath, "S", recurse);
throws RunnerException { List<File> cSources = findFilesInFolder(sourcePath, "c", recurse);
List<File> cppSources = findFilesInFolder(sourcePath, "cpp", recurse);
List<File> objectPaths = new ArrayList<File>(); List<File> objectPaths = new ArrayList<File>();
for (File file : sSources) { for (File file : sSources) {
@ -587,203 +477,83 @@ public class Compiler implements MessageConsumer {
System.err.print(s); System.err.print(s);
} }
///////////////////////////////////////////////////////////////////////////// private String[] getCommandCompilerS(String avrBasePath,
/* List<String> includePaths,
static private List getCommandCompilerS(String avrBasePath, List includePaths, String sourceName, String objectName,
String sourceName, String objectName, Map<String, String> boardPreferences) { PreferencesMap prefs)
List baseCommandCompiler = new ArrayList(Arrays.asList(new String[] { throws RunnerException {
avrBasePath + "avr-gcc",
"-c", // compile, don't link
"-g", // include debugging info (so errors include line numbers)
"-assembler-with-cpp",
"-mmcu=" + boardPreferences.get("build.mcu"),
"-DF_CPU=" + boardPreferences.get("build.f_cpu"),
"-DARDUINO=" + Base.REVISION,
}));
for (int i = 0; i < includePaths.size(); i++) {
baseCommandCompiler.add("-I" + (String) includePaths.get(i));
}
baseCommandCompiler.add(sourceName);
baseCommandCompiler.add("-o"+ objectName);
return baseCommandCompiler;
}
*/
// ///////////////////////////////////////////////////////////////////////////
static private String[] getCommandCompilerS(String avrBasePath,
List<String> includePaths, String sourceName, String objectName,
PreferencesMap configPreferences)
{
System.out.println("getCommandCompilerS: start");
String baseCommandString = configPreferences.get("recipe.cpp.o.pattern");
MessageFormat compileFormat = new MessageFormat(baseCommandString);
//getIncludes to String
String includes = preparePaths(includePaths); String includes = preparePaths(includePaths);
Object[] Args = { PreferencesMap dict = new PreferencesMap(prefs);
avrBasePath, dict.put("ide_version", "" + Base.REVISION);
configPreferences.get("compiler.cpp.cmd"), dict.put("includes", includes);
configPreferences.get("compiler.S.flags"), dict.put("source_file", sourceName);
configPreferences.get("compiler.cpudef"), dict.put("object_file", objectName);
configPreferences.get("build.mcu"), dict.put("toolchain_path", avrBasePath);
configPreferences.get("build.f_cpu"),
configPreferences.get("software"),
Base.REVISION,
includes,
sourceName,
objectName
};
String command = compileFormat.format( Args ); try {
String[] commandArray = command.split("\\|"); String cmd = prefs.get("recipe.S.o.pattern");
return commandArray; return StringReplacer.formatAndSplit(cmd, dict);
} catch (Exception e) {
throw new RunnerException(e);
}
} }
/*
static private List getCommandCompilerC(String avrBasePath, List includePaths,
String sourceName, String objectName, Map<String, String> boardPreferences) {
List baseCommandCompiler = new ArrayList(Arrays.asList(new String[] {
avrBasePath + "avr-gcc",
"-c", // compile, don't link
"-g", // include debugging info (so errors include line numbers)
"-Os", // optimize for size
Preferences.getBoolean("build.verbose") ? "-Wall" : "-w", // show warnings if verbose
"-ffunction-sections", // place each function in its own section
"-fdata-sections",
"-mmcu=" + boardPreferences.get("build.mcu"),
"-DF_CPU=" + boardPreferences.get("build.f_cpu"),
"-MMD", // output dependancy info
"-DARDUINO=" + Base.REVISION,
}));
for (int i = 0; i < includePaths.size(); i++) {
baseCommandCompiler.add("-I" + (String) includePaths.get(i));
}
baseCommandCompiler.add(sourceName);
baseCommandCompiler.add("-o");
baseCommandCompiler.add(objectName);
return baseCommandCompiler;
}
*/
//removed static
private String[] getCommandCompilerC(String avrBasePath, private String[] getCommandCompilerC(String avrBasePath,
List<String> includePaths, String sourceName, String objectName, List<String> includePaths,
PreferencesMap configPreferences) String sourceName, String objectName,
{ PreferencesMap prefs)
System.out.println("getCommandCompilerC: start"); throws RunnerException {
String baseCommandString = configPreferences.get("recipe.c.o.pattern");
MessageFormat compileFormat = new MessageFormat(baseCommandString);
//getIncludes to String
String includes = preparePaths(includePaths); String includes = preparePaths(includePaths);
String[] args = { PreferencesMap dict = new PreferencesMap(prefs);
avrBasePath, dict.put("ide_version", "" + Base.REVISION);
configPreferences.get("compiler.c.cmd"), dict.put("includes", includes);
configPreferences.get("compiler.c.flags"), dict.put("source_file", sourceName);
configPreferences.get("compiler.cpudef"), dict.put("object_file", objectName);
configPreferences.get("build.mcu"), dict.put("toolchain_path", avrBasePath);
configPreferences.get("build.f_cpu"),
configPreferences.get("software"),
"" + Base.REVISION,
includes,
sourceName,
objectName
};
String command = compileFormat.format(args); String cmd = prefs.get("recipe.c.o.pattern");
String[] commandArray = command.split("\\|"); try {
return commandArray; return StringReplacer.formatAndSplit(cmd, dict);
} catch (Exception e) {
throw new RunnerException(e);
} }
/*
static private List getCommandCompilerCPP(String avrBasePath,
List includePaths, String sourceName, String objectName,
Map<String, String> boardPreferences) {
List baseCommandCompilerCPP = new ArrayList(Arrays.asList(new String[] {
avrBasePath + "avr-g++",
"-c", // compile, don't link
"-g", // include debugging info (so errors include line numbers)
"-Os", // optimize for size
Preferences.getBoolean("build.verbose") ? "-Wall" : "-w", // show warnings if verbose
"-fno-exceptions",
"-ffunction-sections", // place each function in its own section
"-fdata-sections",
"-mmcu=" + boardPreferences.get("build.mcu"),
"-DF_CPU=" + boardPreferences.get("build.f_cpu"),
"-MMD", // output dependancy info
"-DARDUINO=" + Base.REVISION,
}));
for (int i = 0; i < includePaths.size(); i++) {
baseCommandCompilerCPP.add("-I" + (String) includePaths.get(i));
} }
baseCommandCompilerCPP.add(sourceName); private String[] getCommandCompilerCPP(String avrBasePath,
baseCommandCompilerCPP.add("-o"); List<String> includePaths,
baseCommandCompilerCPP.add(objectName); String sourceName, String objectName,
PreferencesMap prefs)
return baseCommandCompilerCPP; throws RunnerException {
}
*/
static private String[] getCommandCompilerCPP(String avrBasePath,
List<String> includePaths, String sourceName, String objectName,
PreferencesMap configPreferences)
{
System.out.println("getCommandCompilerCPP: start");
String baseCommandString = configPreferences.get("recipe.cpp.o.pattern");
MessageFormat compileFormat = new MessageFormat(baseCommandString);
//getIncludes to String
String includes = preparePaths(includePaths); String includes = preparePaths(includePaths);
String[] args = { PreferencesMap dict = new PreferencesMap(prefs);
avrBasePath, dict.put("ide_version", "" + Base.REVISION);
configPreferences.get("compiler.cpp.cmd"), dict.put("includes", includes);
configPreferences.get("compiler.cpp.flags"), dict.put("source_file", sourceName);
configPreferences.get("compiler.cpudef"), dict.put("object_file", objectName);
configPreferences.get("build.mcu"), dict.put("toolchain_path", avrBasePath);
configPreferences.get("build.f_cpu"),
configPreferences.get("software"),
"" + Base.REVISION,
includes,
sourceName,
objectName
};
String command = compileFormat.format(args); String cmd = prefs.get("recipe.cpp.o.pattern");
String[] commandArray = command.split("\\|"); try {
return StringReplacer.formatAndSplit(cmd, dict);
/* } catch (Exception e) {
System.out.println("command:" + command); throw new RunnerException(e);
for (int ii = 0; ii < commandArray.length; ii++)
{
System.out.println("'" + commandArray[ii] + "'");
} }
*/
return commandArray;
} }
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
static private void createFolder(File folder) throws RunnerException { private void createFolder(File folder) throws RunnerException {
if (folder.isDirectory()) return; if (folder.isDirectory())
return;
if (!folder.mkdir()) if (!folder.mkdir())
throw new RunnerException("Couldn't create: " + folder); throw new RunnerException("Couldn't create: " + folder);
} }
/** /**
* Given a folder, return a list of the header files in that folder (but * Given a folder, return a list of the header files in that folder (but not
* not the header files in its sub-folders, as those should be included from * the header files in its sub-folders, as those should be included from
* within the header files at the top-level). * within the header files at the top-level).
*/ */
static public String[] headerListFromIncludePath(String path) { static public String[] headerListFromIncludePath(String path) {
@ -796,20 +566,16 @@ public class Compiler implements MessageConsumer {
return (new File(path)).list(onlyHFiles); return (new File(path)).list(onlyHFiles);
} }
static public List<File> findFilesInPath(String path, String extension,
boolean recurse) {
System.out.println("findFilesInPath: " + path);
return findFilesInFolder(new File(path), extension, recurse);
}
static public List<File> findFilesInFolder(File folder, String extension, static public List<File> findFilesInFolder(File folder, String extension,
boolean recurse) { boolean recurse) {
List<File> files = new ArrayList<File>(); List<File> files = new ArrayList<File>();
if (folder.listFiles() == null) return files; if (folder.listFiles() == null)
return files;
for (File file : folder.listFiles()) { for (File file : folder.listFiles()) {
if (file.getName().startsWith(".")) continue; // skip hidden files if (file.getName().startsWith("."))
continue; // skip hidden files
if (file.getName().endsWith("." + extension)) if (file.getName().endsWith("." + extension))
files.add(file); files.add(file);
@ -822,62 +588,37 @@ public class Compiler implements MessageConsumer {
return files; return files;
} }
// 1. compile the sketch (already in the buildPath) // 1. compile the sketch (already in the buildPath)
void compileSketch(String avrBasePath, String buildPath, void compileSketch(String avrBasePath, String buildPath,
List<String> includePaths, PreferencesMap configPreferences) List<String> includePaths, PreferencesMap prefs)
throws RunnerException throws RunnerException {
{ objectFiles.addAll(compileFiles(avrBasePath, buildPath,
System.out.println("compileSketch: start"); new File(buildPath), false, includePaths,
System.out.println("includePaths: "); prefs));
for (int i = 0; i < includePaths.size(); i++) {
System.out.println("-I" + (String) includePaths.get(i));
}
//logger.debug("compileSketch: start");
objectFiles.addAll(compileFiles(avrBasePath, buildPath, includePaths,
findFilesInPath(buildPath, "S", false),
findFilesInPath(buildPath, "c", false),
findFilesInPath(buildPath, "cpp", false),
configPreferences));
} }
// 2. compile the libraries, outputting .o files to: // 2. compile the libraries, outputting .o files to:
// <buildPath>/<library>/ // <buildPath>/<library>/
void compileLibraries (String avrBasePath, String buildPath, void compileLibraries(String avrBasePath, String buildPath,
List<String> includePaths, List<String> includePaths,
PreferencesMap configPreferences) PreferencesMap configPreferences)
throws RunnerException throws RunnerException {
{
System.out.println("compileLibraries: start"); System.out.println("compileLibraries: start");
for (File libraryFolder : sketch.getImportedLibraries()) { for (File libraryFolder : sketch.getImportedLibraries()) {
System.out.println("libraryFolder: " + libraryFolder);
File outputFolder = new File(buildPath, libraryFolder.getName()); File outputFolder = new File(buildPath, libraryFolder.getName());
File utilityFolder = new File(libraryFolder, "utility"); File utilityFolder = new File(libraryFolder, "utility");
createFolder(outputFolder); createFolder(outputFolder);
// this library can use includes in its utility/ folder // this library can use includes in its utility/ folder
includePaths.add(utilityFolder.getAbsolutePath()); includePaths.add(utilityFolder.getAbsolutePath());
//debug includePaths
System.out.println("includePaths: ");
for (int i = 0; i < includePaths.size(); i++) {
System.out.println("-I" + (String) includePaths.get(i));
}
objectFiles.addAll(compileFiles(avrBasePath, outputFolder
objectFiles.addAll( .getAbsolutePath(), libraryFolder, false, includePaths,
compileFiles(avrBasePath, outputFolder.getAbsolutePath(), includePaths,
findFilesInFolder(libraryFolder, "S", false),
findFilesInFolder(libraryFolder, "c", false),
findFilesInFolder(libraryFolder, "cpp", false),
configPreferences)); configPreferences));
outputFolder = new File(outputFolder, "utility"); outputFolder = new File(outputFolder, "utility");
createFolder(outputFolder); createFolder(outputFolder);
objectFiles.addAll( objectFiles.addAll(compileFiles(avrBasePath, outputFolder
compileFiles(avrBasePath, outputFolder.getAbsolutePath(), includePaths, .getAbsolutePath(), utilityFolder, false, includePaths,
findFilesInFolder(utilityFolder, "S", false),
findFilesInFolder(utilityFolder, "c", false),
findFilesInFolder(utilityFolder, "cpp", false),
configPreferences)); configPreferences));
// other libraries should not see this library's utility/ folder // other libraries should not see this library's utility/ folder
includePaths.remove(includePaths.size() - 1); includePaths.remove(includePaths.size() - 1);
@ -886,147 +627,123 @@ public class Compiler implements MessageConsumer {
// 3. compile the core, outputting .o files to <buildPath> and then // 3. compile the core, outputting .o files to <buildPath> and then
// collecting them into the core.a library file. // collecting them into the core.a library file.
void compileCore (String avrBasePath, String buildPath, void compileCore(String avrBasePath, String buildPath, String corePath,
String corePath, String variant, String variantPath, String variant, String variantPath, PreferencesMap prefs)
PreferencesMap configPreferences) throws RunnerException {
throws RunnerException
{
System.out.println("compileCore(...) start");
List<String> includePaths = new ArrayList<String>(); List<String> includePaths = new ArrayList<String>();
includePaths.add(corePath); //include core path only includePaths.add(corePath); // include core path only
if (variantPath != null) includePaths.add(variantPath); if (variantPath != null)
includePaths.add(variantPath);
//debug includePaths List<File> coreObjectFiles = compileFiles(avrBasePath, buildPath, new File(
System.out.println("includePaths: "); corePath), true, includePaths, prefs);
for (int i = 0; i < includePaths.size(); i++)
System.out.println("-I" + (String) includePaths.get(i));
String baseCommandString = configPreferences.get("recipe.ar.pattern");
String commandString = "";
MessageFormat compileFormat = new MessageFormat(baseCommandString);
System.out.println("corePath: " + corePath);
List<File> coreObjectFiles = compileFiles(
avrBasePath,
buildPath,
includePaths,
findFilesInPath(corePath, "S", true),
findFilesInPath(corePath, "c", true),
findFilesInPath(corePath, "cpp", true),
configPreferences);
for (File file : coreObjectFiles) { for (File file : coreObjectFiles) {
//List commandAR = new ArrayList(baseCommandAR);
//commandAR = commandAR + file.getAbsolutePath();
String[] args = { PreferencesMap dict = new PreferencesMap(prefs);
avrBasePath, dict.put("toolchain_path", avrBasePath);
configPreferences.get("compiler.ar.cmd"), dict.put("ide_version", "" + Base.REVISION);
configPreferences.get("compiler.ar.flags"), dict.put("build_path", buildPath + File.separator);
//corePath, dict.put("archive_file", "core.a");
buildPath + File.separator, dict.put("object_file", file.getAbsolutePath());
"core.a",
//objectName
file.getAbsolutePath()
};
System.out.println("compileCore(...) substitute");
commandString = compileFormat.format(args); String[] cmdArray;
String[] commandArray = commandString.split("\\|"); try {
execAsynchronously(commandArray); String cmd = prefs.get("recipe.ar.pattern");
cmdArray = StringReplacer.formatAndSplit(cmd, dict);
} catch (Exception e) {
throw new RunnerException(e);
}
execAsynchronously(cmdArray);
} }
} }
// 4. link it all together into the .elf file // 4. link it all together into the .elf file
void compileLink(String avrBasePath, String buildPath, void compileLink(String avrBasePath, String buildPath, String corePath,
String corePath, List<String> includePaths, List<String> includePaths, PreferencesMap prefs)
PreferencesMap configPreferences) throws RunnerException {
throws RunnerException
{ // TODO: Make the --relax thing in configuration files.
// For atmega2560, need --relax linker option to link larger // For atmega2560, need --relax linker option to link larger
// programs correctly. // programs correctly.
String optRelax = ""; String optRelax = "";
if (configPreferences.get("build.mcu").equals("atmega2560")) if (prefs.get("build.mcu").equals("atmega2560"))
optRelax = ",--relax"; optRelax = ",--relax";
System.out.println("compileLink: start");
String baseCommandString = configPreferences.get("recipe.c.combine.pattern");
String commandString = "";
MessageFormat compileFormat = new MessageFormat(baseCommandString);
String objectFileList = ""; String objectFileList = "";
for (File file : objectFiles)
objectFileList += " \"" + file.getAbsolutePath() + '"';
objectFileList = objectFileList.substring(1);
for (File file : objectFiles) { PreferencesMap dict = new PreferencesMap(prefs);
objectFileList = objectFileList + file.getAbsolutePath() + "|"; dict.put("compiler.c.elf.flags", dict
.get("compiler.c.elf.flags" + optRelax));
dict.put("toolchain_path", avrBasePath);
dict.put("build_path", buildPath + File.separator);
dict.put("archive_file", "core.a");
dict.put("project_name", primaryClassName);
dict.put("object_files", objectFileList);
dict.put("ide_version", "" + Base.REVISION);
dict.put("core_path", corePath);
String[] cmdArray;
try {
String cmd = prefs.get("recipe.c.combine.pattern");
cmdArray = StringReplacer.formatAndSplit(cmd, dict);
} catch (Exception e) {
throw new RunnerException(e);
} }
System.out.println("objectFileList: " + objectFileList); execAsynchronously(cmdArray);
String[] args = {
avrBasePath,
configPreferences.get("compiler.c.elf.cmd"),
configPreferences.get("compiler.c.elf.flags")+optRelax,
configPreferences.get("compiler.cpudef"),
configPreferences.get("build.mcu"),
buildPath + File.separator,
primaryClassName,
objectFileList,
buildPath + File.separator + "core.a",
buildPath,
corePath,
configPreferences.get("ldscript"),
};
commandString = compileFormat.format(args);
String[] commandArray = commandString.split("\\|");
execAsynchronously(commandArray);
} }
// 5. extract EEPROM data (from EEMEM directive) to .eep file. // 5. extract EEPROM data (from EEMEM directive) to .eep file.
void compileEep (String avrBasePath, String buildPath, void compileEep(String avrBasePath, String buildPath,
List<String> includePaths, PreferencesMap configPreferences) List<String> includePaths, PreferencesMap prefs)
throws RunnerException throws RunnerException {
{ PreferencesMap dict = new PreferencesMap(prefs);
//logger.debug("compileEep: start"); dict.put("toolchain_path", avrBasePath);
String baseCommandString = configPreferences.get("recipe.objcopy.eep.pattern"); dict.put("build_path", buildPath + File.separator);
String commandString = ""; dict.put("project_name", primaryClassName);
MessageFormat compileFormat = new MessageFormat(baseCommandString); dict.put("ide_version", "" + Base.REVISION);
String[] args = { String[] cmdArray;
avrBasePath, try {
configPreferences.get("compiler.objcopy.cmd"), String cmd = prefs.get("recipe.objcopy.eep.pattern");
configPreferences.get("compiler.objcopy.eep.flags"), cmdArray = StringReplacer.formatAndSplit(cmd, dict);
buildPath + File.separator + primaryClassName, } catch (Exception e) {
buildPath + File.separator + primaryClassName throw new RunnerException(e);
}; }
commandString = compileFormat.format(args); execAsynchronously(cmdArray);
String[] commandArray = commandString.split("\\|");
execAsynchronously(commandArray);
} }
// 6. build the .hex file // 6. build the .hex file
void compileHex (String avrBasePath, String buildPath, void compileHex(String avrBasePath, String buildPath,
List<String> includePaths, PreferencesMap configPreferences) List<String> includePaths, PreferencesMap prefs)
throws RunnerException throws RunnerException {
{ PreferencesMap dict = new PreferencesMap(prefs);
//logger.debug("compileHex: start"); dict.put("toolchain_path", avrBasePath);
String baseCommandString = configPreferences.get("recipe.objcopy.hex.pattern"); dict.put("build_path", buildPath + File.separator);
String commandString = ""; dict.put("project_name", primaryClassName);
MessageFormat compileFormat = new MessageFormat(baseCommandString); dict.put("ide_version", "" + Base.REVISION);
String[] args = { String[] cmdArray;
avrBasePath, try {
configPreferences.get("compiler.elf2hex.cmd"), String cmd = prefs.get("recipe.objcopy.hex.pattern");
configPreferences.get("compiler.elf2hex.flags"), cmdArray = StringReplacer.formatAndSplit(cmd, dict);
buildPath + File.separator + primaryClassName, } catch (Exception e) {
buildPath + File.separator + primaryClassName throw new RunnerException(e);
}; }
commandString = compileFormat.format(args); execAsynchronously(cmdArray);
String[] commandArray = commandString.split("\\|");
execAsynchronously(commandArray);
} }
private static String preparePaths(List<String> includePaths) { private static String preparePaths(List<String> includePaths) {
String includes = ""; String res = "";
for (String p : includePaths) for (String p : includePaths)
includes += " -I" + p + "|"; res += " \"-I" + p + '"';
return includes;
// Remove first space
return res.substring(1);
} }
} }

View File

@ -28,6 +28,7 @@ package processing.app.debug;
* An exception with a line number attached that occurs * An exception with a line number attached that occurs
* during either compile time or run time. * during either compile time or run time.
*/ */
@SuppressWarnings("serial")
public class RunnerException extends Exception /*RuntimeException*/ { public class RunnerException extends Exception /*RuntimeException*/ {
protected String message; protected String message;
protected int codeIndex; protected int codeIndex;
@ -64,6 +65,10 @@ public class RunnerException extends Exception /*RuntimeException*/ {
} }
public RunnerException(Exception e) {
this(e.getMessage(), true);
}
/** /**
* Override getMessage() in Throwable, so that I can set * Override getMessage() in Throwable, so that I can set
* the message text outside the constructor. * the message text outside the constructor.

View File

@ -35,6 +35,14 @@ import processing.core.PApplet;
public class PreferencesMap extends HashMap<String, String> { public class PreferencesMap extends HashMap<String, String> {
public PreferencesMap(PreferencesMap prefs) {
super(prefs);
}
public PreferencesMap() {
super();
}
/** /**
* Parse a property list file and put kev/value pairs into the Map * Parse a property list file and put kev/value pairs into the Map
* *
@ -67,6 +75,32 @@ public class PreferencesMap extends HashMap<String, String> {
} }
} }
/**
* Create a new Map<String, PreferenceMap> where the keys are the first level
* of the current mapping. E.g. the folowing mapping:<br />
*
* <pre>
* Map (
* alpha.some.keys = v1
* alpha.other.keys = v2
* beta.some.keys = v3
* )
* </pre>
*
* will generate the following result:
*
* <pre>
* alpha = Map(
* some.keys = v1
* other.keys = v2
* )
* beta = Map(
* some.keys = v3
* )
* </pre>
*
* @return
*/
public Map<String, PreferencesMap> createFirstLevelMap() { public Map<String, PreferencesMap> createFirstLevelMap() {
Map<String, PreferencesMap> res = new HashMap<String, PreferencesMap>(); Map<String, PreferencesMap> res = new HashMap<String, PreferencesMap>();
for (String key : keySet()) { for (String key : keySet()) {
@ -84,5 +118,40 @@ public class PreferencesMap extends HashMap<String, String> {
return res; return res;
} }
/**
* Create a new PreferenceMap using a subtree of the current mapping. E.g.
* with the folowing mapping:<br />
*
* <pre>
* Map (
* alpha.some.keys = v1
* alpha.other.keys = v2
* beta.some.keys = v3
* )
* </pre>
*
* a call to createSubTree("alpha") will generate the following result:
*
* <pre>
* Map(
* some.keys = v1
* other.keys = v2
* )
* </pre>
*
* @param parent
* @return
*/
public PreferencesMap createSubTree(String parent) {
PreferencesMap res = new PreferencesMap();
parent += ".";
int parentLen = parent.length();
for (String key : keySet()) {
if (key.startsWith(parent))
res.put(key.substring(parentLen), get(key));
}
return res;
}
private static final long serialVersionUID = 2330591567444282843L; private static final long serialVersionUID = 2330591567444282843L;
} }

View File

@ -0,0 +1,66 @@
package processing.app.helpers;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class StringReplacer {
public static String[] formatAndSplit(String src, Map<String, String> dict)
throws Exception {
// Do a replace with dictionary
src = StringReplacer.replaceFromMapping(src, dict);
// Split the resulting string in arguments
return quotedSplit(src, '"', false);
}
public static String[] quotedSplit(String src, char escapeChar,
boolean acceptEmptyArguments) throws Exception {
String quote = "" + escapeChar;
List<String> res = new ArrayList<String>();
String escapedArg = null;
boolean escaping = false;
for (String i : src.split(" ")) {
if (!escaping) {
if (!i.startsWith(quote)) {
if (!i.trim().isEmpty() || acceptEmptyArguments)
res.add(i);
continue;
}
escaping = true;
i = i.substring(1);
escapedArg = "";
}
if (!i.endsWith(quote)) {
escapedArg += i + " ";
continue;
}
escapedArg += i.substring(0, i.length() - 1);
if (!escapedArg.trim().isEmpty() || acceptEmptyArguments)
res.add(escapedArg);
escaping = false;
}
if (escaping)
throw new Exception("Invalid quoting: no closing '" + escapeChar
+ "' char found.");
return res.toArray(new String[0]);
}
public static String replaceFromMapping(String src, Map<String, String> map) {
return replaceFromMapping(src, map, "{", "}");
}
public static String replaceFromMapping(String src, Map<String, String> map,
String leftDelimiter, String rightDelimiter) {
for (String k : map.keySet()) {
String keyword = leftDelimiter + k + rightDelimiter;
src = src.replace(keyword, map.get(k));
}
return src;
}
}

View File

@ -1,58 +1,22 @@
#########Compiler Recipe#################################
##compile c object files
##Default.recipe, overide if overide exists, these defauls should remain the same, if you need to change them do it as an overide.
#default.recipe.c.o.pattern={0}{1}|{2}|{3}{4}|-DF_CPU={5}|-D{6}={7}|{8}|{9}|-o|{10} # AVR compile variables
#default.recipe.cpp.o.pattern={0}{1}|{2}|{3}{4}|-DF_CPU={5}|-D{6}={7}|{8}|{9}|-o|{10} # ---------------------
#default.recipe.ar.pattern={0}{1}|{2}|{3}{4}|{5}
#default.recipe.c.combine.pattern={0}{1}|{2}|{3}{4}|-o|{5}{6}.elf|{7}|{8}|-L{9}|-lm
#default.recipe.objcopy.eep.pattern={0}{1}|{2}|{3}.elf|{4}.eep
#default.recipe.objcopy.hex.pattern={0}{1}|{2}|{3}.elf|{4}.hex
########avr compile pattern ##########
#recipe.c.o.pattern={0=compiler.path}{1=compiler.c.cmd}{2=compiler.c.flags}{3=compiler.cpudef}{4=build.mcu}-DF_CPU={5=build.f_cpu}-D{7=ARDUINO}={6=Base.REVISION}{7=-I/INCLUDE_PATHS} {8=SOURCE_NAME} -o{9=OBJECT_NAME}
#object name seems to have build path in it.
recipe.c.o.pattern={0}{1}|{2}|{3}{4}|-DF_CPU={5}|-D{6}={7}|{8}|{9}|-o|{10}
##compile cc object files
#recipe.cc.o.pattern={0=compiler.path}{1=compiler.cc.cmd}{2=compiler.c.flags}{3=compiler.cpudef}{4=build.mcu}-DF_CPU={5=build.f_cpu}-DARDUINO={6=Base.REVISION}{-7=I/INCLUDE_PATHS} {8=SOURCE_NAME} -o{9=BUILD_PATH}{10=OBJECT_NAME}
recipe.cpp.o.pattern={0}{1}|{2}|{3}{4}|-DF_CPU={5}|-D{6}={7}|{8}|{9}|-o|{10}
##create archives
#recipe.ar.pattern={0=compiler.path}{1=compiler.ar.cmd}{2=compiler.ar.flags}{3=BUILD_PATH}{4=CORE_NAME=core.a}{5=BUILD_PATH}{6=OBJECT_NAME}
recipe.ar.pattern={0}{1}|{2}|{3}{4}|{5}
##combine gc-sections| archives, and objects
#recipe.c.combine.pattern={0=compiler.path}{1=compiler.c.cmd}{2=compiler.combine.flags}{3=compiler.cpudef}{4=build.mcu} -o {5=BUILD_PATH}{6=SOURCE_NAME}.elf {7=BUILD_PATH}{8=SOURCE_NAME}.o {9=BUILD_PATH}{10=CORE_NAME=core.a} -L{11=BUILD_PATH} -lm
#recipe.c.combine.pattern={0}{1}|{2}|{3}{4}|-o|{5}{6}.elf|{7}{8}|{9}|-L{10}|-lm
recipe.c.combine.pattern={0}{1}|{2}|{3}{4}|-o|{5}{6}.elf|{7}|{8}|-L{9}|-lm
##create eeprom
#recipe.objcopy.eep.pattern={0=compiler.path}{1=compiler.objcopy.cmd}{2=compiler.objcopy.eep.flags} {3=BUILD_PATH}{4=SOURCE_NAME}.elf {5=BUILD_PATH}{6=SOURCE_NAME}.eep
recipe.objcopy.eep.pattern={0}{1}|{2}|{3}.elf|{4}.eep
##create hex
#recipe.objcopy.hex.pattern={0=compiler.path}{1=compiler.objcopy.cmd}{2=compiler.objcopy.elf.flags} {3=BUILD_PATH}{4=SOURCE_NAME}.elf {5=BUILD_PATH}{6=SOURCE_NAME}.hex
recipe.objcopy.hex.pattern={0}{1}|{2}|{3}.elf|{4}.hex
########################################################
name=Arduino name=Arduino
#compiler.path Official default is correct, only need to change this if you want to overide the initial default # Default "compiler.path" is correct, change only if you want to overidde the initial value
#compiler.path={0}/hardware/tools/avr/bin/ #compiler.path={0}/hardware/tools/avr/bin/
compiler.c.cmd=avr-gcc compiler.c.cmd=avr-gcc
compiler.c.flags=|-c|-g|-Os|-w|-ffunction-sections|-fdata-sections compiler.c.flags=-c -g -Os -w -ffunction-sections -fdata-sections
compiler.c.elf.flags=|-Os|-Wl,--gc-sections compiler.c.elf.flags=-Os -Wl,--gc-sections
compiler.c.elf.cmd=avr-gcc compiler.c.elf.cmd=avr-gcc
compiler.S.flags=|-c|-g|-assembler-with-cpp compiler.S.flags=-c -g -assembler-with-cpp
compiler.cpp.cmd=avr-g++ compiler.cpp.cmd=avr-g++
compiler.cpp.flags=|-c|-g|-Os|-w|-fno-exceptions|-ffunction-sections|-fdata-sections compiler.cpp.flags=-c -g -Os -w -fno-exceptions -ffunction-sections -fdata-sections
compiler.ar.cmd=avr-ar compiler.ar.cmd=avr-ar
compiler.ar.flags=rcs compiler.ar.flags=rcs
compiler.objcopy.cmd=avr-objcopy compiler.objcopy.cmd=avr-objcopy
compiler.objcopy.eep.flags=|-O|ihex|-j|.eeprom|--set-section-flags=.eeprom=alloc,load|--no-change-warnings|--change-section-lma|.eeprom=0 compiler.objcopy.eep.flags=-O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0
compiler.elf2hex.flags=|-O|ihex|-R|.eeprom compiler.elf2hex.flags=-O ihex -R .eeprom
compiler.elf2hex.cmd=avr-objcopy compiler.elf2hex.cmd=avr-objcopy
compiler.ldflags= compiler.ldflags=
compiler.cpudef=-mmcu= compiler.cpudef=-mmcu=
@ -62,3 +26,26 @@ compiler.define=-DARDUINO=
library.path=./hardware/arduino/cores/arduino library.path=./hardware/arduino/cores/arduino
library.core.path=./libraries library.core.path=./libraries
# AVR compile patterns
# --------------------
## Compile c files
recipe.c.o.pattern={toolchain_path}{compiler.c.cmd} {compiler.c.flags} {compiler.cpudef}{build.mcu} -DF_CPU={build.f_cpu} -D{software}={ide_version} {includes} {source_file} -o {object_file}
## Compile c++ files
recipe.cpp.o.pattern={toolchain_path}{compiler.cpp.cmd} {compiler.cpp.flags} {compiler.cpudef}{build.mcu} -DF_CPU={build.f_cpu} -D{software}={ide_version} {includes} {source_file} -o {object_file}
## Create archives
recipe.ar.pattern={toolchain_path}{compiler.ar.cmd} {compiler.ar.flags} {build_path}{archive_file} {object_file}
## Combine gc-sections, archives, and objects
recipe.c.combine.pattern={toolchain_path}{compiler.c.elf.cmd} {compiler.c.elf.flags} {compiler.cpudef}{build.mcu} -o {build_path}{project_name}.elf {object_files} {build_path}{archive_file} -L{build_path} -lm
## Create eeprom
recipe.objcopy.eep.pattern={toolchain_path}{compiler.objcopy.cmd} {compiler.objcopy.eep.flags} {build_path}{project_name}.elf {build_path}{project_name}.eep
## Create hex
recipe.objcopy.hex.pattern={toolchain_path}{compiler.elf2hex.cmd} {compiler.elf2hex.flags} {build_path}{project_name}.elf {build_path}{project_name}.hex